2

Excel ワークシートから、VBScript をスクリプト言語として使用するアプリケーション (Quick Test Professional) で使用される配列にデータを抽出する必要があります。そのために次のコードを使用できます。

' ws must be an object of type Worksheet
Public Function GetArrayFromWorksheet(byref ws)
    GetArrayFromWorksheet = ws.UsedRange.Value
End Function

myArray = GetArrayFromWorksheet(myWorksheet)
MsgBox "The value of cell C2 = " & myArray(2, 3)

すべて問題ありませんが、返される配列には、リテラル テキスト文字列だけでなく、date、integer、double などの型のプリミティブも含まれています。そのデータが変換されることは何度もありました。

[編集]例:セルに入力=NOW()し、セルの書式設定を17:45 に設定するhh:mmと、表示される値が17:45になり、上記のメソッドは型の変数と 41194.7400990741 のようdoubleな値を返します

次の解決策はうまく機能しました。.Textプロパティを使用してセルからリテラル テキストを取得できますが、それらは 1 つのセルでのみ機能し、セルの範囲では機能しません。プロパティの場合とは異なり、配列に対して一度にこれを行うことはできないため、一度に.Value1 つのセルを配列に入力する必要があります。

Public Function GetArrayFromWorksheet_2(byref ws)
    Dim range, myArr(), row, col
    Set range = ws.UsedRange

    ' build a new array with the row / column count as upperbound
    ReDim myArr(range.rows.count, range.columns.count)

    For row = 1 to range.rows.count
        For col = 1 to range.columns.count
            myArr(row, col) = range.cells(row, col).text
        Next
    Next

    GetArrayFromWorksheet_2 = myArr
End Function

しかし、ああ...ネストされたfor loop. はい、大きなワークシートでは、顕著なパフォーマンスの低下が見られます。
誰かがこれを行うためのより良い方法を知っていますか?

4

3 に答える 3

2

コメントで説明したように、問題を回避するには、ある時点で配列をループする必要があります。ただし、ワークシートのデータの種類によっては、速度が大幅に向上する可能性があるため、これを投稿しています。200 個のセルの半分が数値であるため、これは約 38% 高速でした。同じ比率の 600 個のセルでは、改善は 41% でした。

配列自体をループし、.Text倍精度 (数値) として解釈される for 値のみを取得することで、倍精度でないデータが大量にある場合に速度の向上を確認できます。.Textこれは、テキストを含むセル、日付として書式設定された日付、または空白のセルをチェックしません。

Public Function GetArrayFromWorksheet_3(ByRef ws)

    Dim range, myArr, row, col
    Set range = ws.UsedRange

    'Copy the values of the range to temporary array
    myArr = range
    'Confirm that an array was returned.
    'Value will not be an array if the used range is only 1 cells
    If IsArray(myArr) Then
        For row = 1 To range.Rows.Count
            For col = 1 To range.Columns.Count
                'Make sure array value is not empty and is numeric
                If Not IsEmpty(myArr(row, col)) And _
                            IsNumeric(myArr(row, col)) Then
                    'Replace numeric value with a string of the text.
                    myArr(row, col) = range.Cells(row, col).Text
                End If
            Next
        Next
    Else
        'Change myArr into an array so you still return an array.
        Dim tempArr(1 To 1, 1 To 1)
        tempArr(1, 1) = myArr
        myArr = tempArr
    End If

    GetArrayFromWorksheet_3 = myArr
End Function
于 2012-10-12T16:15:59.447 に答える
0
  • ワークシートを新しいワークシートにコピーします。
  • 数式を削除するには、値をコピーして貼り付けます
  • 各列の列にテキストを実行し、各列をテキストに変換します
  • 最初に行っていたように配列をロードします
  • 新しいワークシートを削除する
于 2012-10-12T16:25:08.907 に答える
0

ワークシートをループせずにこれをすばやく簡単に行うことはできません。上記の手法を 2 行のコードで使用する場合は、バリアント型配列である必要があります。

A) ワークシート オブジェクトを操作し、B) 元の最後の行で変数を手元に置いておきたいので、6 行で実行するコードの実際の例を含めました。

Dim wsKeyword As Worksheet
Set wsKeyword = Sheets("Keywords")

Dim iLastKeywordRow As Long
iLastKeywordRow = wsKeyword.Range("A" & wsKeyword.Rows.Count).End(xlUp).Row

Dim strKeywordsArray As Variant
strKeywordsArray = wsKeyword.Range("A1:N" & iLastKeywordRow).Value

この方法で使用するには、配列がバリアントでなければならないことに注意してください。

バリアントがこのように機能する理由は、バリアントの配列を作成すると、配列内の各「セル」がバリアント型に設定されるためです。次に、各セルは、それに割り当てられた値の種類に設定されたバリアント型を取得します。したがって、文字列が割り当てられているバリアントは variant.string に設定され、文字列としてのみ使用できるようになります。元の例では、variant.string ではなく variant.time として保存された時間値があったようです。

元の問題にアプローチする方法は 2 つあります。完全な制御を可能にする別の回答で説明されています2)配列内のすべてのデータをそのまま保存し、それを2番目の配列に再フォーマットするか、使用するときに必要なテキストとしてフォーマットします(どちらも高速にする必要があります)

于 2012-10-12T20:53:14.167 に答える