AccessVBAでExcelを操作する2つの方法と使い分けについて

スポンサーリンク

AccessVBAでExcelを操作すると遅くなる

以前こちらの記事でAccessVBAでExcelを操作する方法をご紹介しました。

実際にこの方法を用いてAccessのデータベースから出力したテーブル・クエリ結果などをExcelを用いて加工していたのですが、少し複雑な処理をしたところスピードが大きく下がり、日常的に支障が出ることがありました。

その際AccessVBAでExcelを操作する別の方法を用いて解決できたので備忘録も兼ねてこちらのページで手順を紹介します。

復習:Excelを操作するAccessVBAについて

AccessVBAでExcelを操作する場合、下記のようなコードを書きます。

実行するにあたっては参照設定で「Microsoft Eccel 〇〇 Object Library」にチェックを入れるのを忘れないようにしてください。

参照設定の方法はこちらのページで紹介しています。

ExcelVBAでOutlookを操作するための参照設定の手順を書いていますが、AccessVBAでExcelを操作する場合もチェックするLibraryが異なるだけで手順自体は同じです。

Sub Excel操作1()

Dim 開始時間
Dim 終了時間

開始時間 = Time

Dim ExApp As Object
Set ExApp = CreateObject(“Excel.Application”)
Dim FSO As Object
Set FSO = CreateObject(“Scripting.FileSystemObject”)
Dim i

ExApp.Visible = True
ExApp.Workbooks.Open FileName:=Application.CurrentProject.Path & “\” & “Excel検証用.xlsx”, readOnly:=True

With ExApp

.Workbooks(.Workbooks.Count).Activate
.Workbooks(.Workbooks.Count).Sheets(1).Select
.Cells(1, 1) = 1

’繰り返しの実行
For i = 2 To 1000
If .Cells(i - 1, 1) = 1 Then
.Cells(i, 1) = 2
Else
.Cells(i, 1) = 1
End If
Next i

End With

Set ExApp = Nothing
終了時間 = Time
Debug.Print Format(終了時間 - 開始時間, “hh:mm:ss”)

End Sub

これはAccessのファイルと同じフォルダに格納されているExcel検証用.xlsxというExcelファイルを開いて、シート1のA列の1行目から1,000行目に「1」「2」を交互に入力するコードになります。

実際AccessでExcelを操作する際はExportしたテーブルやクエリを操作することが多いですが、今回は検証として単純にExcelファイルを開いて操作するだけにしています。

スポンサーリンク

AccessVBAでExcelを操作するのは時間がかかる

先ほど復習としてご紹介したExcel操作ですが、1,000回くらいの比較的短い繰り返しだと問題なく実行され、Excel単体で処理するのとさほど体感的に変わらない時間で処理が終了しますが、繰り返しが多くなったり条件分岐が増えてくると徐々に遅くなってしまいます。

10,000行まで同じ処理を繰り返すようにした場合、20秒くらいかかるようになりました。
もちろんExcel単体で実行した場合1~3秒くらいの時間しかかかりません。

AccessでExcelワークシート上に何か書き込むのに時間がかかることがわかったので、改善方法としてExcelのVBAを格納したファイルを用意して、それをAccessVBAで実行する方法を考えました。

少しだけ仕事で付き合いのあるSEの方はこういう方法のことを「ExcelVBAをキックする」と言っていました。
開始処理を加えることをそう呼んだりするようです。

Sub Excelマクロ実行1()

Dim 開始時間
Dim 終了時間

開始時間 = Time

Dim ExApp As Object
Set ExApp = CreateObject(“Excel.Application”)
Dim FSO As Object
Set FSO = CreateObject(“Scripting.FileSystemObject”)

ExApp.Visible = True
ExApp.Workbooks.Open FileName:=Application.CurrentProject.Path & “\” & “Excel検証用マクロファイル.xlsm”, readOnly:=True
ExApp.Workbooks.Open FileName:=Application.CurrentProject.Path & “\” & “Excel検証用.xlsx”, readOnly:=True

With ExApp

.Workbooks(.Workbooks.Count).Activate
.Workbooks(.Workbooks.Count).Sheets(1).Select
.Run “Excel検証用マクロファイル.xlsm!検証用マクロ1”

End With

ExApp.Workbooks(1).Close
Set ExApp = Nothing

終了時間 = Time
Debug.Print Format(終了時間 - 開始時間, “hh:mm:ss”)

End Sub

AccessVBAで起動するExcel検証用マクロファイル.xlsmの検証用マクロ1は下記のようなコードになっています。

Sub 検証用マクロ1()

Cells(1, 1) = 1
’繰り返しの回数
For i = 2 To 1000
If Cells(i - 1, 1) = 1 Then
Cells(i, 1) = 2
Else
Cells(i, 1) = 1
End If
Next i

End Sub

この処理だとExcel操作自体はExcelVBAで実行するので処理時間がかなり短縮されます。
10行、100行、1,000行、10,000行、100,000行繰り返す際にかかる時間を検証した結果は下記の表のとおりです。

繰り返し回数 10 100 1000 10000 100000
直接Excel操作 1秒 2秒 3秒 17秒 2分39秒
ExcelVBA実行 2秒 3秒 3秒 3秒 5秒

ExcelVBAでワークシートを操作する方がかなり早く処理が進むことがわかりました。

シートに値を格納するだけなら配列に入れた値を一気に入力するなどの方法で解決できるかもしれませんが、列を追加して項目を増やしたり、罫線を入れたり、背景色を変えたり、フォーマットを変更するなどの処理を条件分岐・繰り返しを使いながらワークシートの操作を行う場合、ExcelVBAを使った方がよさそうです。

今後AccessVBAのみでExcel操作をするのは簡単なもののみにしようと思います。

コメント