エクセルVBAの技術向上マガジン

 
 
新創刊!

▼[無料]メルマガの登録
「エクセルVBA技術通信」
マガジンID:0000252815 
メールアドレス:

Powered by
まぐまぐ



発行者情報

メルマガの登録/解除

エクセルVBA開発事例

テクニカルライター

著者プロフィール

会社概要

TOP



高速化ランキング

エクセルVBAのシステムを高速化させるために効果的な技術・ノウハウのベスト5を発表していきます。

第1位 画面更新の非表示

第2位 CSVのシート取り込み

第3位 大量データのソート

第4位 セル指定の高速化

第5位 不要行の削除



使い易さランキング

エクセルVBAのシステムをより使い易くさせるため技術・ノウハウのベスト5を発表していきます。

・準備中です。



VBA入門講座

初心者向けのエクセルVBAが学べるサイトは、

こちら


 
■高速化ランキング【第4位】

では、さっそく今回は高速化ランキングの続き、第4位の発表です。


--------------------------------------------------------------------
【今日のテーマ】 セル指定の高速化
--------------------------------------------------------------------


エクセルでデータの読み書きをする際には、必ずどのセルから(又はどのセ
ルへ)ということを指定する必要があるわけですが、通常これを「マクロの
記録」で記録した通りに

Range("A1").Select

という構文をそのまま使っている方も多々見うけます。
これも、少々の工夫で劇的にスピードアップが図れる一因のひとつですので
今回は「セル指定の高速化」ということで、その辺についてご紹介していき
たいと思います。



今回のベンチマークでは、単純に縦に並んだ5万件のデータを1次元配列に放
り込むという処理をサンプルにしました。


まず、通常多く用いられている「マクロの記録」で記録できる上記の構文を
用いたサンプル1の例ですが、

サンプル1
―――――――――――――――――――――――――+
    For i = 1 To 50000
        Range("B" & CStr(i)).Select
        a(i) = ActiveCell.Value
    Next i
―――――――――――――――――――――――――+<

このプログラムの実行速度の計測結果は、14.7秒でした。



同様に、一般的によく用いられているOffset(相対移動)を使った以下の
サンプル2の場合では、

サンプル2
―――――――――――――――――――――――――+
    Range("B1").Select
    For i = 1 To 50000
        a(i) = ActiveCell.Value
        ActiveCell.Offset(1, 0).Activate
    Next i
―――――――――――――――――――――――――+

13.6秒という結果です。


この結果では、セルのアクセスにはOffset(相対移動)を用いた方が、若干
ではありますが早くなるということが分かります。



もうお気付きの方も多いでしょうが、これに高速化ランキングの第1位の時
にお話した「画面の非表示」という構文を加えてみると、

サンプル3
―――――――――――――――――――――――――+
    Application.ScreenUpdating = False
    Range("B1").Select
    For i = 1 To 50000
        a(i) = ActiveCell.Value
        ActiveCell.Offset(1, 0).Activate
    Next i
    Application.ScreenUpdating = True
―――――――――――――――――――――――――+

このサンプル3では、2.6秒という結果となりました。
(当然ですが断然早くなります。)



ですが、
この様な場合、わざわざ「画面の非表示」を使わなくてももっと格段に
スピードアップさせる方法があります。


それは、セレクトせずに直接セルの値を取りに行く下記の方法です。

サンプル4
―――――――――――――――――――――――――+
    For i = 1 To 50000
        a(i) = Range("B" & CStr(i)).Value
    Next i
―――――――――――――――――――――――――+

このサンプル4では、1.0秒という結果が出ました。
(「画面の非表示」をせずにこの結果です。)



ちょっと予断ですが、ちなみにこの

a(i) = Range("B" & CStr(i)).Value

という書き方は、本来は

Dim objRng As Range
Set objRng = Range("B" & CStr(i))
a(i) = objRng.Value
Set objRng = Nothing

の言わば省略形なだけなので、どちらで書いても速度的にほとんど変わりま
せん。

でも、VBAでもやたらとこうしたSetを用いたコードを書きたがるプログラマ
も見うけますが、速度が同じでコードが1行ですっきりするという意味では
なるべく前者の書き方でコーディングすることをおすすめします。



話を元に戻しますが、
更に、スピードアップを図る手段として、Cellsを使う方法が有効です。

サンプル5
―――――――――――――――――――――――――+
    For i = 1 To 50000
        a(i) = Cells(i, "B").Value
    Next i
―――――――――――――――――――――――――+

このサンプル5の結果では、0.8秒となりました。


結論を言うと、
データ取得の際のセル指定は、Cellsプロパティを使ってダイレクトに値を
取り出す方法が最も高速だということになります。


(ちなみに今、最も高速だと言いましたがVariant型を使ってもっと高速に
データ取り込みを行なえる方法もあります。しかしVariant型を使うこと自
体推奨しませんし語り出すと深く脱線してしまいそうなので、今回Variant
型に関しては触れません。)




また(ついでに)、
データの書き込み時のセル指定の方もベンチマークを行なってみた結果では
以下(サンプル6〜9の比較)に示す様に、データを読み込む場合とほぼ同
様の結果が得られました。


サンプル6 ⇒55.9秒
―――――――――――――――――――――――――+
    For i = 1 To 50000<
        Range("A" & CStr(i)).Select
        ActiveCell.FormulaR1C1 = i
    Next i
―――――――――――――――――――――――――+


サンプル7 ⇒6.1秒
―――――――――――――――――――――――――+
    Application.ScreenUpdating = False
    For i = 1 To 50000
        Range("A" & CStr(i)).Select
        ActiveCell.FormulaR1C1 = i
    Next i
Application.ScreenUpdating = True ―――――――――――――――――――――――――+ サンプル8 ⇒4.5秒 ―――――――――――――――――――――――――+ For i = 1 To 50000 Range("A" & CStr(i)).Value = i Next i ―――――――――――――――――――――――――+ サンプル9 ⇒4.3秒 ―――――――――――――――――――――――――+ For i = 1 To 50000 Cells(i, "B").Value = i Next i ―――――――――――――――――――――――――+ ちなみに、 このサンプル8や9でもプラス「画面の非表示」を用いると、 更にもう少しスピードアップを図ることができます。 サンプル10 ⇒3.6秒 ―――――――――――――――――――――――――+ Application.ScreenUpdating = False For i = 1 To 50000 Cells(i, "B").Value = i Next i Application.ScreenUpdating = True ―――――――――――――――――――――――――+ 今回はこれで終了です。

 

----------【サンプルテストの実行環境】----------

   PCスペック:Pentium4 1.8GHz
   OS    :Windows XP
   Excel   :Microsoft Excel2003 or 2002

----------------- r(-●_●-) -----------------



 
▼エクセルVBA技術通信(メルマガ)の登録/解除はこちら((無料))
「エクセルVBA技術通信」 (まぐまぐマガジンID:0000252815)
メールマガジン登録
メールアドレス:
メールマガジン解除
メールアドレス:


 
サイトのご利用にあたって  |  エクセルVBA事例  |  会社概要  |  個人情報の取扱い  |  お問い合わせ


Copyright © 2007 WAT CO.,LTD.
※弊社の許可無く無断で複製・複写・転載することは固くお断りします。