web-dev-qa-db-ja.com

Excel VBA:配列変数のバリアント

バリアントに関する質問。 Excel vbaのバリアントは、デフォルトのデータ型であり、非効率的でもあることに注意してください(大規模アプリでの過剰使用の観点から)。ただし、複数のデータ型を持つ配列にデータを格納するために定期的に使用しています。私が取り組んでいる現在のプロジェクトは、基本的に非常に貧弱なコード(c.7000行)の大規模な最適化を必要とするタスクです。これを回避する方法はありますか?

説明する;コードは頻繁に配列変数にデータを保存します。したがって、10000 x 10列のデータセットを検討してください。列は複数の異なるデータ型(文字列、倍精度、整数、日付など)です。これらを配列に保存したい場合、通常はそうします。

dim myDataSet(10,10000) as variant

しかし、私の知識では、コードが各項目を評価してそれがどのデータ型であるかを判断するコードでは実際には非効率的であると言われています(実際には、Imが何を期待しているのかわかります)。さらに、個々のデータ型をディメンション化すると制御が失われます。だから、(最初の6つは文字列で、次の4つはポイントの説明を簡単にするために2倍になると仮定して)、私はできる。

dim myDSstrings(6,10000) as string
dim myDSdoubles(4,10000) as double

これにより、制御と効率が得られますが、少し不格好です(実際には型が混在しており、各要素に奇数個の要素があり、コード内で個別に割り当てる必要があります) -質量ではなく)。だから、その場合;

myDSstrings(1,r) = cells(r,1)
myDSdoubles(2,r) = cells(r,2)
myDSstrings(2,r) = cells(r,3)
myDSstrings(3,r) = cells(r,4)
myDSdoubles(3,r) = cells(r,5)
..etc...

これは、はるかにいです。

myDataSet(c,r) = cells(r,c)

だから-それは私に考えさせられた-私はここで何かを見逃しているに違いない。さまざまなデータ型の配列を保存する最適な方法は何ですか?または、それを行う方法がないと仮定すると、混合データタイプの配列を格納するための最良のコーディングプラクティスは何ですか?

14
Surferosa

最初に測定せずにコードを最適化しないでください。コードが最も遅いところで驚くかもしれません。 Professional Excel DevelopmentのPerfMonユーティリティを使用していますが、独自のロールを作成することもできます。

Excel Rangesへの読み書きは大きな時間の無駄です。バリアントは多くのメモリを浪費しますが、これは

Dim vaRange as Variant
vaRange = Sheet1.Range("A1:E10000").Value
'do something to the array
Sheet1.Range("A1:E10000").Value = vaRange

一般に、行とセルをループするよりも高速です。

複数のデータ型を持つ配列を使用するための私の好ましい方法は、配列をまったく使用しないことです。むしろ、カスタムクラスモジュールを使用して、要素のプロパティを作成します。これは必ずしもパフォーマンスの向上ではありませんが、コードの書き込みと読み取りがはるかに簡単になります。

11
Dick Kusleika

ボトルネックが配列のVariantタイピングに起因するかどうかはわかりません。

ところで、配列の値をExcelの範囲に設定するには、(Excel 8以降)を使用する必要があります:

Range("A1:B2") = myArray

以前のバージョンでは、次のコードを使用する必要があります。

Sub SuperBlastArrayToSheet(TheArray As Variant, TheRange As Range)
  With TheRange.Parent.Parent 'the workbook the range is in
    .Names.Add Name:="wstempdata", RefersToR1C1:=TheArray
    With TheRange
      .FormulaArray = "=wstempdata"
      .Copy
      .PasteSpecial Paste:=xlValues
    End With
    .Names("wstempdata").Delete
  End With
End Sub

from このソース VBA最適化のために読む必要があります。

ただし、アプリのプロファイルを作成して、ボトルネックがどこにあるかを確認する必要があります。 Issunのこの質問 を参照して、コードのベンチマークを行ってください。

4
JMax