使用变量数组

时间:2017-01-08 04:43:51

标签: arrays excel-vba charts excel-2010 vba

我正在Excel中创建图表仪表板。最终用户无需显示数据,因此我尝试使用数组来设置SeriesCollection.Values。这是有问题的代码块:

'test sub to declare and pass header_arr and series_arr
Sub test()

Dim arr1(), arr2() As Variant
With ThisWorkbook.ActiveSheet
    arr1 = .Range(.Range("I2"), .Range("AI2")).Value
    arr2 = .Range(.Range("I25"), .Range("AI28")).Value
End With

Call CreateWaterfall(arr1, arr2, , , , Range("I30"))

Erase arr1, arr2

End Sub

'sub to create chart
Sub CreateWaterfall(header_arr As Variant, series_arr As Variant, Optional colors As Boolean = True, Optional target_wb = Nothing, Optional target_ws = Nothing, Optional target As Range = Nothing)

'whole bunch of parameter checks that work fine

'trim header_arr
Dim temp() As Variant
ReDim temp(LBound(header_arr, 1) To LBound(header_arr, 1), LBound(header_arr, 2) To UBound(header_arr, 2))
For i = LBound(header_arr, 2) To UBound(header_arr, 2)
    temp(LBound(header_arr, 1), i) = header_arr(1, i)
Next i
ReDim header_arr(LBound(temp, 1) To LBound(temp, 1), LBound(temp, 2) To UBound(temp, 2))
For i = LBound(temp, 2) To UBound(temp, 2)
    header_arr(LBound(temp, 1), i) = temp(LBound(temp, 1), i)
Next i

'declare chart object, start with block...
    '...stuff that works...
For i = 1 To 4
    With .SeriesCollection(i)
        If LBound(series_arr, 1) = 0 Then i = i - 1 'handle base 0 case-operation is reversed at end of loop to avoid incorrect steps
        ReDim temp(LBound(series_arr, 1) To LBound(series_arr, 1), LBound(series_arr, 2) To UBound(series_arr, 2))
        For j = LBound(series_arr, 2) To UBound(series_arr, 2)
            temp(LBound(series_arr, 1), j) = series_arr(i, j)
        Next j
        .Values = temp '<--problem with this line
        .XValues = header_arr
    End With
    If LBound(series_arr, 1) = 0 Then i = i + 1
Next i
'...other stuff that works...
'end with block

End Sub

这是在With块内创建图表并设置其属性。 sub的所有其余部分都正常工作,甚至是设置.XValues的行,但.Values都不正确。当我在电子表格上检查它们时,它们是一系列的0和#N / As。检查显示这不是因为数组填充形式的范围中的空单元格。对于我在调试阶段,使用电子表格范围填充series_arrheader_arr;最终草案中不会出现这种情况。以下是我希望子处理的数据的一个小例子(对不起;我不知道如何让它比这更漂亮......):

215.56空空432.73
空43.184空56.442空 空136.65 186.8 345.67空
空空87.653空空

所有数组都包含通过单步执行确定的正确数据。

我已经查看了here并且卡住了;据我所知,.Values行完全类似。除了使用电子表格范围设置.Values之外,我还使用了与其他图表完全类似的代码,因此我知道问题不存在。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

我能够自己解决这个问题:它是变体数组与变体数组问题。我添加了一些代码来强制数据在temp中用于将SeriesCollection.Values设置为double类型。我最初发布的片段中的最后一个块现在是:

Dim dbl As Double '<--var to hold contents of series_arr in loop
Dim j As Integer
For i = 1 To 4
    With .SeriesCollection(i)
        If LBound(series_arr, 1) = 0 Then i = i - 1 'handle base 0 case-operation is reversed at end of loop to avoid incorrect steps
        ReDim temp(LBound(series_arr, 2) To UBound(series_arr, 2))
        For j = LBound(series_arr, 2) To UBound(series_arr, 2)
            If series_arr(i, j) = "" Then '<--convert series_arr recs
                temp(j) = 0
            Else
                dbl = series_arr(i, j)
                temp(j) = dbl
            End If
        Next j
        .Values = temp
        .XValues = header_arr
    End With
    If LBound(series_arr, 1) = 0 Then i = i + 1
Next i

它有效!这是我(相对)受过教育的猜测,为什么;不过,我会很感激能够提供更好答案的人。

类型Variant的变量原则上可以隐式转换为类型Double,但它们也可以隐式转换为类型String(以及其他类型)。这意味着Empty记录含糊不清;当Excel必须决定将其转换为“”或0时,它需要一些其他标准才能重新开始。

我认为temp在用于设置.Values时包含一些数字这一事实会导致Excel将Empty记录转换为0,但我想这不是'这种情况。我的结论是Excel只会将Variant类型的数组元素转换为正确的类型,如果它们的所有可以转换为另一种类型。因此,即使我通过删除header_arr中的一个元素来测试此假设,String也正确地转换为header_arr类型。另一方面,series_arr因为它包含只能转换为Double类型的元素,但也包含可转换为多种数字类型的元素,但未正确转换。

Source