停止n数组1转换为1维

下面是我写的一些代码来统一处理数组和范围( 接受范围作为数组参数 )。 它包含一个名为sanitise的函数,这个函数的function是可以调用一些二维数字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 

这个实现和你所期望的完全一样:在工作表中select一个范围,比如说A1:B2 ,对它进行清理,并且你将得到两个同样的东西:

在这里输入图像说明

然而,哪里出了问题, sanitise ^ 2。

调用sanitise两次打破,但只有当你打电话给单行 。 多行:罚款,单列:罚款。

在这里输入图像说明

我知道为什么会发生:在第一次sanitise ,Excel会忘记返回的形状数组。 (它也忘记了types:而不是Double()第二个sanitiseVariant()

有谁知道如何解决这个问题?

虽然我不希望连续使用两次,但上面的例子说明了为什么很难在2维数组中组合两个函数。

注意:这只是从工作表中调用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是一个返回数组维数的函数: https : //support.microsoft.com/en-us/kb/152288

我认为这与您的规范有些相符,它有解决您演示的单行问题的好处。 它会为你的目的吗?

 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数组。 那么如果你对一个特殊的需求要求input特定地是某种双精度数组,可以编写一个单独的函数来testing,如果可能的话,将这个types的variablesinput。

编辑2:向前迈进一步,让我声称,在这种情况下,供应给Function sanitise_sugg(inp As Variant) As Variant的元素包含vba中的双精度,或者来自excel表单的数值的单元格,它符合要求的规范Public Function sanitise(ByRef A As Variant) As Double()

编辑3:查看函数如何跟踪其input数组布局,与行向量,列向量或完整matrix无关,独立于从Excel范围或从VBA内部传递的数组,请参考下面的工作表;

在这里输入图像说明

我想不出有什么实际用途,除非你在2D数组上进行了大量的计算,所以如果你提供了更多关于你想要做什么的信息,我们可以推荐一些更简单/更好/更多高效率等

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

 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 

并通过以下testing:

 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