#author("2023-06-18T14:59:47+09:00","default:irrp","irrp")
#author("2024-04-15T11:56:47+09:00","default:irrp","irrp")
→ExcelのVBA

#contents


*正規表現による倍角文字チェック [#rda468e1]
 Sub CheckFullWidthCharacters()
     Dim ws As Worksheet
     Dim cell As Range
     Dim lastRow As Long
     Dim fullWidthPattern As String
     Dim match As Object
 
     ' 使用するワークシートを設定
     Set ws = ActiveSheet
 
     ' C列の最終行を取得
    l astRow = ws.Cells(ws.Rows.Count, "C").End(xlUp).Row
 
     ' 全角文字を検出する正規表現パターン
    f ullWidthPattern = "[^\x00-\x7F]"
 
     ' C列のデータを一つずつチェック
     For Each cell In ws.Range("C1:C" & lastRow)
         If cell.Value <> "" Then
             cell.Select
            '  正規表現オブジェクトを作成
             With CreateObject("VBScript.RegExp")
                .Global = True
                .Pattern = fullWidthPattern
                ' パターンにマッチするかチェック
                Set match = .Execute(cell.Value)
                If match.Count > 0 Then
                    ' マッチする場合、セルの背景を赤色に設定
                    cell.Interior.Color = RGB(255, 0, 0)
                Else
                    ' マッチしない場合、セルの背景を緑色に設定
                    cell.Interior.Color = RGB(0, 255, 0)
                End If
            End With
        End If
        DoEvents
    Next cell
    MsgBox ("OK")
 End Sub



*開いているファイルの中から名前の左側が引数と合致するファイルを探す [#ye1502e2]
 '2つ以上あったらエラー
 Function schFile(name As String) As Workbook
 
     Dim cnt As Integer
     cnt = 0
 
     Set schFile = Nothing
 
     Dim bk As Workbook
     For Each bk In Workbooks
         Dim ln As Integer
         ln = Len(name)
         Debug.Assert (ln > 0)
         If StrConv(Left(bk.name, ln), vbUpperCase) = StrConv(name, vbUpperCase) Then
             If Not (schFile Is Nothing) Then
                 MsgBox ("[" & name & "]で始まるファイルが2つ以上あります")
                 End
             End If
 
             Debug.Assert (schFile Is Nothing)  '同じ名前で始まるファイルが2つ以上あったらエラーになります
             Set schFile = bk
             'ここですぐは返らない 2つ以上あったらまずいから
         End If
     Next
 
     If schFile Is Nothing Then
         MsgBox ("[" & name & "]で始まるファイルが見つかりません")
         End
     End If
 
 End Function

*countifsの数式を元に、同じ条件でフィルタをかける [#db5c2d93]
 Sub 数式からフィルター(r As Range)
 Dim strSuusiki As String
 Dim varPrm As Variant
 Dim sh As Worksheet
 Dim ac As Worksheet
 Dim lngLoop As Long
 Dim lngColNo As Long
 Dim strJoken As String
 Dim rngFil As Range
 
     Application.ScreenUpdating = False
     Application.Calculation = xlCalculationManual
 
     Set sh = Sheets("hoge")
     Set ac = r.Worksheet
 
     strSuusiki = r.Formula ''該当セルの数式を取り出す
     strSuusiki = Replace(strSuusiki, "=countifs(", "", , , vbTextCompare) '’余分なところを消す
     strSuusiki = Replace(strSuusiki, "=countif(", "", , , vbTextCompare) '’余分なところを消す
     strSuusiki = Replace(strSuusiki, ")", "") '’余分なところを消す
     varPrm = Split(strSuusiki, ",") '’Countifsのパラメータのみを配列に分割する
 
     If Not sh.AutoFilterMode Then ''オートフィルターが付いてない場合
         Intersect(sh.UsedRange, sh.Range("10:65535")).AutoFilter '’フィルターをつける
     End If
 
     If sh.FilterMode Then '’フィルターがかかっている状態のときはフィルタークリア
         sh.ShowAllData
     End If
 
     Set rngFil = sh.AutoFilter.Range
 
     For lngLoop = 0 To UBound(varPrm) Step 2
         lngColNo = Range(varPrm(lngLoop)).Column    ''配列の偶数番目=検索条件範囲のカラム番号を取得
         strJoken = varPrm(lngLoop + 1)              ''配列の奇数番目=検索条件を取得
         If InStr(strJoken, """") > 0 Then
             strJoken = Replace(strJoken, """", "") '’""がある場合は定数(””は消す)
         Else
             strJoken = ac.Range(strJoken).Value '’””がない場合はセルへの参照のため参照先の値を取得
         End If
 
 
         rngFil.AutoFilter Field:=lngColNo, Criteria1:=strJoken
     Next
 
     Application.Calculation = xlCalculationAutomatic
     Application.ScreenUpdating = True
 
 End Sub

*ハイパーリンクをクリックしたら上の行(3行目)にあげる [#y32e4897]
 Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink)
    Dim r As Integer
    r = Target.Range.row
    If r = 3 Then
        Exit Sub
    Else
        ThisWorkbook.Worksheets(1).Activate
        Rows("3:3").Select
        Selection.EntireRow.Insert
 
        r = r + 1
        Rows(r & ":" & r).Select
        Selection.Cut
        Range("A3").Select
        ActiveSheet.Paste
 
        Range("A" & r).Select
        Selection.EntireRow.Delete
    End If
 End Sub


*Shift JIS文字列をUTF-8に [#be75801e]
 Public Function encodeUTF8(ByRef strUni As String) As Byte()
    encodeUTF8 = ADOS_Encode("UTF-8", strUni)
 End Function
 
 Private Function ADOS_Encode(ByVal cset As String, ByRef strUni As String) As Byte()
    Dim objStm As ADODB.Stream
    Set objStm = New ADODB.Stream
    objStm.Open
    objStm.Type = adTypeText
    objStm.Charset = cset
    objStm.WriteText strUni
 
    objStm.Position = 0
    objStm.Type = adTypeBinary
    Select Case UCase(cset)
      Case "UNICODE", "UTF-16"
        objStm.Position = 2
      Case "UTF-8"
        objStm.Position = 3
    End Select
    ADOS_Encode = objStm.Read()
 
    objStm.Close
 
 End Function


*シート並べ替えサンプル [#r4181544]
-1シート目の2行目2列目からシート名を並べておき、その順番に2番目以降のシートを入れ替えるマクロの例(ちょっとバグってるかも…)

 Sub シート並べ替え()
 
    Dim bk As Workbook
    Set bk = ThisWorkbook
 
    Dim sht As Worksheet
    Set sht = ActiveSheet
 
    Dim names() As String
    Dim i As Integer
 
    'シート名読み込み
    Dim j As Integer
    j = 0
    For i = 2 To 1000 'とりあえず1000シートまで
        If sht.Cells(i, 2) <> "" Then
            ReDim Preserve names(j)
            names(j) = sht.Cells(i, 2)
            j = j + 1
        Else
            Exit For
        End If
    Next
 
    For i = 0 To UBound(names)
        Dim wsht As Worksheet
        Set wsht = bk.Worksheets(names(i))
        Call wsht.Move(After:=bk.Worksheets(1 + i))
    Next
 
    MsgBox ("OK")
 
 End Sub


*ブックのシートインデックスを作る [#h5eba5dc]
-最初のシートに「目次」という名前をつけるのであらかじめ用意しておく
 Sub MakeIndex()
    
    Dim s_シート名() As String
    
    Dim mokuji As Worksheet
    Set mokuji = Worksheets(1)
    mokuji.Name = "目次"
    
    '《目次》シート情報
    Dim row As Integer
    Dim col As Integer
    row = 1
    col = 2
 
    '  シート名取得
    mokuji.Select
    Dim J As Integer
    For J = 1 To Worksheets.Count
        ReDim Preserve s_シート名(J)
        s_シート名(J) = Worksheets(J).Name
    Next J
    
    mokuji.Activate
 
    '  取得結果反映
    Dim K As Integer
    For K = 2 To UBound(s_シート名)
 
        Dim sht_name As String
        sht_name = s_シート名(K)
        If sht_name <> "" Then
            Dim rnt As Range
            Set rnt = mokuji.Cells(K, col)
            mokuji.Hyperlinks.Add _
                Anchor:=rnt, _
                Address:="", SubAddress:="'" & sht_name & "'!A1", TextToDisplay:=sht_name
            mokuji.Cells(K, col).Select
        End If
 
    Next K
 End Sub


*シートに画像を取り込み、その占めている範囲の右下セルを得る [#l25d83f6]
 Dim acs As Worksheet
 Set acs = ActiveSheet
 acs.Cells(1, 1).Select
 acs.Pictures.Insert(画像のpath).Select
 Dim r As Range
 Set r = acs.Pictures(1).BottomRightCell


*いらないシートを消す [#z5170efa]
    Application.DisplayAlerts = False '警告抑制
    With outbook
        '本当は3つとは限らないが(Excelの設定によって変わるので)、とりあえず
        .Worksheets("Sheet1").Delete
        .Worksheets("Sheet2").Delete
        .Worksheets("Sheet3").Delete
    End With
--※シート数を0にはできませんので注意

*印刷改ページを調整する [#p8c34944]
 '印刷ブレーク位置微調整 13桁目だったら右に1つずらす
 '直接指定できないのだろうか?
 Function adjust_print(st As Worksheet) As Integer
 
         Debug.Print (st.Name)
         st.Activate
         st.Cells(1, 14).Select
         
         'これでは変わってくれないようだ
         If st.VPageBreaks.Count = 0 Then
             st.VPageBreaks.Add st.Range("N1")
         Else
             st.VPageBreaks(1).Location = st.Range("N1")
         End If
         
         'こうしないとあわせられないのだろうか?
         If st.VPageBreaks(1).Location.Column = 13 Then
             ActiveWindow.View = xlPageBreakPreview
             ActiveSheet.VPageBreaks(1).DragOff Direction:=xlToRight, RegionIndex:=1
             ActiveWindow.View = xlNormalView
         End If
         
         st.Cells(1, 1).Select
 
     adjust_print = 0
 End Function
 
 Sub 印刷位置合わせ()
 '
     Dim shts As Sheets
     Set shts = ActiveWorkbook.Worksheets
     Dim i As Integer
     Dim st As Worksheet
     
     '対象シート毎
     For i = 4 To shts.Count
         Set st = shts(i)
         Call adjust_print(st)
         DoEvents
     Next
     
 End Sub


*ブックを開いてシート毎になにかするサンプル [#a3c4ba90]
 Function prcBook(bk As String) As Integer
     
     Debug.Print ("-------book:" & bk & "スタート---------------------")
     
     Dim wbk As Workbook
     '指定 xls を開く
     'Set wbk = Application.Workbooks(bk)
     Set wbk = Workbooks.Open(bk)
     wbk.Activate
     
     Dim cnt As Integer
     cnt = wbk.Worksheets.Count
     Debug.Assert (cnt > 0)
     Dim i As Integer
     For i = 1 To cnt
         Dim wst As Worksheet
         Set wst = wbk.Worksheets(i)
         
         Call prcSheet(wst)
         
     Next
     
     wbk.Close
     Debug.Print ("-------処理終わり---------------------")
 
 End Function


* 現在見ているブックの全シートから_YMDHMSという値の入ったセルをすべて探し、その下にあるセルにフォーマットを設定する [#afb8f6b1]
  Sub 日付のフォーマット修正()
    Debug.Print ("フォーマット修正開始")
    Dim bk As Workbook
    Dim sht As Worksheet
    Set bk = ActiveWorkbook
    Dim i As Integer
    For i = 1 To bk.Worksheets.Count
        Set sht = bk.Worksheets(i)
        With sht
            .Activate
            .Cells(1, 1).Select
            Dim r As Range
            Set r = Cells.Find(What:="_YMDHMS", After:=ActiveCell, LookIn:=xlValues, _
                LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
                MatchCase:=False, MatchByte:=False, SearchFormat:=False)
            If Not r Is Nothing Then
                Dim firstPos As String
                firstPos = r.Address
                Do
                    Dim s As String
                    .Cells(r.row, r.Column).Select
                    If Trim(.Cells(r.row + 1, r.Column)) <> "" Then
                        s = .Cells(r.row, r.Column)
                        Debug.Print (.Name & ":" & r.row & "," & r.Column & "," & s)
                        .Cells(r.row + 1, r.Column).NumberFormatLocal = "yyyy-mm-dd hh:mm:ss"
                        .Cells(r.row + 1, r.Column).HorizontalAlignment = xlLeft
                        Dim rcol As Range
                        Set rcol = .Columns(r.Column)
                        rcol.AutoFit
                    End If
                    Set r = Cells.FindNext(r)
                    DoEvents
                Loop While (r.Address <> firstPos)
            Else
                'そもそもない
            End If
        End With
    Next
    MsgBox ("OK")
  End Sub


* パスワード付きでブックを保存する [#fb962dce]
 ActiveWorkbook.SaveAs Filename:= _
 "hoge.xls", FileFormat:= _
 xlExcel8, Password:="anestec", WriteResPassword:="", ReadOnlyRecommended _
 :=False, CreateBackup:=False

*ハイパーリンク作成 [#s57ccf65]
 表示文字列 = "hoge"
 アドレス = "http://www.kernel-net.ne.jp/tech/"
 Range("A1").Select
 ActiveSheet.Hyperlinks.Add Anchor:=Selection, _
        Address:=アドレス, TextToDisplay:=表示文字列
--削除
 Range("A1").Hyperlinks.Delete
 Range("A1").ClearContents


*データが変わった切れ目で改ページ [#a9524d65]
-http://oshiete1.goo.ne.jp/qa1919970.html
 Worksheets(SheetName).Range("B" + Trim$(Str$(rindex))).Activate
 ActiveWindow.SelectedSheets.HPageBreaks.Add ActiveCell '改ページ挿入
 ActiveWindow.SelectedSheets.VPageBreaks.Add ActiveCell


*データのある最後の行を返す [#i2c480c9]
 e=Worksheets("sheet1").Range("A1").End(xlDown).Row
もしくは
 e=Worksheets("sheet1").Range("A65536").End(xlUp).Row 'データ中に空き行がある場合

-上のやり方では、列なら2列以上ないと256が返ってしまうので、下記のようにやる方がいいようだ。
 Dim row As Integer
 row = sht.UsedRange.Cells(sht.UsedRange.Count).row
 
 Dim line As Integer
 line = sht.UsedRange.Cells(sht.UsedRange.Count).Column

-このやり方について[[こちらのblog>http://d.hatena.ne.jp/takayukis/20090329/1238296405]] でご指摘あり。感謝
 これは、データの入力の有無に関わらず、セルの一部に書式設定などがされていれば、
 有効な範囲として値を返します。
 すっきりとしていて、うまく行きそうですが、実は落とし穴になっています。

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS