- ベストアンサー
VBAプログラム実行処理時間を短縮する方法とは?
- プログラム作成で処理時間が25秒程かかってしまった場合、処理速度を上げる方法はないでしょうか?具体的な改善方法についてお教えください。
- 処理内容は、指定されたCSVファイルを自動で読み込むために作成されたプログラムです。処理が遅い原因や改善点について教えてください。
- 動作環境はWindows10(64bit)およびExcel2016(32bit)です。処理時間を短縮するために必要な環境や設定の変更についてもお教えください。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
私が適当なcsvファイルを作って実行させたところ3.87秒かかった。 なお'Call ClearImmediateはコメントにした。 ----------------------------------------- 次に Start = Timer() ' 処理開始時刻を設定します。 から Finish = Timer() ' 処理終了時刻を設定します。 の間を,以下のように書き換えたら0.28秒になった。 ----------------------------------------- Open file For Input As #1 'CSVファイルを開く n = 0 Do Until EOF(1) '最終行までループ Dim buf As String: Line Input #1, buf '読み込んだデータを1行ずつみていく n = n + 1 Dim tmp As Variant: tmp = Split(buf, ",") 'カンマで分割 With New Class1 'インスタンスの生成 .Name = CStr(tmp(0)) '果物 .Price = CInt(tmp(1)) '単価 .Number = CInt(tmp(2)) '個数 Items.Add .Self 'コレクションに追加 End With Loop Close #1 'CSVファイルを閉じる Dim item As Class1 'ループ用の変数 With ActiveSheet i = 1: j = 1 .Range("A1").Value = "果物": .Range("B1").Value = "単価": .Range("C1").Value = "個数": _ .Range("D1").Value = "小計": .Range("G1").Value = "キー(果物)": .Range("H1").Value = "小計" ReDim aa(1 To n + 1, 1 To 4) ReDim bb(1 To n, 1 To 1) Dim Key As String Key = .Range("G2").Value For Each item In Items 'コレクション内をループ ' Debug.Print item.Name, item.Price, item.Number, item.Sale 'プロパティを取得 aa(i, 1) = item.Name: aa(i, 2) = item.Price: _ aa(i, 3) = item.Number: aa(i, 4) = item.Sale If item.Name = Key Then bb(j, 1) = item.Sale: j = j + 1 'キーで要素取得・取出し i = i + 1 Next .Range("A2").Resize(n, 4) = aa .Range("H2").Resize(j, 1) = bb End With Debug.Print Items(3).Name '要素取出し Application.DisplayAlerts = True Application.ScreenUpdating = True ----------------------------------------- さらに Start = Timer() ' 処理開始時刻を設定します。 から Finish = Timer() ' 処理終了時刻を設定します。 の間を,以下のように書き換えたら0.22秒になった。 ----------------------------------------- Open file For Input As #1 'CSVファイルを開く Dim buf As String Dim Key As String Dim tmp As Variant n = 0 Do Until EOF(1) '最終行までループ Line Input #1, buf '読み込んだデータを1行ずつみていく n = n + 1 Loop ReDim aa(1 To n, 1 To 4) ReDim bb(1 To n, 1 To 1) Key = ActiveSheet.Range("G2").Value i = 1: j = 1 Seek #1, 1 Do Until EOF(1) '最終行までループ Line Input #1, buf '読み込んだデータを1行ずつみていく tmp = Split(buf, ",") 'カンマで分割 aa(i, 1) = CStr(tmp(0)) '果物 aa(i, 2) = CInt(tmp(1)) '単価 aa(i, 3) = CInt(tmp(2)) '個数 aa(i, 4) = aa(i, 2) * aa(i, 3) If aa(i, 1) = Key Then bb(j, 1) = aa(i, 4): j = j + 1 'キーで要素取得・取出し i = i + 1 Loop Close #1 'CSVファイルを閉じる With ActiveSheet .Range("A1").Value = "果物": .Range("B1").Value = "単価": .Range("C1").Value = "個数": _ .Range("D1").Value = "小計": .Range("G1").Value = "キー(果物)": .Range("H1").Value = "小計" .Range("A2").Resize(n, 4) = aa .Range("H2").Resize(j, 1) = bb End With Debug.Print aa(3, 1) '要素取出し Application.DisplayAlerts = True Application.ScreenUpdating = True
その他の回答 (1)
- kon555
- ベストアンサー率51% (1842/3559)
ザッと拝見したところ、ループ処理で毎回セルに値を入れているようなので、「値を配列に入れてからセルに代入する」で高速化できるのではないかと思います。 以下参考ページ http://officetanaka.net/excel/vba/speed/s11.htm https://excel-ubara.com/excelvba1/EXCELVBA414.html https://mmm-program.com/vba-fast-array/
お礼
やはり配列を使うのですね! ありがとうございます。 頑張ります。
お礼
2次元配列を使うのですね! ソースコードまで付けて下さって、本当にありがとうございます。 5000件のCSVデータを処理した所、25秒以上かかっていましたが、Collection処理を追加しても0.5秒以内に収まりました。