【问题标题】:Comparing two excel files and putting the difference in a new sheet比较两个 excel 文件并将差异放入新工作表中
【发布时间】:2015-05-13 02:21:06
【问题描述】:

我正在比较两张这样的表格:

一个工作表比另一个工作表新,可以删除、添加或更新一行。

我的用于检测是否在两者之间删除/添加行的代码对我不起作用,这就是我所拥有的:

Private Sub CompareSpreadsheets()
    Dim xlApp1 As Excel.Application = New Microsoft.Office.Interop.Excel.Application()
    Dim xlApp2 As Excel.Application = New Microsoft.Office.Interop.Excel.Application()
    Dim xlApp3 As Excel.Application = New Microsoft.Office.Interop.Excel.Application()
    Dim xlWorkBook1, xlWorkBook2, xlWorkBook3 As Excel.Workbook
    Dim xlWorkSheet1, xlWorkSheet2, xlWorkSheet3 As Excel.Worksheet
    Dim misValue As Object = System.Reflection.Missing.Value
    Dim xlRange1 As Excel.Range
    Dim maxRows As Short
    Dim qtyChange, mtlChange, newItem, delItem As Boolean
    Dim newRowCount As Short = 1
    Dim w3row As Short = 1

    'Check if Excel is installed on system
    If xlApp1 Is Nothing Then
        MessageBox.Show("Excel is missing/not properly installed on your system.", "ERROR")
        Return
    End If

    xlApp1.Workbooks.Open(path1)
    xlWorkBook1 = xlApp1.ActiveWorkbook
    xlWorkSheet1 = xlWorkBook1.ActiveSheet

    xlApp2.Workbooks.Open(path2)
    xlWorkBook2 = xlApp2.ActiveWorkbook
    xlWorkSheet2 = xlWorkBook2.ActiveSheet

    'Get maximum number of columns and rows from new spreadsheet
    maxRows = xlWorkSheet2.UsedRange.Rows.Count

    pbStatus.Minimum = 1
    pbStatus.Maximum = maxRows

    xlWorkBook3 = xlApp3.Workbooks.Add(misValue)
    xlWorkSheet3 = xlWorkBook3.Sheets("sheet1")

    qtyChange = False
    mtlChange = False
    newItem = False
    delItem = False

    Dim counter = 0 '/temp

    For i As Short = 1 To maxRows
        pbStatus.Value = i

        '[-- Green = Quantity change
        'Yellow = Material change
        'Blue = New item
        'Red = Deleted item --]

        If GetCellData(xlWorkSheet1, newRowCount, 3) = GetCellData(xlWorkSheet2, i, 3) And _
            GetCellData(xlWorkSheet1, newRowCount, 4) = GetCellData(xlWorkSheet2, i, 4) And _
            GetCellData(xlWorkSheet1, newRowCount, 5) = GetCellData(xlWorkSheet2, i, 5) And _
            GetCellData(xlWorkSheet1, newRowCount, 6) = GetCellData(xlWorkSheet2, i, 6) And _
            GetCellData(xlWorkSheet1, newRowCount, 7) = GetCellData(xlWorkSheet2, i, 7) And _
            GetCellData(xlWorkSheet1, newRowCount, 8) = GetCellData(xlWorkSheet2, i, 8) Then
            'DONE
            qtyChange = False
            mtlChange = False
            newItem = False
            delItem = False
            newRowCount += 1
        ElseIf GetCellData(xlWorkSheet1, newRowCount, 3) = GetCellData(xlWorkSheet2, i, 3) And _
            GetCellData(xlWorkSheet1, newRowCount, 4) = GetCellData(xlWorkSheet2, i, 4) And _
            GetCellData(xlWorkSheet1, newRowCount, 5) = GetCellData(xlWorkSheet2, i, 5) And _
            GetCellData(xlWorkSheet1, newRowCount, 6) <> GetCellData(xlWorkSheet2, i, 6) And _
            GetCellData(xlWorkSheet1, newRowCount, 7) = GetCellData(xlWorkSheet2, i, 7) And _
            GetCellData(xlWorkSheet1, newRowCount, 8) = GetCellData(xlWorkSheet2, i, 8) Then
            'DONE
            qtyChange = True
        ElseIf GetCellData(xlWorkSheet1, newRowCount, 1) = GetCellData(xlWorkSheet2, i, 1) And _
            GetCellData(xlWorkSheet1, newRowCount, 2) = GetCellData(xlWorkSheet2, i, 2) And _
            GetCellData(xlWorkSheet1, newRowCount, 3) = GetCellData(xlWorkSheet2, i, 3) And _
            GetCellData(xlWorkSheet1, newRowCount, 4) <> GetCellData(xlWorkSheet2, i, 4) And _
            GetCellData(xlWorkSheet1, newRowCount, 5) = GetCellData(xlWorkSheet2, i, 5) And _
            GetCellData(xlWorkSheet1, newRowCount, 6) = GetCellData(xlWorkSheet2, i, 6) And _
            GetCellData(xlWorkSheet1, newRowCount, 7) = GetCellData(xlWorkSheet2, i, 7) And _
            GetCellData(xlWorkSheet1, newRowCount, 8) = GetCellData(xlWorkSheet2, i, 8) Then
            'DONE
            mtlChange = True
        ElseIf GetCellData(xlWorkSheet1, newRowCount, 3) <> GetCellData(xlWorkSheet2, i, 3) And _
            GetCellData(xlWorkSheet1, newRowCount, 4) <> GetCellData(xlWorkSheet2, i, 4) Then

            If GetCellData(xlWorkSheet1, newRowCount + 1, 4) <> GetCellData(xlWorkSheet2, i, 4) Then
                newItem = True
            ElseIf GetCellData(xlWorkSheet1, newRowCount, 4) <> GetCellData(xlWorkSheet2, i + 1, 4) Then
                delItem = True
            End If
        End If

        'Procedure for each case
        If qtyChange Then
            xlWorkSheet3.Cells(w3row, 1) = GetCellData(xlWorkSheet2, i, 1)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 1), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Green

            xlWorkSheet3.Cells(w3row, 2) = GetCellData(xlWorkSheet2, i, 2)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 2), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Green

            xlWorkSheet3.Cells(w3row, 3) = GetCellData(xlWorkSheet2, i, 3)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 3), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Green

            xlWorkSheet3.Cells(w3row, 4) = GetCellData(xlWorkSheet2, i, 4)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 4), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Green

            xlWorkSheet3.Cells(w3row, 5) = GetCellData(xlWorkSheet2, i, 5)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 5), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Green

            xlWorkSheet3.Cells(w3row, 6) = GetCellData(xlWorkSheet2, i, 6)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 6), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Green

            xlWorkSheet3.Cells(w3row, 7) = GetCellData(xlWorkSheet2, i, 7)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 7), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Green

            xlWorkSheet3.Cells(w3row, 8) = GetCellData(xlWorkSheet2, i, 8)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 8), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Green

            newRowCount += 1
            w3row += 1
        ElseIf mtlChange Then
            xlWorkSheet3.Cells(w3row, 1) = GetCellData(xlWorkSheet2, i, 1)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 1), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Yellow

            xlWorkSheet3.Cells(w3row, 2) = GetCellData(xlWorkSheet2, i, 2)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 2), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Yellow

            xlWorkSheet3.Cells(w3row, 3) = GetCellData(xlWorkSheet2, i, 3)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 3), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Yellow

            xlWorkSheet3.Cells(w3row, 4) = GetCellData(xlWorkSheet2, i, 4)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 4), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Yellow

            xlWorkSheet3.Cells(w3row, 5) = GetCellData(xlWorkSheet2, i, 5)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 5), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Yellow

            xlWorkSheet3.Cells(w3row, 6) = GetCellData(xlWorkSheet2, i, 6)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 6), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Yellow

            xlWorkSheet3.Cells(w3row, 7) = GetCellData(xlWorkSheet2, i, 7)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 7), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Yellow

            xlWorkSheet3.Cells(w3row, 8) = GetCellData(xlWorkSheet2, i, 8)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 8), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Yellow

            newRowCount += 1
            w3row += 1
        ElseIf delItem Then
            xlWorkSheet3.Cells(w3row, 1) = GetCellData(xlWorkSheet1, newRowCount, 1)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 1), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Red

            xlWorkSheet3.Cells(w3row, 2) = GetCellData(xlWorkSheet1, newRowCount, 2)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 2), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Red

            xlWorkSheet3.Cells(w3row, 3) = GetCellData(xlWorkSheet1, newRowCount, 3)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 3), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Red

            xlWorkSheet3.Cells(w3row, 4) = GetCellData(xlWorkSheet1, newRowCount, 4)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 4), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Red

            xlWorkSheet3.Cells(w3row, 5) = GetCellData(xlWorkSheet1, newRowCount, 5)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 5), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Red

            xlWorkSheet3.Cells(w3row, 6) = GetCellData(xlWorkSheet1, newRowCount, 6)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 6), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Red

            xlWorkSheet3.Cells(w3row, 7) = GetCellData(xlWorkSheet1, newRowCount, 7)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 7), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Red

            xlWorkSheet3.Cells(w3row, 8) = GetCellData(xlWorkSheet1, newRowCount, 8)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 8), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Red

            newRowCount += 1
            i -= 1
            w3row += 1
        ElseIf newItem Then
            xlWorkSheet3.Cells(w3row, 1) = GetCellData(xlWorkSheet2, i, 1)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 1), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Blue

            xlWorkSheet3.Cells(w3row, 2) = GetCellData(xlWorkSheet2, i, 2)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 2), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Blue

            xlWorkSheet3.Cells(w3row, 3) = GetCellData(xlWorkSheet2, i, 3)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 3), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Blue

            xlWorkSheet3.Cells(w3row, 4) = GetCellData(xlWorkSheet2, i, 4)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 4), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Blue

            xlWorkSheet3.Cells(w3row, 5) = GetCellData(xlWorkSheet2, i, 5)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 5), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Blue

            xlWorkSheet3.Cells(w3row, 6) = GetCellData(xlWorkSheet2, i, 6)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 6), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Blue

            xlWorkSheet3.Cells(w3row, 7) = GetCellData(xlWorkSheet2, i, 7)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 7), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Blue

            xlWorkSheet3.Cells(w3row, 8) = GetCellData(xlWorkSheet2, i, 8)
            xlRange1 = CType(xlWorkSheet3.Cells(w3row, 8), Excel.Range)
            xlRange1.Font.Color = System.Drawing.Color.Blue

            w3row += 1
        End If

        qtyChange = False
        mtlChange = False
        newItem = False
        delItem = False
    Next

    'Save new spreadsheet [TEMP NAME]
    xlWorkBook3.SaveAs("C:\Users\Windows\Documents\Visual Studio 2013\Projects\test.xls", Excel.XlFileFormat.xlWorkbookNormal, misValue, misValue, misValue, misValue, _
                Excel.XlSaveAsAccessMode.xlExclusive, misValue, misValue, misValue, misValue, misValue)
    xlWorkBook3.Close(True, misValue, misValue)
    xlApp3.Quit()

    '----------------------------------
    'End of process, cleaning up CPU---
    xlWorkBook1.Close(True, misValue, misValue)
    xlApp1.Quit()

    xlWorkBook2.Close(True, misValue, misValue)
    xlApp2.Quit()

    ReleaseObject(xlWorkSheet1)
    ReleaseObject(xlWorkBook1)
    ReleaseObject(xlApp1)

    ReleaseObject(xlWorkSheet2)
    ReleaseObject(xlWorkBook2)
    ReleaseObject(xlApp2)

    ReleaseObject(xlWorkSheet3)
    ReleaseObject(xlWorkBook3)
    ReleaseObject(xlApp3)

    cmdFormat.Text = "Process complete. Compare new files?"
End Sub

编辑:什么不起作用?它会很好地跳过相同的行并检测单元格更改(我设置了第 4 列和第 6 列,它们将它们返回为绿色/黄色)但是一旦我的代码在旧工作表中找到已删除的条目/新工作表中的新条目,它就会搞砸.

这就是我认为它搞砸的地方:

ElseIf GetCellData(xlWorkSheet1, newRowCount, 3) <> GetCellData(xlWorkSheet2, i, 3) And _
        GetCellData(xlWorkSheet1, newRowCount, 4) <> GetCellData(xlWorkSheet2, i, 4) Then

        If GetCellData(xlWorkSheet1, newRowCount + 1, 4) <> GetCellData(xlWorkSheet2, i, 4) Then
            newItem = True
        ElseIf GetCellData(xlWorkSheet1, newRowCount, 4) <> GetCellData(xlWorkSheet2, i + 1, 4) Then
            delItem = True
        End If
    End If

如果有人能看到这个问题,请告诉我。或者,如果您对此有其他解决方案。谢谢!

【问题讨论】:

  • 怎么不工作了?我们需要细节。你的文字墙很吓人。
  • 我会用更好的解释来编辑它,并添加整个代码子。 @ryanyuyu
  • 任何时候你像这样修改 for 循环计数器,它可能会变得很奇怪。您的逻辑说“如果 Sheet1 的下一行不等于 Sheet2 的当前行,那么它是一个新项目。如果 Sheet1 的当前行不等于 Sheet2 的下一行,那么它是一个已删除的项目。这似乎有点倒退。另外,假设您有一个新项目,然后是一个已删除的项目。这不会破坏一切吗?
  • @user1274820 关于到达一个新项目,然后是一个已删除项目......你是对的。这就是破坏一切的原因。

标签: c# vb.net


【解决方案1】:

对不起,我没有得到更多帮助。这肯定有点棘手。我会亲自将每张工作表拉入数据表并在那里进行比较。这就是我用来在两组数据之间确定我的程序的新/已完成 QA 的方法:

http://i.imgur.com/iuI1dGL.png

我最终做的事情和你有点不同。

我使用这种方法将我需要的数据从excel文件中提取到数据表中。

这比使用 excel 互操作一次读取每一行要快得多。

获取 excel 数据并使用它来填充 DataTable:

//////////////////////////////////////////////////////////////////////////////////
//This function is absolute magic >.> - Fill DataTable with excel spreadsheet
//HDR=YES means "Spreadsheet has headers" Change to NO if not.
//name = "Log"; - This is the Sheet name to pull the data from
//////////////////////////////////////////////////////////////////////////////////
//oconn takes an SQL like command (Select Everything from name sheet) using con
//HDR=YES means that our data has headers :)
//////////////////////////////////////////////////////////////////////////////////
String constr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + copyToPath + ";Extended Properties='Excel 12.0 XML;HDR=YES;';";
OleDbConnection con = new OleDbConnection(constr);
OleDbCommand oconn = new OleDbCommand("Select * From [Log$]", con);
con.Open();
OleDbDataAdapter sda = new OleDbDataAdapter(oconn);
DataTable data = new DataTable();
sda.Fill(data);
con.Close();
//////////////////////////////////////////////////////////////////////////////////

这给我们留下了一个包含 Excel 电子表格的所有行/标题的 DataTable。

然后,我们可以使用相同的方法拉入第二个。

到那时,我们将能够比较 C# 中的数据,这在我的经验中要快得多。

最后,您可以使用 Excel Interop 导出到 excel,您只需打开一个实例。

【讨论】:

  • 是的 - 需要有比减少 for 循环 i 变量更好的方法。我正试图绕着它转,却无法自己尝试任何事情。
  • 基本上说,如果您发现两个不匹配的单元格 - 请检查其下方的单元格。如果这两个都不匹配,那么您拥有的既是新项目又是已删除项目,将它们都添加,然后继续。当然,这假设您不会同时添加/删除多个项目。情况可能并非如此。最好遍历每个文件以查找匹配项或不查找匹配项。使用密钥最容易做到这一点,但您可以使用当前数据。
  • 我一小时后回来,抱歉没能帮到你更多。这并不像你试图用你的旗帜那样简单。新项目和已删除项目很难确定。您必须搜索工作表 2 的整个文档以确定某个项目是否确实“已删除”。同样,您必须执行相同操作才能确定它是否实际上是“新”。
  • 感谢酷炫的功能。我将把现有的东西放在一边,并使用此代码开发一个新的解决方案。
  • 你已经是一个主要的帮助了。我正在使用您提供的功能(进行了一些调整),与 excel 对象相比,它的速度非常快。
猜你喜欢
  • 1970-01-01
  • 2021-11-30
  • 2014-06-08
  • 2019-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多