Borders in table styles
Microsoft introduced table styles in Word 2002. There are 7 different objects that manage borders in a table style. My experience is that some of them work and some don't.
This page describes my experiences with borders in table styles. Your mileage, as they say, may vary.
So what's the problem with borders and table styles?
For basics of controlling borders in styles, see Border basics for developers. The issues for table styles are the same as those for non-table styles:
- A
.Borders
property can have 1, 4, 5 or 8 borders, some of which you can control, and some of which you can't. - Sometimes you can set the distance between the borders and the text, and sometimes you can't.
- Sometimes can you set a shadow on the borders, and sometimes you can't.
In addition, the built-in style Table Normal has its own rules, often different from the way any other table style, built-in or custom, behaves. In general, my experience is that it's best to leave style Table Normal alone. Avoid trying to read its properties, and if you do, litter your code with error catching. Certainly don't try to set the properties of Table Normal.
Summary
Item in the Word object model | Usefulness |
---|---|
Style.Borders | Does not work. Word says "That property is not available on that object" |
Style.Table.Borders |
OK most of the time. Can't control diagonal borders, distance between border and text or shadows. |
Style.ParagraphFormat.Borders |
Dodgy. Significant display issues. Can't set distance between border and text. Can set shadows. |
Style.Font.Borders |
OK-ish. 1 border only. Can't control distance between border and text. Can set shadows. |
Style.Table.Condition(n).Borders |
OK-ish. Can't manage diagonal borders. Can't set distance between border and text. Can't use shadows. May have unintended consequences (eg setting a border in the top row will turn off the display of the Total Row, Last Column and Banded Columns). |
Style.Table.Condition(n).ParagraphFormat.Borders |
Only 4 borders, not 5 as you'd expect. Can't see the top border unless the |
Style.Table.Condition(n).Font.Borders |
Not recommended |
How borders behave for different elements of table styles
Style.Borders
The Word Style object has a .Borders property. It doesn't work for a table style, and returns error "That property is not available on that object".
Style.Table.Borders
This is the .Borders
property of the table style's .Table
. For example, ActiveDocument.Styles("MyTableStyle").Table.Borders
.
There are 8 borders: top, right, bottom, left, horizontal, vertical and two diagonals.
Any border on the style's .Table
will be overriden by, eg, Style.Table.Condition(n).Border(m)
. So, for example, if the first column condition has a left border, then you won't see the whole-of-table border. That makes sense, because the specific is over-riding the general. This applies whether the condition's border is set before or after the Style.Table.Borders
border.
Top, right, bottom, left, horizontal and vertical borders
These borders generally work as expected.
Diagonal borders
Diagonal borders are basically uncontrollable:
- Diagonal borders always display as
wdLineStyleSingle
no matter what line style you set. - You can't set a width on diagonal borders.
- Diagonal borders always show as black, regardless of what colour you set.
- You can't read the colour or width of a diagonal border. Both properties always return
wdUndefined
, even when the border is visible. Their default iswdUndefined
, and they always reportwdUndefined
, so you can't rely on the reported value.
Setting distance from top (eg myStyle.Table.Borders.DistanceFromTop = 5
) never works. It does not produce an error, but it makes no difference, either.
.Shadow = True
never works. Word throws error 4198 'Command Failed'. And, when that happens, Word sets the first 6 borders (ie top, right, bottom, left, vertical and horizontal, but not diagonal) of the table to black, single line borders. So you can't just 'on error resume next' your way past the .Shadow
setting, because it has unintended consequences.
Style.ParagraphFormat.Borders
This property controls the borders of text within a table cell.
A Table style has a .ParagraphFormat
property, which has a .Borders
property. For example ActiveDocument.Styles("MyTableStyle").ParagraphFormat.Borders
.
There are 5 borders: top, right, bottom, left plus horizontal borders. If you set the top border, it appears only on the first paragraph in the table cell. If you want a border on the top of every paragraph, use the horizontal border, which displays between paragraphs. As far as I can see, you can't set the Horizontal borders in the user interface. You can only do it through code.
Notes:
-
You may not be able to see the borders at all unless you type some more text in the document. Even a print preview does not force the borders to display.
-
Generally, you can't see the top border if: (a)
.Shadow = False
and (b) theStyle.Table.TopPadding = 5
. Note that you may not be able to see the border in Print Layout view with other settings of.TopPadding
, but you'll see the borders in Print Preview. But with.TopPadding = 5
, you can't see the border in print preview, either. It may or may not print on paper. I've seen other settings for.TopPadding
that also go wrong. So these borders are a bit flaky.
Distance from top (eg myTableStyle.ParagraphFormat.Borders.DistanceFromTop = 20
) causes an error if the value is < 0 or >=31. Within that range, it does not appear to do anything.
.Shadow
works, but expect some display artefacts that don't print.
Style.Font.Borders
In the object model this is Style.Font.Borders
There is only one border.
Trying to set the distance between border and text (eg myStyle.Font.Borders.DistanceFromTop = 10
) never works. It always returns error 5891: "That property is not available on that object."
The .Shadow
property works as expected.
Style.Table.Condition(n).Borders
In the object model, this is Style.Condition(n).Borders
. A table style has 12 conditions (first column, last row, top right cell etc). myStyle.Condition(1)
returns a ConditionalStyle
object, and it has a .Borders
property.
There are 8 borders: top, right, bottom, left, horizontal, vertical and two diagonals.
Top, right, bottom, left, horizontal and vertical borders
These work more-or-less as expected with three exceptions:
-
The Distances between border and text do not cause an error if the value is >=0 and <32, but does not appear to do anything, either. They cause an error if value is <0 or >=32.
-
You can't set the
.Shadow
property. If you try to access this property, Word throws error 4198 'Command failed'. -
Setting a border may have unintended consequences. For example, if the table in the document has been set to show the Total Row, Last Column and Banded Columns, and you set a border on the Top Row, then table will lose its Total Row, Last Column and Banded Column setting. So if you're going to set borders on a style in an existing document, you need to read these settings (for each table to which the style has been applied), store them, modify the style, apply it, then re-apply the individual table settings.
Diagonal borders
Diagonal borders are basically uncontrollable.
- Diagonal borders always display as
wdLineStyleSingle
regardless of what line style you set. - You can't set a width on diagonal borders.
- Diagonal borders always show as black, regardless of what colour you set.
- You can't read the colour or width of a diagonal border. Both properties always return
wdUndefined
, even when the border is in plain sight. Their default iswdUndefined
, and they always reportwdUndefined
, so you can't really manipulate diagonal borders in any way.
Style.Table.Condition(n).ParagraphFormat.Borders
In the object model this is Style.Condition(n).ParagraphFormat.Borders
There are 4 borders. Yes, 4. The Style.ParagraphFormat.Borders
property has 5 borders, but Style.Condition(n).ParagraphFormat.Borders
only has 4. I've no idea why.
Notes:
- These borders over-ride the
Style.ParagraphFormat.Borders
setting for the particular border. That makes sense to me, because the specific is over-riding the general. - In early releases of Word 2007, the
Top
border wasn't visible unless the.Condition(n).TopPadding
was at least 9. This is no longer a problem with Word 2007 Service Pack 2 and it works in Word 2010. - In early releases of Word 2007, the
Bottom
border was unreliable unless the.Condition(n).BottomPadding
was less than 9. This is no longer a problem with Word 2007 Service Pack 2 and it works in Word 2010.
The Distances between border and text do not cause an error if the value is >=0 and <32, but these properties do not appear to do anything, either. They cause an error if value is <0 or >=32.
The .Shadow
works as expected.
Style.Table.Condition(n).Font.Borders
In Word 2003
Avoid this .Borders property.
We can't control these borders in code:
- These borders will be over-ridden by the
Style.Font
border. That doesn't make sense, because we would expect the specific to over-ride the general. Here, the reverse is true. - You can set a
.LineStyle
, but Word will ignore your setting. If you interrogate the property, Word seems to report.LineStyle = 0
or.LineStyle = wdUndefined
even when there is a line I can see. - You can't ever set
.LineWidth
: Word throws an error every time. - You can set a border
.Color
, but if you also set.Shadow
to True, Word will ignore the colour and set the borders to Black, assuming no Style.Font.Borders settings. - Borders whose
.Color
is undefined sometimes return the number −399507165 instead of 9999999 (the normalWord.wdUndefined
constant). This number appears sporadically as the return value of a table style's.Table.Condition(x).Font.Borders(1).Color
, but only if we're barging through the code, and not if we're using F8 to step through the code line by line. I have only seen it appear on some Conditions: last row, first column, last column, odd and even rows, even columns, top right cell and bottom right cell. I have not seen it appear on the other Conditions. - Even if you do set the colour, and leave
.Shadow = False
, Word will not return the correct colour of the border.
These borders are badly behaved. For example, I used the user interface to set a border on the .Font
of the first row (.Condition(0)
). I could see the border. I then interrogated it in the Immediate pane in the VBE:
How can this happen?
? ActiveDocument.Styles("Shauna").Table.Condition(0).Font.Borders(1).LineStyle 0 Set brdr = ActiveDocument.Styles("Shauna").Table.Condition(0).Font.Borders(1) ? brdr.LineStyle 9999999
The display seems to come and go. The same code will sometimes display a border and sometimes not. That might just be a display or memory issue, but testing suggests otherwise. It may have something to do with the presence, or absence, of a border around the table as a whole, If the table has a border, you can't see the .Condition(x).Font.Borders
.
Style.Table.Condition(0)
(condition 0 is the top row) is flakier than the rest. You rarely see the effect of the border in the top row.
Distances between text and border (eg .DistanceFromTop = 5
) never works. You always get error 5891 'That property is not available on that object'.
In Word 2007 and Word 2010
Avoid this Borders property. It produces no borders, and will crash Word 2007 in a trice.
Setting the .Borders(1).LineStyle
property or .Borders(1).Color
property has no visible effect.
Setting the .LineWidth
causes error 5843. In Word 2007, if you re-run the line of code with the error, Word may crash. To demonstrate, close and re-open Word, then run the following VBA code:
Sub HowToCrashWord2007() Dim doc As Word.Document Dim sty As Word.Style Set doc = Documents.Add Set sty = doc.Styles.Add(Name:="ATableStyle", Type:=wdStyleTypeTable) With sty.Table.Condition(wdLastRow).Font.Borders(1) On Error Resume Next .LineWidth = wdLineWidth025pt 'Following line causes Word to crash .LineWidth = wdLineWidth025pt End With End Sub
In the original version of Word 2007, setting the .Shadow
caused no error. In Word 2007 with SP2, attempting to set the .Shadow
property causes error 4198. There's a nice case for testing our code against service packs!
Finally, we cannot read the property values of these borders. .LineStyle
and .LineWidth
always return wdUndefined
. .Colour
always returns 0. And .Borders.Shadow
always returns True even though there is patently no shadow since no border is displayed.