利用帖子here,我能够构建一个VBA宏来比较工作表之间的单元格以满足我的目的。但是,到目前为止,我还没有在A1范围内开始测试它。
当给出像B1:X50这样的范围时,我遇到一个问题,即纸张阵列的列尺寸的LBound是1而给定范围的开始处的列是2(B)。以下是我正在使用的代码的一部分:
'Define the range to be checked
strRangeToCheck = Summary_ws.Range("I2").Value
'Store the range to be checked on each sheet in an array
varSheetA = New_Data_ws.Range(strRangeToCheck)
varSheetB = Old_Data_ws.Range(strRangeToCheck)
'Clear current highlighted cells on data tabs
New_Data_ws.Cells.Interior.Color = xlNone
Old_Data_ws.Cells.Interior.Color = xlNone
'Initialize counter
Counter = 0
Counter_rng.Value = Counter
For iRow = LBound(varSheetA, 1) To UBound(varSheetA, 1)
For iCol = LBound(varSheetA, 2) To UBound(varSheetA, 2)
On Error GoTo Err_Handler
If IsError(New_Data_ws.Cells(iRow, iCol).Value) Or IsError(Old_Data_ws.Cells(iRow, iCol).Value) Then
Counter = Counter + 1
Error_Flag = True
Call Flag_Changes
ElseIf varSheetA(iRow, iCol) = varSheetB(iRow, iCol) And _
Len(varSheetA(iRow, iCol)) = Len(varSheetB(iRow, iCol)) Then
'Cells are identical and lengths match
'Do Nothing
Else 'Cells are different
Counter = Counter + 1 'increment counter
Error_Flag = False
Call Flag_Changes
End If
Next iCol
Next iRow
我能够评估strRangeToCheck以确定它是否从A列开始。根据该确定,是否可以手动设置工作表的LBound以匹配strRangeToCheck中的起始列?
答案 0 :(得分:1)
回答问题"然后可以手动设置工作表的LBound以匹配起始列",答案是否定的。 Range.Value
将始终返回一个下限为1的数组 - Excel负责创建返回的数组,并且您无法通过VBA更改该行为(即使您不愿意也不想这样做可以出于各种其他原因)。
解决方案是在将Range
引入数组之前,从传递的地址中创建.Value
作为中间步骤:
'Store the range to be checked on each sheet in an array
Dim newRange As Range
Dim oldRange As Range
Set newRange = New_Data_ws.Range(strRangeToCheck)
Set oldRange = Old_Data_ws.Range(strRangeToCheck)
varSheetA = newRange.Value
varSheetB = oldRange.Value
然后使用Worksheet.Cells
而不是在循环中使用Range.Cells
。如果您需要将其转换为工作表地址,则可以从A1
中的第一个Row
找到Range
的偏移量。使用B1:X50
的示例:
Dim example As Range
Set example = Sheet1.Range("B1:X50")
Debug.Print example.Columns(1).Column '<-- column 2
Debug.Print example.Rows(1).Row '<-- row 1
请注意,在上面的代码中,您只能在一行上使用工作表索引(虽然我不知道您在Call Flag_Changes
中正在做什么):
If IsError(New_Data_ws.Cells(iRow, iCol).Value) Or IsError(Old_Data_ws.Cells(iRow, iCol).Value) Then
根本不需要这样做。 New_Data_ws.Cells(iRow, iCol).Value
与varSheetA(iRow, iCol)
完全相同。那就是你把它拉进阵列的原因吧?只需用以下内容替换该行:
If IsError(varSheetA(iRow, iCol)) Or IsError(varSheetB(iRow, iCol)) Then
最后,您没有包含iRow
和iCol
的声明,但是根据匈牙利符号来判断它们是否被声明为Integer
您需要更改它们到Long
以避免溢出错误。如果他们 声明为Long
,那又是反对不使用匈牙利符号开始的另一个论点...
答案 1 :(得分:0)
我不确定这是否是实现建议的最优雅方式,但是这是工作代码,感谢共产国际:
'Store the range to be checked on each sheet in an array
Set newRange = New_Data_ws.Range(strRangeToCheck)
Set oldRange = Old_Data_ws.Range(strRangeToCheck)
varSheetA = newRange.Value
varSheetB = oldRange.Value
'Variables used to track difference between array start and given range start
row_diff = newRange.Rows(1).Row - 1
col_diff = newRange.Columns(1).Column - 1
'Loop through given range
For rngRow = newRange.Rows(1).Row To newRange.Rows.Count + row_diff
arrRow = rngRow - row_diff 'increment row of array being evaluated
For rngCol = newRange.Columns(1).Column To newRange.Columns.Count + col_diff
arrCol = rngCol - col_diff 'increment column of array being evaluated
On Error GoTo Err_Handler
If IsError(varSheetA(arrRow, arrCol)) Or IsError(varSheetB(arrRow, arrCol)) Then
Counter = Counter + 1
Error_Flag = True
Call Flag_Changes
ElseIf varSheetA(arrRow, arrCol) = varSheetB(arrRow, arrCol) And _
Len(varSheetA(arrRow, arrCol)) = Len(varSheetB(arrRow, arrCol)) Then
'Cells are identical and lengths match
'Do Nothing
Else 'Cells are different
Counter = Counter + 1 'increment counter
Error_Flag = False
Call Flag_Changes
End If
Next rngCol
Next rngRow
在我的Flag_Changes子目录中,我只是在突出显示两个工作表上的不同单元格,打印该单元格的地址,打印每个单元格的值以及差异(如果单元格是数字)。