■ VBAでUTF-8文書を一括書き換え 8月22日
ホームページのCopyrightの更新年号が2022のまま3年経ちました。更新年号は書き換える必要は無いそうですが、ブログやま帽子のCopyrightはワードプレスの機能で2025に書き換えられています。
ファイルの数は3千個余り。これをVBAで一括書き換えしましたので、コードを下記に掲載します。本サイトに特化したコードですが、文字列置換などに応用出来るのではないでしょうか。
このコードを実行すると、書き換えたファイルの文字コードはUTF-8(BOM無し)、
改行コードは Lf となります。
注意 元ファイルを上書きしています。必ずバックアップを取ってから実行してください。
【 マクロコード 】 Option Explicit Dim A As Variant Dim B As Variant Dim C As Variant Dim FileType As String Dim LastYear As String Dim tgtWord0 As String Dim nCorr As Long '********************************************************************* '** UTF-8(BOM無し)ファイルのCopyrightを更新する '** ファイル読込関数(ADODB.Streamを使用) '********************************************************************* Sub UTF8Copyright更新() Dim j As Long FileType = ".htm" tgtWord0 = "Copyright" LastYear = "2025" nCorr = 0 '対象フォルダーを取得 With Application.FileDialog(msoFileDialogFolderPicker) If .Show = True Then j = MsgBox(Filetype & "ファイルのCopyright年度を更新します。 _ " & vbCrLf & "OKですか?", vbOKCancel) If j = 1 Then A = .SelectedItems(1) Else j = MsgBox("キャンセルされました。", vbOKOnly) Exit Sub End If 'Coryright更新処理 Call CopyrightUpdate(A) End If End With j = MsgBox(nCorr & "個のファイルを更新しました", vbOKOnly) End Sub Sub CopyrightUpdate(A) Dim FSO As Variant Dim List As Variant Dim buf As Variant Dim tmp As Variant Dim adFile As Variant Dim pos As Long Dim pos0 As Long Dim blen As Long Dim UList As Variant Dim adoSt As Object Dim byteData() As Byte Set FSO = CreateObject("Scripting.FileSystemObject") 'フォルダ内のファイルをループ For Each B In FSO.getfolder(A).Files If InStr(B.Name, ".htm") > 0 Then Set adoSt = CreateObject("ADODB.Stream") UList = "" With adoSt .Charset = "UTF-8" .Open .LoadFromFile B buf = .ReadText(-1) 'ファイルの改行コードにあわせてLineSeparatorを設定 If InStr(1, buf, vbCrLf) <> 0 Then .LineSeparator = -1 ElseIf InStr(1, buf, vbCr) <> 0 Then .LineSeparator = 13 Else .LineSeparator = 10 End If 'ファイルを1行ずつ読み込み最終年度を更新する .LoadFromFile B Do Until adoSt.EOS buf = .ReadText(-2) pos = InStr(buf, tgtWord0) If pos = 0 Then Else blen = Len(buf) pos0 = InStr(buf, "-") buf = Left(buf, pos0) & LastYear & Right(buf, blen - pos0 - 4) nCorr = nCorr + 1 End If If InStr(1, buf, vbLf) = 0 Then buf = buf & vbLf End If UList = UList & buf Loop .Close '改行コードをLFに設定してBOM有りUTF-8ファイルを書き出す .Charset = "UTF-8" .LineSeparator = 10 .Open .WriteText UList 'BOM無しにして入力ファイルを上書きする .Position = 0 .Type = 1 .Position = 3 byteData = .Read .Close .Open .Write byteData .SaveToFile B, 2 .Close End With Set adoSt = Nothing End If Next 'フォルダ内のサブフォルダをループ For Each C In FSO.getfolder(A).subfolders '再帰する Call CopyrightUpdate(C) Next Set FSO = Nothing End Sub
【 解説 】 Sub UTF8Copyright更新() * 対象フォルダーを選択、置換プログラムを呼び出し、置換処理したファイル数を 表示して終了します。 * Application.FileDialog(msoFileDialogFolderPicker)で対象フォルダーを指定。 指定したフォルダー内とその下層ホルダー内全ての指定拡張子ファイルが処理 対象となります。 * 設定項目は下記で、目的に合わせて設定値を書き換えます。 FileType = ".htm" :対象ファイルの拡張子を設定します tgtWord0 = "Copyright" :検索文字列を設定します LastYear = "2025" :更新年度を設定します Sub CopyrightUpdate(A) * "ADODB.Stream"を使用してUTF-8テキストファイルの操作を行っています。 * 改行コード設定 →1行毎の置換処理 → UTF8(BOM付き) → UTF8(BOM無し) → 上書き保存 を繰り返して下層を含め対象フォルダーを一括処理します。 * ファイルを1行ずつ読み込むには改行コード(LineSeparator)をファイルに合わせて 設定しなければなりません。ファイルを ReadText(-1) :-1 で全行読み込み、2 で1行ずつ読み込み でファイルを全部読み込み、 InStr(1, buf, vb****) で改行コードを調べ CrLf なら .LineSeparator = -1 Cr なら .LineSeparator = 13 Lf なら .LineSeparator = 10 に設定しています。 * 文字列の検索置換はDo ~ Loop内で ReadText(-1) で1行ずつ読み込んだ後、置換のコードで処理しています。 * ここのコードを目的に合わせ変更すれば文字列置換ができます。例えば buf = Replace(1, buf, tgtWord0, LastYear) に変更すると、tgtWord0 を LastYear に置き換えることが出来ます。 * 処理テスト中に改行が行われずされず1行で出力されることがあり、 If InStr(1, buf, vbLf) = 0 Then buf = buf & vbLf End If この処理を付け加えました。原因は未だに判りません。 * 処理の結果はBOM付きになるので、バイナリーで読み込みBOMを削除します。 * 再帰処理を追加してあるので、一番下層のフォルダーまで一括で処理します。
【 参考サイト 】 Shift_JISのテキストファイルをUTF-8に一括変換 : https://excel-ubara.com/excelvba5/EXCELVBA267.html Excel VBAでUTF-8形式 HTMLファイルの読み込みと書き込み方法 :https://excel-excel.com/tips/vba_488.html
コードの実行はせいぜい数分ですが、完成までには試行錯誤して思いのほか時間を費やしました(実は、へっぽこなのではいつもの通りなのですが)。まあ、毎日が日曜日の身分なのでこれも良い時間の使い方なのでしょうが、残り時間のカウントダウンが気になるこの頃です。