Table Styles

This article may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. To maintain the flow of the article, we've left these URLs in the text, but disabled the links.

VBA Hacker

This content is no longer actively maintained. It is provided as is, for anyone who may still be using these technologies, with no warranties or claims of accuracy with regard to the most recent product version or service release.

Creating Consistent Tables with Named Formats

By Romke Soldaat

Styles have been with Word from its earliest MS-DOS versions in the mid eighties. They've become such an integrated part of this word processor that you can't even create a document without them. According to Microsoft: "A style is a set of formatting characteristics that you can apply to text in your document to quickly change its appearance. When you apply a style, you apply a whole group of formats in one simple task."

Sure, styles are great. They're so powerful and flexible that I've often wondered why our friends in Redmond never thought of applying the style concept to Word's table feature. The closest you can get to easy table formatting is by using the options in the Table AutoFormat dialog box. But the silly names used for the formats don't make them easy to remember and use. Would you know the difference between "Classic 1" and "Classic 4"? What makes the "Elegant" format elegant, and what's so professional about the "Professional" format? And do the three "Colorful" formats still deserve their name if they turn into shades of gray when you clear the Colors checkbox in the AutoFormat dialog box?

In this article I'll introduce a way to personalize your table formatting by creating Table Styles. With the application in the download file (see end of article for download details), you can format your tables using styles that have names that make sense to you, such as "Sales report," "Zebra stripes," or "Black header above white rows" (see FIGURE 1). There's even an option to apply an identical style to all tables in a document, so you don't have to format each table separately.


FIGURE 1: The official format names (clockwise from top left) are Simple 3, Colorful 1, Columns 5, and List 8. By creating Table Styles, you could name them "Black Header," "Pistachio," "White and gray columns," and "Symphony in Pink and Yellow."

AutoFormatting Tables

When you select Table AutoFormat from the Table menu (while the insertion point is inside a table), the dialog box shown in FIGURE 2 is displayed. This dialog box lets you choose from no fewer than 42 predefined formats, and within each format, you can apply or remove up to nine sub-formats. Since the preview is fully interactive, you can see the effect of your choice immediately. After clicking the OK button, the selected formats are applied to the underlying table.


FIGURE 2: Powerful formatting, but silly format names.

The VBA way. Although Microsoft doesn't explicitly say so, there are two ways to AutoFormat tables from a macro. VBA Help only mentions the AutoFormat method, which uses the following syntax:

expression.AutoFormat(Format, ApplyBorders, ApplyShading, _
        ApplyFont, ApplyColor, ApplyHeadingRows, ApplyLastRow, _
        ApplyFirstColumn,  ApplyLastColumn, AutoFit) 

In this syntax, expression must return a Table object, and all other (optional) parameters are treated as Variants. The Format parameter must be one of the WdTableFormat constants, or its matching numeric value (see FIGURE 3).

WdTableFormat constants

Value

wdTableFormatNone

0

wdTableFormatSimple1

1

wdTableFormatSimple2

2

wdTableFormatSimple3

3

wdTableFormatClassic1

4

wdTableFormatClassic2

5

wdTableFormatClassic3

6

wdTableFormatClassic4

7

wdTableFormatColorful1

8

wdTableFormatColorful2

9

wdTableFormatColorful3

10

wdTableFormatColumns1

11

wdTableFormatColumns2

12

wdTableFormatColumns3

13

wdTableFormatColumns4

14

wdTableFormatColumns5

15

wdTableFormatGrid1

16

wdTableFormatGrid2

17

wdTableFormatGrid3

18

wdTableFormatGrid4

19

wdTableFormatGrid5

20

wdTableFormatGrid6

21

wdTableFormatGrid7

22

wdTableFormatGrid8

23

wdTableFormatList1

24

wdTableFormatList2

25

wdTableFormatList3

26

wdTableFormatList4

27

wdTableFormatList5

28

wdTableFormatList6

29

wdTableFormatList7

30

wdTableFormatList8

31

wdTableFormat3DEffects1

32

wdTableFormat3DEffects2

33

wdTableFormat3DEffects3

34

wdTableFormatContemporary

35

wdTableFormatElegant

36

wdTableFormatProfessional

37

wdTableFormatSubtle1

38

wdTableFormatSubtle2

39

wdTableFormatWeb1

40

wdTableFormatWeb2

41

wdTableFormatWeb3

42

FIGURE 3: WdTableFormat constants.

If no format is specified, Word assumes wdTableFormatSimple1 (value 1). All other nine parameters must be set to True or False, corresponding to the status of the checkboxes in the dialog box. If omitted, these values default to True, except ApplyLastRow and ApplyLastColumn, which are assumed to be False if no value is specified. The instruction in FIGURE 4 demonstrates the AutoFormat method.

With Selection.Tables(1)  ' First table in the selection. 
  .AutoFormat _
    Format:=wdTableFormat3DEffects1,_
    ApplyBorders:= True, _
    ApplyShading:= True, _
    ApplyFont:= True, _
    ApplyColor:= True, _
    ApplyHeadingRows:= True, _
    ApplyLastRow:= True, _
    ApplyFirstColumn:= True, _
    ApplyLastColumn:= True, _
    AutoFit:= True
End With

FIGURE 4: The AutoFormat method.

The second method to AutoFormat a table is by directly communicating with the Table AutoFormat dialog box. Like all Word's dialog boxes, it's part of the Dialogs collection, so you can set its arguments from VBA code, and use the Execute method to make the settings active without displaying the dialog box. The code in FIGURE 5 applies the same table formatting as the instruction in FIGURE 4.

With Dialogs(wdDialogTableAutoFormat) 
  .Format = wdTableFormat3DEffects1
  .Borders = True
  .Shading = True
  .Font = True
  .Color = True
  .HeadingRows = True
  .LastRow = True
  .FirstColumn = True
  .LastColumn = True
  .AutoFit = True
  .Execute  ' Apply the settings. 
End With

FIGURE 5: The Dialog method.

The difference between these two methods is that the AutoFormat method can be applied to any table in any open document, no matter where the insertion point is. The Dialog method can only be used if the insertion point is inside a table.

On the other hand, the first method doesn't allow you to retrieve a table's AutoFormat settings, with the exception of the main format itself, which you can obtain using the AutoFormatType property of the Table object. That's a serious omission. Microsoft could have done a better job if AutoFormat had been an object with read/write properties, just as the CalloutFormat, ParagraphFormat, and PictureFormat objects.

Fortunately, the Dialog method is more generous with information, even though you can only use it if the insertion point is in a table. FIGURE 6 demonstrates how you can get the status of any AutoFormat setting in the active table. (Note that, unlike checkboxes in Microsoft forms, checkboxes in Word's internal dialog boxes return 1 if they are checked, not -1.)

With Dialogs(wdDialogTableAutoFormat) 
  FormatChosen = .Format              ' 0 - 42
  BordersActivated = .Borders         ' 0 or 1
  ShadingActivated = .Shading         ' 0 or 1
  FontActivated = .Font               ' 0 or 1
  ColorActivated = .Color             ' 0 or 1
  HeadingRowsActivated = .HeadingRows ' 0 or 1
  LastRowActivated = .LastRow         ' 0 or 1
  FirstColumnActivated = .FirstColumn ' 0 or 1
  LastColumnActivated .LastColumn   ' 0 or 1
  AutoFitActivated = .AutoFit         ' 0 or 1
End With

FIGURE 6: You can obtain the status of any AutoFormat setting in the active table.

Defining Table Styles

The table styles we'll be using in this project must be based on one of the 43 predefined formats; any additional manual formatting isn't taken into account. If this sounds like a limitation, remember that you can apply up to nine sub-formats within each main format, so you have around 3,000 variations at your disposal. Just experiment a bit with the Borders, Color, and Shading checkboxes in the dialog box, and you'll see how versatile table auto-formatting can be.

Once you've found the right combination of main format and sub-formats, you can assign a meaningful name to the result, just as you would do with paragraph and character styles. After that, you can re-apply your table style, simply by selecting its name from your list of available styles. (We'll look at the interface later.)

Retrieving table style definitions. After you've used the Table AutoFormat dialog box or VBA code to format a table, Word "remembers" your settings. If you select the table again, and redisplay the dialog box, you'll see that your original format and sub-formats are pre-selected. This must mean that Word saves the AutoFormat information inside the table. You can get part of this information by looking at the table's AutoFormatType property. This read-only property returns a Long value in the range 0-42, corresponding to the values shown in FIGURE 3.

However, there are no documented table properties that tell you which of the nine sub-formats are applied. The only clue I see in the Object Browser is a series of WdTableFormatApply constants; their values are shown in FIGURE 7. This is an interesting range. If you're familiar with the binary system, you'll see immediately that these values are bit settings. If this sounds foreign to you, read on for a simplified explanation.

WdTableFormatApply constants

Value

wdTableFormatApplyBorders

1

wdTableFormatApplyShading

2

wdTableFormatApplyFont

4

wdTableFormatApplyColor

8

wdTableFormatApplyAutoFit

16

wdTableFormatApplyHeadingRows

32

wdTableFormatApplyLastRow

64

wdTableFormatApplyFirstColumn

128

wdTableFormatApplyLastColumn

256

FIGURE 7: WdTableFormatApply constants. The values represent bit settings.

Hacking Bits

Computers don't know anything about our decimal system (which is based on the fact that humans happen to have 10 fingers). Computers can only think in two values - 0 and 1 - so numbers must be expressed as a combination of 0s and 1s. For example, the decimal number 343 is expressed as the binary number 101010111. Each element of this number represents a bit, so this number is a nine-bit binary value. Because binary numbers are read from right to left, the first three bits have a value of 1; bits four, six, and eight are 0; and bits five, seven, and nine are 1. Each bit represents an integer value that's twice as large as the value of the previous bit. To be more precise: The integer value represented by a bit is the same as 2 to the power of the bit position (see FIGURE 8).


FIGURE 8: How bits are organized and interpreted. This range covers decimal values that can be expressed in 15 bits.

Row 1 represents the positions of bits in a 15-bit number (counting starts at zero, and bits are arranged from right to left). Row 2 lists the decimal value associated with each bit. Row 3 shows the same values as row 2, but are expressed as values in which 2 is raised to the power of the bit position. The gray part of row 4 shows the binary representation of our example (the decimal value 343).

Now, look at the WdTableFormatApply constants in FIGURE 7. They're exactly the same as the values in the gray part of the second row in FIGURE 8 - ranging from 1 to 256.

Next, look at the checkbox settings in FIGURE 2 in the following order: Borders, Shading, Font, Color, AutoFit, Heading rows, Last row, First column, and Last column. Compare their values (0 for unchecked, 1 for checked) with the ones in the fourth row in FIGURE 8, starting from the right. As you'll see, they match, too.

Finally, multiply the bit values in row 4 with their corresponding decimal values in row 2, and add them up. What you get is (1x1) + (1x2) + (1x4) + (0x8) + (1x16) + (0x32) + (1x64) + (0x128) + (1x256) = 343. If all nine bits were set (meaning that all checkboxes are checked in the dialog box), you would end up with a value of 511; if none were set, you would get zero.

This binary arithmetic demonstrates that we can store all nine sub-format settings of the Table AutoFormat dialog box in a single numeric value. We already know how to get the main format: either by evaluating the AutoFormatType property of the Table object, or by looking at the value of the Format argument in the Table AutoFormat dialog box, each of which gives us one of the WdTableFormat values shown in FIGURE 3.

We could of course save both values separately as part of our table style definition, but there's a more interesting way. How about combining them in a single numeric value?

Shifting Bits

Since we've stored the nine sub-formats in the first nine bits, we can't cram the main format in the same bits. So we have to go higher up. Literally. The WdTableFormat constants cover values from 0 to 42, which can be represented in a six-bit binary number. What we'll do is elevate that value so that its bits are stored in positions nine through 14. In programmer's jargon this is called "bit shifting." We can do that by multiplying the WdTableFormat value with the value that's associated with the first bit position we want to use, in this case 2^9, or 512 (see the right-most yellow column in FIGURE 8). So, if the main format is wdTableFormat3DEffects2 (decimal 33, binary 100001), we save it as 33 * 512 = 16896, and then add the value we retrieved for the sub-formats (which was 343). This gives us a total of 16896 + 343 = 17239. Row 5 in FIGURE 7 shows that the result is a binary value of 100001101010111.

FIGURE 9 lists a function that combines all these calculations, and returns the unique numeric style definition for the table that contains the insertion point.

Function GetTableFormat()As Long
  If Selection.Information(wdWithInTable) Then
    With Dialogs(wdDialogTableAutoFormat) 
      GetTableFormat = _
        .Borders * wdTableFormatApplyBorders + _
        .Shading * wdTableFormatApplyShading + _
        .Font * wdTableFormatApplyFont + _
        .Color * wdTableFormatApplyColor + _
        .AutoFit * wdTableFormatApplyAutoFit + _
        .HeadingRows * wdTableFormatApplyHeadingRows + _
        .LastRow * wdTableFormatApplyLastRow + _
        .FirstColumn * wdTableFormatApplyFirstColumn + _
        .LastColumn * wdTableFormatApplyLastColumn + _
        .Format * 2 ^ 9
    End With
  End If
End Function
 
Sub SetTableFormat(ByVal objTable As Table, _
                   ByVal iDef As Long)
  If Not objTable Is Nothing Then
    With objTable
      .AutoFormat _
        Format:=iDef \ 512, _
        ApplyBorders:= CBool(iDef And _
          wdTableFormatApplyBorders), _
        ApplyShading:= CBool(iDef And _
          wdTableFormatApplyShading), _
        ApplyFont:= CBool(iDef And _
          wdTableFormatApplyFont), _
        ApplyColor:= CBool(iDef And _
          wdTableFormatApplyColor), _
        AutoFit:= CBool(iDef And _
          wdTableFormatApplyAutoFit), _
        ApplyHeadingRows:= CBool(iDef And _
          wdTableFormatApplyHeadingRows), _
        ApplyLastRow:= CBool(iDef And _
          wdTableFormatApplyLastRow), _
        ApplyFirstColumn:= CBool(iDef And _
          wdTableFormatApplyFirstColumn), _
        ApplyLastColumn:= CBool(iDef And _
          wdTableFormatApplyBorders) 
    End With
  End If
End Sub

FIGURE 9: The GetTableFormat function returns a unique value, representing all Table AutoFormat settings. The SetTableFormat subroutine applies a table style value to a given table.

Recreating the Table Format

Once we've stored a table format as a number, we should be able to use that value to apply the same format to another table. Let's assume we have a table style definition, stored as 17239. Since we multiplied the original main format with 512, we can get that value back by reversing the process. So, we divide the table style value by 512, and use the integer part of the result. The formula is (note the use of the backslash as the "integer division" symbol):

OriginalFormat = StyleDef \ 512

If StyleDef equals 17239, this calculation gives us a value of 33, which is the value of the wdTableFormat3DEffects2 constant.

To extract the settings of the nine sub-formats, we have to perform some bit manipulation. The way to do this is by using the logical And operator. And compares identically positioned bits in two numbers. If the bit in each number has a value of 1, the corresponding integer value is returned; otherwise you'll get a 0 value. The trick is to ensure that at least one of the values has the specified bit set, so we get only a non-zero result if the same bit is also set in the other value. The formula is:

BitValue = StyleDef And 2^BitPos

For example, to check the bit status of the fifth bit in the value 17239, which represents the AutoFit setting of the table format, you use this VBA statement:

' 4 is the number of the fifth bit. 
      AutoFitSetting = (17239 And 2 ^ 4) 

But there's a more user-friendly way. The value 2^4 is the same as the value of the wdTableFormatApplyAutoFit constant (16). Our code becomes more readable if we use the following instruction:

AutoFitSetting = (17239 And wdTableFormatApplyAutoFit) 

If the table style definition has its fifth bit set (which it has; see FIGURE 8), this instruction returns the decimal value (16) associated with bit position 4; otherwise we get a 0. Since the AutoFormat method wants its parameters as Boolean values, we can use the CBool function and change the instruction so we get a "real" True or False value:

AutoFitSetting = CBool(17239 And wdTableFormatApplyAutoFit) 

For purists, we can also use the following Boolean comparison to get the same result:

AutoFitSetting = (17239 And wdTableFormatApplyAutoFit) = _
        wdTableFormatApplyAutoFit

The SetTableFormat routine in FIGURE 9 uses all these formulas to apply a given style to a given table. For example, to apply style definition 17239 to the table that contains the insertion point, you use the following instruction:

SetTableFormat Selection.Tables(1), 17239

To create consistently formatted tables throughout a document, the code is equally simple:

For Each objTable In ActiveDocument.Tables
        SetTableFormat objTable, 17239
      Next

The Application

The accompanying download file contains a ready-to-use Word 2000 template that uses the code shown in Listing One and Listing Two. The application creates a new menu item on the Table menu (see FIGURE 10), that lets you create, apply, rename, and delete table styles. Each style definition is stored in the Windows registry under the section HKEY_CURRENT_USER\Software\VB and VBA Program Settings\Tweak Office 2000\Word\Table Styles. The interface is deliberately kept simple, and uses standard VBA input boxes and message boxes when it enters into a dialog with the user. The project is unprotected, so you can study and customize the code.


FIGURE 10: The Table Styles application in action.

Conclusion

The purpose of this series is to demonstrate that there is a lot more to VBA programming than you may think. With a bit of hacking, you can greatly enhance your Office environment. In this installment, I showed you how you can use Word's Table AutoFormat feature to create table styles that can be applied just like paragraph and character styles. Watch this space for more VBA hacks!

Dutchman Romke Soldaat was hired by Microsoft in 1988 to co-found the Microsoft International Product Group in Dublin, Ireland. That same year he started working with the prototypes of WinWord, writing his first macros long before the rest of the world. In 1992 he left Microsoft, and created a number of successful add-ons for Office. Living in Italy, he divides his time between writing articles for this magazine, enjoying the Mediterranean climate, and steering his Land Rover through the world's most deserted areas. Romke can be contacted at romke@soldaat.com.

Begin Listing One - TableStylesInterface.bas

Option Explicit
 
Dim objContext As Template
Dim varAllStyles As Variant
Const BAR_TABLE As String = "Table" 
Const MNU_STYLE As String = "Table St&yle" 
Public Const REG_APP As String = "Tweak Office 2000\Word" 
Public Const REG_SEC As String = "Table Styles" 
 
Sub AutoExec()
  ' This macro runs when the add-in is loaded. 
  InitializeContext
  If objContext Is Nothing Then Exit Sub
  CreateInterface
  CleanUpContext
End Sub
 
Sub AutoExit()
  ' This macro runs when the add-in is unloaded. 
  DeleteInterface
End Sub
 
Sub InitializeContext()
  ' This routine makes sure that all changes are
  ' made in this add-in template. 
  On Error Resume Next
  With MacroContainer
    Set objContext = Templates(.Path & _
      Application.PathSeparator & .Name) 
  End With
  CustomizationContext = objContext
  ' Bail out if the template isn't a loaded add-in. 
  If Err Then
    MsgBox UCase(MacroContainer) & _
      " is an addin template that " & vbCr & _
      "must be placed in the Word Startup Path:" & vbCr & _
      UCase(Options.DefaultFilePath(wdStartupPath)), _
      vbCritical, "Initialization aborted" 
    Set objContext = Nothing
  End If
End Sub
 
Sub CleanUpContext()
  ' Set the Saved status of this add-in to True. 
  If objContext Is Nothing Then
    InitializeContext
  End If
  If Not (objContext Is Nothing) Then
    objContext.Saved = True
  End If
End Sub
 
Sub CreateInterface()
  ' Create the menu item in the Table menu. 
  On Error Resume Next
  With CommandBars(BAR_TABLE) 

    .Controls(MNU_STYLE).Delete
      With .Controls.Add(Type:=msoControlPopup, _
        Before:=.Controls("Table Autoformat...").Index + 1) 
        .BeginGroup = False
        .Caption = MNU_STYLE
        .OnAction = "InitTableStyleMenu" 
        ' Parameter contains name of OnAction macro
        ' in submenu. 
        .Parameter = "ApplyToThisTable" 
      End With
  End With
End Sub
 
Sub DeleteInterface()
  ' Delete the menu item from the Table menu. 
  On Error Resume Next
  InitializeContext
  CommandBars(BAR_TABLE).Controls(MNU_STYLE).Delete
  CleanUpContext
End Sub
 
Sub InitTableStyleMenu()
  ' Create object for control that triggers this routine. 
  Dim ActiveCtl As CommandBarControl
  Dim Ctl As CommandBarControl
  Set ActiveCtl = CommandBars.ActionControl
  ' Start with a clean slate, deleting all current items. 
  For Each Ctl In ActiveCtl.Controls
    Ctl.Delete
  Next
  If Documents.Count = 0 Then
    ' No tables available. 
    With ActiveCtl.Controls.Add()
      .Caption = "(No documents open)" 
      .Enabled = False
    End With
    Exit Sub
  End If
  ' Get all style definitions from the Registry. 
  varAllStyles = GetAllSettings(REG_APP, REG_SEC) 
  ' Create style list on main menu. 
  If Selection.Information(wdWithInTable) Then
    AddStylesToMenu
  End If
  With ActiveCtl.Controls.Add(Type:=msoControlPopup) 
    .Caption = "Apply to &All Tables" 
    .Visible = (ActiveDocument.Tables.Count > 0) 
    ' Parameter contains name of OnAction macro in submenu. 
    .Parameter = "ApplyToAllTables" 
    .OnAction = "AddStylesToMenu" 
    .BeginGroup = True
  End With
  ' Add the other menu items. 
  With ActiveCtl.Controls.Add()
    .Caption = "&Create Table Style..." 
    .BeginGroup = True
    .OnAction = "CreateTableStyle" 
  End With
  With ActiveCtl.Controls.Add(Type:=msoControlPopup) 
    .Caption = "&Delete Table Style" 
    .Parameter = "DeleteStyle" 
    .OnAction = "AddStylesToMenu" 
    ' Don't show this item if there are no styles yet. 
    .Visible = VarType(varAllStyles) <> vbEmpty
  End With
  With ActiveCtl.Controls.Add(Type:=msoControlPopup) 
    .Caption = "&Rename Table Style" 
    .Parameter = "RenameStyle" 
    .OnAction = "AddStylesToMenu" 
    .Visible = VarType(varAllStyles) <> vbEmpty
  End With
  CleanUpContext
End Sub
 
Sub 
AddStylesToMenu()
  ' This routine creates a list of available styles. 
  Dim Ctl As CommandBarControl
  Dim strOnAction As String
  Dim iCount As Integer
 
  With CommandBars.ActionControl
    ' Clear the menu. 
    For Each Ctl In .Controls
      Ctl.Delete
    Next
    If VarType(varAllStyles) <> vbEmpty Then
      ' We have at least one style. 
      If Selection.Information(wdWithInTable) Then
        ' See if the table has a style attached. 
        Dim iCurDef As Long
        iCurDef = GetTableFormat
      End If
      ' Parameter contains name of OnAction macro. 
      strOnAction = .Parameter
      ' Loop through the list of styles. 
      For iCount = LBound(varAllStyles, 1) To _
                   UBound(varAllStyles, 1) 
        ' Create an item for each style. 
        With .Controls.Add()
          .Caption = varAllStyles(iCount, 0) 
          ' Parameter gets the numeric style definition. 
          .Parameter 
= varAllStyles(iCount, 1) 
          ' Use Face ID of Table AutoFormat item. 
          .FaceId = 107
          ' Highlight if these values are the same. 
          .State = (.Parameter = iCurDef) 
          .OnAction = strOnAction
        End With
      Next iCount
    Else
      ' No styles defined yet. 
      With .Controls.Add()
        .Caption = "(no styles defined)" 
        .Enabled = False
      End With
    End If
  End With
 
  CleanUpContext
End Sub
 
Sub ApplyToAllTables()
  ' Apply selected style to all tables in active document. 
  If (ActiveDocument.Tables.Count > 0) Then
    Dim objTable As Table
    For Each objTable In ActiveDocument.Tables
      SetTableFormat objTable, _
        CommandBars.ActionControl.Parameter
    Next
  End If
End Sub
 
Sub ApplyToThisTable()
  ' Apply selected style to active table. 
  If Selection.Information(wdWithInTable) Then
    SetTableFormat Selection.Tables(1), _
      CommandBars.ActionControl.Parameter
  End If
End Sub
 
Sub DeleteStyle()
  ' Delete selected style. 
  On Error Resume Next
  Dim iReply As Integer
  With CommandBars.ActionControl
    iReply = MsgBox( _
      "Please confirm that you want to delete ' " & _
      .Caption & "'", vbOKCancel + vbExclamation, _
      "Delete Table Style") 
    ' We have an OK, so we can delete the style. 
    If iReply = vbOK Then
      DeleteSetting REG_APP, REG_SEC, .Caption
    End If
  End With
End Sub
 
Sub RenameStyle()
  ' Rename selected style. 
  Dim strName As String
  With CommandBars.ActionControl
    strName = InputBox("Type a New name for: '" & _
      .Caption & "'", "Rename Table Style", .Caption) 
    If strName <> vbNullString Then
      Dim strCurrentDef As String
      Dim strExistingDef As String
      ' Get current value of this style. 
      strCurrentDef = _
        GetSetting(REG_APP, REG_SEC, .Caption) 
      ' See if we already have this style. 
      strExistingDef = _
        GetSetting(REG_APP, REG_SEC, strName) 
      ' No? Delete the old style, save the new one. 
      If strExistingDef = vbNullString Then
        DeleteSetting 
REG_APP, REG_SEC, .Caption
        SaveSetting REG_APP, REG_SEC, strName, _
                    strCurrentDef
      Else
        ' Name already exists; 
        ' ask for overwrite permission. 
        Dim iReply As Integer
        iReply = MsgBox("'" & strName & _
          "' already exists. " & _
          "Do you want to replace the existing style?", _
          vbYesNoCancel + vbExclamation, _
          "Rename Table Style") 
        Select Case iReply
          Case vbYes  ' Overwrite old style. 
            DeleteSetting REG_APP, REG_SEC, .Caption
            SaveSetting REG_APP, REG_SEC, strName, _
                        strCurrentDef
          Case vbNo   ' Start again. 
            RenameStyle
          Case vbCancel
            Exit Sub  ' Don't do anything. 
          Case Else:
        End Select
      End If
    End If
  End With
End Sub

End Listing One

Begin Listing Two - TableStylesLib.bas

Option Explicit
 
Const MSG_PROMPT As String = "Table Styles" 
 
Sub CreateTableStyle()
  ' Intro messages. 
  If Not Selection.Information(wdWithInTable) Then
    MsgBox "Please select or create a table first.", _
      vbExclamation, MSG_PROMPT
    Exit Sub
  Else
    MsgBox "In the following dialog box, apply a Table" & _
      " Format." & vbCr & "When done, you will be " & _
      "asked to give a Style name to this format.", _
      vbExclamation, MSG_PROMPT
  End If
  With Dialogs(wdDialogTableAutoFormat) 
    If .Show Then
      ' Make sure the dialog wasn't cancelled. 
      Dim lDef As Long
      Dim strName As String
      ' Create a numeric style definition. 
      lDef = _
        .Borders * wdTableFormatApplyBorders + _
        .Shading * wdTableFormatApplyShading + _
        .Font * wdTableFormatApplyFont + _
        .Color * wdTableFormatApplyColor + _
        .AutoFit * wdTableFormatApplyAutoFit + _
        .HeadingRows * wdTableFormatApplyHeadingRows + _
        .LastRow * wdTableFormatApplyLastRow + _
        .FirstColumn * wdTableFormatApplyFirstColumn + _
        .LastColumn * wdTableFormatApplyLastColumn + _
        .Format * 2 ^ 9
      ' Ask for a style name. 
      strName = InputBox( _
        "Which Style Name do you want to " & _
        "give to this Table Format?", MSG_PROMPT) 
      If strName <> vbNullString Then
        SaveSetting REG_APP, REG_SEC, strName, lDef
      End If
    End If
  End With
End Sub
 
Function GetTableFormat()As Long
  ' Make sure the insertion point is inside a table. 
  If Selection.Information(wdWithInTable) Then
    ' Get the dialog settings and return a unique
    ' table style definition. 
    With Dialogs(wdDialogTableAutoFormat) 
      .Update
      GetTableFormat = _
        .Borders * wdTableFormatApplyBorders + _
        .Shading * wdTableFormatApplyShading + _
        .Font * wdTableFormatApplyFont + _
        .Color * wdTableFormatApplyColor + _
        .AutoFit * wdTableFormatApplyAutoFit + _
        .HeadingRows * wdTableFormatApplyHeadingRows + _
        .LastRow * wdTableFormatApplyLastRow + _
        .FirstColumn * wdTableFormatApplyFirstColumn + _
        .LastColumn * wdTableFormatApplyLastColumn + _
        .Format * 2 ^ 9
    End With
  End If
End Function
 
Sub SetTableFormat(ByVal objTable As Table, _
                   ByVal iDef As Long)
  ' Make sure we have a valid table object, and that the
  ' table style definition isn't greater than 2^15-1. 
  If IsObjectValid(objTable) And (iDef <= 32767) Then
    ' Format the table object. 
    With objTable
      .AutoFormat _
        Format:=iDef \ 512, _
        ApplyBorders:= CBool(iDef And _
          wdTableFormatApplyBorders), _
        ApplyShading:= CBool(iDef And _
          wdTableFormatApplyShading), _
        ApplyFont:= CBool(iDef And _
          wdTableFormatApplyFont), _
        ApplyColor:= CBool(iDef And _
          wdTableFormatApplyColor), _
        AutoFit:= CBool(iDef And _
          wdTableFormatApplyAutoFit), _
        ApplyHeadingRows:= CBool(iDef And _
          wdTableFormatApplyHeadingRows), _
        ApplyLastRow:= CBool(iDef And _
          wdTableFormatApplyLastRow), _
        ApplyFirstColumn:= CBool(iDef And _
          wdTableFormatApplyFirstColumn), _
        ApplyLastColumn:= CBool(iDef And _
          wdTableFormatApplyBorders) 
    End With
  End If
End Sub

End Listing Two