Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 阻止将1×n数组转换为一维数组_Arrays_Vba_Excel - Fatal编程技术网

Arrays 阻止将1×n数组转换为一维数组

Arrays 阻止将1×n数组转换为一维数组,arrays,vba,excel,Arrays,Vba,Excel,下面是我为统一处理数组和范围而编写的一些代码()。它包含一个名为sanitise的函数,该函数意味着您可以调用某个二维数字集合a,并将相同的数字作为二维双精度数组返回 Public Function item(ByRef A As Variant, i As Integer, j As Integer) As Double If TypeName(A) = "Range" Then item = A.Cells(i, j) Else item =

下面是我为统一处理数组和范围而编写的一些代码()。它包含一个名为
sanitise
的函数,该函数意味着您可以调用某个二维数字集合
a
,并将相同的数字作为二维双精度数组返回

Public Function item(ByRef A As Variant, i As Integer, j As Integer) As Double
    If TypeName(A) = "Range" Then
        item = A.Cells(i, j)
    Else
        item = A(i, j)
    End If
End Function

Public Function rows(ByRef A As Variant) As Integer
    If TypeName(A) = "Range" Then
        rows = A.rows.Count
    Else
        rows = UBound(A, 1) - LBound(A, 1) + 1
    End If
End Function

Public Function cols(ByRef A As Variant) As Integer
    If TypeName(A) = "Range" Then
        cols = A.columns.Count
    Else
        cols = UBound(A, 2) - LBound(A, 2) + 1
    End If
End Function

Public Function sanitise(ByRef A As Variant) As Double()

    Debug.Print TypeName(A)

    If TypeName(A) = "Double()" Then
        sanitise = A
    Else
        Debug.Print rows(A)

        Dim B() As Double
        ReDim B(1 To rows(A), 1 To cols(A))

        Dim i As Integer, j As Integer
        For i = 1 To rows(A)
            For j = 1 To cols(A)
                B(i, j) = item(A, i, j)
            Next j
        Next i

        sanitise = B
    End If
End Function
该实现的工作原理与您预期的完全相同:在工作表中选择一个范围,比如说
A1:B2
,在其上调用sanitize,您将拥有相同内容的两个副本:

然而,问题在于
消毒
^2

调用
sanitise
两次会发生故障,但仅当您在单行调用它时才会发生故障。多行:精细,单列:精细

我知道为什么会发生这种情况:在第一次清理后,Excel会忘记返回的是什么形状数组。(它还忘记了类型:第二个
sanitise
的输入不是
Double()
,而是
Variant()

有人知道如何解决这个问题吗

虽然我不太可能连续两次使用
sanitise
,但上面的示例说明了为什么很难沿二维数组组合两个函数

注意:此问题仅在从工作表中调用
sanitise
时发生

更新,我已经解决了它:对于与行同义的工作表1D存储,需要考虑到这一点

我的最终版本:

Public Function get_2D(ByRef A As Variant) As Double()
    'turns various forms of input into a 2D array of Doubles
    Dim result() As Double
    Dim i As Integer
    If TypeOf A Is Range Or dims(A) = 2 Then
        ReDim result(1 To rows(A), 1 To cols(A))
        Dim j As Integer
        For i = 1 To rows(A)
            For j = 1 To cols(A)
                result(i, j) = item(A, i, j)
            Next j
        Next i
    Else
        '1D storage is treated as a row
        ReDim result(1 To 1, 1 To rows(A)) 'rows(A) gets length of the first axis
        For i = 1 To rows(A)
            result(1, i) = A(i)
        Next i
    End If

    sanitise = result
End Function

dims
是一个返回数组维数的函数:

我认为这在某种程度上符合您的规范,它有助于解决您演示的单行问题。这对你有用吗

Function sanitise_sugg(inp As Variant) As Variant
Dim result As Variant
If TypeOf inp Is Object  Then
result = inp.Value
Else
result = inp
End If
sanitise_sugg = result
End Function
编辑:退一步,我认为您应该将手头的任务分为两部分:首先使用“sanitise_sugg”交替使用excel范围和excel vba数组。然后,如果您因特殊需要而要求输入指定为某种类型的双精度数组,请编写一个单独的函数来测试并在可能的情况下将变量输入强制转换为这种类型

编辑2:向前一步,让我声明,如果作为变量馈送到
函数sanitise_sugg(inp作为变量)的元素包含vba中的双精度,或者包含excel工作表中数值的单元格,则它满足作为双精度(
公共函数sanitise(ByRef A作为变量)的要求)

编辑3:要查看函数如何独立于行向量、列向量或完整矩阵跟踪其输入数组布局,独立于从excel范围或VBA中通过数组,请参阅下面的工作表


除非你对二维双精度阵列进行大量计算,否则我想不出这有什么实际用途,因此如果你提供更多关于你到底想做什么的信息,我们可能会推荐一些更简单/更好/更有效的方法

.Value
.Value2
当范围内有多个单元格时,返回二维变量数组:

v = [a1:b1].Value2  ' Variant/Variant(1 to 1, 1 to 2)
v = [a1:a2].Value2  ' Variant/Variant(1 to 2, 1 to 1)
v = [a1].Value2     ' Variant/Double
因此,天真的方法可以是:

Function to2D(v) As Double()
    'Debug.Print TypeName(v), VarType(v)
    Dim d2() As Double, r As Long, c As Long
    If IsArray(v) Then
        If TypeOf v Is Range Then v = v.Value2
        ReDim d2(1 To UBound(v, 1), 1 To UBound(v, 2))
        For r = 1 To UBound(v, 1)
            For c = 1 To UBound(v, 2)
                If IsNumeric(v(r, c)) Then d2(r, c) = v(r, c)
            Next c
        Next r
    Else
        ReDim d2(1 To 1, 1 To 1)
        If IsNumeric(v) Then d2(1, 1) = v
    End If
    to2D = d2
End Function
并通过以下方式进行测试:

d2 = to2D([a1:b2])
d2 = to2D([a1:b1])
d2 = to2D([a1:a2])
d2 = to2D([a1])
d2 = to2D(1)
d2 = to2D([{" 1 ";" 2.0 "}]) ' works with strings too
d2 = to2D([{1,2;3,4}]) 
'd2 = to2D([{1,2}]) ' doesn't work with 1D arrays

如果在
Debug.Print行(a)
之后包含
Debug.Print cols(a)
,则在执行外部
sanitise
时,它将不会打印任何内容,即调用
cols(a)
时崩溃。这是因为内部
sanitise
返回了一个(1到1,1到2)形状的数组,在传递到外部
sanitise
之前,该数组已被转换为(1到2)形状的数组(不知道为什么-Excel有时会很奇怪),而您的代码不处理一维数组,只是一个范围或二维数组。我无法复制你的错误。你能提供一个下载链接吗?很酷!
sanitise
的目标是,无论您的输入是什么,您总是知道输出是2D
Double
数组。这样,您就知道如何访问元素:如果您连续传递,则是
B(1,i)
。我认为该规范太过分了。如果您的输入是文本字符串,该怎么办?使用“sanitise_sugg”,您至少满足了知道如何访问元素的规范,无论这些元素是行、列还是矩阵。谢谢Mats,您的回答真的帮助我找出了问题所在!查看我问题的底部,了解我的更新结果。这很酷,但不符合要求!试试看
{=to2D(to2D(A1:B1))}我正在使用VBA对金融数据进行数据分析,所以它都是双精度的和数组