Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/16.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
“我怎么能?”;“雷迪姆保护区”;Excel 2007 VBA中的二维数组,以便我可以向数组中添加行而不是列?_Excel_Vba - Fatal编程技术网

“我怎么能?”;“雷迪姆保护区”;Excel 2007 VBA中的二维数组,以便我可以向数组中添加行而不是列?

“我怎么能?”;“雷迪姆保护区”;Excel 2007 VBA中的二维数组,以便我可以向数组中添加行而不是列?,excel,vba,Excel,Vba,我正在使用Excel VBA中的动态数组。列数(m)是固定的,但是,我不知道需要多少行(n) 帮助文档指出,ReDim Preserve myArray(n,m)允许我将m变大,但不能将n变大。但是,我需要增加行数(n),同时保留数据,而不是列数(m) 例如,我可能有一个(5,20)数组,我希望在保留数据的同时将其扩展为(10,20) 似乎如果有某种方法可以转置我的数组,执行ReDim Preserve以扩展“列”的数量,然后重新转置我的数组,我就可以完成我想要的 这是正确的方法吗?如果是,我该

我正在使用Excel VBA中的动态数组。列数(m)是固定的,但是,我不知道需要多少行(n)

帮助文档指出,ReDim Preserve myArray(n,m)允许我将m变大,但不能将n变大。但是,我需要增加行数(n),同时保留数据,而不是列数(m)

例如,我可能有一个(5,20)数组,我希望在保留数据的同时将其扩展为(10,20)

似乎如果有某种方法可以转置我的数组,执行ReDim Preserve以扩展“列”的数量,然后重新转置我的数组,我就可以完成我想要的

这是正确的方法吗?如果是,我该怎么做


是否有更好的方法来实现我的目标?

无法确定第一维度中的元素数量?真倒霉对于具有固定第二维度的二维数组,您可能需要考虑将其作为类型数组(其他语言中的“结构”)。这将允许您使用Redim Preserve,并且仍然为您提供了添加和访问值的合理方式,尽管您现在将以该类型的命名成员而不是is索引值的身份访问第二维度。

解决了我自己的问题;这是我如何解决我的问题的。我创建了一个临时数组,将myArray的内容复制到临时数组,调整myArray的大小,然后将内容从临时数组复制回myArray

tempArray = myArray
ReDim myArray(1 To (UBound(myArray()) * 2), 1 To m)
For i = 1 To n
     For j = 1 To m
          myArray(i, j) = tempArray(i, j)
     Next j
Next i

如果有人能提出一种更有效的方法,我很乐意听到。

一种方法是使用包含一维数组的一维数组,而不是二维数组。然后,您可以根据需要重新定义并保留外部阵列。如果您从函数返回外部数组,Excel将做正确的事情并将其强制为二维数组

例如,下面的函数将向调用它的单元格返回3x2数组:

Public Function nested()
    Dim outer
    outer = Array(Array(1, 2), Array(3, 4))

    ReDim Preserve outer(1 To 3)

    outer(3) = Array(5, 6)

    nested = outer
End Function
我对这些问题的回答也可能对你有用:以及

当然,如果你不是从UDF返回这个,你必须自己强制它。在不编写循环代码的情况下执行此操作的简单方法是:

Dim coerced
coerced = Application.Index(outer, 0, 0)

这只是调用Excel的内置索引函数,零表示要返回所有行和列。Excel将自动将一维数组强制为二维数组。(注意:有一些尺寸限制,但它们比10x20大得多。)

一想到“转置”这个词就立刻想到了。您可以通过翻转列和行(即转置)简单地将数据输入到二维数组中,从而在需要时有效地使n(现在是列数,但存储行值)变大


要引用这些值,比如在双循环中,交换索引。例如,如果参考值(i,j)从i=1到n,从j=1到m,使用i=1到m,从j=1到n。如果您是开发人员,行和列之间的区别是什么? 使用数组(N,2)(如果您有两列)与使用数组(2,N)相同,您可以

ReDim Preserve arr(1 to 2, 1 to N+1). 
对于您(作为开发人员)来说,不同之处在于将循环中的变量放在第二位,而不是第一位:

N = ubound(arr)
FOR i=1 to N
    GetColumn1Value = arr(1, i)
    GetColumn2Value = arr(2, i)
NEXT i
或者你想要这个:

N = ubound(arr)
FOR i=1 to N
    GetColumn1Value = arr(i, 1)
    GetColumn2Value = arr(i, 2)
NEXT i

有什么不同吗?

解决这个问题的一种方法是通过改变列数进行双转置。但是,这仅适用于二维阵列。具体做法如下:

' Adding one row is done by a double transposing and adding a column in between.
' (Excel VBA does not allow to change the size of the non-last dimension of a
' multidimensional array.)
myArray = Application.Transpose(myArray)
ReDim Preserve myArray(1 To m, 1 To n + 1)
myArray= Application.Transpose(myArray)
m = UBound(myArray, 1)
n = UBound(myArray, 2)
当然,
m
n
可以推断如下:

' Adding one row is done by a double transposing and adding a column in between.
' (Excel VBA does not allow to change the size of the non-last dimension of a
' multidimensional array.)
myArray = Application.Transpose(myArray)
ReDim Preserve myArray(1 To m, 1 To n + 1)
myArray= Application.Transpose(myArray)
m = UBound(myArray, 1)
n = UBound(myArray, 2)

因此,您可以使用Excel本身的内置转置功能。正如代码注释中提到的,这对高阶矩阵不起作用。

当数据跨度大于2^16行(~92000行)时,强制或切片似乎不适用于基于多个条件筛选数组(w/o循环)的索引(或匹配(索引)

转置不适用于大的记录集,因此双转置也不起作用。难道不存在过滤数组和获取数据而不诉诸多个循环的方法吗


我正在考虑使用Excel尝试字典方式或ADO。

可以这样创建二维数组,其中列数固定,行数动态:

Sub test2DimArray()
Dim Arr2D() As String
Dim NumberOfCol As Long
Dim I As Long, J As Long, x As Long
Dim tmpValue As String, tmpValue2 As String, tmpValue3 As String

NumberOfCol = 3
J = 1
Debug.Print "Run " & Now()
Debug.Print "Sheet content"
Debug.Print "Row   col1     col2     col3"

For I = 1 To 10
tmpValue = Cells(I, 1).Value
tmpValue2 = Cells(I, 2).Value
tmpValue3 = Cells(I, 3).Value
Debug.Print I & " =    " & tmpValue & "     " & tmpValue2 & "     " & tmpValue3
    If Len(tmpValue) > 0 Then
        ReDim Preserve Arr2D(NumberOfCol, 1 To J)
        Arr2D(1, J) = tmpValue
        Arr2D(2, J) = tmpValue2
        Arr2D(3, J) = tmpValue3
        J = J + 1
    End If
Next

'check array values
Debug.Print vbLf; "arr2d content"
Debug.Print "Row   col1     col2     col3"

For x = LBound(Arr2D, 2) To UBound(Arr2D, 2)
Debug.Print x & " =   " & Arr2D(1, x) & "        " & Arr2D(2, x) & "        " & Arr2D(3, x)
Next

Debug.Print "========================="
End Sub
从单元格A1:A10读取TempValue,如果单元格Ax中有值,则使用+1重新划分数组,并将TempValue添加到数组col1,将Bx中的内容添加到数组col2,将Cx中的内容添加到数组col3。如果Ax值的长度为0,则不会向数组添加任何内容

Debug.print在VB编辑器的“即时窗口”中显示结果

如果没有测试行,并添加动态数据范围,代码可以是:

Sub my2DimArray()
Dim Arr2D() As String
Dim NumberOfCol As Long, NumberOfRow As Long
Dim FirstCol As Long, FirstRow As Long, LastCol As Long, LastRow As Long
Dim I As Long, J As Long, X As Long
Dim tmpValue As String, tmpValue2 As String, tmpValue3 As String

'if cells with values start in A1
With ActiveSheet.UsedRange
    NumberOfCol = .Columns.Count
    NumberOfRow = .Rows.Count
End With

'if cells with values starts elsewhere
With ActiveSheet.UsedRange
    FirstCol = .Column
    FirstRow = .Row
    LastCol = .Column + .Columns.Count - 1
    LastRow = .Row + .Rows.Count - 1
End With

J = 1

For I = 1 To NumberOfRow 'or For I = FirstRow to LastRow
tmpValue = Cells(I, 1).Value 'or tmpValue = Cells(I, FirstCol).Value
    If Len(tmpValue) > 0 Then
        ReDim Preserve Arr2D(NumberOfCol, 1 To J)
            For X = 1 To NumberOfCol 'or For X = FirstCol to LastCol
                Arr2D(X, J) = Cells(I, X).Value
            Next X
        J = J + 1
    End If
Next I

End Sub

我没有使用或尝试这个方法,因为这次我的解决方案足以满足我的需要。乍一看,这看起来确实是一种更优雅、更高效的方法来完成我想要的。谢谢。我很惊讶这有多快。16200行*14列=226000个值(2x转置,1x重拨)嗯,当我执行第一行代码时,我得到了一个类型不匹配错误。这必须在实际的工作表范围而不是二维数组变量上执行吗?-1:数组的每个redim都有两个嵌套的循环-一点也不好!如果有一个10000个元素的数组,会发生什么?好吧,区别是不需要同时更改这两个维度。或者我不知道哪个维度会受到影响。@Ister,如果使用“保留”关键字,则只能调整最后一个数组维度的大小,而不能更改维度的数量。该规则不仅适用于Office 2013及更高版本(如上面的链接所示),而且适用于从2003年开始的任何Office(我没有使用旧版本的经验)。我完全意识到这一局限性。我的意思是,我不能每次都简单地转置数组,也不能满足于改变