2016-09-19 44 views
0

私はスピードの問題があります。 (長いポストの謝罪...)。私はWindows用のExcel 2013と2016を使用しています。SUMPRODUCTとCOUNTIFSを使用したExcel VBA - 速度の問題

私は200,000のセルテーブル(1000行×200列)で10,000+計算を実行するブックを持っています。

各計算は整数(フィルタリングされた行の数など)または通常は割合(たとえば、フィルタされた行の値の合計を行の値の合計で割ったもの)を返します。上記で説明する

=IF($B6=0, 
    0, 
    SUMPRODUCT(COUNTIFS(
    Data[CompanyName], 
    CompanyName, 
    Data[CurrentYear], 
    TeamYear, 
    INDIRECT(VLOOKUP(TeamYear&"R2",RealProgress,2,FALSE)), 
    "<>"&"", 
    Data[High Stage], 
    NonDom[NonDom] 
    )) 
    /$B6 
) 

  1. 対データ[会社名]と得意テーブルの列れる計算の構造は、線に沿って、SUMPRODUCT(COUNTIFS())思想の変形であります最初のフィルタの条件値。
  2. データ[現在の年]とTeamYearのペアは上記と同じで、2番目のフィルタを構成します。
  3. 第3対が仲介テーブルを検索し、列の名前を返しますが、条件("<>"&"")「は空白ではない」で、つまりは
  4. 最後に、この列の値を持つすべての行を返し、第四対です上記の3に似ていますが、値のセットに一致する値のセットを返します
  5. 最後に、4つのフィルターはANDステートメントで結合されています。 すべての計算において、同じ原理がSUMPRODUCT(COUNTIFS())を使用して適用されますが、このテーマには多くのバリエーションがあります。 現在、ワークブック全体の計算速度が遅くなるのではなく、選択範囲のシートでCalculateを使用すると、約30〜40秒の計算速度が得られます。いつも計算が実行されないので、悪くなくても大丈夫です。

残念ながら、モデルは拡張され、現在は1,000行ではなく20,000行に近づくことができます。計算のパフォーマンスは行数やセル数に直接関係しているため、パフォーマンスが急激に低下することが予想されます。

明白な解決法[1]は、配列を使用して、メモリ内に保持されている配列をセルの式に渡し、フィルタとその条件(配列も参照する)とともに処理することが理想です。

代替ソリューション[2]は、配列を使用してUDFを記述することですが、UDFがネイティブのExcel関数よりもはるかに遅いという意見をインターネットで読んでいます。

つの質問:

  1. [1]の可能なソリューションであり、そしてこれを行うための最善の方法、およびその場合はどのように私はそれを構築するのでしょうか?
  2. ソリューション[1]が可能でないか、最善の方法でない場合、誰かが私の現在のソリューションと比較できる迅速なソリューション[2]にどのような考えを持っていますか?
  3. 他にも優れたソリューションはありますか?私はPower BI Desktop、PowerPivot、PowerQueryについて知っていますが、これはExcel以外のユーザーが使用する商用アプリケーションで、現在のExcelのグリッド形式の行と列で表示する必要があります。

お読みいただきありがとうございます!

補足:Worksheet.Activateイベントで各シートの配列計算を実行し、時間の節約があるかどうかを確認します。

+1

IMOこの質問はに良い答えを提供することは不可能です。 *役立つかもしれないものがあまりにも多くありますが、もっと多くの情報がなく、ワークブックのコピーが望ましいとは言えません。たとえば、ピボットテーブルは良い解決策かもしれません。 VLOOKUPをバイナリ検索バージョンまたはINDEXとMATCHに置き換えると役立ちます。いくつかの処理を短絡することができる場合、UDFは場合によっては数式より速くなることがあります。ソースデータ内の最後の条件をTRUE/FALSE式に変換すると役立ちます。私が言ったように、あまりにも多くのオプション。 ;) – Rory

+0

ありがとうロリー。 VLOOKUPではなくINDEX MATCHを試しましたが、速度が遅かったです。私は「2 VLOOKUP」のソリューションも試しましたが、それもうまくいかなかったのです。 出力の上に密接なコントロールと適切な書式設定が必要なため、ピボットは答えではありません。 TRUE/FALSEのアイデアについて考えてみましょう...興味深いですね! 他の人のために、私は一般的なポインタとアドバイスを探しています。具体的な解決策が私には分かります! – WithnailsHoliday

+0

私が言ったように、あまりにも多くの可能性があります...パフォーマンスの問題の絶対的な治療法はほとんどありません。 FastExcelに投資して、ボトルネックがどこにあるかを正確に判断できます。 (当事者は明らかに問題を助けることはありません) – Rory

答えて

0

データを配列に書き込むことは、高速化を目指す場合には、通常は良いアイデアです。このように完了:

Dim myTable As ListObject 
Dim myArray As Variant 

'Set path for Table variable 
    Set myTable = ActiveSheet.ListObjects("Table1") 

'Create Array List from Table 
    myArray = myTable.DataBodyRange 

Source

関連する問題