web-dev-qa-db-ja.com

ピボットテーブルの各ループの最適化

VBAを最適化するのに苦労していますFor Each Excelテーブルに基づくピボットテーブルの10〜15k行をすべて同じブック内で解析する必要があるループ。現在、完了までに約2分かかりますが、会議で使用しているので改善したいと思います。

画面の更新、手動計算の無効化、他のデータ型としての変数の「dim」など、いくつかの興味深い提案を検索して見つけましたが、速度に違いはありません。私はFor Eachループは、この目的を目的としたものではありません。

this スーパーユーザーの投稿を読んでいると、関連する値を「辞書」に入れることができ、非常に高速になるようです。フィルタリングする項目が2つあるという事実は、私にとっては少し複雑になります。

私は「やって学ぶ」ので、VBAコーダーであるとは主張していません。ですから、どんな助けでも大歓迎です!

Dim pvtTable As PivotTable
Dim pvtField1, pvtField2 As PivotField
Dim pvtItem1, pvtItem2 As PivotItem

Set ws = ActiveSheet
Set pvtTable = ws.PivotTables("PTReport")
Set pvtField1 = pvtTable.PivotFields("callNummer")
Set pvtField2 = pvtTable.PivotFields("Destination")

Application.ScreenUpdating = False

For Each pvtItem1 In pvtField1.PivotItems
  If InStr(UCase(pvtItem1), "STORE") > 0 Then
    pvtItem1.Visible = True
  Else
    pvtItem1.Visible = False
  End If
Next

For Each pvtItem2 In pvtField2.PivotItems
  If InStr(UCase(pvtItem2), "221") > 0 Then
    pvtItem2.Visible = True
  Else
    pvtItem2.Visible = False
  End If
Next

Application.ScreenUpdating = True

何か明確にしたり、提供したりできる場合は、詳細をお知らせください。

1
SeattleITguy

InStr(UCase())への20-30Kの呼び出しが問題だと思います。いくつかのヘルパー列を定義することをお勧めします。たとえば、「callNummer」と「Destination」のデータが列ABにある場合は、

  • _Y1_→=IFERROR(SEARCH("store", A1), 0)
  • _Z1_→=IFERROR(SEARCH("221", B1), 0)

次に、VBAコードを変更して、_Yn_と_Zn_が_> 0_であるかどうかを確認します。このように、「callNummer」と「Destination」のデータが変更されるたびに文字列内の文字列チェックが実行され、VBAルーチンが実行する作業が大幅に少なくなります。そしてもちろん、すべてが機能するようになったら、ヘルパー列を非表示にすることができます。

_pvtItemN.Visible = …_ステートメントをこのフレームワークに変換する方法が正確にわかりません。

ただし、これを機能させることができない場合でも、InStr(UCase(pvtItem2), "221")テストをInStr(pvtItem2, "221")に変更できます。探しているのが数字だけの場合、セルのアルファベットの内容を大文字に変換する理由はありません。

1
Scott

最初のfor ... nextループの直前に、次のコードを追加します。

Dim saveCalc as xlCalculation

With Application
   .ScreenUpdating = False
   saveCalc = .Calculation
   .Calculation = xlCalculationManual
End With

次に、2番目のfor ... nextループの後に、次のコードを追加します。

With Application
    .ScreenUpdating = True
    .Calculation = saveCalc
End With
1
Rich Holton