お世話になっています
今回はエクセルVBAに関する質問です
文字列処理がメインのコードを作成しています
以下のコードのように
判定対象文字列に文字列(例として 果物の名前)が含まれているかを
チェックしたいのですが
実際には 判定すべき文字列は くだものの他にも いくつかあります
現在はループで回していますが
少しでも 処理速度を速くしたいのですが
何かよい方法は ないでしょうか?
VBA
1 2Sub fruits_check() 3 4 5 Dim くだもの判定(5) As String 6 7 くだもの判定(1) = "桃" 8 くだもの判定(2) = "パイナップル" 9 くだもの判定(3) = "みかん" 10 くだもの判定(4) = "バナナ" 11 くだもの判定(5) = "檸檬" 12 13 14 15 exist_flag = False 16 17 For i = 1 To 5 18 19 If (InStr(判定対象文字列, くだもの判定(i)) > 0) Then 20 exist_flag = True 21 Exit For 22 End If 23 24 Next i 25 26 27 If exist_flag = True Then 28 29 MsgBox ("ありました") 30 31 End If 32 33 34End Sub 35
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答4件
0
既に試されている方が居られました。
VBAで特定の文字が含まれているのかの確認方法の処理速度比較
結果からはlike演算子。
但し、以下注釈がありました。
ただしWin7 64bit Excel 2010 32bitの環境ではInStrの方が早かった記憶があるので環境によっては変化するかも
#測定条件
- 実行環境:Windows 10 Pro 64bit / Microsoft Excel 2016 64bit
- 検索文字列:2文字目が"b"、残りが"a"からなる10万文字の文字列 "abaaa....a"
- ループ回数:1万回
- 時間測定方法:VBAのTimer関数を用いた簡易計測
#測定結果
方法 | 時間(秒) |
---|---|
InStr関数 | 0.141 |
InStrRev関数 | 4.352 |
Like演算子 | 0.000 |
正規表現(事前バインド) | 0.008 |
正規表現(実行時バインド) | 0.141 |
Replace関数 | 1.563 |
追記
高速化についての小技的なものが紹介されています。
Excel VBA の高速化
投稿2018/06/09 12:28
編集2018/06/09 12:34総合スコア25419
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/06/09 14:54

0
ベストアンサー
文字列の検索、という事でしたら、経験上 InStr 一択でしょう。
もちろん、正規表現を使いたいのであれば、Like や RegExp を使えばいいですが、
早そうだから、などという安易な気持ちで使ってしまうと、
[*]等の正規表現で使わていれる文字が検索値に含まれた場合にバグになる可能性がある、
という事も留意しなければなりません。
そこまで考えず、とりあえず文字を探すだけなら 、
InStr が高速かつ意図しない結果を返さないので安心して使えるかと。
また、環境によって左右されるのかもしれませんが、
当方で試した環境(Win7 32bit, Office2010 32bit)では、
InStr 、Like で差は得られなかったです。
※ランダムな10000文字(アルファベット)に対して、
ランダムな10文字を、10万回検索する、という方法を数十回試しました。
※Like実行時に、"" & [変数] & "" とすると、文字列の演算処理の時間まで計測されるので、
元から変数に[*]を結合させて計測しています。
回答ではないですが、何かを判定する関数のテンプレを載せておきますので、参考まで。
※ポイントは、対象外の場合は Exit Function 、最後まで辿り着いたら TRUE を返す点です。
こう記述する事で、何度も戻り値を書く必要がなく、
Ifのネストが激減するのでコードが簡潔になり見やすくなります。
VBA
1Public Function IsNumber(Value As String) As Boolean 2 3 If IsNumeric(Value) = False Then Exit Function 4 5 Dim i As Long 6 For i = 1 To Len(Value) 7 If InStr(1, "0123456789", Mid$(Value, i, 1)) = 0 Then Exit Function 8 Next 9 10 IsNumber = True 11 12End Function
投稿2018/06/11 09:30
総合スコア1175
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
VBAでInStrを使わない方法というと Like演算子か RegExpオブジェクト(正規表現)になりますね。
Like演算子は前にテストした時は、InStrより遅かったです。
RegExpはやったことがないので、テストした結果を教えてほしいです。
vba
1Public Sub fruits_check() 2 Dim 判定対象文字列 As String 3 Dim reg As Object 4 5 Set reg = CreateObject("VBScript.RegExp") 6 7 With reg 8 .Pattern = "桃|パイナップル|みかん|バナナ|檸檬" 9 .IgnoreCase = True 10 .Global = False 11 End With 12 13 判定対象文字列 = "あああああああ檸檬ああああああ" 14 15 If reg.Test(判定対象文字列) Then MsgBox "ありました" 16 17End Sub
テストしてみました
時間の計測は、VBAでミリ秒以下の高精度で処理時間計測 の関数を使いました。マイクロ秒の精度で計測てきますので、ループさせる必要なく計測できます。
判定対象文字列は、Wikipedia:引用のガイドラインから5500字エディターにコピーして真ん中ぐらいに「檸檬」を挿入しました。それをA1セルにコピペしました。
実行環境:Windows 10 Home 64bit / Microsoft Excel 2016 32bit
テストコード
vba
1Public Sub fruits_check() 2 3 Const 検索パターン = "桃|パイナップル|みかん|バナナ|檸檬" 4 5 Dim くだもの判定(5) As String 6 くだもの判定(1) = "桃" 7 くだもの判定(2) = "パイナップル" 8 くだもの判定(3) = "みかん" 9 くだもの判定(4) = "バナナ" 10 くだもの判定(5) = "檸檬" 11 12 Dim 判定対象文字列 As String 13 判定対象文字列 = Range("A1").Value 14 15 Dim lateReg As Object 16 Set lateReg = CreateObject("VBScript.RegExp") 17 18 Dim earlyReg As RegExp 19 Set earlyReg = New RegExp 20 21 Dim result As Boolean, i As Long, j As Long 22 23 For j = 1 To 2 24 result = False 25 SWStart 26 With lateReg 27 .Pattern = 検索パターン 28 .IgnoreCase = True 29 .Global = False 30 result = .Test(判定対象文字列) 31 End With 32 SWStop 33 SWShow "lateReg : " & result & " " 34 35 result = False 36 SWStart 37 With earlyReg 38 .Pattern = 検索パターン 39 .IgnoreCase = True 40 .Global = False 41 result = .Test(判定対象文字列) 42 End With 43 SWStop 44 SWShow "earlyReg: " & result & " " 45 46 result = False 47 SWStart 48 For i = 1 To 5 49 If (InStr(判定対象文字列, くだもの判定(i)) > 0) Then 50 result = True 51 Exit For 52 End If 53 Next i 54 SWStop 55 SWShow "InStr : " & result & " " 56 57 result = False 58 SWStart 59 For i = 1 To 5 60 If 判定対象文字列 Like "*" & くだもの判定(i) & "*" Then 61 result = True 62 Exit For 63 End If 64 Next i 65 SWStop 66 SWShow "Like : " & result & " " 67 68 '一致なし用のサンプルデータ 69 判定対象文字列 = Replace(判定対象文字列, "檸檬", "") 70 Debug.Print "" 71 Next j 72 73End Sub
計測結果
text
1lateReg : True 1.0089 2earlyReg: True 0.6539 3InStr : True 0.0472 4Like : True 0.0526 5 6lateReg : False 1.5676 7earlyReg: False 1.2376 8InStr : False 0.0501 9Like : False 0.0558
単位はミリ秒です。
当方の環境、用意したサンプルでは、InStrが最も速いという結果になりました。
投稿2018/06/09 09:42
編集2018/06/09 15:10総合スコア34343
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
「部分一致」とすると下記記事の中盤に出てくるfilter関数が使えそうです。
Filter関数を使用して配列を検索する方法
ループをしない分、多少は速く、コードも短くなるとは思いますが、
もっと大量データで検証しないとその差は分からないかもしれません。
投稿2018/06/09 07:33
総合スコア80886
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。