若读者还不了解Beyond Compare(后文将统一使用简称:BC)这款软件及其下载地址等,或许您需要先阅读我的前置博客:Excel入门指导中的第4.2小节,包括掌握“工作簿”、“工作表”、“记录”、“字段”等基本术语。
表格对比的基本对象,应该是两张二维表。所以正文集中在第2节描述。最后会在第3节,讲述一点工作簿对比时提高效率的小技巧。本文相关附件下载:http://pan.baidu.com/s/1o6L3xlK。
其实我用BC还不是特别多,若读者有发现文中阐述错误的地方,望批评指正。
BC对要进行比较的电子表格格式要求比较严,首先,为了排除杂项干扰,我们用两个工作簿里正好都只有一张工作表的文档进行对比。两份表格,一份代表旧数据,一份代表新数据,格式必须满足:①表头只有一行,没有合并单元格;②两份表格的表头模板完全一致(相同字段所在列也必须相同);③整份表格左上角在[A1]单元格处,记录内容从第2行开始。
如上图,为了方便讲解,我将新旧数据先放在一张工作表里介绍。左边是旧数据,右边是新数据。被矩形框包含的三条记录是“删除”掉的记录,被椭圆框包含的三条记录是“新增”的记录。其它是信息未变或部分字段值更改的记录。
我用红色字体标记出的更改部分,只是为了方便说明和理解,实际工作中,这些记录是没有高亮显示差异,以及乱序的。但这两点都不会影响BC的比较算法。BC只考虑内容上的匹配,不考虑格式,在结果输出中,默认用黑色字体,有差异的部分用红色字体显示。
将上述新旧数据分别放到“旧.xlsx”,“新.xlsx”,并打乱记录顺序后,就可以用BC开始比较了。
如下图,选中两个文件后,点击鼠标右键,选择椭圆框处的选项,就能用BC打开进行两个文件的对比了。
打开后,常用的功能都是见名知意的:下图中,椭圆框处的部分是显示的内容控制,表示显示“全部”结果,或者只显示“有差别”的结果;矩形框处的部分,主要是设置列为“关键列”还是“不重要的列”,默认会以第一列为关键列。
为了和后文内容相对应,注意这里旧表在左,新表在右。可以用”交换”按钮改变左右顺序。
多操作,熟悉一些基本功能后,我们开始进入重点。
“文件比较”是个很模糊的概念,具体要如何比?明确要做什么很重要,所以我结合BC的功能定义了一套规则:
~
以上述测试数据为例,理想的结果是输出下图的结论([变化情况]字段未填的代表“不变”):
提示1:Excel有按颜色筛选的功能。
提示2:图中[H11]也是设置为“红色字体”属性的,只是因为没有内容所以“表现”不出来,但在筛选的时候,[H11]会被正确的归到“红色字体”。
选择“会话(S)->表格比较(B) 报告(P)…”,在弹出的窗口中,设置下图中三处选项:
备注:有兴趣的读者,可以在选项窗口中,更改成其它选项,试试不同的报告效果。
选择“在浏览器中查看”,可以直接在浏览器看到对比结果。然后从浏览器复制,或者在窗口中直接选择“复制到剪切板”,将结果粘贴到Excel,删除额外信息(前5行)后,效果如下:
有了2.4小节BC输出的结果,理论上就可以完成我们需要的目标表格了。但每次手动操作毕竟太麻烦,所以我写了一个自动化程序。这里先介绍使用方法与结果,在2.7选读小节介绍VBA程序。
打开附件中的“BC对比讲解x工具薄.xlsm”,将BC运行出的结果,粘贴至“3-BC出来的结果”,将旧表数据粘贴至“4-旧表->最终报表”,然后进入“程序按钮”工作表,点击“对BC输出的结果深加工”,等待程序运行结束即可。
备注1:只要“3-BC出来的结果”和“4-旧表->最终报表”数据对应,且注意新旧数据顺序,程序是可以通用的。
备注2:程序会把BC结果中的格式一同复制。若不喜欢其格式,只需事先对BC的结果进行格式修改即可。
备注3:发现此处结果与之前的目标有些许差别。但只要关键列设置得当,BC得出的结论还是比较精确,无法逆推导致分析错误的记录很少。或者这里可以不分析“变更”,而是采用全部当成“删除”、“新增”的极端手段来处理结果。
附件“BC对比讲解x工具薄.xlsm”中有两个模块的代码,主要代码在“对BC输出的结果深加工”模块,其中调用了一些“stdvba”模块的内容,而“stdvba”是我个人收集的一些常用的函数、方法等,以后有机会我会写博客再介绍。以下是“对BC输出的结果深加工”模块的完整代码:
Option Explicit Function has下划线(rng As Range) As Boolean has下划线 = Not rng.Borders(xlEdgeBottom).LineStyle = xlNone End Function Private Sub 根据BC对比结果回填旧表(旧表 As Worksheet, 对比结果表 As Worksheet) '(1)表头更新 Dim 字段数 As Long 字段数 = 对比结果表.UsedRange.Columns.Count - 2 '填充字段名 旧表.Cells(1, 字段数 + 1) = "变化情况" 对比结果表.Cells(1, 3).Resize(1, 字段数).Copy 旧表.Cells(1, 字段数 + 2).Resize(1, 字段数).PasteSpecial xlPasteValues '设置颜色 旧表.Cells(1, 字段数 + 1).Resize(1, 字段数 + 1).Interior.Color = 额外字段颜色 '(2)遍历BC的结果进行加工 Dim p As Range, q As Range Dim 最后一行 As Long Set p = 对比结果表.Cells(2, 1) With 旧表 最后一行 = .Cells(.Rows.Count, 1).End(xlUp).Row Do While (p <> "" Or p.Offset(0, 1) <> "") If has下划线(p) Then If p = "" Then '新增 最后一行 = 最后一行 + 1 p.Offset(0, 2).Resize(1, 字段数).Copy .Cells(最后一行, 1).Resize(1, 字段数) .Cells(最后一行, 字段数 + 1) = "新增" Else '删除 .Cells(p, 字段数 + 1) = "删除" End If Else '变更类型 .Cells(p, 字段数 + 1) = "变更" p.Offset(0, 2).Resize(1, 字段数).Copy .Cells(p, 字段数 + 2).Resize(1, 字段数) Set p = p.Offset(1, 0) End If Set p = p.Offset(1, 0) Loop End With End Sub Sub main() Call 程序初始化与反初始化(True) Call 根据BC对比结果回填旧表(sheets("4-旧表->最终报表"), sheets("3-BC出来的结果")) Call 程序初始化与反初始化(False) End Sub
main过程作为外部接口的起始调用函数,给“根据BC对比结果回填旧表”这个sub传递需要处理的两张表格参数。“根据BC对比结果回填旧表”模块先对目标表格增加必要的表头,然后对BC的结果按行遍历,处理至目标表格。
前文讲述了只有一个工作表的工作薄如何进行对比。
如果遇到一个工作薄里工作表不只一张,则此时要注意:用BC对比两个工作薄时,BC只会以工作薄保存时所停留的工作表为准,进行两个工作表的对比。
如果有同一个内容的新旧两个版本工作薄,里面都有二三十张表格,那么每次选择指定表格,保存关闭后用BC进行对比,这操作不繁琐死?
其实不用这么麻烦,用BC打开两个工作薄进行对比后,依次选择两个工作薄里需要比较的表格,按“Ctrl+S”(不必关闭工作薄),然后再回到BC的对比界面,会有如下的提示窗口:
将左右两边的文件都重载,新的表格对比结果就出来了。熟练后,多工作表的对比操作还是很快的。