excel - 如何将 Variant 数组转换为 Range?

标签 excel vba excel-2007

我有一个 Variant 类型的二维数组。填充数组的大小和值是根据工作表中的数据生成的。该数组需要进一步处理,主要是几个值的插值。我正在使用这个interpolation function (我知道 Excel 等效函数,但设计时选择不使用它们)。我遇到的问题是 Interpolation 函数需要 Range 对象。

我已经尝试修改函数以使用 Variant (r as Variant) 参数。以下行 nR = r.Rows.Count 可以替换为 nR = Ubound(r)。虽然这有效,但我也想在任何工作表中正常使用此函数,并且不以任何方式更改该函数。

Sub DTOP()
    Dim term_ref() As Variant
    ' snip '
    ReDim term_ref(1 To zeroRange.count, 1 To 2)

    ' values added to term_ref '

    ' need to interpolate x1 for calculated y1 '
    x1 = Common.Linterp(term_ref, y1) 
End Sub

插值函数

Function Linterp(r As Range, x As Double) As Double
    Dim lR As Long, l1 As Long, l2 As Long
    Dim nR As Long

    nR = r.Rows.Count
    ' snipped for brevity ' 
End Function

如何将内存中的变体数组转换为 Range,以便将其用于插值函数? (不输出到工作表)

回答

简而言之,答案是你不能。 Range 对象必须引用工作表。

更改后的插值函数会检查参数的 TypeName 并相应地设置 nR 的值。不是最漂亮的解决方案。

请注意,VarType 函数在这种情况下被证明毫无用处,因为 VarType(Variant())VarType(Range) 都返回相同的值(即 vbArray)并且无法用于消除数组与范围的歧义

Function Linterp(r As Variant, x As Variant) As Double
    Dim lR As Long, l1 As Long, l2 As Long
    Dim nR As Long

    Dim inputType As String
    inputType = TypeName(r)

    ' Update based on comment from jtolle      
    If TypeOf r Is Range Then
        nR = r.Rows.Count
    Else
        nR = UBound(r) - LBound(r) 'r.Rows.Count
    End If
    ' ....
 End Function 

最佳答案

据我所知,您无法创建不以某种方式引用工作簿的工作表位置的 Range 对象。它可以是动态的,例如 Named =OFFSET() 函数,但它必须绑定(bind)到某个工作表。

为什么不改变插值函数呢?保持 Linterp 签名不变,但将其放入在数组上插值的函数的包装器中。

类似这样的事情:

Function Linterp(rng As Range, x As Double) As Double
' R is a two-column range containing known x, known y
' This is now just a wrapper function, extracting the range values into a variant
    Linterp = ArrayInterp(rng.Value, x)

End Function

Function ArrayInterp(r As Variant, x As Double) As Double

Dim lR As Long
Dim l1 As Long, l2 As Long
Dim nR As Long

    nR = UBound(r) ' assumes arrays are all 1-based

    If nR = 1 Then
        ' code as given would return 0, better would be to either return
        ' the only y-value we have (assuming it applies for all x values)
        ' or perhaps to raise an error.
        ArrayInterp = r(1, 2)
        Exit Function
    End If

    If x < r(1, 1) Then ' x < xmin, extrapolate'
        l1 = 1
        l2 = 2
    ElseIf x > r(nR, 2) Then ' x > xmax, extrapolate'
        l2 = nR
        l1 = l2 - 1
    Else
        ' a binary search might be better here if the arrays are large'
        For lR = 1 To nR
            If r(lR, 1) = x Then ' no need to interpolate if x is a point in the array'
                ArrayInterp = r(lR, 2)
                Exit Function
            ElseIf r(lR, 2) > x Then ' x is between tabulated values, interpolate'
                l2 = lR
                l1 = lR - 1
                Exit For
            End If
        Next
    End If

    ArrayInterp = r(l1, 2) _
           + (r(l2, 2) - r(l1, 2)) _
           * (x - r(l1, 1)) _
           / (r(l2, 1) - r(l1, 1))

End Function

关于excel - 如何将 Variant 数组转换为 Range?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3235107/

相关文章:

java - 使用Java将10000行word文档转换为excel表格耗尽堆空间

Excel公式生成3位数系列

database - 关闭 Access 数据库而无需打开应用程序外壳的 VBA 代码

excel - 计算满足特定条件的 Excel 电子表格中的唯一行

excel - 在 excel 2010 图表的动态命名范围中使用 OFFSET 会导致崩溃

pagination - 如何在多个页面中将Excel表另存为Word文档

Excel 2013 模态 VBA 用户窗体在用户窗体可见时更改 Activeworkbook

string - 在 Excel If 语句中返回数字和文本字符串

vba - 使用 VBA 条件格式化数据透视表

vba - Excel R1C1 引用的类型是什么?