• ベストアンサー

EXCEL VBAによるEXCELファイル作成時の高速化案がありますでしょうか。

EXCEL VBAによるEXCELファイル作成時の高速化案がありますでしょうか。 行いたい内容は、以下の通りです。 1.CSVファイルの1行目をフィールド名としてシートの1行目に記述する。   ※フィールド数は、いつも同じとは限りません。 2.CSVファイルの内容の取得の際に、抽出条件の指定が発生する事がある。   ※データ量と抽出条件の兼ね合いで、SQLでデータを取得しています。 また、データ数は、サンプルでは5万行程度。 今後は、6万行を超えていく予定です。この際は一定の件数毎に書き出すEXCELファイルを増やしていく予定です。 このEXCELファイルへの書き出し方法の場合、私のPCでは5万行の場合、5分程かかります。 処理方法を変更する事によって、処理速度の改善は見込めるものでしょうか。 なお、あくまで5分と言う数字がダメなのではなく、よりスピードが上がれば、データ件数が増えた際にも、快適であろうと言う程度であります。 皆様のお知恵を拝借出来ればと思っております。 よろしくお願いいたします。 -------------------------------------------------------------------------------- 以下のように、SQLを使って、CSVファイルからデータを取り出し、EXCELファイルを新規に作成しています。 (エラー処理等は省いております。) -------------------------------------------------------------------------------- '設定。 strDIR = "C:\temp" strCSV = "sample.csv" strFileName = "output.xls" strCon = "Provider=Microsoft.Jet.OLEDB.4.0;" & "Data Source=" & strDIR & ";" & "Extended Properties=""Text;HDR=YES;FMT=Delimited""" '画面の自動更新をOFF Application.ScreenUpdating = False '新しいEXCELファイルをデータと同じディレクトリに作成。(旧バージョンでの互換性を維持) Set Newbook = Workbooks.Add Newbook.SaveAs Filename:=strDIR & "\" & strFileName, FileFormat:=xlNormal Newbook.Activate Set objSheet = Newbook.Sheets("Sheet1") 'データ取得。 Set objDB = CreateObject("ADODB.Connection") objDB.Open strCon Set objRes = objDB.Execute("SELECT * FROM " & strCSV) '1行目にフィールド名を記述。 For m = 0 To (objRes.Fields.Count - 1) objSheet.Range("A1").Cells(1, (m + 1)).Value = objRes.Fields(m).Name Next m '2行目からデータ記述。 GYO = 2 Do Until objRes.EOF = True For k = 0 To (objRes.Fields.Count - 1) objSheet.Range("A1").Cells(GYO, (k + 1)).Value = objRes(k) Next k GYO = GYO + 1 objRes.MoveNext Loop 'EXCELファイルの保存 Newbook.Save '後処理。 objDB.Close Set objRes = Nothing Set objDB = Nothing '画面の自動更新をON Application.ScreenUpdating = True

質問者が選んだベストアンサー

  • ベストアンサー
  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.1

こんにちは。 > '2行目からデータ記述。 > GYO = 2 > Do Until objRes.EOF = True > For k = 0 To (objRes.Fields.Count - 1) > objSheet.Range("A1").Cells(GYO, (k + 1)).Value = objRes(k) > Next k > GYO = GYO + 1 > objRes.MoveNext > Loop の部分を Range("A2").CopyFromRecordset objRes に置き換えてみたら? 一概には言えませんが、1データ毎にセルに順次書込みするよりは、速い のではないかと思いますよ。   ■VBA HELP 引用 Microsoft ActiveX Data Object Library 参照   expression.CopyFromRecordset(Data, MaxRows, MaxColumns)   解説   コピーは Recordset オブジェクトのカレント レコードの位置から   行われます。コピーが完了すると、Recordset オブジェクトの EOF   プロパティは True になります。 > この際は一定の件数毎に書き出すEXCELファイルを増やしていく予定です。 これは、引数 MaxRows が利用できますね。 あと、CSV ファイルなので Schema.ini なんかも必要かもしれません。 [MSDN:CopyFromRecordset メソッド] http://msdn.microsoft.com/ja-jp/library/cc362496.aspx [三流君ASP:ADO CSV接続 schema.iniを使い型を設定してみた] http://www.ken3.org/asp/backno/asp102.html では。

BENGAL
質問者

お礼

お返事が遅くなりまして、申し訳ありません。 CopyFromRecordsetを使用する方法に変更してみました。 そして、8万行のCSVファイルを2つのエクセルファイルに読み込む処理を作成した所、なんと、数十秒で処理が完了しました。 驚くほどの速度改善となりました。 本当に、ありがとうございます! 感謝するばかりでございます。 知識と言うものは素晴らしいと改めて実感した次第です。 VBAのおもしろさも、もちろん、実感した次第です。 閲覧されている他の方々にも参考になるかと思いますので、サンプルを以下に提示します。 8万行のCSVを5万行ずつエクセルに分割するサンプルです。 '全データの取得。 Set objRes = objDB.Execute("SELECT * FROM sample.csv") For i = 1 To 2 Set Newbook = Workbooks.Add Newbook.SaveAs Filename:=example_" & i & ".xls, FileFormat:=xlNormal Newbook.Activate Set objSheet = Newbook.Sheets("Sheet1") '1行目にフィールド名を記述。 intFieldMax = objRes.Fields.Count - 1 For m = 0 To intFieldMax objSheet.Range("A1").Cells(1, (m + 1)).Value = objRes.Fields(m).Name Next m 'データの取得。 tmp = Range("A2").CopyFromRecordset(objRes, 50000) Newbook.Save 'EOFがTrueになるので、最初に戻す。 objRes.MoveFirst 'すでに取得したデータを飛ばす。 objRes.Move (50000 * i) Next i なお、動作確認は、Excel2000、Excel2007で行いました。

その他の回答 (1)

  • o_chi_chi
  • ベストアンサー率45% (131/287)
回答No.2

・複数使用しかつ変わらない値は一端変数へ代入する。 lngMax = objRes.Fields.Count - 1 ・修飾を省略しない。 objRes.fields.Item(k) ・Withステートメントを使う。 With objRes 微々たる改善ですが。

BENGAL
質問者

お礼

お礼が遅くなりまして申し訳ありません。 CopyFromRecordsetの使用と合わせて、繰り返し同じ値を参照する部分の計算は、変数にまとめてみました。 驚くべき改善がみられ、感謝するばかりでございます。 本当にありがとうございました!

関連するQ&A

  • Excelからテキストファイルを読み込み、読み込んだ行を削除する方法

    Excelからテキストファイルを読み込み、読み込んだ行を削除する方法 いつもお世話になりますm(__)m Excel2003のVBAで、以下のようにテキストファイルを読み込む処理を作成しています。 Sub LoadFile() Dim intFF As Integer Dim strFILENAME As String Dim DtC, DtD, DtE As String Dim GYO As Long strFILENAME = ActiveWorkbook.Path & "\sample.txt" If Dir(strFILENAME) <> "" Then intFF = FreeFile Open strFILENAME For Input As #intFF GYO = 1 Do Until EOF(intFF) Input #intFF, DtC, DtE, DtE If DtC = 1 Then GYO = GYO + 1 Worksheets("DataSheet").Range("C" & GYO).Value = DtC Worksheets("DataSheet").Range("D" & GYO).Value = DtD Worksheets("DataSheet").Range("E" & GYO).Value = DtE End If Loop Close #intFF End If End Sub sample.txtからデータを読み込み、1個目のデータが「1」なら、DataSheetのC,D,Eの各列に、テキストファイルから読み込んだデータがセットされます。 1個目のデータが1以外なら、DataSheetにはセットされないようにしています。 そこで、読み込んだデータ(1個目のデータが「1」の行)を読み込んでDataSheetに挿入した後に、その行をsample.txtから削除したいのですが、どうすればいいかわかりません(>_<) 最終的に、処理を実行した後のsample.txtは、DataSheetにセットしたデータ以外が残るようにしたいのです。 お詳しい方、何卒ご教授のほど宜しくお願い致しますm(__)m

  • 複数のcsvファイルを1つのEXCELファイルにマージするVBAを教えてください

    csvファイル数は700~1000個程度でひとつのフォルダに格納されています。 このファイルをEXCEL形式で開くと、1行目にフィールド名(A~Z列で固定)、2行目以降にデータが入っています。行数はファイルにより1~100行程度で変動します。 このファイルを1つのエクセルファイルの同一シートに結合(マージ)するVBAがほしいです。 ここで、(できればですが)EXCELにマージするにあたり、1行目のみフィールドの値、2行目以降にそれぞれのcsvの2行目以降データの値を入れていくようにしたいです。つまり、フィールド名の行が何行も出てくるのを避けたいです。 申し訳ございませんが、ご指導いただけたら幸いです。よろしくお願いします。

  • Excel VBAにてCSVファイルを読みたい

    ExcelにてCSVファイルを読んで処理をしたい。 ただし、CSVファイルをExcelでopenすると遅いので、 VBAにてファイルとして読み込みで処理をしたいのですが、 皆さんは、どのように行っていますか? ※CSVファイルは、テキスト区切り→"(ダブルコーテーション)です  テキスト区切り無しであれば、1行読んで、カンマをsplitすれば良いと思いますが。。。。

  • excel vbaで複数のcsvファイルの読み込み

    100シート分のcsvファイルのデーターを一つずつ読み込んでexcelにコピーして使用してますが莫大な時間がかかって困ってます。 vbaを使用して作業を簡素化出来る事は出来ないでしょうか? ------------------------------------------ ※ csvの概要 excelで1枚のcsvファイルを開くとA列の11行目から65536行まで数値データがあります。 ※ vbaできたらよいなと思う仕様 そこで、複数のcsvファイルを選択して読み込むとCSV_データと言うSeetのA列の10行目から1枚目のcsvファイル、B列の10行目から2枚目のcsvファイルと言う風に選択した分のcsvを列に続けて数値データを貼り付けしてくれるvbaをご教授していただけると大変助かります。 不躾で申し訳ございませんが宜しくお願い致します。 excel2003 ------------------------------------------

  • VB及びエクセルのVBAにて、

    VB及びエクセルのVBAにて、 300000行のCSVデータを読み込もうと試みました。 ファイルOpenで、Line InputやInputBを使用しましたが、 どちらもあまり処理速度は変わらないようです。 高速で1行ずつCSVデータを読み込む方法をご存じないでしょうか。 ご存知でしたら、関連するサイトを教えていただければ助かります。 お手数をおかけしますが、よろしくお願いします。

  • エクセルVBAで65536レコードを超えるCSVファイルの読み込み

    エクセル2000です。 現在CSV形式のファイルをもらい、エクセルVBAで1行づつエクセルに取り込み、加工しています。(CODEは、かなり省略していますが下記の通り) データは将来的には何万件におよぶことも考えられます。 ためしに65536を超えるデータを読み込ませたところ65536を超えたところでやはりエラーになりました。Workbooks.Openでエクセル形式で開いているので65536を超える部分は無視されるからだと思います。 このような場合には、どうやってCSVファイルからデータを読み込めばよいのでしょうか?(なお、エクセルは当分2007にはなりそうもありません。アクセスはまったく使えません。) Sub TEST01() Set cf = Workbooks.Open(Filename:=ThisWorkbook.Path & "\test.csv") Set zerro = cf.Sheets(1).Range("A1:AX1") ThisWorkbook.Sheets("Sheet1").Activate Do Until zerro.Cells(1).Value = "" ThisWorkbook.Sheets("Sheet1").Range("A1:AX1").Value = zerro.Value '処理マクロ省略 Set zerro = zerro.Offset(1) Loop End Sub

  • Excel VBA 突然停止

    お世話になります。 標記の件で悩んでおります。 out.csv→→→中間ファイル.xlsm→本処理ファイル.xlsm 201510.csv→ 上記の通り、2つのExcelフォーマットのcsvファイルを中間ファイルに読み込ませるVBAを作成し、中間ファイルを一度作りました。これは正常に処理が止まらず、正しく書き込まれています。 因みに、csvエクセル形式行数は3万行ぐらいです。レコード数は、100万行ですが、私は、csvのデータをレコード数で読み込ませていません。 単純に、エクセルフォーマットでcsvファイルを開き、範囲指定してそれを、単純に中間ファイルでTempシートに単純にコピペし、不要なコメント行とか空欄を中間ファイルのマクロで、削除し、中間ファイルで必要なデータを作成しています。 ここまでは、間違いなく出来ております。つまり、レコード数を何か別のPGで読み込ませてエクセルに取り込ませることはしておりません。 そこで、最終の本処理ファイル.xlsmに中間ファイルをオープンして読み込ませると、途中で停止してしまいます。 そこで、本処理ファイルのVBAのプログラムの関数の一つ一つにブレークポイントを入れ、処理したところ、今度は、問題なく出来てしまいます。 結果を担当者に聞くと、間違いなく出来ているようだと言っていました。 そこで、ブレークポイントではなく、自動処理できないかと思い、もう一度、中間ファイルを本処理ファイルでオープンすると、予想通り、停止します。 そこで、再度、先ほどと同じ様にブレークポイントを入れて処理をしようとしたところ、読み込むこともあるし、読み込んでも停止してしまいます。 論理上、このようなことが、あるのかと思って困っています。 環境は、各ファイルをファイルサーバーに置いて処理しています。 ローカル、自分のPC単体ではやっていません。 Win 7 Professional 32bit版 4GBのPCです。 2010 Excel ご回答よろしくお願い致します。

  • エクセルVBA 一枚のシートにcsvファイルをまとめる 

    教えてください。 以下の処理をしたいのですが、どのようにしたらよいか教えてください。 (1)デスクトップの1つのフォルダに格納しているcsvファイルを全て開く(ファイルがいくつあるかはその時によって違う) (2)開いたcsvファイルのデータがある行を全て選択して、開いてあるデータベースとしてあるシートに貼り付ける。 (これをcsvファイル数分実行する) (3)コピーの終わったcsvファイルを全て閉じる どうしても(2)の処理がわからず、どなたか教えてください。 よろしくお願い致します。

  • ACCESS VBAで作成済のExcelのコピーを作りたい

    ACCESS VBAで作成済みのExcelファイル (複数シートがあります)の コピーを作成し そのファイルでテーブルのデータを 出力したいと思っています。 シートが1つならできましたが シートが複数あるとできません。 できる方法を教えてください。 なおシートが一つの場合は、下記でできました。 Dim oXLS As New Excel.Application Dim NewBook As Excel.Workbook oXLS.Workbooks.Open Filename:=既存ファイル名 oXLS.ActiveWorkbook.Sheets(シート名).Copy Set NewBook = oXLS.ActiveWorkbook oXLS.Workbooks(ファイル名).Close 複数シートがある場合の 作成方法を教えてください。 よろしくお願いします。

  • エクセルVBAでCSVファイルから取り込みたいのですが・・・

    CSVファイルのデータを取り込むコードを教えていただけないでしょうか。 「共有フォルダ」の中に「作業用.xls」と「090820.csv」があります。csvファイルは日によって名前が変わりますが、必ず一つしか入れないことにしています。 CSVファイルの1行目は見出しです。2行目以降がデータになっています。 A2からI列最終行を「作業用.xls」のsheet1のA6にコピー(取り込み)したいのですが、よろしくお願いします。

専門家に質問してみよう