043 ファイル名の禁止文字の処理

こんにちは、くのへ@MasazaneKunoheです。
10月16日にTwitterで大変お世話になっているしゃあさん主催のVBAer会に登壇させて頂きました。

第26回 VBA会 登壇者 くのへ|しゃあ@やっぱりVBAが好き|note

その際にメールを一気に保存するマクロを紹介したのですが、なんか保存できないメールアイテムがありました。

これは、ファイル名に禁止されている文字が原因だと分かりました。
メールにはRe:やFw:のように「:」が件名についていることが多いので、このメール件名をフォルダ名・ファイル名にしようとすると、結構な問題になります。

この処理を行うマクロがTwitterで盛り上がっていたので、これを纏めました。

力業でReplace法

私がVBA一般ユーザに推奨したいと思うのは次のReplace法です。

Function ファイル禁止文字処理(ByVal strFileName As String) As String

'それぞれ全角文字に置き換える
    strFileName = Replace(strFileName, "\", "¥")
    strFileName = Replace(strFileName, "/", "/")
    strFileName = Replace(strFileName, ":", ":")
    strFileName = Replace(strFileName, "*", "*")
    strFileName = Replace(strFileName, "?", "?")
    strFileName = Replace(strFileName, "<", "<")
    strFileName = Replace(strFileName, ">", ">")
    strFileName = Replace(strFileName, "|", "|")
    strFileName = Replace(strFileName, "[", "[")
    strFileName = Replace(strFileName, "]", "]")

'ダブルクオーテーション処理(VBAではダブルクオーテーションを書けないのでChrを使う)
    strFileName = Replace(strFileName, Chr(34), Chr(&HFA57))

    ファイル禁止文字処理 = strFileName
End Function

スマートではありませんが、学習コストが非常に低く、Functionが使えるVBAユーザならReplace関数をちょっとググりさえすればすぐに理解できると思います。
もちろんこれが優れたコードだとは思いませんが、学習コストの低いという1点において十分に価値があるコードだと思います。

スマートReplace法

Twitterでお世話になっているりゅうりゅうさんから教えて頂いた「スマートなReplace法」。

Function ファイル禁止文字処理スマートReplace版(ByVal strFileName As String) As String

  Dim i As Integer
  Const strBefore As String = "\/:*?<>|[]"
  Const strAfter As String = "¥/:*?<>|[]"
  
  For i = 1 To Len(strBefore)
    strFileName = Replace(strFileName, Mid(strBefore, i, 1), Mid(strAfter, i, 1))
  Next i

'ダブルクオーテーション処理(VBAでは上手くダブルクオーテーションを書けないのでChrを使う
  ファイル禁止文字処理スマートReplace版 = Replace(strFileName, Chr(34), Chr(&HFA57))

End Function

これはやっている原理はReplace法と変わらないのですが、変換前と変換後の文字を最初にConstで登録しておき、Mid関数を使って1文字ずつ変換されています。

Mid関数は次のように記載することで、文字列の中のi番目から1文字を抽出することができます。

Mid(文字列, i番目, 1文字)

これを使い、iが「1」の時は、strBeforeから「 \ (小文字の¥)」、strAfter 「¥」が抽出され、Replaceで置き換わっているという仕組みです。

あと、Lenって何それ?とかLenって何に使うの?と思ってた方もおられると思います。

Lenは文字列の文字数をカウントする関数です。Len(“あいうえお”)だと「5」となります。

「For + Lenの組み合わせ」により1文字ずつ処理することができます。私はLenを使うのは、For+Lenの組み合わせが一番多いと思います。

しかし流石りゅうりゅうさんだ、、、
実はかなり尊敬しています。が、本人には言わないでおこう。

配列使用版

Twitterでお世話になっている としじさんから配列を用いたアイディアも頂きました。それを反映したものがこちら。

Function ファイル禁止文字処理Array版(ByVal strFileName As String) As String

  Dim i As Integer
  Dim arr As Variant
  
  arr = Array("\¥", "//", "::", "**", "??", "<<", ">>", "||", "[[", "]]")
    
  For i = LBound(arr) To UBound(arr)
    strFileName = Replace(strFileName, Mid(arr(i), 1, 1), Mid(arr(i), 2, 1))
  Next i

'ダブルクオーテーション処理(VBAでは上手くダブルクオーテーションを書けないのでChrを使う
  ファイル禁止文字処理Array版 = Replace(strFileName, Chr(34), Chr(&HFA57))

End Function

これも先ほどと同じようなコードですが、配列を使ってスマートに処理しています。

StrConv版

禁止文字は全て大文字にすればいいので、小文字を大文字にする「StrConv関数」を使うという方法があります。
この場合、a~zや数字の0~9までもが大文字になるのはカッコ悪いため、一度すべての文字をを大文字(vbWide)に変換し、Like関数を使ってアルファベットと数字だけを小文字に戻してやるという処理を行えば実装できます。

ただし、¥マークは上手く処理されないので、手動でリプレースする必要があります。

Function ファイル禁止文字処理StrConv版(ByVal strFileName As String) As String
  
  Dim i As Integer
  
  strFileName = StrConv(strFileName, vbWide)
  
  For i = 1 To Len(strFileName)
  
    If Mid(strFileName, i, 1) Like "[A-Z , a-z ,0-9]" Then
      Mid(strFileName, i, 1) = StrConv(Mid(strFileName, i, 1), vbNarrow)
    End If
  
  Next i
  
  strFileName = Replace(strFileName, "\", "¥")
  
  ファイル禁止文字処理StrConv版 = strFileName

End Function

まあ、これもりゅうりゅうさんのコードのほぼ丸パクりですw

ただし、StrConvを使う場合には注意が必要です。

以下のように、英語環境PCではStrConvの「vbWide、vbNarrow」は使えない(エラーになる)のだそうです。

なんてマニアックな罠なんだw


以上!ファイル名の禁止文字処理でした~

ではまた別の記事で~
🦅バサバサ~

くのへスタジオはこちら。
Outlook-VBAコーナーはこちら。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です