検索の所要時間を調べた
ちょっと興味があったので、調べてみた。
このように、1000
行1000
列目のセル、すなわちALL1000
セルに「ち~んw
」という値(笑)を入力したシートを準備する。
で、この「ち~んw
」を検索するのにどのぐらい時間がかかるものなのか、測ってみたわけである。
検索方法
私は所詮素人なので、次の三つの方法を用いた。
- 1000×1000のセル範囲のセルの
Value
プロパティを一つ一つ調べる方式 - 1000×1000のセル範囲の
Range
オブジェクトのValue
プロパティの値を一旦二次元配列にぶち込んで、同じく一つ一つ調べる方式 - 1000×1000のセル範囲に対してExcelの
Find
メソッドを使う方式
以上三つである。
実験用のコード
下記のコードを用いる。
時間計測用に、自作のWindowsAPI
クラスを用いているが、これについては、
コチラをどうぞ。WindowsAPI.callGetTickCount
メソッドというのは、WindowsAPIのGetTickCount
を利用するメソッドです。
リスト1 標準モジュール
'エントリポイント。' Public Sub testSearch() '自作WindowsAPIクラスのインスタンスを用意。' Dim winAPI As New WindowsAPI 'セルを一つ一つ巡回する方式の時間を表示する。' Dim startTime As Long startTime = winAPI.callGetTickCount Dim ret As Boolean ret = testSearchByNormalForLoop Dim elapsedTime As Double elapsedTime = winAPI.callGetTickCount - startTime Call showResult(ret, "testSearchByNormalForLoop", elapsedTime) '二次元配列にぶち込んで一つ一つ巡回する方式の時間を表示する。' startTime = winAPI.callGetTickCount ret = testSearchBy2DimensionArray elapsedTime = winAPI.callGetTickCount - startTime Call showResult(ret, "testSearchBy2DimensionArray", elapsedTime) 'ExcelのFindメソッドを使う方式の時間を表示する。' startTime = winAPI.callGetTickCount ret = testSearchByFindMethod elapsedTime = winAPI.callGetTickCount - startTime Call showResult(ret, "testSearchByFindMethod", elapsedTime) End Sub '計測結果を表示するためのメソッド。' Private Sub showResult(ByVal isSuccessed As Boolean, _ ByVal methodName As String, _ ByVal elapsedTime As Double) Debug.Print methodName & " の結果:" If isSuccessed Then Debug.Print "「ち~んw」を みつけた!" Else Debug.Print "見つけられなかった……。" End If Debug.Print elapsedTime / 1000 & "秒かかった!" Debug.Print String(20, "=") End Sub 'セルを一つ一つ巡回する方式。' Public Function testSearchByNormalForLoop() As Boolean ' Dim ret As Boolean' ' ret = False' testSearchByNormalForLoop = False Dim sh As Worksheet Set sh = ActiveSheet Dim r As Long Dim c As Long For r = 1 To 1000 For c = 1 To 1000 If sh.Cells(r, c).Value = "ち~んw" Then _ ' ret = True: Exit For' '///アホすぎる誤りを修正' testSearchByNormalForLoop = True: _ Exit Function Next Next ' If ret Then testSearchByNormalForLoop = True' End Function '一旦二次元配列にぶち込んで一つ一つ巡回する方式。' Public Function testSearchBy2DimensionArray() As Boolean ' Dim ret As Boolean' ' ret = False' testSearchBy2DimensionArray = False Dim sh As Worksheet Set sh = ActiveSheet Dim rng As Range With sh Set rng = .Range(.Cells(1, 1), _ .Cells(1000, 1000)) End With Dim ar As Variant ar = rng.Value Dim r As Long Dim c As Long For r = 1 To 1000 For c = 1 To 1000 If ar(r, c) = "ち~んw" Then _ ' ret = True: Exit For' '///アホすぎる誤りを修正' testSearchBy2DimensionArray = True: _ Exit Function Next Next ' If ret Then testSearchBy2DimensionArray = True' End Function 'ExcelのFindメソッドを使う方式。' Public Function testSearchByFindMethod() As Boolean Dim ret As Boolean ret = False Dim sh As Worksheet Set sh = ActiveSheet Dim rng As Range With sh Set rng = .Range(.Cells(1, 1), _ .Cells(1000, 1000)).Find(what:="ち~んw") End With If Not rng Is Nothing Then ret = True testSearchByFindMethod = ret End Function
処理内容はコード内のコメントの通り。行数の割に中身はないw
追記
2018/1/19
コード中、あまりにアホ過ぎる誤りに気付いたので、修正しました。実は、うpした次の日には気付いていたのですが、連休が明けると本業の方が絶讃炎上中となっておりまして、連日アレな感じだったために修正ができなかったのです。
修正箇所は、リスト内にコメントで記した通りです。
実行結果
ご覧の通り。
1000×1000のセル範囲のセルのValue
プロパティを一つ一つ調べる方式
4.016
秒。
1000×1000のセル範囲のRange
オブジェクトのValue
プロパティの値を一旦二次元配列にぶち込んで、同じく一つ一つ調べる方式
0.235
秒。
1000×1000のセル範囲に対してExcelのFind
メソッドを使う方式
0.015
秒。
なんと、まさにケタ違い。
ちょっとビックリの結果。
まあ、一つ目、二つ目については、一番時間がかかるところに値(笑)を配置するという意地悪な実験なんですが。
しかし、こうなると、ExcelのFind
メソッドの実装がどうなっとるのか、非常に気になるのであります。