如何在VBA的立即窗口中打印二维数组?

24
如何在VBA的立即窗口中打印二维数组?是否存在任何通用方法来完成此操作?如果可以将数组的每一行绘制成一行,则可以解决此问题,因为只需为每行循环执行此代码即可。请注意保留HTML标记。

3
一种通用的方法是将整个二维数组写入临时工作表中。这比在立即窗口中逐行读取要容易得多。 - user688334
8个回答

35

如果这是为了调试的目的,在程序执行过程中编写宏以查看数组内容不太方便。这甚至可能会导致问题。

为了在程序执行过程中进行调试,您需要一种无需编码即可在所有VB项目中使用的方法来窥视数组的内容。

  1. 在VBA IDE中,单击“View”菜单>“Locals Window”
  2. 在本地窗格中,找到数组名称。 enter image description here
  3. 展开节点以查找您的值。节点将因数组类型而异。

在此示例中,“aLookList”是变体数组。 “Value2”下的值来自一个范围。

enter image description here

enter image description here

另一个答案建议使用监视窗格。这与我的答案类似,但发布者没有解释您可以通过将数组名称添加到监视中来窥视整个数组(所有单元格)。然后,深入节点。与监视窗口相比,本地窗格的优势在于您不必手动将数组添加到窗格中,因为它已经存在。所以这需要更少的努力。


1
代码执行完成后,本地变量消失了。在 Sub 结束前添加一个调试点,我成功获取了所需的本地变量.. 感谢这个好建议! - Mitalee Rao

12

我为大家的参考制作了一个简单的循环:

Sub WriteArrayToImmediateWindow(arrSubA As Variant)

Dim rowString As String
Dim iSubA As Long
Dim jSubA As Long

rowString = ""

Debug.Print
Debug.Print
Debug.Print "The array is: "
For iSubA = 1 To UBound(arrSubA, 1)
    rowString = arrSubA(iSubA, 1)
    For jSubA = 2 To UBound(arrSubA, 2)
        rowString = rowString & "," & arrSubA(iSubA, jSubA)
    Next jSubA
    Debug.Print rowString
Next iSubA

End Sub

4
在程序执行期间,为了调试目的运行宏不是一个实用的方法。这样甚至可能会引起问题。为了调试,你需要一种无需编写代码而能查看数组内容的方法。请看我下面的无代码方法。 - johny why
1
假设arrsuba的两个维度的索引/下限均为1。如果有任何一个维度是0,则跳过0元素。 - Trashman

10

不,您需要:

  • 创建并调用一个循环打印数组内容到调试窗口的函数。
  • 如果这是用于调试,则在IDE中右键单击变量并选择“添加监视”选项,这将打开一个窗口,在断点命中时跟踪数组值的变化并显示其内容。

这与我下面的回答类似,但发帖者没有解释您可以通过将数组名称添加到监视中来窥视整个数组(所有单元格)。然后,深入节点。 - johny why

1

这个方法将一个数组输出到即时调试窗口。它会自动调整列的宽度并在右侧列上加上轮廓,使得在同一列中比较数字更加容易。

Public Sub Array2DToImmediate(ByVal arr As Variant, _
                                Optional ByVal spaces_between_columns As Long = 2, _
                                Optional ByVal NrOfColsToOutlineLeft As Long = 2)
'Prints a 2D-array of values to a table (with same sized column widhts) in the immmediate window

'Each character in the Immediate window of VB Editor (CTRL+G to show) has the same pixel width,
'thus giving the option to output a proper looking 2D-array (a table with variable string lenghts).
Dim i As Long, j As Long
Dim arrMaxLenPerCol() As Long
Dim str As String
Dim maxLength As Long: maxLength = 198 * 1021& 'capacity of Immediate window is about 200 lines of 1021 characters per line.

'determine max stringlength per column
ReDim arrMaxLenPerCol(UBound(arr, 1))
For i = LBound(arr, 1) To UBound(arr, 1)
    For j = LBound(arr, 2) To UBound(arr, 2)
        arrMaxLenPerCol(i) = IIf(Len(arr(i, j)) > arrMaxLenPerCol(i), Len(arr(i, j)), arrMaxLenPerCol(i))
    Next j
Next i

'build table
For j = LBound(arr, 2) To UBound(arr, 2)
    For i = LBound(arr, 1) To UBound(arr, 1)
        'outline left --> value & spaces & column_spaces
        If i < NrOfColsToOutlineLeft Then
            On Error Resume Next
            str = str & arr(i, j) & space$((arrMaxLenPerCol(i) - Len(arr(i, j)) + spaces_between_columns) * 1)
        
        'last column to outline left --> value & spaces
        ElseIf i = NrOfColsToOutlineLeft Then
            On Error Resume Next
            str = str & arr(i, j) & space$((arrMaxLenPerCol(i) - Len(arr(i, j))) * 1)
                    
        'outline right --> spaces & column_spaces & value
        Else 'i > NrOfColsToOutlineLeft Then
            On Error Resume Next
            str = str & space$((arrMaxLenPerCol(i) - Len(arr(i, j)) + spaces_between_columns) * 1) & arr(i, j)
        End If
    Next i
    str = str & vbNewLine
    If Len(str) > maxLength Then GoTo theEnd
Next j

theEnd:
'capacity of Immediate window is about 200 lines of 1021 characters per line.
If Len(str) > maxLength Then str = Left(str, maxLength) & vbNewLine & " - Table to large for Immediate window"
Debug.Print str
End Sub

用于例如输出的子程序:

Sub testArray2DToImmediate()
Dim ar() As Variant
ReDim ar(1 To 5, 1 To 4)

ar(1, 1) = "ID": ar(2, 1) = "Name": ar(3, 1) = "Values1": ar(4, 1) = "Values2": ar(5, 1) = "Values3"
ar(1, 2) = 1: ar(2, 2) = "Example where only": ar(3, 2) = FormatNumber(123 * 123#, 2): ar(4, 2) = 89: ar(5, 2) = "Wow"
ar(1, 3) = 2: ar(2, 3) = "first 2 columns are": ar(3, 3) = FormatNumber(234 * 234#, 2): ar(4, 3) = 456789: ar(5, 3) = "Nice"
ar(1, 4) = 3: ar(2, 4) = "outlined Left": ar(3, 4) = FormatNumber(567 * 567#, 2): ar(4, 4) = 123456789: ar(5, 4) = "Table":

Array2DToImmediate ar
End Sub

示例输出:

ID  Name                    Values1    Values2  Values3
1   Example where only    15.129,00         89      Wow
2   first 2 columns are   54.756,00     456789     Nice
3   outlined Left        321.489,00  123456789    Table

1

试试看

你也可以使用 code1: code2 而不是 code1 来显示内容
这只是为了显示而已
如果 arr 定义为 array(array(,),array(,)…)
然后
你应该用 For c = Lbound(arr(r),1) to ubound(arr(r),1)
Debug.Print arr(r)(c)
因为第一个是 2D 数组,最后一个是 1D 数组。
'Define 2d array
arr = [ {"A",1; "B",2; "C",3 } ]: _
For r = LBound(arr, 1) To UBound(arr, 1): _
        For c = LBound(arr, 2) To UBound(arr, 2): _
            Debug.Print arr(r, c): _
       Next c: _
Next

(1) 在 debug.print: 之间加上分号可以防止在列之间换行。 (2) 在 next cnext r 之间再加上一个 print 可以强制在行之间换行。 (3) 将 next c 改为 next r 可以帮助紧张的人。 (4) 在即时窗口中不需要使用 debug.。将以上内容放在一行中,代码如下:For r = LBound(arr, 1) To UBound(arr, 1) : For c = LBound(arr, 2) To UBound(arr, 2) : Print arr(r, c) ; : Next c : Print : Next r。同时,我必须记住使用 : _ 技巧来提高可读性。 - northern-bradley

1
请将以下数据粘贴到A列(姓名)中,B列(年龄)中。
Name    Age
A   10
B   20
C   30
D   40
E   50
F   60
G   70

运行以下代码。
Sub Array_Demo()

Dim arr() As String
Dim i As Integer, j As Integer

' fill the array with strings

Last = Range("A" & Rows.Count).End(xlUp).Row
ReDim arr(Last, 1)

For i = 0 To Last - 1

    arr(i, 0) = Cells(i + 1, 1).Value
    arr(i, 1) = Cells(i + 1, 2).Value


Next

' only one loop to display its contents !!!
Dim v As Variant

For Each v In arr

    Debug.Print v

Next


End Sub

你可以在立即窗口中看到以下输出。
Name
A
B
C
D
E
F
G

Age
10
20
30
40
50
60
70

0
以下过程使用一个函数在立即窗口中打印数组。该函数逐行将数组转换为字符串。
Sub test()
'declare the 2D array
   Dim intA(0 To 2, 0 To 3) As Integer
'populate the array
   intA(0, 0) = 45:   intA(0, 1) = 50:   intA(0, 2) = 55:   intA(0, 3) = 60
   intA(1, 0) = 65:   intA(1, 1) = 70:   intA(1, 2) = 75:   intA(1, 3) = 80
   intA(2, 0) = 85:   intA(2, 1) = 90:   intA(2, 2) = 95:   intA(2, 3) = 100
Debug.Print Print2DArrayToImmediate(intA)

' <<<<<<<<<<    Or  >>>>>>>>>>
Dim myarr()
myarr = Range("A1:C5").Value
Debug.Print Print2DArrayToImmediate(myarr)

End Sub

Function Print2DArrayToImmediate(arr)
Dim arrStr As String, x As Long, y As Long
arrStr = ""

For i = LBound(arr, 1) To UBound(arr, 1)
    If LBound(arr, 1) = 0 Then i = i + 1
    arrStr = arrStr & vbCrLf
    arrStr = arrStr & Join(Application.Index(arr, i, 0), vbTab & vbTab)
Next i

Print2DArrayToImmediate = arrStr
End Function

enter image description here


-1
我为此编写了自己的函数。它类似于VBA中的print_r()函数。 它可以评估数组、字典、集合、MatchCollection等等。 整个过程也是嵌套的。此外,数据类型已经给出,并且字符串中的特殊字符以Unicode形式显示。

http://wiki.yaslaw.info/doku.php/vba/functions/print_r/index

print_r(array(1,2,3,array("A","B")))
<Variant()>  (
    [0] => <Integer> 1
    [1] => <Integer> 2
    [2] => <Integer> 3
    [3] => <Variant()>  (
        [0] => <String> 'A'
        [1] => <String> 'B'
    )
)

print_r([{1,2;3,4}])
<Variant()>  (
    [1.1] => <Double> 1
    [1.2] => <Double> 2
    [2.1] => <Double> 3
    [2.2] => <Double> 4
)

测试数组是一个嵌套数组,而不是一个二维数组。 - S Meaden

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接