Quantcast
Channel: t-hom’s diary
Viewing all articles
Browse latest Browse all 493

VBA マクロの高速化のためのApplication設定をクラスモジュールにまとめる

$
0
0

今回はちょっと変わったクラスモジュールのテクニック案。
異端扱いされそうな気がするので、思いついた私自身、採用には慎重なのだけれど、アイデアとしては面白いと思ったので備忘録として公開してしまうことにした。

さて、過去にPropertyプロシージャを使った高速化テクニックというのをやった。
thom.hateblo.jp

今回も基本的にはApplication設定を変更するだけなのだが、クラスモジュールを使って更に怠慢にやろうという話。

作り方

クラスモジュールを挿入し、オブジェクト名を「OneTimeSpeedBooster」に変更する。
このクラスの名前付けは超重要!!
そもそも馴染みのない異端テクニックなので、何がしたいのか名前で示さないと訳が分からなくなる。

クラスに書くコードはこちら。

PrivateSub Class_Initialize()With Application
        .ScreenUpdating =False.Calculation = xlCalculationManual
        .EnableEvents =False.PrintCommunication =FalseEndWithEndSubPrivateSub Class_Terminate()With Application
        .ScreenUpdating =True.Calculation = xlCalculationAutomatic
        .EnableEvents =True.PrintCommunication =TrueEndWithEndSub

見ての通り、コンストラクタとデストラクタしかない。
コンストラクタで高速化設定を行い、デストラクタで標準設定にもどしている。

使い方

OneTimeSpeedBoosterを使う前に、まずは時間のかかるマクロを作ってみる。
計算が必要かつ、画面更新が発生するものが良い。

九九を100×100まで計算させつつ、セルの色をランダムで塗りつぶすようにしてみよう。

コードはこのとおり。

Sub hoge()Dim t AsDouble: t =TimerFor i =1To100For j =1To100With Sheet1.Cells(i, j).Value="="& i &"*"& j
                .Interior.Color = RandomColor
            EndWithNextNext
    Debug.PrintTimer- t
EndSubFunction RandomColor()
    RandomColor =RGB( _Int(256*Rnd), _Int(256*Rnd), _Int(256*Rnd))EndFunction

完成!
f:id:t-hom:20170319111224p:plain

タイムは、3.7秒。はやっ!

では、ズームで10%まで小さくして、画面に入る描画範囲を増やしてみよう。
f:id:t-hom:20170319111649p:plain

タイムは、9秒。

ではこれがどれだけ早くなるか。
コードは次のとおり。

Sub hoge()Dim t AsDouble: t =TimerDim booster: Set booster =New OneTimeSpeedBooster
    For i =1To100For j =1To100With Sheet1.Cells(i, j).Value="="& i &"*"& j
                .Interior.Color = RandomColor
            EndWithNextNext
    Debug.PrintTimer- t
EndSubFunction RandomColor()
    RandomColor =RGB( _Int(256*Rnd), _Int(256*Rnd), _Int(256*Rnd))EndFunction

タイムは、1.16秒!

9秒から1秒なので実に90%も高速化したことに、、、、なる、、のか。。
っ!計算に自信がない!!

で、肝心のコードだけれど、足したのは以下の1行のみ。
Dim booster: Set booster = New OneTimeSpeedBooster

名前付けが超重要と書いたのは、上手い名前を付けていても変数宣言してセットしたはいいけど何も使われていないアホなコードに見えるのに、まして下手な名前なんてつけたら。。ということ。

OneTimeSpeedBoosterのインスタンスが作られるとコンストラクタによって各種アプリケーション設定が変更され、プロシージャの終了とともにこのbooster変数は破棄されるので、デストラクタによってアプリケーション設定がもとに戻る仕組み。

あるいは、Withを使ってこの区間ブーストするみたいな表記もアリか。

Sub hoge()Dim t AsDouble: t =TimerWithNew OneTimeSpeedBooster
        For i =1To100For j =1To100With Sheet1.Cells(i, j).Value="="& i &"*"& j
                    .Interior.Color = RandomColor
                EndWithNextNextEndWith
    Debug.PrintTimer- t
EndSub

ま、今回は思考実験みたいなものなので、あまり真に受けないでほしい。
特にマジに批判するとかはナシで!!

良いと思った方は自己責任でどうぞ!


Viewing all articles
Browse latest Browse all 493

Trending Articles