質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Q&A

解決済

1回答

105閲覧

VBA DictionaryとListObjectを使った処理の高速化

user202102

総合スコア11

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

0グッド

1クリップ

投稿2024/11/21 09:38

編集2024/11/21 12:44

実現したいこと

VBAにて、DictionaryとListObjectを使った処理の高速化を実現したいです。
処理の概要とフローについては以下になります。

[概要]
独自クラスの配列(Dictionary)の中身をループでテーブルに書き込む

[フロー]

  1. 別シートの他テーブルより、1行ずつ各列の値を独自クラスのプロパティに設定しDictionaryに格納
  2. 書き込むテーブルの行を全削除(リセット)
  3. Dictionaryをループしてテーブルの先頭行に各プロパティの値を設定、行を増やす
  4. Dictionaryの最後まで3を繰り返す ★ここが重い
  5. シートの最適化

発生している問題・分からないこと

ループ以外にも処理を行っていますが、そちらは1秒もかからず終了していて、Rangeを参照している処理に時間がかかっているようなのでこちらのリファクタリングを行いたいです。具体的には30行を書き込むのみ40秒ほどかかりますので短縮したいです。

該当のソースコード

visual

1Sub reflection() 2 Application.ScreenUpdating = False 3 Call AP_ref.reflection '他のシートの最適化、メソッドの記載は省略 4 Call AR_ref.reflection '他のシートの最適化、メソッドの記載は省略 5 6 Dim allTable As ListObject 7 Set allTable = ActiveWorkbook.Worksheets("全取引").ListObjects("All") 8 9 Call sortTable '他のシートのソート、メソッドの記載は省略 10 11 Dim allSlipList As Object: Set allSlipList = getSlips() 'フロー:1. 別シートの他テーブルより、1行ずつ各列の値を独自クラスのプロパティに設定しDictionaryに格納、メソッドの記載は省略 12 13 'フロー:2. 書き込むテーブルの行を全削除(リセット) 14 With allTable 15 If Not .DataBodyRange Is Nothing Then 16 .DataBodyRange.Delete 17 End If 18 End With 19 20 Dim allSlipListKey As Variant 21 Dim yayoi As yayoi 22 ' フロー:3. Dictionaryをループしてテーブルの先頭行に各プロパティの値を設定、行を増やす 23 For Each allSlipListKey In allSlipList.Keys 24 Set yayoi = allSlipList(allSlipListKey) 25 Range(tableRow, 1) = yayoi.columns("id_Flag") 26 With allTable 27 ' .Range(.Range.Rows.Count, 1) = yayoi.columns("id_Flag") 28 ' .Range(.Range.Rows.Count, 2) = yayoi.columns("slipNum") 29 ' .Range(.Range.Rows.Count, 3) = yayoi.columns("financStat") 30 ' .Range(.Range.Rows.Count, 4) = yayoi.columns("slipDay") 31 ' .Range(.Range.Rows.Count, 5) = yayoi.columns("debitName") 32 ' .Range(.Range.Rows.Count, 6) = yayoi.columns("debitSub") 33 ' .Range(.Range.Rows.Count, 7) = yayoi.columns("debitDep") 34 ' .Range(.Range.Rows.Count, 8) = yayoi.columns("debitTaxType") 35 ' .Range(.Range.Rows.Count, 9) = yayoi.columns("debitAmo") 36 ' .Range(.Range.Rows.Count, 10) = yayoi.columns("debitTax") 37 ' .Range(.Range.Rows.Count, 11) = yayoi.columns("creditName") 38 ' .Range(.Range.Rows.Count, 12) = yayoi.columns("creditSub") 39 ' .Range(.Range.Rows.Count, 13) = yayoi.columns("creditDep") 40 ' .Range(.Range.Rows.Count, 14) = yayoi.columns("creditTaxType") 41 ' .Range(.Range.Rows.Count, 15) = yayoi.columns("creditAmo") 42 ' .Range(.Range.Rows.Count, 16) = yayoi.columns("creditTax") 43 ' .Range(.Range.Rows.Count, 17) = yayoi.columns("summary") 44 ' .Range(.Range.Rows.Count, 18) = yayoi.columns("num") 45 ' .Range(.Range.Rows.Count, 19) = yayoi.columns("settlement") 46 ' .Range(.Range.Rows.Count, 20) = yayoi.columns("slipType") 47 ' .Range(.Range.Rows.Count, 21) = yayoi.columns("origin") 48 ' .Range(.Range.Rows.Count, 22) = yayoi.columns("memo") 49 ' .Range(.Range.Rows.Count, 23) = yayoi.columns("tag1") 50 ' .Range(.Range.Rows.Count, 24) = yayoi.columns("tag2") 51 ' .Range(.Range.Rows.Count, 25) = yayoi.columns("adjustment") 52 .ListRows.Add 53 End With 54 tableRow = tableRow + 1 55 Next `フロー:4. Dictionaryの最後まで3を繰り返す 56 57 `フロー:5. シートの最適化 58 allTable.Range.AutoFilter Field:=3 59 allTable.Sort.SortFields.Clear 60 allTable.Sort.SortFields.Add2 key:= _ 61 Range("All[[#All],[日付]]"), SortOn:=xlSortOnValues, Order:=xlAscending, _ 62 DataOption:=xlSortNormal 63 With allTable.Sort 64 .Header = xlYes 65 .MatchCase = False 66 .Orientation = xlTopToBottom 67 .SortMethod = xlPinYin 68 .Apply 69 End With 70 71End Sub

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

Application.ScreenUpdatingの設定で高速化対応はしていますが、テーブルの処理の高速化についてはまだ調査中です。

補足

修正後の該当ソースコード

visual

1Dim rangeStr As String: rangeStr = "A2:Y" & allSlipList.Count 2 ReDim tableArray(yayoiCount, 25) As Variant 3 For Each allSlipListKey In allSlipList.Keys 4 Set yayoi = allSlipList(allSlipListKey) 5 tableArray(x, 0) = yayoi.columns("id_Flag") 6 tableArray(x, 1) = yayoi.columns("slipNum") 7 tableArray(x, 2) = yayoi.columns("financStat") 8 tableArray(x, 3) = yayoi.columns("slipDay") 9 tableArray(x, 4) = yayoi.columns("debitName") 10 tableArray(x, 5) = yayoi.columns("debitSub") 11 tableArray(x, 6) = yayoi.columns("debitDep") 12 tableArray(x, 7) = yayoi.columns("debitTaxType") 13 tableArray(x, 8) = yayoi.columns("debitAmo") 14 tableArray(x, 9) = yayoi.columns("debitTax") 15 tableArray(x, 10) = yayoi.columns("creditName") 16 tableArray(x, 11) = yayoi.columns("creditSub") 17 tableArray(x, 12) = yayoi.columns("creditDep") 18 tableArray(x, 13) = yayoi.columns("creditTaxType") 19 tableArray(x, 14) = yayoi.columns("creditAmo") 20 tableArray(x, 15) = yayoi.columns("creditTax") 21 tableArray(x, 16) = yayoi.columns("summary") 22 tableArray(x, 17) = yayoi.columns("num") 23 tableArray(x, 18) = yayoi.columns("settlement") 24 tableArray(x, 19) = yayoi.columns("slipType") 25 tableArray(x, 20) = yayoi.columns("origin") 26 tableArray(x, 21) = yayoi.columns("memo") 27 tableArray(x, 22) = yayoi.columns("tag1") 28 tableArray(x, 23) = yayoi.columns("tag2") 29 tableArray(x, 24) = yayoi.columns("adjustment") 30 If isFirstLoop = False Then 31 allTable.ListRows.Add 32 End If 33 isFirstLoop = False 34 35 x = x + 1 36 Next 37Range(rangeStr) = tableArray

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

挙動が確認できないので当てずっぽうですが
cellにひとつひとつ値を与えるのではなく、配列にいれて一気に設定すると早いです

VBA

1Dim a(10, 10) 2For i = 0 To 9 3For j = 0 To 9 4a(i, j) = i + j * 10 5Next 6Next 7Range("a1:j10") = a

セル指定の汎用化

※上記が決め打ちすぎたので一応追記しておきます

VBA

1Dim a() 2 3Let x = 8 4Let y = 7 5Let offset_x = 2 6Let offset_y = 3 7 8ReDim a(x, y) 9 10For i = 0 To x - 1 11For j = 0 To y - 1 12a(i, j) = i + j * x 13Next 14Next 15Range(Cells(1 + offset_x, 1 + offset_y), Cells(x + offset_x, y + offset_y)) = a

投稿2024/11/21 10:00

編集2024/11/22 00:40
yambejp

総合スコア116466

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

user202102

2024/11/21 12:50

ありがとうございます。補足の修正後の該当ソースコードの通り、配列にいれて一気に設定することで30秒が6秒ほどになりました。 ただ配列の要素が800程度だと80秒くらいですが、VBAの速度的にはこんなものなのでしょうか。
yambejp

2024/11/22 00:22

あとは適当にブレークポイントをいれて時間計測して効率の悪い箇所を探してみてください。 場合によってはその箇所をピンポイントでリファクタリングできるかもしれません ScreenUpdatingなども設定されているようですし、小技でできることはこんなものかと。
user202102

2024/11/22 05:47

上記、お返事ありがとうございます。 「allTable.ListRows.Add」の部分をまとめて行追加することで更に短縮できました。 結果的に800行で4秒ほどになりました。先述していた80秒のうち70秒は省略していた処理が影響しておりました。 大変助かりました、ベストアンサーとさせていただきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問