ExcelマクロでテキストファイルやCSVファイルを書き出すのは簡単です。
- Open でファイルを開く
- Print でファイルに1行書き出す
- Close でファイルを閉じる
が基本的な流れです。
複数行の書き出しは、2番を繰り返します。
しかし、書き出しが大量になるとネックは遅さです。
1行にどれくらいの文字数があるか、で異なりますが、1,000行で5分程度、10万行ならば数十分かかります。
テストデータを作成するときに、数十分も待てません。
(パソコンのCPUやメモリが占有状態になるので、パソコンで他の作業をしながら待つのも無理です)
そこで今回は、Excelマクロの大量書き出しを高速化する「ADODB.Stream」を紹介します。
この機能を使うと10万行が1分で書き出されます。
ExcelCSVでUTF-8を扱う場合にも、このADODB.Streamが使えます。
基本構文は次のとおりです。
- object.Open で、ADODBのstreamオブジェクトを開く
- object.WriteText で、stream内(メモリ内)にデータを溜める
- object.SaveToFile で、stream内のデータを外部ファイルに書き出す
- object.Close で、streamオブジェクトを閉じる
複数行の書き出しは、2番を繰り返します。
処理は、Print で一行ずつファイル書き出しするのとは異なり、WriteText(上記2番) でメモリ内に処理データを全て溜め込んでから SaveToFile(上記3番) で一気に書き出します。
処理速度のボトルネックは外部ストレージに対するI/O(Input/Output)なので、ここを一度で済ませれば速度改善になるのです。そのため、数行~数十行程度の処理では速度の差が分かりませんが、数万件とデータ量が多くなればなるほど顕著な差が出ます。
オプション指定も色々できます。
よく使われるのが、Charset プロパティ(文字コード指定)です。
デフォルトはUnicodeですが、それ以外にUTF-8、Shift_JIS、euc-jp、ISO-2022-JPなどが使えます。
ADODBを使うときは、マクロの参照設定が必要です。
このコードエディタのメニューの「ツール」⇒「参照設定」を開きます。
「Microsoft ActiveX Data Objects x.x Library」を選びます。(x.xの部分は一番大きな数字でOK)
サンプルコードを載せます。
私がよく使う「Excelで作成した(システム開発時の)テストデータを、CSVファイルとして書き出す」処理です。
A1⇒テーブル名 ※処理中では使っていない
2行目⇒論理名 ※処理中では使っていない
3行目⇒属性 ※処理中では使っていない
4行目⇒桁数 ※処理中では使っていない
5行目⇒物理名
6行目以降で、テストデータ
50カラムある場合はA~AX列
1,000レコードある場合は6~1,006行
にテストデータが記載されているものと想定します。
Option Explicit Public Sub BULK_INSERT用のCSV作成() 'ADODB.Streamを使う Dim ado As Object Set ado = CreateObject("ADODB.Stream") '変数 Dim i As Long 'データ開始行 Dim j As Integer '列 Dim ColNRow As Integer '何行目にカラム物理名を記載しているか Dim eCol As Integer '一番右の列の位置(要素数が不明な場合でも処理可能) Dim eRow As Long '一番下の行の位置( 〃 ) '定数 Const SaveF = "C:\test.csv" '保存ファイル名 'カラム物理名の行 ColNRow = 5 '5行目に物理名を書いている(右端を取得する基準として使用) '一番下の行の位置を取得する eRow = Cells(ColNRow, 1).End(xlDown).Row '一番右の列の位置を取得する eCol = Cells(ColNRow, 1).End(xlToRight).Column '処理開始 ado.Open 'ADODB.Streamを開く ado.Charset = "UTF-8" '文字コード指定(UTF-8) 'メイン処理(A列の値がある間はループする) For i = 6 To eRow 'A列のみ(先頭にカンマを付けたくないから) j = 1 ado.WriteText Cells(i, j) 'B列より右側 For j = 2 To eCol ado.WriteText "," & Cells(i, j) Next '行の最後で改行コード ado.WriteText "", adWriteLine Next 'ADODB.Streamに保管されている内容を、ファイルに保存する ado.SaveToFile SaveF, 2 'ADODB.Streamを閉じる ado.Close MsgBox "完了" End Sub