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
Arrays 组合二维(二维)阵列_Arrays_Vba_Excel - Fatal编程技术网

Arrays 组合二维(二维)阵列

Arrays 组合二维(二维)阵列,arrays,vba,excel,Arrays,Vba,Excel,我在Excel中使用VBA使用XML文件,并将特定信息转储到各个选项卡中。我希望能够组合二维数组。数组的列数“已知”,但行数“未知”。考虑下面两个数组: 阵列1: a b c d e f 阵列2: 1 2 3 4 5 6 如果希望得到以下结果,如何将这些组合到数组中: 阵列3: a b c d e f 1 2 3 4 5 6 出于好奇,如果我想添加到右边而不是底部,我该如何编写代码,如下所示:

我在Excel中使用VBA使用XML文件,并将特定信息转储到各个选项卡中。我希望能够组合二维数组。数组的列数“已知”,但行数“未知”。考虑下面两个数组:

阵列1:

a    b    c
d    e    f
阵列2:

1    2    3
4    5    6
如果希望得到以下结果,如何将这些组合到数组中:

阵列3:

a    b    c
d    e    f
1    2    3
4    5    6
出于好奇,如果我想添加到右边而不是底部,我该如何编写代码,如下所示:

阵列4:

a    b    c    1    2    3
d    e    f    4    5    6
我似乎在任何地方都找不到这个问题的答案

请记住,我上面的示例非常小,但实际上,我试图一次使用大约100000行数据来实现这一点。如果这有关系的话,只有六列数据

这里的目标是组装一个大型数组,然后一步将其写入Excel工作表,因为当我将其拆分时,性能非常差

如果可能,我更喜欢不需要迭代的解决方案

我问这两种方法的原因是,实际上我想按顺序添加。例如,假设我有四个数组,A,B,C,D

首先,添加一个数组:

A
然后,添加数组B:

A    B
然后,添加数组C:

A    B
C
然后,添加数组D:

A    B
C    D
等等

请记住,上述每个数组的大小都应确保它们“适合”,这意味着A和B的行数相同,但列数不同。另一方面,A和C的列数相同,但行数不同。等等

我想从下面添加一个使用Macro Man代码的演示。以下是他提供的内容(我添加了一些内容,以便读者只需复制/粘贴):

当您运行上述代码时,每次都会返回到电子表格以写入少量数据,这需要很长时间才能运行。在我的双Xeon机器上,大约25-30秒

但是,如果您先重写并填充数组,然后写入电子表格一次,它将在大约一秒钟内运行

Option Explicit

Sub Testing()

    Dim Array1(0 To 99999, 0 To 2) As String
    Array1(0, 0) = "a"
    Array1(0, 1) = "b"
    Array1(0, 2) = "c"
    Array1(1, 0) = "d"
    Array1(1, 1) = "e"
    Array1(1, 2) = "f"

    Dim i As Long
    For i = 0 To 99999

        Array1(i, 0) = "a"
        Array1(i, 1) = "b"
        Array1(i, 2) = "c"

    Next i

    With Range("A" & Rows.Count).End(xlUp).Offset(IIf(IsEmpty([A1]), 0, 1), 0)
        .Resize(UBound(Array1, 1) - LBound(Array1, 1) + 1, _
                UBound(Array1, 2) - LBound(Array1, 2) + 1).Value = Array1
    End With

End Sub
我希望看到一个解决方案,除了能够添加“块”数据,而不是单个项目之外,它也能做同样的事情。理想情况下,将阵列添加到更大的阵列。如果“父”数组以某种方式动态调整自身大小,则更好

约翰·科尔曼下面的回答非常有效

实际上,我将一些Macro Man与John的test()子例程结合起来,动态地重新调整了范围:

Option Explicit

Sub test()
    Dim A As Variant, B As Variant
    ReDim A(0 To 1, 0 To 1)
    ReDim B(0 To 1, 0 To 1)
    A(0, 0) = 1
    A(0, 1) = 2
    A(1, 0) = 3
    A(1, 1) = 4
    B(0, 0) = 5
    B(0, 1) = 6
    B(1, 0) = 7
    B(1, 1) = 8

    Dim Array1 As Variant
    Array1 = Combine(A, B)

    With Range("A" & Rows.Count).End(xlUp).Offset(IIf(IsEmpty([A1]), 0, 1), 0)
    .Resize(UBound(Array1, 1) - LBound(Array1, 1) + 1, _
            UBound(Array1, 2) - LBound(Array1, 2) + 1).Value = Array1
    End With
End Sub

您可以尝试重新调整目标大小以匹配阵列的尺寸。大致如下:

(假设您的数组名为“Array1”和“Array2”)


下面是一个VBA函数,它可以将两个二维数组合并为一个二维数组。它既可以从VBA使用,也可以直接在Excel中作为数组公式使用。在VBA中,迭代是不可避免的,因为该语言没有用于连接数组的原语:

Function Combine(A As Variant, B As Variant, Optional stacked As Boolean = True) As Variant
    'assumes that A and B are 2-dimensional variant arrays
    'if stacked is true then A is placed on top of B
    'in this case the number of rows must be the same,
    'otherwise they are placed side by side A|B
    'in which case the number of columns are the same
    'LBound can be anything but is assumed to be
    'the same for A and B (in both dimensions)
    'False is returned if a clash

    Dim lb As Long, m_A As Long, n_A As Long
    Dim m_B As Long, n_B As Long
    Dim m As Long, n As Long
    Dim i As Long, j As Long, k As Long
    Dim C As Variant

    If TypeName(A) = "Range" Then A = A.Value
    If TypeName(B) = "Range" Then B = B.Value

    lb = LBound(A, 1)
    m_A = UBound(A, 1)
    n_A = UBound(A, 2)
    m_B = UBound(B, 1)
    n_B = UBound(B, 2)

    If stacked Then
        m = m_A + m_B + 1 - lb
        n = n_A
        If n_B <> n Then
            Combine = False
            Exit Function
        End If
    Else
        m = m_A
        If m_B <> m Then
            Combine = False
            Exit Function
        End If
        n = n_A + n_B + 1 - lb
    End If
    ReDim C(lb To m, lb To n)
    For i = lb To m
        For j = lb To n
            If stacked Then
                If i <= m_A Then
                    C(i, j) = A(i, j)
                Else
                    C(i, j) = B(lb + i - m_A - 1, j)
                End If
            Else
                If j <= n_A Then
                    C(i, j) = A(i, j)
                Else
                    C(i, j) = B(i, lb + j - n_A - 1)
                End If
            End If
        Next j
    Next i
    Combine = C
End Function
A12:F13包含数组公式

{=combine(A1:C2,A4:C5,FALSE)}
然后,我运行了以下子系统:

Sub test()
    Dim A As Variant, B As Variant
    ReDim A(0 To 1, 0 To 1)
    ReDim B(0 To 1, 0 To 1)
    A(0, 0) = 1
    A(0, 1) = 2
    A(1, 0) = 3
    A(1, 1) = 4
    B(0, 0) = 5
    B(0, 1) = 6
    B(1, 0) = 7
    B(1, 1) = 8    
    Range("A15:B18").Value = Combine(A, B)
    Range("C15:F16").Value = Combine(A, B, False)    
End Sub
输出:

如果可能,我更喜欢不需要迭代的解决方案

试试这个:

Function Combine(m, n)
    Dim m1&, m2&, n1&, n2&
    m1 = UBound(m, 1): m2 = UBound(m, 2)
    n1 = UBound(n, 1): n2 = UBound(n, 2)
    With Worksheets.Add
        .[a1].Resize(m1, m2) = m
        .[a1].Resize(n1, n2).Offset(m1) = n
        Combine = .[a1].Resize(m1 + n1, m2)
        Application.DisplayAlerts = False
        Application.ScreenUpdating = False
        .Delete
        Application.DisplayAlerts = True
        Application.ScreenUpdating = True
    End With
End Function
注意:这只是一个演示,展示概念验证。目前,它对两个二维阵列进行垂直堆叠。简单的修改也做水平堆叠


注意:我通常反对这类事情,但如果你仔细想想,Excel工作表类似于一个非常大的2d数组,虽然这确实是一种更简单的方法,但它很快而且没有迭代

我想我误解了“数组”。您可以将所有这些值存储到一个数组中,然后在Excel中以您想要的方式显示它们…您可以在三列上,然后向下一行,重复。或者你可以在六列上下移动一行。我的观点是,(AFAIK)Excel数组不是以某种物理方式存储的……它只是一个项目列表。如何在Excel中显示它们完全取决于您。这有意义吗?我澄清了我的问题。这与最终写入excel工作表的VBA有关。如果我在工作表上一次更新每个值,甚至更新一大块值,这将花费很长时间。当我从单独存储每个值转移到以块的形式将它们放在工作表上时,性能显著提高。我希望找到一种方法来做同样的事情,但在VBA中进一步组合数组。
Redim PRESERVE
命令只能扩展最后一列。您可能最好创建一个新的数组,通过添加UBounds来调暗,然后从那个里填充。远离
.Transpose
以完成重拨。您的100K“行”数据超出了其限制。@BruceWayne数组,即使在VBA中,也可以有多个维度。这是一个二维数组,在视觉上看起来像一组单元格。更多information@BruceWayne天哪,蝙蝠侠。VBA中的数组绝对存储为称为SAFEARRAY的OLE构造。阅读此内容:将数据放在工作表的适当位置即可。我已经在做类似的事情,放置所有数据需要很长时间。我想在VBA代码(ie-memory)中完全做到这一点,然后一次性将其全部转储到工作表中。我在上面添加了另一个说明来演示。这对于这个示例非常有效。回答得很好,方法很有趣。我已经做过这样的事情(添加和删除一个工作表来处理一个数组)来排序一个数组。进行一些计时测试,看看速度与仅VBA方法相比如何,这将是一件有趣的事情。好的观点。我想关闭屏幕更新(以及任何计算)也会加快速度。这也是一种独特的解决方案,它有助于防止(或解决)与数组中不同类型数据的类型不匹配相关的任何问题。编译代码时会出现错误,因为未声明变量
b
<代码>[a1]。调整大小(n1,n2)。偏移量(m1)=b{=combine(A1:C2,A4:C5,FALSE)}
Sub test()
    Dim A As Variant, B As Variant
    ReDim A(0 To 1, 0 To 1)
    ReDim B(0 To 1, 0 To 1)
    A(0, 0) = 1
    A(0, 1) = 2
    A(1, 0) = 3
    A(1, 1) = 4
    B(0, 0) = 5
    B(0, 1) = 6
    B(1, 0) = 7
    B(1, 1) = 8    
    Range("A15:B18").Value = Combine(A, B)
    Range("C15:F16").Value = Combine(A, B, False)    
End Sub
Function Combine(m, n)
    Dim m1&, m2&, n1&, n2&
    m1 = UBound(m, 1): m2 = UBound(m, 2)
    n1 = UBound(n, 1): n2 = UBound(n, 2)
    With Worksheets.Add
        .[a1].Resize(m1, m2) = m
        .[a1].Resize(n1, n2).Offset(m1) = n
        Combine = .[a1].Resize(m1 + n1, m2)
        Application.DisplayAlerts = False
        Application.ScreenUpdating = False
        .Delete
        Application.DisplayAlerts = True
        Application.ScreenUpdating = True
    End With
End Function