Excel VBA-从ArrayList到Excel工作表的ArrayList

Excel VBA-从ArrayList到Excel工作表的ArrayList,excel,vba,arraylist,Excel,Vba,Arraylist,寻找更合适的方法。我有一个有效的解决方案,但似乎应该有一个内置的或更优雅的方法 我正在比较两份单独工作簿中的工作表,在当前工作簿的工作表上记录差异。每次发现差异时,我都会生成一行输出数据。由于我不知道我将发现的差异总数,所以输出数据行被追加到ArrayList中 我有一些代码,但有效的方法是: 创建一行作为arraylist 将行转换为数组 将该行添加到arraylist以进行输出 转换为数组时两次转置输出arraylist 将数组输出到工作表 尽管使用ArrayList有很多好处,但似乎应该有

寻找更合适的方法。我有一个有效的解决方案,但似乎应该有一个内置的或更优雅的方法

我正在比较两份单独工作簿中的工作表,在当前工作簿的工作表上记录差异。每次发现差异时,我都会生成一行输出数据。由于我不知道我将发现的差异总数,所以输出数据行被追加到ArrayList中

我有一些代码,但有效的方法是:

  • 创建一行作为arraylist
  • 将行转换为数组
  • 将该行添加到arraylist以进行输出
  • 转换为数组时两次转置输出arraylist
  • 将数组输出到工作表
  • 尽管使用ArrayList有很多好处,但似乎应该有一种直接的方法来输出2D“ArrayList of ArrayList”或类似的东西

    以下是当前代码:

    Sub findUnmatchingCells()
    
        Dim oWB_v1 As Workbook, oWB_v2 As Workbook, oRange_v1 As Range, oRange_v2 As Range
        
        On Error GoTo endofsub
        
        With Me
        
            .Cells.Clear
            .Cells(1, 1) = "Row"
            .Cells(1, 2) = "Column"
            .Cells(1, 3) = "v1"
            .Cells(1, 4) = "v2"
            
        End With
        Dim missing_items As Object
        Dim output_row(), output(), missing_row As Object
        
        Set oWB_v1 = Workbooks("foo.xls")
        Set oWB_v2 = Workbooks("bar.xls")
    
        Set oRange_v1 = oWB_v1.Sheets(1).Range("A1:AD102")
        Set oRange_v2 = oWB_v2.Sheets(1).Range("A1:AD102")
        
        Set missing_items = CreateObject("System.Collections.ArrayList")
        
        For rRow = 1 To oRange_v1.Rows.Count
            For cCol = 1 To oRange_v1.Columns.Count
                
                If oRange_v1.Cells(rRow, cCol) <> oRange_v2.Cells(rRow, cCol) Then
                    
                    Set missing_row = CreateObject("System.Collections.ArrayList")
                    
                    missing_row.Add rRow
                    missing_row.Add cCol
                    missing_row.Add oRange_v1.Cells(rRow, cCol).Value2
                    missing_row.Add oRange_v2.Cells(rRow, cCol).Value2
                    
                    output_row = missing_row.toarray
                    
                    missing_items.Add output_row
                    
                End If
            
            Next cCol
        Next rRow
        
        output = Application.WorksheetFunction.Transpose(Application.WorksheetFunction.Transpose(missing_items.toarray))
        
        'my own output routine
        If Not outputArrayToRange(output, Me.Range("A2")) Then Stop
        
        Exit Sub
        
    endofsub:
        Debug.Print rRow, cCol, missing_items.Count, missing_row.Count, Error
        Stop
    
    End Sub
    
    子findUnmatchingCells()
    将oWB_v1设置为工作簿,将oWB_v2设置为工作簿,将橙色_v1设置为范围,将橙色_v2设置为范围
    关于错误转到endofsub
    和我一起
    .细胞,清除
    .单元格(1,1)=“行”
    .单元格(1,2)=“列”
    .单元格(1,3)=“v1”
    .单元格(1,4)=“v2”
    以
    将缺少的\u项作为对象进行调暗
    Dim output_row(),output(),缺少作为对象的_row
    设置oWB_v1=工作簿(“foo.xls”)
    设置oWB_v2=工作簿(“bar.xls”)
    设置橙色_v1=oWB_v1.Sheets(1.Range)(“A1:AD102”)
    设置橙色_v2=oWB_v2.图纸(1).范围(“A1:AD102”)
    设置缺少的\u items=CreateObject(“System.Collections.ArrayList”)
    对于rRow=1到oRange_v1.Rows.Count
    对于cCol=1到橙色_v1.Columns.Count
    如果橙色单元格(rRow,cCol)橙色单元格(rRow,cCol),则
    Set missing_row=CreateObject(“System.Collections.ArrayList”)
    缺少_行。请添加箭头
    缺少行。添加cCol
    缺少行。添加橙色单元格(箭头、cCol)。值2
    缺少行。添加橙色单元格(箭头、cCol)。值2
    输出\行=缺少\行。到阵列
    缺少\u项。添加输出\u行
    如果结束
    下一个cCol
    下一个箭头
    输出=Application.WorksheetFunction.Transpose(Application.WorksheetFunction.Transpose(缺少项.toarray))
    “我自己的输出例程
    如果未输出ArrayToRange(输出,Me.Range(“A2”)),则停止
    出口接头
    endofsub:
    调试。打印错误,cCol,缺少\u项。计数,缺少\u行。计数,错误
    停止
    端接头
    
    在ArrayList中,当您没有真正使用任何有用的东西时,似乎需要做很多额外的工作。正如您所知,不匹配计数不能超过开始元素的数量,并且列的末尾将是4,您可以使用单个数组来完成所有这一切。预先调整数组大小并在循环中填充它


    简化示例:

    当您使用
    Me
    时,此代码将出现在“Sheet1”中

    现在,如果您想重估不匹配的实际数量以避免过度编写某些内容,那么情况会变得更加复杂,但通常明智的做法是规划开发以避免此类风险。您需要使用双重转置,才能将行重新划分为列,然后返回到行

    对于您提到的范围,我不认为转置限制是一个问题,但在其他情况下这是一个问题,需要通过额外的循环来解决

    有效的方法是一直使用数组。将两个范围读入数组,循环其中一个并与另一个进行比较,将更改写入预先调整大小的数组,将数组写入工作表


    如果这只是关于ArrayList中是否有更好的功能,那么答案是否定的。您所做的是简短有效的,但所产生的开销超出了必要的范围


  • 在循环中不断地重新创建
    缺少的行
    ArrayList,这是在浪费已经创建的对象。在循环之前创建一次,然后在再次循环之前调用
    .Clear
    方法

  • 是跨1)行->阵列列表的实际读取;2) 数组列表->数组;3) 是否将数组添加到arrayList?如果是这样的话,我发现这比你现在的措辞更容易混淆。是的,然后将final arraylist->array->sheetThank双重转置。我用这个例子来说明如何将2D数组列表输出到电子表格。在我看来,通常会定义列的数量,因此行数组显然可以简化。不过,对于大多数具有数千行的情况,最好使用整体数组列表。我只是想找到一种输出的方法。我想问题仍然是,在这里使用ArrayList有什么好处?没有它们会更快。事实上,我应该只循环数组,而不是表。如果您对如何使用ArrayList感到好奇,我认为您当前的方法很好,不过请看我的最后两点。在这种情况下,不。我希望在500000多行的情况下,在这方面做得更好一些。然后,您可能会冒着达到转置限制的危险,不得不对数组做更多的工作。这实际上取决于存在多少不匹配。但迪福是一个风险。这就是为什么我希望有一个更有效、更直接的方法。
    Option Explicit
    
    Public Sub findUnmatchingCells()
    
        Dim oWB As ThisWorkbook, oRange_v1 As Range, oRange_v2 As Range
    
        With Me
        
            .Cells.Clear
            .Cells(1, 1) = "Row"
            .Cells(1, 2) = "Column"
            .Cells(1, 3) = "v1"
            .Cells(1, 4) = "v2"
            
        End With
        
        Dim rRow As Long, cCol As Long
        
        Set oWB = ThisWorkbook
    
        Set oRange_v1 = oWB.Worksheets("Sheet2").Range("A1:D3") 'would be faster to read this into array and later loop that
        Set oRange_v2 = oWB.Worksheets("Sheet3").Range("A1:D3") 'would be faster to read this into array and later loop that
        
        Dim totalElements As Long, output()
        
        totalElements = oRange_v1.Rows.Count * oRange_v1.Rows.Count
        
        ReDim output(1 To totalElements, 1 To 4)
    
        For rRow = 1 To oRange_v1.Rows.Count 'would be faster to loop arrays than sheet
            For cCol = 1 To oRange_v1.Columns.Count
                If oRange_v1.Cells(rRow, cCol) <> oRange_v2.Cells(rRow, cCol) Then
                    output(rRow, 1) = rRow
                    output(rRow, 2) = cCol
                    output(rRow, 3) = oRange_v1.Cells(rRow, cCol).Value2
                    output(rRow, 4) = oRange_v2.Cells(rRow, cCol).Value2
                End If
            Next cCol
        Next rRow
            
        oWB.Worksheets("Sheet1").Cells(2, 1).Resize(UBound(output, 1), UBound(output, 2)) = output
    
    End Sub
    
    ThisWorkbook.VBProject.References.AddFromFile "C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\mscorlib.tlb"
    
    ThisWorkbook.VBProject.References.AddFromguid "{BED7F4EA-1A96-11D2-8F08-00A0C9A6186D}", 2, 4