Как передать массив из C # (VSTO) в VBA Macro - PullRequest
2 голосов
/ 07 октября 2009

У меня проблемы с производительностью моего решения VSTO, я думаю, что причина в основном в том, как cellColor устанавливается ячейка за ячейкой.

Это зависит от данных из набора записей и поэтому каждый раз отличается. (Я не могу использовать copyFormats из другой строки / столбца)

это похоже на заполнение диапазона значений, только для этого есть несколько методов.

Сначала я подумал о создании всего этого в C # в памяти (массив XlColorIndex [,]), через который я передаю метод VBA, аналогичный приведенному ниже:

Sub fillInterior(ByRef rg As Range, a As Variant)
    //a is a double array that represents the colors for the spreadsheet
    Dim r As Long, c As Long
    Dim tmpRg As Range
    r = 1
    c = 1
    For Each Row In a
        For Each colorIdx In Row
            Set tmpRg = rg(r, c)
            With tmpRg.Interior
                .ColorIndex = colorIdx
                .PatternColorIndex = xlAutomatic
                .PatternColor = xlSolid
            End With
            c = c + 1
        Next
        c = 1
        r = r + 1
    Next
End Sub

Я пытался назвать этот макрос следующим образом, но пока не увенчался успехом, любые указатели очень ценятся:

            Excel.Range rg = this.Range[this.Cells[5, 3], this.Cells[6, 4]];

            object[,] test2 = new object[2, 2];
            test2[0, 0] = 15;
            test2[0, 1] = 15;
            test2[1, 0] = 15;
            test2[1, 1] = 15;

            this.Application.Run("Sheet1.fillInterior",  rg,  test2,
                System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing,
                System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing,
                System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing,
                System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing);

Я пробовал int [,] -

Я получил другую ошибку, когда попробовал Nullable int или Double: double? [,] (Array of Nullable Double):

The parameter is incorrect. (Exception from HRESULT: 0x80070057 (E_INVALIDARG))

Если я не пробую обнуляемые типы, я получаю следующую ошибку HRESULT (Несоответствие типов?)

Exception from HRESULT: 0x800A000D

Ответы [ 2 ]

2 голосов
/ 08 октября 2009

Хорошо, я должен был прочитать это лучше: следует избегать вариантов, поэтому, если у меня есть выбор написания моего VBA, я лучше сделаю это без варианта, но с правильным массивом.

Во-вторых, я неправильно использовал массивы VBA, я должен сделать следующее для многомерных массивов ( source ):

Мой код VBA теперь выглядит следующим образом:

Sub fillInteriorMulti(rg As Range, Arr() As Long)
    Dim N As Long, Ndx1 As Long, Ndx2 As Long
    Dim icol As Long
    Dim irow As Long
    Dim NumDims As Long


    // Custom Function: Get the number of array dimensions.
    // NumberOfArrayDimensions will return 0
    // if the array is not allocated.

    NumDims = NumberOfArrayDimensions(Arr:=Arr)
    Select Case NumDims
        Case 0
            // unallocated array
            Exit Sub
        Case 1
            // single dimensional array
            For N = LBound(Arr) To UBound(Arr)
                With rg(N, 1).Interior
                    .ColorIndex = Arr(N)
                    .PatternColorIndex = xlAutomatic
                    .PatternColor = xlSolid
                End With
            Next N
        Case 2
            // 2 dimensional array
            For Ndx1 = LBound(Arr, 1) To UBound(Arr, 1)
                For Ndx2 = LBound(Arr, 2) To UBound(Arr, 2)
                    With rg(Ndx1, Ndx2).Interior
                        .ColorIndex = Arr(Ndx1, Ndx2)
                        .PatternColorIndex = xlAutomatic
                        .PatternColor = xlSolid
                    End With
                Next Ndx2
            Next Ndx1
        Case Else
            // Too many dimensions - Do Nothing
    End Select
End Sub

Public Function NumberOfArrayDimensions(Arr As Variant) As Integer
    // NumberOfArrayDimensions
    // This function returns the number of dimensions of an array. An unallocated dynamic array
    // has 0 dimensions. This condition can also be tested with IsArrayEmpty.

    Dim Ndx As Integer
    Dim Res As Integer
    On Error Resume Next
    // Loop, increasing the dimension index Ndx, until an error occurs.
    // An error will occur when Ndx exceeds the number of dimension
    // in the array. Return Ndx - 1.
    Do
        Ndx = Ndx + 1
        Res = UBound(Arr, Ndx)
    Loop Until Err.Number <> 0

    NumberOfArrayDimensions = Ndx - 1
End Function

Наконец, код C # для проверки:

            int[] test3 = new int[3];
            test3[0] = 15;
            test3[1] = 15;
            test3[2] = 48;

            int[,] test4 = new int[2, 2];
            test4[0, 0] = 15;
            test4[0, 1] = 15;
            test4[1, 0] = 15;
            test4[1, 1] = 15;

            this.Application.Run("Sheet1.fillInteriorMulti", rg, test4,
                missing, missing, missing, missing, missing, missing, missing, missing, missing, missing,
                missing, missing, missing, missing, missing, missing, missing, missing, missing, missing,
                missing, missing, missing, missing, missing, missing, missing, missing);
0 голосов
/ 08 октября 2009

Гадкий взлом или подтверждение концепции, преобразование двойного массива в строку. Pass на String.

Sub fillInteriorString(rg As Range, str As String)
    Dim i As Long, j As Long
    i = 1
    j = 1
    a = Split(str, "@")
    For Each part In a
        b = Split(part, ",")
        For Each colorIdx In b
            With rg(i, j).Interior
                .ColorIndex = colorIdx
                .PatternColorIndex = xlAutomatic
                .PatternColor = xlSolid
            End With
            j = j + 1
        Next
        j = 1
        i = i + 1
    Next
End Sub

C # код:

            string testString = "15,15,48@48,48,15";


            this.Application.Run("Sheet1.fillInteriorString",  rg,  testString,
                System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing,
                System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing,
                System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing,
                System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing);

В любом случае, я знаю, что это работает - теперь я смотрю на SafeArrays в надежде, что смогу передать массив вместо строки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...