新奇的Word表格单元格合并
实例需求:Word文档中表格如下图左侧所示,不知道是某个系统导出的,还是某个神人的创意作品。总之,有点儿反人类,看起来有些费劲。现在需要整理为标准表格,并合并第一列和第2列的相关单元格,如下图中右侧所示。
具备Excel VBA使用的经验的小伙伴,可以会觉得合并单元格在Excel中就是个小儿科的课题,so easy。
但是使用VBA处理具有合并单元格的Word表格就不是那么容易了,合并单元格操作将影响单元格的行序号和列序号,如果处理不当,代码非常容易出现运行时错误5941(访问的成员不存在)。
实现过程分为如下几个步骤
- 删除第3列空单元格,对于前两列的非空值,需要做相应的移动,以避免丢失信息,注意表格中含有空行(3个单元格全部为空),也需要在此步骤中删除
- 遍历表格前两列,记录待合并单元格区域的起止行号
- 执行合并单元格操作
示例代码如下:
Sub MergeTab()Dim oTab As Table, r As Long, arSet oTab = ThisDocument.Tables(1)For r = oTab.Rows.Count To 1 Step -1If Len(oTab.Cell(r, 3).Range.Text) = 2 ThenIf Len(oTab.Cell(r, 2).Range.Text) = 2 ThenIf Len(oTab.Cell(r, 1).Range.Text) > 2 ThenoTab.Cell(r + 1, 1).Range.Text = Split(oTab.Cell(r, 1).Range.Text, vbCr)(0)End IfElseoTab.Cell(r + 1, 2).Range.Text = Split(oTab.Cell(r, 2).Range.Text, vbCr)(0)End IfoTab.Rows(r).DeleteEnd IfNextDim Col As New Collection, sRow1 As Long, eRow1 As Long, sRow2 As Long, eRow2 As LongFor r = 1 To oTab.Rows.CountIf Len(oTab.Cell(r, 1).Range.Text) = 2 TheneRow1 = rElseIf eRow1 > sRow1 ThenCol.Add Array(sRow1, eRow1, 1)eRow1 = rEnd IfsRow1 = rEnd IfIf Len(oTab.Cell(r, 2).Range.Text) = 2 TheneRow2 = rElseIf eRow2 > sRow2 ThenCol.Add Array(sRow2, eRow2, 2)eRow2 = rEnd IfsRow2 = rEnd IfNextIf eRow1 > sRow1 And eRow1 = oTab.Rows.Count Then Col.Add Array(sRow1, eRow1, 1)If eRow2 > sRow2 And eRow2 = oTab.Rows.Count Then Col.Add Array(sRow2, eRow2, 2)For r = Col.Count To 1 Step -1ar = Col.Item(r)oTab.Cell(ar(0), ar(2)).Merge MergeTo:=oTab.Cell(ar(1), ar(2))Next
End Sub
【代码解析】
第3行代码将当前文档中的第一个表格对象赋值给 oTab。
第4行代码开启循环,从表格最后一行向上倒序遍历。
第5行代码判断当前行第3列单元格内容长度是否为2(即空单元格)。
Cell(…).Range.Text属性返回值是一个字符串,包含单元格结束标记( Chr(13)和Chr(7))。这个标记是隐藏字符,Word应用程序界面中看不到这个标记。对于空白单元格(即里面没有任何文字或空格),Text属性实际返回两个字符(单元格结束标记)。
若第3列为空,第6行代码再判断第2列是否也为空。
若第2列为空,第7行代码判断第1列不为空,则将第1列内容复制到下一行第1列。
第8行代码使用 Split 函数截取文本内容中第一个换行符前的文本,即去除单元格结束标记。
第10行代码若第2列不为空,则将该列内容复制到下一行第2列。
第11行代码与第8行代码功能类似。
第13行代码删除当前行。
第16行代码定义变量,其中
- sRow1和eRow1记录第1列需要合并单元格的起始行和结束行
- sRow2和eRow2记录第2列需要合并单元格的起始行和结束行
第17行代码从第一行到最后一行的循环变量表格。
第18行代码判断当前行第1列单元格是否为空。
若为空,第19行代码则将当前行号记录为结束行 eRow1。
第21行代码判断如果 eRow1 大于 sRow1,说明存在连续空白区域,添加至集合 Col。
第22行代码将 eRow1 更新为当前行号。
第25行代码将 sRow1 更新为当前行号,用于下一个待合并区域的起始行。
第27~35行代码记录第2列合并单元格信息。
第37行代码判断如果 eRow1 大于 sRow1 且为最后一行,则将最后一段连续区域加入集合。
第32行代码判断如果 eRow2 大于 sRow2 且为最后一行,则同样将该区域加入集合。
第33行代码从集合最后一个元素开始向前倒序遍历。
第34行代码将集合中的数组取出赋值给变量 ar。
第35行代码执行表格单元格合并操作,将指定列指定范围单元格合并为一个单元格。