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
的目标是,无论您的输入是什么,您总是知道输出是2DDouble
数组。这样,您就知道如何访问元素:如果您连续传递,则是B(1,i)
。我认为该规范太过分了。如果您的输入是文本字符串,该怎么办?使用“sanitise_sugg”,您至少满足了知道如何访问元素的规范,无论这些元素是行、列还是矩阵。谢谢Mats,您的回答真的帮助我找出了问题所在!查看我问题的底部,了解我的更新结果。这很酷,但不符合要求!试试看
{=to2D(to2D(A1:B1))}我正在使用VBA对金融数据进行数据分析,所以它都是双精度的和数组