我尝试比较excel中的两个工作表,以便使用vba查找新的/更新的记录。 (假设工作表1已旧,而工作表2具有潜在的新/更新条目)
这些表格中存储的信息非常相似,只是顺序不同。
例如: 工作表1在E列中具有街道地址,而工作表2在列H中具有街道地址。还有许多其他列如此。
我不确定从哪里开始。我尝试通过切割和插入来重新排列第二张纸中的列,以匹配第一张纸中的列,但这很快就失控了。
此外,如果是新记录,则需要将其附加到数据的末尾。
答案 0 :(得分:0)
**已更新以允许定义“密钥”列。只需将'iKeyCol = 2'行更改为所需的列。
这是一些尝试的代码。我懒得去修改我正在使用的所有代码,所以其中一些可能对你来说是额外的。确保您的工作簿 1.至少有三张(名称'Sheet1,Sheet2,NewSheet') 2.具有Sheet1&的列标题。 Sheet2中 3. Col1必须在两张纸上都匹配 4.两列中的列数必须匹配。 其他col1,其他列可以是任何顺序。
将代码粘贴到新模块中并执行。
如果您有问题,请告诉我。
Option Explicit
' This module will compare differences between two worksheets.
Sub Compare106thWorksheets()
Dim iKeyCol As Integer
'>>>> CHANGE THE FOLLOWING LINE TO IDENTIFY THE KEY COLUMN
iKeyCol = 2
Dim i, i2, i3 As Integer
Dim iRow As Long
Dim iR1, iR2 As Long
Dim iC1, iC2 As Integer
Dim iColMap(30) As Integer
Dim iCol1, iCol2 As Integer
Dim LastRow1 As Long, LastRow2 As Long
Dim LastCol1 As Integer, LastCol2 As Integer
Dim MaxRow1 As Long
Dim MaxCol1 As Integer
Dim sFld1 As String, sFld2 As String
Dim sFN1, sFN2 As String
Dim rptWB As Workbook
Dim DiffCount As Long
Dim iLastRow, iLastColumn As Integer
Dim strDeleted, strInserted As String
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim wsChg As Worksheet
Dim iCHGRows As Long
Dim iCHGCols As Long
Application.ScreenUpdating = False
Application.StatusBar = "Creating the report..."
Set ws1 = ThisWorkbook.Worksheets("Sheet1")
Set ws2 = ThisWorkbook.Worksheets("Sheet2")
Set wsChg = ThisWorkbook.Worksheets("NewSheet")
With ws1.UsedRange ' Get used range of Sheet1
LastRow1 = .Rows.Count
LastCol1 = .Columns.Count
End With
With ws2.UsedRange ' Get used range of Sheet1
LastRow2 = .Rows.Count
LastCol2 = .Columns.Count
End With
With wsChg.UsedRange ' Get used range of Sheet1
iCHGRows = .Rows.Count
iCHGCols = LastCol1
End With
MaxRow1 = LastRow1
MaxCol1 = LastCol1
Debug.Print ws1.Name & " has " & LastRow1 & " rows and " & LastCol1 & " columns."
Debug.Print ws2.Name & " has " & LastRow2 & " rows and " & LastCol2 & " columns."
If MaxRow1 < LastRow2 Then MaxRow1 = LastRow2
If MaxCol1 < LastCol2 Then MaxCol1 = LastCol2
' Build a column map. Require both sheets to have the same names - but different order.
For i = 1 To 30
iColMap(i) = 0
Next i
For iC1 = 1 To MaxCol1
For i = 1 To LastCol2
If ws1.Cells(1, iC1) = ws2.Cells(1, i) Then
iColMap(iC1) = i
Exit For
End If
Next i
Next iC1
' Check if any column headers failed to match.
For i = 1 To MaxCol1
If iColMap(i) = 0 Then
MsgBox "Column named '" & ws1.Cells(1, i) & " not found in Sheet2. Please correct and start again."
GoTo Exit_Code
End If
Next i
strDeleted = "": strInserted = ""
iR2 = 1
DiffCount = 0
For iR1 = 1 To MaxRow1
If ws1.Cells(iR1, iKeyCol) <> ws2.Cells(iR2, iKeyCol) Then ' Cell is different - is it an ADD or Delete?
Debug.Print "Row: " & iR1 & vbTab & ws1.Cells(iR1, iKeyCol) & vbTab & "versus: " & ws2.Cells(iR2, iKeyCol)
sFld1 = Trim(ws1.Cells(iR1, iKeyCol).FormulaLocal)
sFld2 = Trim(ws2.Cells(iR2, iKeyCol).FormulaLocal)
If sFld1 < sFld2 Then
Debug.Print "Deleted Row " & ws1.Cells(iR1, iKeyCol)
DiffCount = DiffCount + 1
wsChg.Cells(DiffCount, iKeyCol) = "Deleted:"
wsChg.Cells(DiffCount, 2) = ws1.Cells(iR1, iKeyCol)
strDeleted = strDeleted & ws1.Cells(iR1, iKeyCol) & vbCrLf
iCHGRows = iCHGRows + 1
wsChg.Cells(iCHGRows, 1) = Now()
For i = 1 To LastCol1
wsChg.Cells(iCHGRows, i + 1) = ws1.Cells(iR1, i)
Next i
ws1.Rows(iR1).EntireRow.Delete
iR1 = iR1 - 1
GoTo Its_OK
ElseIf sFld1 > sFld2 Then
Debug.Print "Inserted Row " & ws2.Cells(iR1, iKeyCol)
Debug.Print "R1: " & iR1 & " R2: " & iR2 & vbTab & ws1.Cells(iR1, iKeyCol) & vbTab & "versus: " & ws2.Cells(iR2, iKeyCol)
DiffCount = DiffCount + 1
strInserted = strInserted & ws2.Cells(iR2, iKeyCol) & vbCrLf
ws1.Rows(iR1).EntireRow.Insert
For i = 1 To LastCol1
ws1.Cells(iR1, i) = ws2.Cells(iR2, iColMap(i))
Next i
iR2 = iR2 + 1
GoTo Its_OK
Else
iR2 = iR2 + 1
End If
Else ' Values are the same
iR2 = iR2 + 1
End If
Its_OK:
Next iR1
Debug.Print "Deleted:"
Debug.Print strDeleted
Debug.Print "------------------------------------------------------------------"
Debug.Print "Inserted:"
Debug.Print strInserted
Debug.Print "------------------------------------------------------------------"
For iRow = 2 To LastRow2
Application.StatusBar = "Comparing cells " & Format(iCol1 / MaxCol1, "0 %") & "..."
For iCol1 = 1 To LastCol1
iCol2 = iColMap(iCol1)
sFld1 = ""
sFld2 = ""
On Error Resume Next
sFld1 = ws1.Cells(iRow, iCol1).FormulaLocal
sFld2 = ws2.Cells(iRow, iCol2).FormulaLocal
On Error GoTo 0
If sFld1 <> sFld2 Then
Debug.Print "Row: " & iRow & vbTab & ws1.Cells(iRow, iCol1) & vbTab & "versus: " & ws2.Cells(iRow, iCol2)
DiffCount = DiffCount + 1
wsChg.Cells(DiffCount, 1) = ws1.Cells(iRow, iKeyCol)
wsChg.Cells(DiffCount, 2) = ws1.Cells(1, iCol1)
wsChg.Cells(DiffCount, 3) = sFld1
wsChg.Cells(DiffCount, 4) = sFld2
ws1.Cells(iRow, iCol1).FormulaLocal = ws2.Cells(iRow, iCol2).FormulaLocal
End If
Next iCol1
Next iRow
wsChg.Activate
Application.StatusBar = "Formatting the report..."
With Range(Cells(1, 1), Cells(MaxRow1, MaxCol1))
.Interior.ColorIndex = 19
With .Borders(xlEdgeTop)
.LineStyle = xlContinuous
.Weight = xlHairline
End With
With .Borders(xlEdgeRight)
.LineStyle = xlContinuous
.Weight = xlHairline
End With
With .Borders(xlEdgeLeft)
.LineStyle = xlContinuous
.Weight = xlHairline
End With
With .Borders(xlEdgeBottom)
.LineStyle = xlContinuous
.Weight = xlHairline
End With
On Error Resume Next
With .Borders(xlInsideHorizontal)
.LineStyle = xlContinuous
.Weight = xlHairline
End With
With .Borders(xlInsideVertical)
.LineStyle = xlContinuous
.Weight = xlHairline
End With
On Error GoTo 0
End With
Columns("A:IV").ColumnWidth = 20
MsgBox DiffCount & " cells contain different formulas!", vbInformation, _
"Compare " & ws1.Name & " with " & ws2.Name
Exit_Code:
Application.StatusBar = False
Application.ScreenUpdating = True
End Sub