我们来看一个Word文档中的两个表格,第一个表格如下:
RowIndex=1 ColumnIndex=1 |
RowIndex=1 ColumnIndex=2 |
RowIndex=1 ColumnIndex=3 |
RowIndex=1 ColumnIndex=4 |
RowIndex=2 ColumnIndex=1 |
RowIndex=2 ColumnIndex=2 |
RowIndex=2 ColumnIndex=3 |
RowIndex=2 ColumnIndex=4 |
RowIndex=3 ColumnIndex=1 |
RowIndex=3 ColumnIndex=2 |
RowIndex=3 ColumnIndex=3 |
RowIndex=3 ColumnIndex=4 |
第二个表格如下:
RowIndex=1 ColumnIndex=1 |
RowIndex=1 ColumnIndex=2 |
RowIndex=1 ColumnIndex=3 |
|
RowIndex=2 ColumnIndex=1 |
RowIndex=2 ColumnIndex=2 |
RowIndex=2 ColumnIndex=3 |
RowIndex=2 ColumnIndex=4 |
RowIndex=3 ColumnIndex=1 |
RowIndex=3 ColumnIndex=2 |
RowIndex=3 ColumnIndex=3 |
RowIndex=3 ColumnIndex=4 |
RowIndex=4 ColumnIndex=2 |
RowIndex=4 ColumnIndex=3 |
RowIndex=4 ColumnIndex=4 |
我们知道,如下代码可以取得表格对象“aTable”的总行数和总列数:
' 取得aTable的总列数
iCols = aTable.Columns.Count
' 取得aTable的总行数
iRows = aTable.Rows.Count
通常情况下,通过使用索引变量,可以完成表格全部单元格的遍历,示例代码如下:
' 使用索引变量i和j行序优先遍历表格中的单元格
For i = 1 To iRows
For j = 1 To iCols
' 将表格内容中最末的不能显示的字符替换为空后在提示框中显示
MsgBox Replace(aTable.Cell(i, j).Range.Text, Chr(13) & Chr(7), "")
Next
Next
但是,上述遍历代码在遍历第二个表格(存在合并单元格的表格)时,会出现运行时错误“无法访问此集合中单独的行或列,因为表格有纵向或横向合并的单元格。”。
表格中是否有合并单元格可以通过表格的“Uniform”属性检测,表格的“Uniform”属性为“True”则没有合并单元格,否则存在合并单元格。对于存在合并单元格的表格,不能采用上述使用索引的方式遍历单元格,而只能通过For each的方式来遍历单元格(当然没有合并单元格的表格也可以通过这种方式遍历)。下面的代码演示了针对有合并单元格的表格和没有合并单元格的表格采用不同的方式遍历所有单元格:
Sub 遍历word中表格单元格示例()
Dim aCell As Cell
Dim aTable As Table
Dim i, j, iCols, iRows As Integer
For Each aTable In ActiveDocument.Tables
With aTable
' 表格中不存在合并单元格,采用行列索引的方式遍历。
' 存在合并单元格的表格用这种方式遍历将发生运行时错误。
If .Uniform Then
iCols = aTable.Columns.Count
iRows = aTable.Rows.Count
For i = 1 To iRows
For j = 1 To iCols
MsgBox "uniform:" & vbCrLf & Replace(.Cell(i, j).Range.Text, Chr(13) & Chr(7), "")
Next
Next
Else ' 表格中存在合并单元格, 采用For Each方式遍历。不存在合并单元格的表格同样可用这种方式遍历。
For Each aCell In .Range.Cells
MsgBox Replace(aCell.Range.Text, Chr(13) & Chr(7), "")
Next
End If
End With
Next
End Sub
下面来个应用实例:遍历表格中的各单元格,如单元格中的内容是数字,则保留两位小数,否则维持原状不变:
Sub 将word表格中的数字单元格保留两位小数()
Dim aCell As Cell
Dim aTable As Table
Dim sText As String
For Each aTable In ActiveDocument.Tables
With aTable
For Each aCell In .Range.Cells
With aCell
' 记录单元格文本,需去掉最后的回车和响铃,否则不能得到正确结果
sText = Replace(.Range.Text, Chr(13) & Chr(7), "")
If IsNumeric(sText) Then
' 单元格中的内容是数字,则设置为保留两位小数格式
sText = VBA.Format(sText, "##0.00")
' 重写单元格内容
.Range.Text = sText
End If
End With
Next
End With
Next
End Sub
在涉及表格的Word VBA问题中,有一个难题是判断表格的单元格是否是合并单元格。Word中的表格不象Excel中的表格那样有一个MergCells属性直接判定单元格是否是合并单元格,但Word表格具有一个特性:
选择单元格所在行,该单元格在纵向没有合并多行时,Selection.Rows.Count的值为1,该单元格在纵向合并了多行时,Selection.Rows.Count的值为合并的行数。同样,选择单元格所在列,该单元格在横向没有合并多列时,Selection.Columns.Count的值为1,该单元格在横向合并了多列时,Selection.Columns.Count的值为合并的列数。
因此,在Word中要判断单元格是不是合并单元格尽管比较复杂,还是可以利用上述特性得到如下算法思路:
选定当前单元格所在行,如果选区的总行数大于1,那么当前单元格肯定在纵向合并了多行。如果总行数不大于1,再选定当前单元格所在列,如果选区的总列数大于1,那么当前单元格在横向合并了多列。如果选定当前单元格所在行和所在列时选区的总行数和总列数都是1,则当前单元格不是合并单元格。实现代码如下:
Sub 判断表格单元格是不是合并单元格()
Dim aCell As cell
Dim aTable As Table
Dim iRows As Integer
For Each aTable In ActiveDocument.Tables
With aTable
For Each aCell In .Range.Cells
With aCell
.Select
' 先选择单元格所在行
Selection.SelectRow
' 如果选区总行数大于1,则该单元格在纵向合并了多行
If Selection.Rows.Count > 1 Then
iRows = Selection.Rows.Count
' 再选择该单元格所在列,可以得到该单元格横向合并的列数
.Select
Selection.SelectColumn
MsgBox "RowIndex=" & .RowIndex & vbCrLf & "ColumnIndex=" & _
.ColumnIndex & vbCrLf & "此单元格是合并单元格,合并行数为:" & iRows & _
";合并列数为:" & Selection.Columns.Count
Else ' 如果选区总行数为1,则该单元格在纵向没有合并
.Select
' 再选择单元格所在列
Selection.SelectColumn
' 如果选区总列数大于1,则该单元格在横向合并了多列
If Selection.Columns.Count > 1 Then
MsgBox "RowIndex=" & .RowIndex & vbCrLf & "ColumnIndex=" & _
.ColumnIndex & vbCrLf & "此单元格是合并单元格,合并行数为1;" & _
"合并列数为:" & Selection.Columns.Count
Else ' 如果选区总列数为1,则该单元格在横向也没有合并,该单元格不是合并单元格
MsgBox "RowIndex=" & .RowIndex & vbCrLf & "ColumnIndex=" & _
.ColumnIndex & vbCrLf & "此单元格不是合并单元格"
End If
End If
End With
Next
End With
Next
End Sub