Aligning table cell contents based on style

D

david_alex_smith

Hello.

I'm trying to align all table cell contents to the bottom of the cell if
they are "Table Heading Style".

I've written the following macro to do this.

Sub AlignTables()
'Aligns table headings
Dim Table, aRow, aCell, myRange
For Each Table In ActiveDocument.Tables
For Each aRow In Table.Rows
For Each aCell In aRow.Cells
myRange = aCell
If myRange.Style = "Table Heading" Then
aCell.VerticalAlignment = wdAlignVerticalBottom
End If
Next aCell
Next aRow
Next Table
End Sub


This doesn't work though. I get an error - "Object variable or With block
variable not set".

Any ideas how I can get this working. Thanks in advance.

Dave.
 
J

Jean-Guy Marcil

david_alex_smith was telling us:
david_alex_smith nous racontait que :
Hello.

I'm trying to align all table cell contents to the bottom of the cell
if they are "Table Heading Style".

I've written the following macro to do this.

Sub AlignTables()
'Aligns table headings
Dim Table, aRow, aCell, myRange
For Each Table In ActiveDocument.Tables
For Each aRow In Table.Rows
For Each aCell In aRow.Cells
myRange = aCell
If myRange.Style = "Table Heading" Then
aCell.VerticalAlignment = wdAlignVerticalBottom
End If
Next aCell
Next aRow
Next Table
End Sub


This doesn't work though. I get an error - "Object variable or With
block variable not set".

Any ideas how I can get this working. Thanks in advance.

Five comments:

1) It is not a good idea to use a variable name that happens to be a
constant, an object name, a method name or a property name in the Object
model. Table is an object name.

2) It is much better practice to explicitly cast the variable to a type.
When you do that, you and the compiler both know what you are dealing with
anywhere in the code. This way you don't need to let the compiler decide for
you and then produce funny results...as you have experienced. As a big plus
to this practice, Intellisense will work when you write your code, so if you
try to use a method/property with an object that does not support it, you
will know right away.

3) It is also much better not to use default assignment ("myRange = aCell"
You want myRange to be a range object, but have not said so anywhere in your
code, and you want aCell to be the range in the cell represented by aCell
which the compiler had to infer...) Also, we do not know if in future
versions of the Word object model if the default will remain the same, or
even be allowed to be used.

4) It is recommended not to use the object in the Next statement.
For Each myThingy In ActiveDocument.Thingies
Test myThingy
Next
If you want, you can comment it so that you know what each next is referring
to:
For Each myThingy In ActiveDocument.Thingies
Test myThingy
Next 'myThingy

5) Finally, and this is where you had the problem generating the error
message, you need a "Set" statement to assign a document range to a range
object in the code.

Here is a revised version of your code.

'_______________________________________
Sub AlignTables()
'Aligns table headings
Dim aTable As Table
Dim aRow As Row
Dim aCell As Cell
Dim myRange As Range

For Each aTable In ActiveDocument.Tables
For Each aRow In aTable.Rows
For Each aCell In aRow.Cells
Set myRange = aCell.Range
If myRange.Style = "Table Heading" Then
aCell.VerticalAlignment = wdAlignVerticalBottom
End If
Next
Next
Next

End Sub
'_______________________________________

--
Salut!
_______________________________________
Jean-Guy Marcil - Word MVP
(e-mail address removed)
Word MVP site: http://www.word.mvps.org
 
D

david_alex_smith

Merci Jean-Guy,

Thanks for the tips on good practice. I still get the same error though.
- "Object variable or With block variable not set".

Dave.
 
J

Jean-Guy Marcil

david_alex_smith was telling us:
david_alex_smith nous racontait que :
Merci Jean-Guy,

Thanks for the tips on good practice. I still get the same error
though. - "Object variable or With block variable not set".

Have you tried the code I posted?

It worked without any problems on many test runs on my machine.

--
Salut!
_______________________________________
Jean-Guy Marcil - Word MVP
(e-mail address removed)
Word MVP site: http://www.word.mvps.org
 
G

Greg

JGM,

I read with great interest. Thank you.

David's orginal code worked in the limited testing I did.

Can you shed a little insight on why you use the Rows statement and why
you use the myRange statement. Seems to me that both can be
eliminated.


Sub AlignTables()
Dim aTable As Table
Dim aCell As Cell

For Each aTable In ActiveDocument.Tables
For Each aCell In aTable.Range.Cells
If aCell.Range.Style = "Table Heading" Then
aCell.VerticalAlignment = wdAlignVerticalBottom
End If
Next
Next

End Sub

Thanks.
 
D

david_alex_smith

Yes - I'm using the code exactly as you posted. I'm still getting the same
error. Am going to try Greg's solution now.
 
D

david_alex_smith

Greg,

I orignally tried to do something very like your suggestion but couldn't
make it work.

I've just tried your code and i get the same error as i get when i run mine
or JGM's.

Am running Word 2003 on XP. Is it possible there is something wrong with my
installation? Am puzzled if these work on your machines but not mine.

Dave.
 
G

Greg

JGM,

Runnig a test on a table with 6300 rows. The method that you posted
took 34.63 seconds. The method I posted took 3.375 seconds.

There is an even faster method that Steve Hudson showed me.

Public Sub AlignTables3()
Dim aTable As Table
Dim myRange As Range
Dim oCell As Cell
Dim StartTime As Single

StartTime = Timer

For Each aTable In ActiveDocument.Tables
With aTable.Range
Set myRange = .Cells(1).Range
Do
If myRange.Style = "Table Heading" Then
Set oCell = myRange.Cells(1)
oCell.VerticalAlignment = wdAlignVerticalBottom
End If
myRange.Collapse wdCollapseEnd
myRange.MoveEnd wdParagraph, 1
Loop Until myRange.End = .End
End With
Set myRange = Nothing
MsgBox "Time taken was: " & (Timer - StartTime) & " seconds"
Next
End Sub

There isn't must difference with a 6300 cell table, (less than 1/2 a
second) but the difference grows as the number of cells increases.

Again, my purpose for pointing this out is to see if there is some
stability issues that I am not aware by using either of these faster
methods.
 
D

david_alex_smith

I still get the same error when running this code. What on earth is wrong
with my Word?

Dave.
 
J

Jean-Guy Marcil

Greg was telling us:
Greg nous racontait que :
JGM,

I read with great interest. Thank you.

David's orginal code worked in the limited testing I did.

Can you shed a little insight on why you use the Rows statement and
why you use the myRange statement. Seems to me that both can be
eliminated.

I was not really thinking about streamlining the code. I just took the
poster's code and rewrote it.
pointing out where he went wrong with the assignment.

You are right that myRange/myRow are not necessary in this case because we
are not doing anything else with it.
Sub AlignTables()
Dim aTable As Table
Dim aCell As Cell

For Each aTable In ActiveDocument.Tables
For Each aCell In aTable.Range.Cells
If aCell.Range.Style = "Table Heading" Then
aCell.VerticalAlignment = wdAlignVerticalBottom
End If
Next
Next

End Sub

Thanks.

--
Salut!
_______________________________________
Jean-Guy Marcil - Word MVP
(e-mail address removed)
Word MVP site: http://www.word.mvps.org
 
J

Jean-Guy Marcil

Greg was telling us:
Greg nous racontait que :
JGM,

Runnig a test on a table with 6300 rows. The method that you posted
took 34.63 seconds. The method I posted took 3.375 seconds.

There is an even faster method that Steve Hudson showed me.

Public Sub AlignTables3()
Dim aTable As Table
Dim myRange As Range
Dim oCell As Cell
Dim StartTime As Single

StartTime = Timer

For Each aTable In ActiveDocument.Tables
With aTable.Range
Set myRange = .Cells(1).Range
Do
If myRange.Style = "Table Heading" Then
Set oCell = myRange.Cells(1)
oCell.VerticalAlignment = wdAlignVerticalBottom
End If
myRange.Collapse wdCollapseEnd
myRange.MoveEnd wdParagraph, 1
Loop Until myRange.End = .End
End With
Set myRange = Nothing
MsgBox "Time taken was: " & (Timer - StartTime) & " seconds"
Next
End Sub

There isn't must difference with a 6300 cell table, (less than 1/2 a
second) but the difference grows as the number of cells increases.

Again, my purpose for pointing this out is to see if there is some
stability issues that I am not aware by using either of these faster
methods.

Thanks for reminding me about the speed factor...
--
Salut!
_______________________________________
Jean-Guy Marcil - Word MVP
(e-mail address removed)
Word MVP site: http://www.word.mvps.org
 
J

Jean-Guy Marcil

david_alex_smith was telling us:
david_alex_smith nous racontait que :
I still get the same error when running this code. What on earth is
wrong with my Word?

Describe you document content.
Also, are you running any code before the code Greg posted?
How are you calling the code?

--
Salut!
_______________________________________
Jean-Guy Marcil - Word MVP
(e-mail address removed)
Word MVP site: http://www.word.mvps.org
 
G

Greg Maxey

Dave,

As I mentioned, I ran the original code you posted with no problem.

Have you tried stepping through the code one line at a time with the F8 key?
What line is generating the error?
 
D

david_alex_smith

Thanks for your continued help on this guys.

The word documented is created by AuthorIT (a single-souce publishing
solution) http://www.author-it.com/.

This populates a Word template with content from a database when publishing
a particular document. This template includes an AfterPublish macro which is
run when AuthorIT has finished building the document. I'm using this to call
my code (however, I get the same error if I call it manually from the VB
editor).

The line that causes the error is indicated below:

Sub AlignTables()
Dim aTable As Table
Dim aCell As Cell

For Each aTable In ActiveDocument.Tables
For Each aCell In aTable.Range.Cells
If aCell.Range.Style = "Table Heading" Then '***This one causes error***
aCell.VerticalAlignment = wdAlignVerticalBottom
End If
Next
Next

End Sub


The error is:

Run-time error '91'

Object variable or With block variable not set.


I could send a sample document by email if anyone would like to try and
discover a solution.

Thanks

Dave.
 
G

Greg

Dave,

Hmm. Here is what help says about Error 91:

Object variable or With block variable not set (Error 91):

There are two steps to creating an object variable. First you must
declare the object variable. Then you must assign a valid reference to
the object variable using the Set statement. Similarly, a With...End
With block must be initialized by executing the With statement entry
point. This error has the following causes and solutions:

You attempted to use an object variable that isn't yet referencing a
valid object.
Specify or respecify a reference for the object variable. For example,
if the Set statement is omitted in the following code, an error would
be generated on the reference to MyObject:

Dim MyObject As Object ' Create object variable.
Set MyObject = Sheets(1) ' Create valid object reference.
MyCount = MyObject.Count ' Assign Count value to MyCount.

You attempted to use an object variable that has been set to Nothing.
Set MyObject = Nothing ' Release the object.
MyCount = MyObject.Count ' Make a reference to a released object.

Respecify a reference for the object variable. For example, use a new
Set statement to set a new reference to the object.

The object is a valid object, but it wasn't set because the object
library in which it is described hasn't been selected in the References
dialog box.
Select the object library in the Add References dialog box.

The target of a GoTo statement is inside a With block.
Don't jump into a With block. Make sure the block is initialized by
executing the With statement entry point.

You specified a line inside a With block when you chose the Set Next
Statement command.
The With block must be initialized by executing the With statement.

For additional information, select the item in question and press F1
(in Windows) or HELP (on the Macintosh).

Lets try:
Sub AlignTables()
Dim aTable As Table
Dim aCell As Cell
Dim oStyle As Style

Set oStyle = ActiveDocument.Styles("Table Heading")

For Each aTable In ActiveDocument.Tables
For Each aCell In aTable.Range.Cells
'On Error Resume Next
If aCell.Range.Style = oStyle Then

aCell.VerticalAlignment = wdAlignVerticalBottom
End If
'On Error Goto 0
Next
Next
Exit Sub

End Sub

If nothing changes, then try uncommenting the On Error lines.
 
J

Jean-Guy Marcil

david_alex_smith was telling us:
david_alex_smith nous racontait que :
Thanks for your continued help on this guys.

The word documented is created by AuthorIT (a single-souce publishing
solution) http://www.author-it.com/.

This populates a Word template with content from a database when
publishing a particular document. This template includes an
AfterPublish macro which is run when AuthorIT has finished building
the document. I'm using this to call my code (however, I get the same
error if I call it manually from the VB editor).


Without knowing what this other code that runs first does, it is difficult
to find the problem.
Can you post the relevant bits of code (The part about calling your code
from the other code)
Alternatively, can you set up a sample document somewhere that we can look
at?

--
Salut!
_______________________________________
Jean-Guy Marcil - Word MVP
(e-mail address removed)
Word MVP site: http://www.word.mvps.org
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top