LoginSignup
6
12

More than 3 years have passed since last update.

【ExcelVBA】文字列操作用のユーティリティ関数を自作してみた

Last updated at Posted at 2019-10-22

はじめに

JavaやC#といった言語に比べて、VBAは文字列操作の関数が貧弱だと感じることが多いため、これまでに作った関数にプラスアルファで付け足したものをまとめてみました。
今後良い処理を思いついたら、随時書き足していく予定です。

なお、関数名の命名はJavaのStringクラスなどを参考にしたため、あまりVBっぽくないかもしれませんがご了承ください。

※とりあえず関数はABC順に並べていますが、後で読みやすくするために順番を変えるかもしれません。

作成した関数群

Compare

StringUtils.bas
'--------------------------------------------------------------------------------
' 大文字/小文字、全角/半角の区別なく、2つの文字列を辞書的に比較する。
'
' targetString:比較対象の文字列。
' anotherString:もう一方の比較対象の文字列。
' return:比較対象の文字列が等しい場合はtrueを返す。
'--------------------------------------------------------------------------------
Public Function Compare(targetString As String, anotherString As String) As Boolean
    ' 2つの文字列を「大文字の半角文字」に直して比較する。
    Compare = (StrConv(UCase(targetString), vbNarrow) = StrConv(UCase(anotherString), vbNarrow))
End Function

Contains

  • 組み込みのInStr関数を使えば簡単に実現できる処理ですが、他の言語に慣れている人にはInStrという名称が分かりづらいため、Containsという名前の関数を作ってラップしました。
StringUtils.bas
'--------------------------------------------------------------------------------
' 探索対象の文字列中に、探索する部分文字列が存在するかを調べる。探索する部分文字列が空文字の場合もtrueを返す。
'
' targetString:探索対象の文字列
' substring:探索する部分文字列。
' return:探索対象の文字列中に、部分文字列が存在すればtrueを返す。
'--------------------------------------------------------------------------------
Public Function Contains(targetString As String, substring As String) As Boolean
    Contains = (InStr(targetString, substring) > 0)
End Function

ContainsAny

  • 第一引数で指定した探索対象の文字列に、第二引数で指定した部分文字列"群"が存在するかを返します。
    • ContainsAny("すもももももももものうち", "りんご", "みかん", "すもも")だとTrueが返されます。
    • ContainsAny("すもももももももものうち", "りんご", "みかん", "ぶどう")だとFalseが返されます。
  • VBAのParamArrayという可変長引数の仕組みを活用しているため、第二引数は1ないし複数個を指定できるのがポイントです。
StringUtils.bas
'--------------------------------------------------------------------------------
' 探索対象の文字列中に、1ないし複数個の部分文字列が存在するかを調べる。
'
' targetString:対象の文字列。
' searchTexts:探索する部分文字列。1ないし複数個を指定できる。
' return:探索対象の文字列中に、部分文字列が存在すればtrueを返す。
'--------------------------------------------------------------------------------
Function ContainsAny(targetString As String, ParamArray searchTexts() As Variant) As Boolean
    Dim txt As Variant
    Dim result As Boolean
    For Each txt In searchTexts
        If (InStr(targetString, CStr(txt)) > 0) Then
            result = True
            Exit For
        End If
    Next txt

    ContainsAny = result
End Function

CountMatches

  • 第1引数の文字列中に、第2引数の部分文字列が何回出現したかを返します。
  • 例えばCountMatches("すもももももももものうち", "もも")と書くと、4が返されます。
StringUtils.bas
'--------------------------------------------------------------------------------
' 引数の文字列中に、探索文字列が何回出現したかを返す。
'
' targetString:対象の文字列。
' subStr:探索する部分文字列。
' return:探索文字列が出現した回数を返す。
'--------------------------------------------------------------------------------
Public Function CountMatches(targetString As String, subStr As String) As String
    MsgBox Replace(targetString, subStr, "")
    CountMatches = (Len(targetString) - Len(Replace(targetString, subStr, ""))) / Len(subStr)
End Function

DeleteWhitespace

  • 引数の文字列から空白文字を除去します。
  • Trimとの相違点は以下の通りです。
    • 「スペース」だけでなく、「タブ」「改行コード」も除去します。
    • 文字列の前後だけでなく、文字列の途中にある空白文字も除去します。
StringUtils.bas
'--------------------------------------------------------------------------------
' 引数の文字列から空白を除去する。
'
' targetString:比較対象の文字列。
' return:文字列の前後、および文字列中から以下の文字を除去した文字列を返す。
'         全角空白、半角空白、タブ、改行コード(CR,LF,CRLF)
'--------------------------------------------------------------------------------
Public Function DeleteWhitespace(targetString As String) As String
    ' 正規表現オブジェクトの作成
    Dim reg As Object
    Set reg = CreateObject("VBScript.RegExp")

    ' 正規表現のオプションの指定
    With reg
        .Pattern = " | |\t|\r|\n"
        .IgnoreCase = False         '大文字と小文字を区別する
        .Global = True              '文字列全体を検索する
    End With

    DeleteWhitespace = reg.Replace(targetString, "")
End Function

EndsWith

  • StartsWithに比べてあまり使われる機会がない気もしますが、StartsWithと対になる処理なのでセットで作成しました。
StringUtils.bas
'--------------------------------------------------------------------------------
' 探索対象の文字列が、指定された接尾辞で終わるかを判定する。
'
' targetString:探索対象の文字列
' suffix:探索する接尾辞。
' return:探索対象の文字列が、指定された接尾辞で終わればtrueを返す。接尾辞が空文字の場合もtrueを返す。
'--------------------------------------------------------------------------------
Public Function EndsWith(targetString As String, suffix As String) As Boolean
    If (Len(targetString) >= Len(suffix)) Then
        ' 文字数が【探索対象の文字列】≧【接尾辞】の時、探索対象の文字列の末尾が接尾辞と一致すればtrueを返す。
        Dim subStr As String
        subStr = Right(targetString, Len(suffix))
        EndsWith = (subStr = suffix)
    Else
        ' 文字数が【探索対象の文字列】<【接尾辞】の時、falseを返す。
        EndsWith = False
    End If
End Function

Lines

  • 引数の文字列を改行コードで区切って、区切られた文字列を配列の要素として返します。
  • 改行コードはCRLFCRLFに対応しています。
StringUtils.bas
'--------------------------------------------------------------------------------
' 引数の文字列を改行コード(行終了記号)で区切った配列として返す。
'
' targetString:対象の文字列。
' return:改行コードの単位で区切られた配列。
'--------------------------------------------------------------------------------
Public Function Lines(targetString) As String()
    ' 正規表現オブジェクトの作成
    Dim reg As Object
    Set reg = CreateObject("VBScript.RegExp")

    '正規表現の指定(CRLF/CR/LF)
    With reg
        .Pattern = "\r\n|\r|\n"
        .IgnoreCase = False         '大文字と小文字を区別する
        .Global = True              '文字列全体を検索する
    End With

    ' CRLF/CR/LFをCRLFに統一する
    Dim buff As String
    buff = reg.Replace(targetString, vbCrLf)

    Lines = Split(buff, vbCrLf)
End Function

Repeat

  • 第1引数の文字列を、第2引数で指定した回数繰り返した文字列を生成して返します。
  • 例えばRepeat("*", 5)と書くと、*****が返されます。
StringUtils.bas
'--------------------------------------------------------------------------------
' 引数の文字列を指定した回数繰り返す。
'
' targetString:対象の文字列。
' repeatCount:繰り返しの回数。1以上の値を指定する。
' return:引数の文字列を指定した回数繰り返した結果の文字列を返す。
'--------------------------------------------------------------------------------
Public Function Repeat(targetString As String, repeatCount As Integer) As String
    Dim buff As String
    Dim i As Integer

    For i = 1 To repeatCount
        buff = buff + targetString
    Next i

    Repeat = buff
End Function

StartsWith

  • 自作したContains関数と同様に、組み込みのInStr関数を使えば簡単に実現できますが、処理内容を理解しやすくするためにStartsWithという名前の関数を作ってラップしました。
StringUtils.bas
'--------------------------------------------------------------------------------
' 探索対象の文字列が、指定された接頭辞で始まるかを判定する。
'
' targetString:探索対象の文字列
' prefix:探索する接頭辞。
' return:探索対象の文字列が、指定された接頭辞で始まればtrueを返す。接頭辞が空文字の場合もtrueを返す。
'--------------------------------------------------------------------------------
Public Function StartsWith(targetString As String, prefix As String) As Boolean
    StartsWith = (InStr(targetString, prefix) = 1)
End Function

ToCharArray

  • 引数で指定した文字列を一文字ずつに分解して、それを文字配列として返します。
  • ある文字列の2文字目、4文字目、6文字目...と飛び石で取得したい時などは、Mid関数を直接使うよりもこの関数の戻り値を使った方が楽だと思います。
StringUtils.bas
'--------------------------------------------------------------------------------
' 引数の文字列を文字配列に変換して返す。
'
' targetString:対象の文字列。
' return:文字配列。
'--------------------------------------------------------------------------------
Public Function ToCharArray(targetString As String) As String()

    Dim aryLength As Long
    Dim charAry() As String

    aryLength = Len(targetString)
    ReDim charAry(aryLength - 1)

    Dim i As Long
    For i = 1 To aryLength
        charAry(i - 1) = Mid(targetString, i, 1)
    Next i

    ToCharArray = charAry
End Function

Truncate

  • 第1引数の文字列を、第2引数で指定した文字数に切り詰めた文字列を返します。
    • 例えば、表示可能な文字数に制限がある時などに使えると思います。
  • 組み込みのLeft関数を使えば簡単に実現できますが、処理内容を理解しやすくするためにTruncateという名前の関数を作ってラップしました。
StringUtils.bas
'--------------------------------------------------------------------------------
' 引数の文字列を指定した文字数に切り詰める。
'
' targetString:対象の文字列。
' maxLength:文字列の最大文字数。この文字数を超えた部分は削除される。
' return:引数の文字列を指定した文字数に切り詰めた文字列を返す。
'--------------------------------------------------------------------------------
Public Function Truncate(targetString As String, maxLength As Integer) As String
    Truncate = Left(targetString, maxLength)
End Function
6
12
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
12