エクセル顧客管理
記述による処理速度の違い(GW特別号No2)

Excelマクロを駆使したカスタマイズ可能なエクセル顧客管理、エクセルVBAの学習教材
公開日:2013年5月以前 最終更新日:2014-11-11

第15回.記述による処理速度の違い(GW特別号No2)


エクセルで顧客管理を作ろう、


ゴールデンウイーク特別号No2です、


今回は、記述の違いで、どの程度処理速度に変化があるかを検証します。


テストは以下の4点です。


1.変数の型指定

2.罫線の引き方

3.行高の変更

4.配列を使用した処理


この4点について、実測して検証してみました。



1.変数の型指定


以下の2通りのプログラムで検証しました。


Sub Test1()
  Dim i As Long, j As Long, k As Long
  Dim v1, v2
  Debug.Print Now
  For i = 1 To 1000
    For j = 1 To 1000
      For k = 1 To 1000
        v1 = 1
        v2 = v1
      Next
    Next
  Next
  Debug.Print Now
End Sub
Sub Test2()
  Dim i As Long, j As Long, k As Long
  Dim v1 As Long, v2 As Long
  Debug.Print Now
  For i = 1 To 1000
    For j = 1 To 1000
      For k = 1 To 1000
        v1 = 1
        v2 = v1
      Next
    Next
  Next
  Debug.Print Now
End Sub


Test1とTest2の違いは太字の部分だけです。


つまり、テストは変数に型指定するかしないかで、処理速度がどの程度変化するかの検証です。


結果は、


Test1=34秒

Test2=24秒


テスト機は、結構古いノートPCなので、読者のPCならもっと早いと思います。(笑)


で、結構差がつきましたね。


でも本当にそうでしょうか?


このテストでは、1000*1000*1000*2回の変数への値代入のテストです。


つまり、20億回ですよ。


地球シミュレーターじゃないのですから、そんな処理はしないですよね。


普通の処理なら、100万回だってやるかどうかでしょう。


つまり、その場合でも、10秒/1000=0.01秒です。


100万回で、0.01秒ですよ、差がないのも同然と言えます。


つまり、変数における型指定は、処理速度の面では、あまり意味を持たないということです。


ではなぜ、私の書くプログラムは、型指定をきっちりとしているのでしょうか。


理由は全く別の所にあります。


私が型指定をする理由

それは可読性を上げるためです。

例えば、Integerの変数なら、行数はいれないですよね、値がオーバーしてしまいますから。

つまり、読み手に対し、この変数には、行数は入れませんよ、と宣言しているのです。

Integerを宣言するというより、小さい整数しか入れません、と読み手に宣言しているのです。

特にFunctionの戻り値の型では、単にObjectでは、どんなオブジェクトを返す関数か、

プログラムの内容を見ないと分かりません。

正確な型を指定することで、プログラムの内容を見なくても、

「あー、このFunctionはRangeを返す」と直ぐに理解できるようにしているのです。

もちろん、コメントを書くことで伝える事はできますが、まずは、ソースプログラムで伝えているのです。


ですから、プログラムを他人に見せる事がないなら、それほど意味がありません。



2.罫線の引き方


以下の2通りのプログラムで検証しました。



Sub Test1()
  Dim i As Long, j As Long
  Application.ScreenUpdating = False
  Debug.Print Now
  For i = 1 To 10000
    Range(Cells(i, 1), Cells(i, 100)).Select
    Selection.Borders(xlDiagonalDown).LineStyle = xlNone
    Selection.Borders(xlDiagonalUp).LineStyle = xlNone
    With Selection.Borders(xlEdgeLeft)
      .LineStyle = xlContinuous
      .ColorIndex = xlAutomatic
      .TintAndShade = 0
      .Weight = xlThin
    End With
    With Selection.Borders(xlEdgeTop)
      .LineStyle = xlContinuous
      .ColorIndex = xlAutomatic
      .TintAndShade = 0
      .Weight = xlThin
    End With
    With Selection.Borders(xlEdgeBottom)
      .LineStyle = xlContinuous
      .ColorIndex = xlAutomatic
      .TintAndShade = 0
      .Weight = xlThin
    End With
    With Selection.Borders(xlEdgeRight)
      .LineStyle = xlContinuous
      .ColorIndex = xlAutomatic
      .TintAndShade = 0
      .Weight = xlThin
    End With
    With Selection.Borders(xlInsideVertical)
      .LineStyle = xlContinuous
      .ColorIndex = xlAutomatic
      .TintAndShade = 0
      .Weight = xlThin
    End With
    Selection.Borders(xlInsideHorizontal).LineStyle = xlNone
  Next
  Debug.Print Now
  Application.ScreenUpdating = True
End Sub
Sub Test2()
  Dim i As Long, j As Long
  Application.ScreenUpdating = True
  Debug.Print Now
    For i = 1 To 10000
      Range(Cells(i, 1), Cells(i, 100)).Borders.LineStyle = xlContinuous
    Next
  Debug.Print Now
  Application.ScreenUpdating = False
End Sub


100列のセルの四辺に実線を引く、これを10000行繰り返す。


結果は、

Test1=74秒

Test2=4秒


これはかなり差が付きました。


もちろん、これは、罫線だけでなく、セルをSelectしている事も関係しています。


つまり、初心者がマクロの自動記録で作ったマクロがいかに遅いかの検証です。


少し、VBAを覚えれば、遥かにスピードアップするということです。



3.行高の変更


以下の2通りのプログラムで検証しました。


Sub Test21()
  Dim i As Long
  Debug.Print Now
    For i = 1 To 10000
      Rows(i).RowHeight = 15
    Next
  Debug.Print Now
End Sub

Sub Test22()
  Dim i As Long
  Debug.Print Now
    For i = 1 To 10000
      If Rows(i).RowHeight <> 15 Then
        Rows(i).RowHeight = 15
      End If
    Next
  Debug.Print Now
End Sub


10000行の行高の変更です。


最初は、行高を標準の13.5にしておき、連続2回実行します。


つまり2回目は実質行高は変化しません。


結果は、


Test1=1回目:8秒、2回目63秒

Test2=1回目:9秒、2回目1秒未満


1回目はほとんど差がありません、IF文での判定がある分、Test2が若干遅い位です。


問題は2回目です。


実際の行高は変化しないのに、この結果は・・・


Test1の2回目が遅いのは、間違いではありません、何度やっても結果は同じです。


私は、経験則からこの結果を承知していましたが、理由は分かりません。


ネットを調べたら、何か分かるかも知れませんが・・・


どなたか、理由が分かる方がおりましたら、お教え願いたいです。



4.配列を使用した処理


以下の2通りのプログラムで検証しました。




Sub Test3()
  Dim i As Long, j As Long, k As Long
  Dim v As Variant

  Application.ScreenUpdating = False
  Debug.Print Now
  For i = 1 To 100
    For j = 1 To 100
      For k = 1 To 100
        Cells(j, k) = 1
      Next
    Next
  Next
  Debug.Print Now
  For i = 1 To 100
    For j = 1 To 100
      For k = 1 To 100
        v = Cells(j, k)
      Next
    Next
  Next
  Debug.Print Now

  Application.ScreenUpdating = True
End Sub

Sub Test4()
  Dim i As Long, j As Long, k As Long
  Dim v As Variant
  Dim ary As Variant

  Application.ScreenUpdating = False
  Debug.Print Now
  ary = Range(Cells(1, 1), Cells(100, 100))
  For i = 1 To 100
    For j = 1 To 100
      For k = 1 To 100
        ary(j, k) = 1
      Next
    Next
    Range(Cells(1, 1), Cells(100, 100)) = ary
  Next
  Debug.Print Now
  For i = 1 To 100
    For j = 1 To 100
      For k = 1 To 100
        v = ary(j, k)
      Next
    Next
  Next
  Debug.Print Now

  Application.ScreenUpdating = True
End Sub


プログラムは全然違いますが、やっていることは同じです。


1.100行100列のセルに「1」を入れる、これを100回繰り返す。

2.100行100列のセルから値を変数に取り出す、これを100回繰り返す。


つまり100万回のセルに対する読み書きのテストです。


Test4は、Function「最終行取得」で使ったテクニックです。(その時は多分早いで誤魔化しました)


結果は、


Test3=54秒、8秒

Test4=3秒、0.1秒(0.1秒は上記では実測できませんが、10000回の繰り返しで10秒です)


左の数値が、セルへの書き込み、右の数値が、セルからの取得です。


これは驚きですね!これは使えます。


しかし、これとて、100万回のセルに対する読み書きなんて、普通はやらないですよね。


ただ、VBAにおいては、むやみにセルを参照するのは、なるべく控えた方が良い事も事実です。



処理速度を早くする為には


1.画面描画を停止、計算を手動

  Application.ScreenUpdating = False '画面描画を停止

  Application.Calculation = xlCalculationManual '計算を手動に

2.無駄な記述は減らす(ただし、引数の省略はご注意を)

3.プロパティを事前に取得し、変更が無い場合は、むやみに変更しない

4.セルへの同一操作は、Rangeで一括にする。

5.ワークシート関数(WorksheetFunction)が使えるなら、なるべく使う。(これは早いようです。)


まだまだ、いろいろありますが、後はそんなに気にする必要が無いと思います。


処理速度を上げる為に可読性を落とすのは、現在のPC性能を考えれば愚かしい事です。



今回は、難しい話では無かったので、参考にはなったと思います。


おそらく、結構長くVBAをやっている人でも、正しい把握はしていない人が多いと思います。


私とて、今回実測してみて、多少以外な面もありましたから。





同じテーマ「エクセル顧客管理」の記事

第12回.最終行の判定、Rangeオブジェクトと配列、高速化の為に
第13回.コントロールのボタンを配置
第14回.オブジェクトとプロパティの真実(GW特別号No1)
第15回.記述による処理速度の違い(GW特別号No2)
第16回.処理速度の向上はどこまでやれば良い(GW特別号No3)
第17回.商品マスタを作成、2段階の可変リスト
第18回.納品書を作成、顧客情報を取得(1)
第19回.納品書を作成、顧客情報を取得(2)
第20回.納品書を作成、顧客情報を取得(3)
第21回.イベント処理について
第22回.コントールについて


新着記事NEW ・・・新着記事一覧を見る

TRIMRANGE関数(セル範囲をトリム:端の空白セルを除外)|エクセル入門(2024-08-30)
正規表現関数(REGEXTEST,REGEXREPLACE,REGEXEXTRACT)|エクセル入門(2024-07-02)
エクセルが起動しない、Excelが立ち上がらない|エクセル雑感(2024-04-11)
ブール型(Boolean)のis変数・フラグについて|VBA技術解説(2024-04-05)
テキストの内容によって図形を削除する|VBA技術解説(2024-04-02)
ExcelマクロVBA入門目次|エクセルの神髄(2024-03-20)
VBA10大躓きポイント(初心者が躓きやすいポイント)|VBA技術解説(2024-03-05)
テンキーのスクリーンキーボード作成|ユーザーフォーム入門(2024-02-26)
無効な前方参照か、コンパイルされていない種類への参照です。|エクセル雑感(2024-02-17)
初級脱出10問パック|VBA練習問題(2024-01-24)


アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.繰り返し処理(For Next)|VBA入門
3.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
4.変数宣言のDimとデータ型|VBA入門
5.RangeとCellsの使い方|VBA入門
6.ブックを閉じる・保存(Close,Save,SaveAs)|VBA入門
7.セルのクリア(Clear,ClearContents)|VBA入門
8.メッセージボックス(MsgBox関数)|VBA入門
9.条件分岐(Select Case)|VBA入門
10.ブック・シートの選択(Select,Activate)|VBA入門




このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


記述には細心の注意をしたつもりですが、
間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。
掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。


このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
本文下部へ