1
votes

I use a program that exports a document to Word 2016 and auto updates the TOC, Table of Figures, Table of Tables to add any entries it finds and assigns the page number(s). However, in some cases, the exported Word document will not contain a figure, table caption descriptions (and possibly headings) so that when the TOC, Table of Figures, and tables is generated, it will write i.e. for no figures this message, "No table of figures entries found." What I would like the VBA to do is find this message, set a variable flag noToF_flag to True, and then remove the title "TABLE OF FIGURES" and the field code so that upon opening the word file again, the error message doesn't get generated again. But in the case that this particular error message isn't written out, to leave the figures, titles and page #'s it found. The same applies to the table and TOC. In my case, I can't find the error text to be able to set a flag although I can have the VBA code delete the title and fieldcode information. I must detect the error message and leave the good figures and titles, pages alone.

Here's the VBA code I've been playing with that is run manually after the document is opened to find the error message. The TABLE of FIGURES and field code entries are commented out for now but once I can delete the error message, I then can set a flag that is used to delete the title and field code. There are no runtime errors for the case of empty TOC, TOF, and TOT entries that could be used.

Thanks for any pointers on deleting this dynamically generated text by Word 2016.

Public Sub FindAndDeleteEmptyTOCFields()

Dim doc As Word.Document
Dim fld As Word.Field
Dim rngFind As Word.Range

Set doc = ActiveDocument
Set rngFind = doc.Content
rngFind.TextRetrievalMode.IncludeFieldCodes = True
rngFind.TextRetrievalMode.IncludeHiddenText = True


With rngFind.Find
    .MatchWildcards = True
    ' .Text = "TABLE OF FIGURES"
    .Text = "No table of figures entries found."
    ' .Text = "^dTOC \h \z \c ""Figure"""
    .Forward = True
    .Wrap = wdFindAsk   'Good for debugging since it gives a popup
    ' .Wrap = wdFindContinue
    .Replacement.Text = ""
    .Execute Replace:=wdReplaceAll
    If .Execute Then
    Debug.Print rngFind.Text
    Else
    Debug.Print "not Found"
    End If
    ' End If
End With

EDIT2:

Using the first code listing from the answer, the following program logic will be done. I probably can use the TableId and CaptionLabels or Caption to narrow down the particular source of the error message so that the title for the TOC, TOF, TOT can be deleted.

' //=======================================================================

' Part A (Variation 1 & 2)
' After searching the Word document for the two error messages,
'  If no rewrite of captions set noATOCflg to True
  ' .Text = "No table of contents entries found."
' If rewrite of captions set noTBLFIGflg to True
  ' .Text = "No table of figures entries found."
   

' Part B or,
' If noFIGTBLflg is True for the Error message generated as "No table of figures entries found." Then
' search for the fieldcode text and set the associated flag.
' IE. doc.CaptionLabels("Figure").count >=0 then delete fieldcode and title. However, used Caption instead.
' The TOF.caption is equivalent to the \c label.
' The TOF.TableId is equivalent to a one letter code for the \f label.

  ' .Text = "^dTOC \h \z \c ""Figure"""    then set noTOFflg = True
  ' .Text = "^dTOC \h \z \c ""Table"""     then set noTOTflg = True
' Delete the fieldcode for the associated flag being True.
  
'Part C
' If noATOCflg is True for the Error message generated as "No table of contents entries found." Then
' search for the field code text and set the associated flag.
' The TOC.TableId is equivalent to a one letter code for the \f label.

  ' .Text = "^dTOC \h \z \t"   ' for the main TOC header styles  then set noTOCflg = True
  ' .Text = "^dTOC \h \z \u \f FIG"        then set noTOFflg = True
  ' .Text = "^dTOC \h \z \u \f TBL"        then set noTOTflg = True
 ' Delete the fieldcode for the associated flag being True.

'Part D
' If the any of the noTOCflg, noTOFflg and noTOTflg flags are True then
' search for the corresponding title and delete it,
  '  .Text = "TABLE OF CONTENTS"
  '  .Text = "TABLE OF FIGURES"
  '  .Text = "TABLE OF TABLES"

' //=======================================================================

EDIT 3:

I have been able to get the above working to delete each of the fieldcodes using your first code listing and add to it the capability to remove the associated Title. I have been able to remove the paragraph mark thats on the end of the Title since I didn't want empty lines in the document. However, using the ".delete" in your listing I was running into problems with trying to delete the paragraph mark after the fieldcode when it got deleted so that I wouldn't have blank lines in the document.

I was just about to post a question on deleting the paragraph mark after the fieldcode string. However, you have beat me to it based on your second VBA code listings comments on the paragraph mark. I'll substitute your code for mine since its alot simplier. I had looked at the Word object model for the various paragraph object collections, but there was no method to delete the paragraph either for straight text or the fieldcodes. So I'll take a look at the way you use the paragraph object.

Also during the search for the field label for the switch \f, VBA only returns the first letter of the label i.e. 'f' for "FIG" and 't' for TBL and not even capitalized. Thus, if I have multiple labels that start with "F" I wouldn't be able to determine which of my labels it is since only 'f' would be returned. The same applies for having multiple labels starting with "T". As for the switch \c, it returns the exact user-defined label I specified even though in this case it matches the default label that Word uses.

EDIT 4:

Your second code listing worked in getting rid of the title(s), fieldcode(s) with paragraph marks so that there isn't any blank lines filling up the page. It works when there aren't any empty tables, or any combination of them being empty. One could now apply this to TABLE OF APPENDIXES based on the Header style being defined for it using the TableOfFigures and also for TABLE OF EQUATIONS too. This will be really useful when the VBA code is run automatically upon opening the document.

Also your suggestion on retrieving the fieldcodes string is also useful since one doesn't have to maintain a hardcoded version in VBA code but can retrieve it add the ^d for the { and vbCr to it to remove the fieldcode and paragraph mark to solve the problem with the paragraph mark on the end of the fieldcode that stills shows up after the fieldcode is deleted. This could be used as another way to delete the fieldcode with paragraph mark vs. adjusting the range on the paragraph that your second listing does.

EDIT 5:

I was curious to see if the second code listing would work on Words builtin automatic 1 and 2 table of contents when the table is empty. The error message "No table of contents entries found." and fieldcode is {TOC \o "1-3" \h \z \u } shows up; however, the TOC title is not editable to change the text but the title and section entries can be changed by applying a heading style on top of the builtin ones and the title format style will change. The second code listing will remove the builtin 1 and 2 TOCS.

The question is how to edit the title both by user command and via VBA to a different title and style format? Also can I use this modification or vba code to duplicate the functionality of the builin TOCs so that when selected I'd get all the table tabs (two of them) to update and change things? This would give me the ability to create my own TOCs that act like the builtin ones. I know that Word allows one to create custom TOCs but it doesn't have the tabs on them.

Another question is on the "manual" builtin TOCs. They have the two tabs but already come with a list of default template entries. One can manually change each of them on the list; however, the second code listing can't delete the "manual" TOC when its empty since the "No table of contents entries found." message never gets generated that it is looking for to delete it. Moreover, the Title can't be edited, and if you select any row in the TOC a three vertical dot icon is shown. If you right click on this row (not the icon) a popup is shown where you can select "remove content control" and when selected the three dot icon disappears. How can one create their own "manual" builtin TOC that acts similarly and has the "content control" using VBA to act like the manual built-in TOC?

Additionally, when generating the lists of references in a document, it generates a table without borders and sets the text 0.01 from the borders edge. This is tedious to constantly reformat this bibliography table everytime it gets updated/created. There doesn't seem to be a way to control the table format since it is builtin table. VBA code might help here to control its formating automatically when opening or during editing.

EDIT 6:

Here is a weblink to another post using the IF fieldcode for TOCS. I'm not sure how this could be used since only a text string can be output based on the condition. Maybe, its a way to rewrite the original error message to another one and VBA code can capture either of the two messages to do something with it. Also, I'm not sure on the maximum number of IF fieldcode nesting levels allowed within an IF fieldcode.

test for error returned by TOC field code

{IF {TOC \h \z \c "Figure"} = " No table of figures entries found." " No table" "Entries exist"}

1
You can access the field codes directly from the Range - ActiveDocument.TablesOfFigures(index).Range.Fields(1).CodeTimothy Rylatt
I have edited my answer to give you a fully worked example.Timothy Rylatt
What about builtin in TOCS (see EDIT 5) and using IF fieldcodes (see EDIT 6)?M SW
If you have follow-up questions they need to be posted as new questions, not continual edits to one that has already been answered.Timothy Rylatt
I think all the questions are related to the same topic of using VBA to control some tedious editing of word document TOC/TOF etc. If a question(s) on the same topic are spread across numerous questions, then others needing to resolve similar issues will spend alot of time trying to search for them. This leads one to then to have a question refer back to an earlier question using web hyperlinks resulting in hyperlinks everywhere. If the topic is not related, then of course another different question should be posted.M SW

1 Answers

1
votes

Using Find doesn't work because the text that you see in the document is the result of a field.

A document has both a TablesOfContents collection and a TablesOfFigures collection. You can loop through these collections to find and delete any that have no entries.

Sub RemoveEmptyTOCandTOF()
   Dim index As Long
   For index = ActiveDocument.TablesOfContents.Count To 1 Step -1
      With ActiveDocument.TablesOfContents(index)
         If .Range.Text = "No table of contents entries found." Then .Delete
      End With
   Next index
   For index = ActiveDocument.TablesOfFigures.Count To 1 Step -1
      With ActiveDocument.TablesOfFigures(index)
         If .Range.Text = "No table of figures entries found." Then .Delete
      End With
   Next index
End Sub

EDIT:

If you work with the Range object you can do all the necessary deletions without needing to set flags, count captions or even test which ToF type you have.

Sub RemoveEmptyTOCandTOFExpanded()
   Dim index As Long
   Dim tblRange As Range
   For index = ActiveDocument.TablesOfContents.Count To 1 Step -1
      With ActiveDocument.TablesOfContents(index)
         If .Range.text = "No table of contents entries found." Then
            Set tblRange = .Range
            With tblRange
               'expand the range to include the paragraph mark after the field
               .Expand wdParagraph
               'move the start of the range back one paragraph so that the range includes the title
               .MoveStart wdParagraph, -1
               'delete both paragraphs
               .Delete
            End With
         End If
      End With
   Next index
   For index = ActiveDocument.TablesOfFigures.Count To 1 Step -1
      With ActiveDocument.TablesOfFigures(index)
         If .Range.text = "No table of figures entries found." Then
            Set tblRange = .Range
            With tblRange
               'expand the range to include the paragraph mark after the field
               .Expand wdParagraph
               'move the start of the range back one paragraph so that the range includes the title
               .MoveStart wdParagraph, -1
               'delete both paragraphs
               .Delete
            End With
         End If
      End With
   Next index
End Sub