質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Q&A

解決済

4回答

13980閲覧

【VBA】処理の高速化 について

Reach

総合スコア733

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

0グッド

0クリップ

投稿2018/06/09 06:00

お世話になっています

今回はエクセル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ページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2018/06/09 07:19

現時点でも遅いと感じるようなことはあるのでしょうか?
m.ts10806

2018/06/09 07:34 編集

部分一致を前提として回答しました。(完全一致だと別の関数があったはず)
guest

回答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
sazi

総合スコア25083

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hatena19

2018/06/09 14:54

このリンク先のテスト結果は私のテスト結果とかなり異なった結果ですね。 10万文字中の2文字目に一致する文字があるというかなり特殊なサンプルデータだからでしょうかね。
sazi

2018/06/09 15:04

そうですね。 個人的には内部処理的にinstr()が一番単純で高速だと思うのですが、likeが高速な場合は、データや検索条件によって、最速なパターンがあるのかなって感じです。
sazi

2018/06/10 02:29 編集

他の関数にしても、内部的なソートのロジックはあるでしょうから、取得したデータやOSが扱えるbit数によって性能が変わる可能性は大きい気がします。
guest

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

ExcelVBAer

総合スコア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
hatena19

総合スコア33610

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sazi

2018/06/09 12:05

共にcreateobjectや配列の作成などは事前に行って比較のみの時間を、 API使ってマイクロ秒までで計測してみました。 instr()は0.005ミリ秒。 .RegExpは0.015ミリ秒。 誤差はあるとは思いますが、性能差は2~3倍程度でした。
hatena19

2018/06/09 14:45

テストした結果を追記しました。当方の環境、用意したサンプルデータでは、instrとregexpでは10倍以上の差がでました。データによってかなり差がでるのかも。どちらにしてもInstrが速いようです。
guest

0

「部分一致」とすると下記記事の中盤に出てくるfilter関数が使えそうです。

Filter関数を使用して配列を検索する方法

ループをしない分、多少は速く、コードも短くなるとは思いますが、
もっと大量データで検証しないとその差は分からないかもしれません。

投稿2018/06/09 07:33

m.ts10806

総合スコア80731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sazi

2018/06/09 08:24

リンク先は配列内を検索で、質問は検索対象を検索パターン(配列)で検索ですよ。 完全一致なら逆でもいけそうですが、部分一致だと不能。
m.ts10806

2018/06/09 10:57

ご指摘ありがとうございます。 ちょっと別の方法考えてみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問