首页 > 解决方案 > 在 Word 2016 中使用 VBA 代码删除空目录、图表和表格错误消息?

问题描述

我使用一个程序将文档导出到 Word 2016 并自动更新目录、图表、表格以添加它找到的任何条目并分配页码。但是,在某些情况下,导出的 Word 文档将不包含图形、表格标题描述(可能还有标题),因此当生成 TOC、图形表和表格时,它会写 ie for no graphics 这个消息,“未找到数字表条目。” 我希望 VBA 做的是找到此消息,将变量标志 noToF_flag 设置为 True,然后删除标题“图表”和域代码,以便在再次打开 word 文件时,错误消息不会再次生成。但是,如果没有写出这个特定的错误消息,请留下它找到的数字、标题和页码。这同样适用于表格和 TOC。就我而言,虽然我可以让 VBA 代码删除标题和字段代码信息,但我找不到能够设置标志的错误文本。我必须检测错误信息并留下好的数字和标题,单独的页面。

这是我一直在使用的 VBA 代码,它在打开文档后手动运行以查找错误消息。图形表和域代码条目现在已被注释掉,但是一旦我可以删除错误消息,我就可以设置一个用于删除标题和域代码的标志。对于可以使用的空 TOC、TOF 和 TOT 条目,没有运行时错误。

感谢您提供有关通过 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

编辑2:

使用答案中的第一个代码清单,将完成以下程序逻辑。我可能可以使用 TableId 和 CaptionLabels 或 Caption 来缩小错误消息的特定来源,以便可以删除 TOC、TOF、TOT 的标题。

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

' 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"

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

编辑 3:

我已经能够使用您的第一个代码列表删除每个字段代码,并添加删除相关标题的功能。我已经能够删除标题末尾的段落标记,因为我不希望文档中有空行。但是,在您的列表中使用“.delete”时,我在尝试删除字段代码后的段落标记时遇到了问题,这样我就不会在文档中出现空行。

我正要发布一个关于删除字段代码字符串后的段落标记的问题。但是,根据您对段落标记的第二个 VBA 代码列表注释,您已经击败了我。我会用你的代码代替我的,因为它更简单。我查看了各种段落对象集合的 Word 对象模型,但没有方法可以删除纯文本或域代码的段落。所以我来看看你使用段落对象的方式。

同样在为开关\f 搜索字段标签期间,VBA 只返回标签的第一个字母,即“FIG”的“f”和TBL 的“t”,甚至没有大写。因此,如果我有多个以“F”开头的标签,我将无法确定它是哪个标签,因为只会返回“f”。这同样适用于以“T”开头的多个标签。至于开关 \c,它返回我指定的确切用户定义标签,即使在这种情况下它与 Word 使用的默认标签匹配。

编辑4:

您的第二个代码清单有助于摆脱标题、带有段落标记的字段代码,这样页面上就不会出现任何空白行。当没有任何空表或它们的任何组合为空时,它可以工作。现在可以根据使用 TableOfFigures 为其定义的 Header 样式将其应用于 TABLE OF APPENDIXES,也可以用于 TABLE OF EQUATIONS。当 VBA 代码在打开文档时自动运行时,这将非常有用。

此外,您关于检索字段代码字符串的建议也很有用,因为不必在 VBA 代码中维护硬编码版本,但可以检索它,将 { 和 vbCr 的 ^d 添加到它以删除字段代码和段落标记以解决删除字段代码后仍然显示的字段代码末尾的段落标记有问题。这可以用作另一种删除带有段落标记的字段代码与调整第二个列表所做的段落范围的方法。

编辑 5:

我很想知道当表格为空时,第二个代码清单是否适用于 Words 内置自动 1 和 2 目录。错误消息“未找到目录条目”。并且字段代码是 {TOC \o "1-3" \h \z \u } 出现;但是,目录标题不可编辑以更改文本,但可以通过在内置标题样式之上应用标题样式来更改标题和部分条目,并且标题格式样式将更改。第二个代码清单将删除内置的 1 和 2 TOCS。

问题是如何通过用户命令和通过 VBA 将标题编辑为不同的标题和样式格式?我还可以使用此修改或 vba 代码来复制内置 TOC 的功能,以便在选择时获得所有表格选项卡(其中两个)来更新和更改内容?这将使我能够创建自己的 TOC,其行为类似于内置的 TOC。我知道 Word 允许创建自定义目录,但它没有选项卡。

另一个问题是关于“手动”内置目录的。它们有两个选项卡,但已经带有默认模板条目列表。可以手动更改列表中的每一个;但是,由于“未找到目录条目”,第二个代码列表在其为空时无法删除“手动”目录。永远不会生成它正在寻找删除它的消息。此外,无法编辑标题,如果您选择目录中的任何行,则会显示三个垂直点图标。如果您右键单击该行(不是图标),则会显示一个弹出窗口,您可以在其中选择“删除内容控件”,选择后三点图标消失。如何创建自己的“手动”内置 TOC,其行为类似,并使用 VBA 进行“内容控制”,就像手动内置 TOC 一样?

此外,在文档中生成参考列表时,它会生成一个没有边框的表格,并将文本从边框边缘设置为 0.01。每次更新/创建此书目表时,不断重新格式化此书目表是很乏味的。似乎没有办法控制表格格式,因为它是内置表格。VBA 代码可能有助于在打开或编辑期间自动控制其格式。

编辑 6:

这是另一个使用 TOCS 的 IF 域代码的帖子的网络链接。我不确定如何使用它,因为只能根据条件输出文本字符串。也许,它是一种将原始错误消息重写为另一个错误消息的方法,VBA 代码可以捕获这两个消息中的任何一个来对其进行处理。此外,我不确定 IF 域代码中允许的 IF 域代码嵌套级别的最大数量。

测试 TOC 域代码返回的错误

{IF {TOC \h \z \c "Figure"} = "未找到图表条目。" " 没有表" "条目存在"}

标签: vbams-word

解决方案


使用 Find 不起作用,因为您在文档中看到的文本是字段的结果。

文档同时具有 TablesOfContents 集合和 TablesOfFigures 集合。您可以遍历这些集合以查找和删除任何没有条目的集合。

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

编辑:

如果您使用该Range对象,您可以执行所有必要的删除操作,而无需设置标志、计算字幕甚至测试您拥有的 ToF 类型。

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

推荐阅读