Table and Cell Data

Home Up Odds & Ends Photo Gallery Search Contact Me

 

 

The information in this website is provided without risk or obligation and free of charge.  However, if you have benefitted from my efforts here and would like to make a contribution to help me continue and maintain this work then any donation will be greatly appreciated. Please click the adjacent button to access PayPal.  Thank you.
 

This Microsoft Word Help and Tips Page provides my version of a Table & Cell Data macro that I find more reliable than the TableCellHelper macro provided by Microsoft in earlier Word versions and distributed with the Macros8.Dot template.  In fact I couldn't get Microsoft's version to work reliably at all.  If you are interested in experimenting with Microsoft's TableCellHelper macro you can download it from Macros8.Dot (Note: This opens a Word MVP FAQ page with a link to the Macros8.Dot file.)

I call my macro TableCellData.  Unlike WordPerfect, Word has a shortcoming when it comes to determining the location of the IP or selection in a table.  This can be frustrating when you are working in a table with many rows or columns.  TableCellData can provide this and other information about your tables as either a message box or status bar display.  You can initiate the display by firing the macro from a keyboard shortcut, toolbar icon or menu command.

The illustration below shows the standard status bar report for a single uniform table (i.e., a table with no split or merged cells)

Table cells can be merged or split.  For this reason, TableCellData reports the maximum "Max" column and row count.  For example, in the following table, cell C5 has been split into three cells.  Therefore there are now 12 Max columns.  While the hard column headings indicate the cursor is in column "J," notice the cursor is location is accurately reported as L5.  This would be important if you needed to reference this cells value in a calculation field.

TableCellData can also report the range of selected cells. This feature is only 100% accurate in uniform tables (i.e., tables without split or merged cells). 

Word can determine if a table has split or merged cells, but it can't determine if there are split or merged cells in the current selection.   Therefore, all selection span reports on tables that  contain split or merged cells are susceptible to error.  (Note:  TableCellHelper has the same problems but it doesn't tell you about it).

Reports for selections containing split or merged cells may or may not be accurate depending on the relationship of the selected cells to other split or merged cells.  This is shown in the following illustrations:

In this first illustration, the selection consist of the 6 cells A2, B2, C2, A3, B3 and C3.   The light orange cells are the result of a split.  The light green cells result from a merge. The column IDs compare to the header row column IDs and the range is unaffected by split and merged cells in the table.  The reported span span is accurate.  Using the span in a calculation produces the correct answer.


Here the selection appears blue and consist of the 3 cells split from the former cell F6 resulting in new cells F6, G6 and H6.  The reported span is accurate.  Using the span in a calculation produces the correct answer.


Here is were it starts getting ugly.  Cells I6 and J6 of the original table are merged in what appears to be a single cell spanning the header row column IDs I an J.  The selection appears to consist of cells H5, I5, J5,H6, and the merged cell, which left unaffected by other split or merged cells would be reported individually as I6.  Look at the reported range!!  Where did "K" come from??!  If you noticed the results of the calculation you might be getting the picture.  The split cells in the "F" column are actually F6, G6, and H6.  Therefore the selected cells are in fact H5, I5, J5, J6 and K6.  H6 is not in the selected range and K5 doesn't even exist!  The value in cell H6 is "5" which explains the apparent error in the calculation.

There is no readily avaliable VBA solution to this range reporting problem.  It is pretty much hit and miss and therefore I have provided an option in the TableCellHelper code to completely suppress span reports if the table contains split or merged cells.  An example of the suppressed report is shown below.

TableCellData will identify nested tables down two levels.  The following illustration will help you understand how nested tables are reported.  The cursor is located in cell A2 of the second table in cell B3 of the first table in cell B1 of the second table of the document.  While the table IDs are reported, only the cell ID of the lowest level nested cell is reported.  To determine the cell ID in the higher level tables, you must put the cursor directly in the cell proper (i.e, in the cell, but outside of any nested table in the cell).    

Here is the macro and function required to determine the table and cell data illustrated above:
Sub TableCellData()
Dim i&, oColMax&, oRowMax&, oCellCnt
Dim oColS$, oRowS$, oColE$, oRowE$
Dim Msg1$, Msg2$, Msg3$, Msg4$, Msg5$

If Application.Documents.Count Then
    With Selection
        If .Information(wdWithInTable) Then
            i = ActiveDocument.Range(0, .Tables(1).Range.End).Tables.Count
            Msg1$ = TableConfigID(i)
            oColMax = .Tables(1).Columns.Count
            oRowMax = .Tables(1).Rows.Count
            oCellCnt = .Tables(1).Range.Cells.Count
            Msg2$ = "/Max. columns: " & oColMax & "/" _
                            & "Max. rows: " & oRowMax
            Msg3$ = "Total cells: " & oCellCnt & ". "
            oColS = alphaChar(.Information(wdStartOfRangeColumnNumber))
            oRowS = .Information(wdStartOfRangeRowNumber)
            oColE = alphaChar(.Information(wdEndOfRangeColumnNumber))
            oRowE = .Information(wdEndOfRangeRowNumber)
            Select Case .Cells.Count
                Case Is < 2
                    Msg4$ = "At cell: " & oColS & oRowS & ". "
                    If Not .Tables(1).Uniform Then
                        Msg5$ = "This table contains split or merged cells."
                    End If
                Case Else
                    If .Tables(1).Uniform Then
                        Msg4$ = "Selection spans: " _
                                        & oColS & oRowS & ":" & oColE & oRowE & "."
                    Else
                       
'Suppress or report spans in tables with split or merged cells
                        'Msg4$ = "Table contains split/merged cells." _
                                         & " The span can not be positively determined."

                        Msg4$ = "Selection spans: " & oColS & oRowS & ":" _
                                        & oColE & oRowE & ". Span susceptible to" _
                                        & " error due to split/merged cells."
                        Msg5$ = ""
                End If
            End Select
           
'Can use message box, status bar, or both
            'MsgBox Msg1$ & Msg2$ & vbCr & vbCr & Msg3$ _
                            & vbCr & vbCr & Msg4$ & vbCr & vbCr & Msg5$, _
                            vbInformation + vbOKOnly, "Table Data"

            Application.StatusBar = Msg1$ & Msg2$ & "/" & Msg3$ & Msg4$ & Msg5$
        End If
    End With
End If
End Sub

Function TableConfigID(ByVal i As Long) As String
Dim TopTbl As Table, Nest1Tbl As Table, Nest2Tbl As Table
Dim x&, y&
Dim ttCell As Word.Cell, ntCell As Word.Cell
Dim tmpMsg1$, tmpMsg2$, tmpMsg3$

Set TopTbl = ActiveDocument.Tables(i)
tmpMsg1$ = "Table " & i
x = 0
For Each ttCell In TopTbl.Range.Cells
    If ttCell.Tables.Count > 0 Then
       For Each Nest1Tbl In ttCell.Tables
            x = x + 1
            If Selection.InRange(Nest1Tbl.Range) Then
                tmpMsg1$ = "Table " & i & "{Table " & x & "}"
            End If
            y = 0
            For Each ntCell In Nest1Tbl.Range.Cells
                If ntCell.Tables.Count > 0 Then
                   For Each Nest2Tbl In ntCell.Tables
                        y = y + 1
                        If Selection.InRange(Nest2Tbl.Range) Then
                            tmpMsg1$ = "Table " & i & "{Table " & x & "{Table " & y & "}}"
                        End If
                    Next Nest2Tbl
                End If
            Next ntCell
        Next Nest1Tbl
    End If
Next ttCell
TableConfigID = tmpMsg1$
End Function

Function alphaChar(pAribicNum As Integer) As String
Select Case pAribicNum
    Case Is < 27
        alphaChar = String(1, (pAribicNum + 64))
    Case Is < 53
        alphaChar = "A" & String(1, (pAribicNum - (26) + 64))
    Case Is >= 53
        alphaChar = "B" & String(1, (pAribicNum - (52) + 64))
End Select
End Function

To use TableCellData, simply copy the macro and two functions to a module in your VBA project.  For help with this, see fellow MVP Graham Mayor's Guide for Installing Macros.

 To assign TableCellData to a keyboard shortcut see How to assign a Word command or macro to a hot-key.  To assign to a menu (including mouse right button shortcut menu) or toolbar button, see How to assign a Word command or macro to a toolbar or menu.

I have my shortcut on the built-in Table menu:

With a bit of razzmatazz coding (and help from regular Word VBA newsgroup contributors "Jezebel" and Tony Jollans) I set it up so that the menu command is dimmed to mimic the Table Properties command whenever the selection is not in a table.

This is accomplished using a Class module and a WindowsChangeEvent.  It is hardly worth the extra coding, but I wanted to present the process for any users that might be interested.
1.  Create a Class module in the same Project as the macro (mine is in Normal.Dot)
2.  Name the Class myClass1
3.  Insert the following code in the Class:

     Option Explicit
     Private WithEvents mWordApp As Word.Application

     Private Sub Class_Initialize()
     Set mWordApp = Word.Application
     End Sub

     Private Sub mWordApp_WindowSelectionChange(ByVal oSel As Selection)
     Dim bSavedState As Boolean
     bSavedState = NormalTemplate.Saved
     CommandBars("Table").Controls("Table Data").Enabled = oSel.Information(wdWithInTable)
     NormalTemplate.Saved = bSavedState
     End Sub

4.  Insert the following code in the same module as the TableCellData  macro:

     Option Explicit
     Private myDynamicMenu As myClass1

     Sub SetMyClass1()
     Set myDynamicMenu = New myClass1
     End Sub

5.  Call the macro from an AUTOEXEC macro in the project:

     Sub AutoExec()
     SetMyClass1
     End Sub

Enjoy!!

Looking for something else?

Google