Reputation: 21
In a MS Word (2016) subroutine (macro), I am trying to confirm if a table containing the current user selection on a subsequent macro call is the same table as the one selected on a previous call and preserved in static variables.
I confirm that the selection is within a table using .Information
and have saved the previous table as a Variant object Set Tbl1 = Selection.Tables(1)
. However, when I try to test if the second table is the same object using Tbl1 Is Tbl2
, the result is False
even when the tables are known to be the same and no other changes have occurred to the document.
Moreover, even (in a document containing several tables) the test ActiveDocument.Tables(1) Is ActiveDocument.Tables(1)
results in False
, when I would expect these to be exactly the same Object. Compare Excel ActiveSheet.ListObjects(1) Is ActiveSheet.ListObjects(1)
which is True
.
Can anyone explain this (or reveal the error in my test)?
I could solve my identification problem by, eg, comparing some table content or feature, but this is unreliable (due to possible replication in another table), or by uniquely setting an often unused table property, eg, .Descr
or .Title
, or by wrapping the table in a Bookmark (which is at least uniquely identifiable by its .Name
, though Bookmarks, too, fail the Is
test above), but I would rather not have to modify the table or the document simply in order to do the test. I could also compare the table locations, eg, by Tbl1.Range.Start
, but this also could be unreliable if the document has been modified between selections/calls. Any other suggestions? Does Word not have any kind of unique table identifier/property?
Added background:-
I frequently have long Word tables (maybe over several pages) in which I have merged (some) cells horizontally and/or vertically. If I later need to change the width of a 'notional' column, this can be very tedious, especially if several shorter tables have been joined and the notional columns don't even align. NB I appreciate that Word doesn't preserve any understanding of the uniform, rectangular column structure that would have existed before any merging - a 'merged' cell is just another cell, and a 'merged' table simply has varying numbers of odd-sized cells ('columns') per row; and it's even messier with vertical merging.
Even though Word has a nice facility to click & drag a left/right cell boundary, and all cell 'columns' with the same position will move together, this is awkward to use successfully on long tables, especial if they have similar but not identical cell boundaries. So I wanted to write a macro that would let me pre-set desired boundaries for 'notional' columns (eg, using the widths of a reference row having the maximum number of cells) and apply them to the whole table, making allowance for 'merged' cells that appeared to span more than one of these reference row columns. I anticipated that I might not find a fully successful algorithm for doing this and that I might keep having to relinquish control to the user to manually adjust 'awkward' rows and then restart the automatic process. Hence the need to verify that, when the macro is re-called, the same table is being worked on (even though some aspects of it have changed).
There are several ways round this identification problem that are probably good enough in practice (eg, based on range start/end points, etc) but I was intrigued that my initial supposition that I would be able to compare Table objects directly (as I thought I could in Excel) didn't seem to work in Word. I am surprised that a Word table doesn't seem to maintain an 'identity' that survives document editing, either inside or outside the table.
Further Info:-
In Excel, where cell D6 is within a table and is selected:
ActiveSheet.ListObjects(1) Is ActiveSheet.ListObjects(1)
-> true;
Range("D6").ListObject Is Range("D6").ListObject
-> false;
Selection.ListObject Is Selection.ListObject
-> false.
So, even here, some 'derived' objects (eg, table from cell or selection) do not seem to be exactly equivalent even though they purport to represent the same entity on the worksheet. It would still be nice to have some technical explanation for these phenomena, if anyone can oblige, but it seems clear that I cannot just compare objects using Is
in the way I was hoping.
Upvotes: 0
Views: 142
Reputation: 3387
It seems that the Tables
collection does not keep a list of pointers based on the result of running this sub:
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
Running the above sub twice on the same document that has 4 tables return a result which is puzzling since the pointers are totally different despite no changes has been made:
1440600498992
1440600502352
1440600503472
1440600499440
=========
1439972070768
1439972068416
1439972065616
1439972066624
=========
Using InRange
method, below sub will work as long as the table previously called is not moved/cut-paste onto other part of the document (which in this case, will return Error 5825 - Object has been deleted
that I suppose you can make a handler for this scenario):
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
Upvotes: 0