在MS Word(2016)子例程(宏)中,我试图确认包含后续宏调用上当前用户选择的表是否与之前调用中选择的表相同,并保存在静态变量中。
我确认选择是在使用.Information
的表内,并且已将前一个表保存为变体对象Set Tbl1 = Selection.Tables(1)
。但是,当我尝试使用Tbl1 Is Tbl2
测试第二个表是否为相同对象时,结果是False
,即使已知表是相同的并且没有其他更改发生在文档中。
此外,即使(在包含几个表的文档中)测试ActiveDocument.Tables(1) Is ActiveDocument.Tables(1)
的结果是False
,当我期望这些是完全相同的对象时。比较ExcelActiveSheet.ListObjects(1) Is ActiveSheet.ListObjects(1)
和True
。
谁能解释这个(或揭示我的测试中的错误)?
我可以解决我的身份问题,例如,一些比较表内容或功能,但这是不可靠的(由于可能的复制在另一个表),或通过独特的设置通常未使用的表属性,如.Descr
或.Title
,或通过包装表在一个书签(至少这是唯一标识.Name
,尽管书签,也失败Is
测试),但我宁愿没有修改表格或文档只是为了做测试。我也可以比较表位置,例如,通过Tbl1.Range.Start
,但如果文档在选择/调用之间被修改,这也可能是不可靠的。还有其他建议吗?Word没有任何类型的唯一表标识符/属性吗?
添加背景:-
我经常有很长的Word表(可能超过几页),我在其中水平和/或垂直合并(一些)单元格。如果我稍后需要更改"名义"列的宽度,这可能会非常繁琐,特别是如果几个较短的表已经连接并且名义列甚至没有对齐。NB我很欣赏Word没有保留任何对合并之前存在的统一的矩形列结构的理解——"合并"的单元格只是另一个单元格,"合并"的表只是每行有不同数量的奇数大小的单元格("列");垂直合并就更麻烦了。
尽管Word有一个很好的工具来点击&拖动左/右单元格边界,所有具有相同位置的单元格"列"将一起移动,这在长表上成功使用是尴尬的,特别是如果它们具有相似但不相同的单元格边界。所以我想写一个宏,让我预先设置所需的边界为"名义"列(例如,使用具有最大数量的单元格的参考行的宽度),并将它们应用到整个表,使"合并"的单元格似乎跨越一个以上的这些参考行列。我预计我可能找不到一个完全成功的算法来做这件事,而且我可能不得不放弃对用户手动调整"尴尬"行的控制权,然后重新启动自动过程。因此,需要验证当重新调用宏时,是否正在处理同一表(即使它的某些方面发生了变化)。
有几种方法可以解决这个识别问题,在实践中可能足够好(例如,基于范围开始/结束点等),但我很好奇,我最初的假设,我将能够直接比较表对象(因为我认为我可以在Excel中)似乎在Word中不起作用。我很惊讶,一个Word表似乎没有保持一个"身份",在文档编辑中幸存下来,无论是在表内还是在表外。
进一步信息:-
在Excel中,单元格D6在一个表中并被选中:ActiveSheet.ListObjects(1) Is ActiveSheet.ListObjects(1)
→真正;Range("D6").ListObject Is Range("D6").ListObject
→虚假的;Selection.ListObject Is Selection.ListObject
→假的。
因此,即使在这里,一些"派生"对象(例如,来自单元格或选择的表)似乎并不完全等同,即使它们声称在工作表上表示相同的实体。对这些现象有一些技术上的解释仍然是很好的,如果有人能强迫,但很明显,我不能像我希望的那样使用Is
来比较对象。
似乎Tables
集合没有根据运行此子的结果保留指针列表:
Sub GetTablesPointer()
Dim i As Long
For i = 1 To ThisDocument.Tables.Count
Debug.Print ObjPtr(ThisDocument.Tables(i))
Next i
Debug.Print "========="
End Sub
在有4个表的同一文档上运行上述子函数两次,返回一个令人困惑的结果,因为指针完全不同,尽管没有做任何更改:
1440600498992
1440600502352
1440600503472
1440600499440
=========
1439972070768
1439972068416
1439972065616
1439972066624
=========
使用InRange
方法,只要之前调用的表没有移动/剪切粘贴到文档的其他部分(在这种情况下,将返回Error 5825 - Object has been deleted
,我想你可以为这种情况做一个处理程序),下面的子将工作:
Sub Test()
Static wdTable As Table
If Selection.Information(wdWithInTable) Then
If wdTable Is Nothing Then
Set wdTable = Selection.Tables(1)
Else
If Selection.Range.InRange(wdTable.Range) Then
Debug.Print "Same table"
Else
Debug.Print "Different table"
Set wdTable = Selection.Tables(1)
End If
End If
End If
End Sub