【问题标题】:How to print two dimensional array in Immediate window in VBA?如何在 VBA 的即时窗口中打印二维数组?
【发布时间】:2012-12-25 20:17:28
【问题描述】:

如何在 VBA 的即时窗口中打印二维数组?它是否存在任何通用方法来做到这一点?一些在即时窗口中每行绘制一行数组的方法可以解决这个问题,因为唯一要做的就是为每一行数组循环这段代码。

【问题讨论】:

  • 一种通用方法是将整个二维数组写入临时工作表。这肯定比在即时窗口中阅读行更容易。

标签: arrays vba immediate-window


【解决方案1】:

以下过程使用函数在即时窗口中打印数组。该函数将数组逐行转换为字符串。

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

【讨论】:

    【解决方案2】:

    此方法将数组输出到即时调试窗口。它会自动调整列的宽度并向右勾勒出列,从而更容易比较同一列中的数字。

    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 例如输出:

    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
    

    【讨论】:

      【解决方案3】:

      我为此编写了自己的函数。 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
      )
      

      【讨论】:

      【解决方案4】:

      试试这个

      您也可以输入 code1: code2 而不是 code1 _
      这仅用于显示
      如果 arr 定义为 array(array(,),array(,)...)
      然后
      你应该 For c = Lbound(arr(r),1) 到 ubound(arr(r),1)
      Debug.Print arr(r)(c)
      因为第一个是二维数组,最后一个是第一个数组。
      一世
      '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 c 和之间的额外printnext r 在行之间强制换行 (3) 更改为 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 (并且我必须尝试记住: _ 技巧以提高可读性)
      【解决方案5】:

      如果这是出于调试目的,那么在程序执行期间编写宏来查看数组的内容并不方便。甚至可能导致问题。

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

      1. 在 VBA IDE 中,单击查看菜单 > 本地窗口
      2. 在本地窗格中,找到阵列名称。
      3. 展开节点以找到您的值。节点会有所不同,具体取决于阵列的类型。

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

      此处的另一个答案建议使用“监视”窗格。这与我的回答类似,但海报并未解释您可以通过简单地将数组名称添加到 Watch 来监视整个数组(所有单元格)。然后,向下钻取节点。 Locals Window 优于 Watch Window 的优势在于,使用 Locals 窗格,您不必手动将数组添加到窗格中,它已经存在。因此,它的努力要少一些。

      【讨论】:

      • 代码执行完成后,本地人消失了。通过在 Sub 结束之前添加一个调试点,我能够获得所需的本地人.. 感谢您的精彩提示!
      【解决方案6】:

      在B列(年龄)的A列(姓名)中粘贴以下数据

      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
      

      【讨论】:

        【解决方案7】:

        我做了一个简单的循环来做这个供大家参考:

        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
        

        【讨论】:

        • 为了在程序执行期间进行调试,运行宏是不切实际的。甚至可能导致问题。对于调试,您需要一种无代码的方法来监视数组内容。请参阅下面我的无代码方法。
        • 这里假设arrsuba的两个维度的索引/下界都是1。如果其中一个是0,它将跳过0元素。
        【解决方案8】:

        不,你要么需要;

        • 创建和调用一个循环并打印到调试窗口的函数。
        • 如果这是为了调试,请右键单击 IDE 中的变量并“添加观察”,这将打开一个窗口,该窗口将跟踪数组值的变化并在遇到断点时显示其内容。

        【讨论】:

        • 这与我在下面的回答类似,但海报并未解释您只需将数组名称添加到 Watch 即可窥探整个数组(所有单元格)。然后,向下钻取节点。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-08-31
        • 2016-11-27
        • 1970-01-01
        • 1970-01-01
        • 2011-03-02
        • 2020-11-17
        相关资源
        最近更新 更多