How to check if a Paragraph is in a Table or not in MS-Word macro? - vba

The paragraph object in the Word has a property called Range. Within this Range object has a property called Cells.
For paragraph that are not in a table, this property Paragraph.Range.Cells is set to "". This can be seen in the Watches window in debug mode.
For paragraph that are in a table, the property Paragraph.Range.Cells has other properties in it, for example it has a property called Count.
I am using this property of Paragraph.Range.Cells to determine if the paragraph is in a table or not. However, I cant seem to figure out how to test this.
For example, I cannot simply test like this...
If paragraph.Range.Cells <> Null Then.... or even
If IsNull(paragraph.Range.Cells) Then ...
It throws a Run-time error '5907' There is no table at this location
So, how would I test for this? thanks

You can use the Information property:
If Selection.Information(wdWithInTable) Then
'What ever you'd like to do
End If
Hence you don't need any manual error catching mechanisms.

You can't call the Cells method unless the paragraph is in a table. You need to use a different method to determine whether the range is in a table.
You can use either...
paragraph.Range.Tables.Count > 0
...or...
paragraph.Range.Information(wdWithinTable)
Note that the second one looks more obvious, but is actually slower (only a problem if you're doing this inside a loop).

*Edited (if Err=) changed to (If Err<>)
You can simply allow the error to happen and catch it using OnError statement
Dim ParagraphIsTable As Object
OnError Resume Next 'allows errors to happen but execute next instruction
ParagraphIsTable = paragraph.Range.Cells
If Err <> 5907 Then '(this is to check for a specific error that might have happened)
'No Error occured, this means that ParagraphIsTable variable must contain a value
' Do the rest of your code here
Else
' an Error occured, this means that this is not a table
' do whatever
End If
OnError Goto 0 ' This cancels the effect of OnError Resume Next
' Which means if new errors happen, you will be prompt about them

Related

Run-time error '5852' when iterating over revisions

I am easily annoyed by word tracking format changes (even in text that is newly inserted in a revision), so I am using a macro to accept all format changes, once they summed up:
Sub AcceptAllFormatChanges()
Dim xRev As Revision
Dim count As Integer
count = 0
For Each xRev In ActiveDocument.Revisions
If Not xRev Is Nothing Then
If xRev.Type = wdRevisionProperty Then
count = count + 1
xRev.Accept
End If
End If
Next xRev
MsgBox ("Accepted " & count & " format changes")
End Sub
This works fine most of the time, but on some documents, it gives me a run-time error '5852' - Requested object is not available on the "If xRev.Type" line. I am looking for a way to check the object that is yielded by ActiveDocument.Revisions without it throwing a run-time error. Checking for Nothing is not enough. The issue also occures when removing the xRev.Accept or when looping backwards through the revisions.
Update: I tracked down the issue to a Word Bug today. If the macro strikes, I am also unable to iterate through changes in the document using the Next Change button on the review panel. Additionally, if I open the revision panel, the number of revisions jumps back and forth between two numbers. This helped me track down those ghost revisions to a few insertions which included fields (references to other sections). I am able to correct those by deleting/reinserting, so at least now I know how to fix my documents to make the macro work again. Unfortunately, I cannot reproduce the bug in order to actually file a bug report.
The VBA question though remains open: Is there a way for the macro to skip those ghost revisions without throwing a run-time error?
Use the WdRevisionType enumeration instead of cryptic numbers in the code for checking the Type property. Also you may try to check for Nothing before getting the Type property value. The following code works like a charm for me:
Public Sub AcceptSelection()
Dim rev As Revision
For Each rev In Selection.Range.Revisions
rev.Accept
Next rev
End Sub
And the last resort is to replace the for each loop with a reverse for loop.

Check if a property of an object has value or not

I couldn't find a solution for this on SO or other source. I apologize in advance if this is a tired question:
I have a macro that iterates through placeholders in shapes. Some of these placeholders have text, some don't. I'm trying to figure out if
.Shapes.Placeholder.TextFrame.TextRange has any value or not (In the 'watches' section of the VBA editor, this property has <The specified value is out of range.>). If it does, do something. Otherwise, continue the For Each statement. However, everything I tried has thrown out of bounds errors or something of that type.
I have tried:
If Not (placeholder.TextFrame.TextRange.Length = 0) Then: Immediately throws out of bounds error
Try/catch, which doesn't seem to exist in VBA (Gives me Sub or Function not registered)
If Not CStr(placeholder.TextFrame.TextRange) = "0" then
I'm quite out of my depth as I don't have experience with any Visual Basic iteration. I just need to, if that property is empty or null, skip over the placeholder.
EDIT: Following suggestions, I tried this:
For Each placeholder In sld.NotesPage.Shapes.Placeholders
If Not (placeholder.TextFrame Is Nothing) Then
If Not (placeholder.TextFrame.TextRange Is Nothing) Then
If Not (placeholder.TextFrame.TextRange.LanguageID Is Nothing) Then
placeholder.TextFrame.TextRange.LanguageID = lng
End If
End If
End If
Next
I still get an out of bounds error on placeholder.TextFrame.TextRange Is Nothing. Did I make a syntax error?
FINAL EDIT: Turns out there was an answer in SO after all. For this specific problem, it was enough to add On Error Resume Next right after theFor Each.

Why does my comparator not work after first loop?

I have a pretty simple If Else statement in my code that looks like this:
If GUI.editedFH = "" Then
fhNumField.Value = fhNumField.List(0)
Else
fhNumField.Value = editedFH
End If
This block of code is in a UserForm_Initialize() sub that I call fairly often after users use the form to edit or delete rows of data. I unload the form and reload it as a way to "refresh" the data presented in the form.
The code fails at the first line in that If statement. VBE throws this error
Run-time error '1004':
Application-defined or object-defined error
GUI.editedFH is a global string that is declared in a separate module. GUI is the name of the module, and editedFH is the string variable name. I put a watch on GUI.editedFH and I'm getting String as the type and the value that I want.
When I hardcode string values in, instead of GUI.editedFH, it still doesn't work i.e.
If "abc" = "" Then
'....
End If
The part that is most confusing is that I can compare strings like this elsewhere, and it is seemingly random on when the error will throw. It will work the first time through the initialize and a few subsequent times, but eventually it will throw an error.

VBA: Run-time error '5825' Object has been deleted

I was putting this code ActiveDocument.Variables("time1").Delete before End Sub and I get that error "Object has been deleted" so that if a variable "time1" exist, it will be deleted at the end of the procedure. I understand why I get that code because "time1" has already deleted on the first run but I want to skip and end the sub if it encounter errors. I tried to do this
On Error Goto here
ActiveDocument.Variables("time1").Delete
here:
End sub
but I still get that Error. Why is it that the error handler did not work?
You should be able to avoid this if you are not interested in whether the Variable existed or not.
ActiveDocument.Variables("time1") = ""
should remove a Variable called "time" if there is one, and execute without errors if there is not.
In a similar way,
ActiveDocument.Variables("time1") = "something"
will create the Variable if it does not exist.
This is one of the things that makes Variables slightly easier to work with than Custom Document Properties, although it does mean that empty variables are not allowed.

Error on ActiveSelection.Tasks

Does anyone know what this means
Set oProjTasks = ActiveSelection.Tasks
I have a macro that generates status reports from MS project and exports them directly into MS Word. It is a slick tool when it works.
When I run it now it throws "runtime error '424': object required" at this point.
How do I fix this?
The code that you are displaying is a set statement, that is setting the object ProjTasks equal to the task that is selected in the message box. The ActiveSelection property returns a selection object that represents the active selection.
It could be that you are experiencing an issue where there are no items selected, in which case it will throw a trappable error code 424. There is a code snippet that you can modify from the MSDN that will work to prevent this type of error from occuring.
Here is the link to the MSDN article... just remember to not use this code verbatim, but modify it to work with your macro.
http://msdn.microsoft.com/en-us/library/aa169315%28v=office.11%29.aspx
You could try just wrapping the error check around the set statement. I've written a small macro on a non-empty project file:
Sub Testing()
On Error GoTo ActiveSelectionErrHandler:
Set oProjTasks = ActiveSelection.Tasks
If oProjTasks Is Nothing Then
MsgBox "No tasks in current project"
End If
ActiveSelectionErrHandler:
Set oProjTasks = ThisProject.Tasks 'or something like that
Resume Next
End Sub
This handles the error but as Steve has already expressed more work is required to integrate the code.
You will have to follow the code to make changes to handle oProjTasks being empty where it is expected to have some values. Otherwise you will see more errors perhaps where the oProjTasks is found to be empty.
Another alternative solution could be to launch the macro after selecting a project as the code you have quoted will work fine if something is selected.