【问题标题】:Delete text between parentheses if text between quotes has fewer than 3 words如果引号之间的文本少于 3 个单词,则删除括号之间的文本
【发布时间】:2015-03-20 16:57:34
【问题描述】:

我有一个包含多个段落的文档。我想遍历文档的每一段并检查引号中是否有单词。如果引号中的单词少于 3 个,我想删除括号内所有出现的文本。

想象一下下面的段落。

您需要包含的信息取决于材料的来源类型。对于“印刷材料”,您通常只需要包括作者(s) (或文章标题,如果没有作者)和出版年份(从不月或日) 在您的参考中。在引用来源的特定部分时(例如,直接引用),您还需要指出页码(s)或其他名称(章、图、表、方程等)。对于 Internet 资源,当页码不可用时,可以使用段落编号。

由于短语 “印刷材料” 仅包含 2 个单词,因此我想删除括号中的所有单词以及括号本身。

我将如何在 Microsoft Word 中使用 VBA 做这样的事情?我发布了一些失败的代码,以表明这是一个真诚的问题。

Sub RemoveUnnecesaryTexts()

Dim doc As Document
Dim para As Paragraph

Set doc = ActiveDocument

For Each para In doc.Paragraphs
    Application.ScreenUpdating = False
    Selection.HomeKey Unit:=wdStory
    With Selection.Find
        .ClearFormatting
        .Text = "(""<*>"")"
    End With

    If Selection.Find.Execute Then
        Selection.Parent.Select
        With Selection.Find
            .Text = "\((<*>)\)"
            .Replacement.Text = ""
            .Forward = True
            .Wrap = wdFindContinue
            .Format = False
            .MatchCase = False
            .MatchWholeWord = False
            .MatchWildcards = False
            .MatchSoundsLike = False
            .MatchAllWordForms = False
        End With
        Selection.Find.Execute Replace:=wdReplaceAll

    End If
Next para

End Sub  

此代码没有检查引文中的字数,因为我还没有成功做到这一点。但至少它会让你知道我正在尝试做什么。关于我在这里做错了什么有什么想法吗?

【问题讨论】:

  • 这个问题表明没有任何研究工作或自助尝试。你已经有一段时间了……你应该比这更清楚吗?
  • @Jean-FrançoisCorbett 很抱歉,如果您是这样看的。我实际上已经寻找了相当长的一段时间,并且已经在这个问题上苦苦挣扎了几个小时。我选择不发布失败尝试的代码,因为我认为它可能会误导潜在的响应,因为我真的迷路了。
  • @Jean-FrançoisCorbett 我已经发布了我失败的代码的示例,它不起作用,以表明我确实尝试过研究这个问题。我只是不知道该去哪里。
  • 好的。这可能会让你走上正轨:stackoverflow.com/questions/25617920/…

标签: vba ms-word


【解决方案1】:

基于我之前的回答:Format number between markers as subscript

这对我有用:

Dim wd As Document
Dim para As Paragraph
Dim rOpeningQuote As Range
Dim rClosingQuote As Range
Dim rBewteenQuotes As Range
Dim quoteFound As Boolean
Dim nWordsBetweenQuotes As Long
Dim rOpeningParenthesis As Range
Dim rClosingParenthesis As Range
Dim openingParenthesisFound As Boolean

Set wd = ActiveDocument

For Each para In wd.Paragraphs
    para.Range.Select
    'Look for opening quote
    quoteFound = Selection.Find.Execute("""")
    If quoteFound Then
        Set rOpeningQuote = Selection.Range
        'Look for closing quote
        Selection.Find.Execute """"
        Set rClosingQuote = Selection.Range
        'Count words between the two
        Set rBewteenQuotes = wd.Range(rOpeningQuote.End, rClosingQuote.Start)
        nWordsBetweenQuotes = UBound(Split(rBewteenQuotes.Text, " ")) + 1

        If nWordsBetweenQuotes < 3 Then
            para.Range.Select
            Do
                'Look for opening parenthesis
                openingParenthesisFound = Selection.Find.Execute("(")
                If Not openingParenthesisFound Then Exit Do
                Set rOpeningParenthesis = Selection.Range
                'Look for closing parenthesis
                wd.Range(Selection.End, para.Range.End).Select
                Selection.Find.Execute ")"
                Set rClosingParenthesis = Selection.Range
                'Delete and select rest of paragraph for next iteration
                wd.Range(rOpeningParenthesis.Start, rClosingParenthesis.End).Delete
                wd.Range(Selection.End, para.Range.End).Select
            Loop
        End If
    Else
        'No quote found in this paragraph. Do nothing.
    End If
Next para

结果:

请注意,删除括号中的位会留下多个连续的空格(上图中以粉红色突出显示的示例)。不确定您是否要解决这个问题,但如果是这样,请尝试一下,如果遇到问题,请提出一个新问题。

【讨论】:

  • 由于某种原因,我不时在“quoteFound = Selection.Find.Execute("""")" 行上遇到错误。错误说,替换为文本包含组号这超出了范围。如果您愿意,我很乐意发布另一个问题。 :)
  • 我在运行代码之前运行了一个空白的 Selection.Find,从而超越了这一点。让我印象深刻,但它确实有效。
【解决方案2】:

伪代码:

Iterate through the paragraphs. 
Regex Match the quoted sub string "...." and then count the spaces in the match
If spaces < 2 then 
    Second Regex match all occurrences of (....) and delete all matches in the paragraph 
Else 
    Continue to next paragraph 

请注意,这取决于仅存在一个带引号的子字符串。如果不是这种情况,则必须实现逻辑以选择正确的引号。

编辑:我离正则表达式专家还差得很远,但匹配可能很简单:

String match1 = "/".*/""
String match2 = "/(.*/)"

这些将贪婪地匹配您想要的模式,这意味着它们将匹配“1”、“12345”、(123456....1223447748557),以及空字符串“”和空括号 ()。如果不需要空,则用“+”切换“*”。

我没有对此进行测试,我只是破解正则表达式,直到他们做我想要的。此外,您需要处理(或忽略)引号内出现的括号。

此外,对于您选择在其中实现此功能的任何语言,您可以逐个字符地遍历匹配的引号子字符串,如果该字符是空格,则增加一个计数器,或者,更好的是:查看您的将为您执行此操作的字符串库。

最后,对于某些语言,您应该有一个 String.replace() 函数,在这种情况下,我会遍历每个括号匹配并将匹配输入到函数中,例如 Paragraph.replace(matches[i], " "),它只是用一个空字符串替换你的匹配项。

编辑: 哦。我不知何故错过了标题的 VBA 部分。然后你需要处理 Word 的对象模型。 AFAIK 有一个 Document 对象,它应该返回一个可以迭代的 Paragraph[] 集合。我知道 VBA 有一个您可以使用的 Regex 类,并且 String 方法应该可以正常工作。不确定 VBA 是否有 'int HowManyTimesDoesThisCharAppearInThisString(String search, char target)' 但自己实现它并不难。可以在 MSDN 上查看字符串文档。这是我在使用 M$ 代码时唯一最喜欢的事情,其他人遇到与您相同的问题的可能性高于平均水平,而且 MSDN 的文档也相当不错。

另外,我发现了这个,可能对你有帮助:Counting the Words in a String 该方法实际上更简单,它只是将字符串拆分为空格并计算结果数组的长度。

【讨论】:

  • 非常感谢您的回答。我从概念上理解如何实现它我只是很难在 VBA 中实现这个概念。
  • 我无法评论您的主要帖子,但我看到您已对其进行了编辑。现在我有更多问题:为什么您在正则表达式中有 ,您是否有意尝试匹配这些字符?其次,这很重要,你没有'。在正则表达式中,所以除非我弄错了,否则正则表达式匹配这个:“”而不是这个“我是一个字符串”。此外,更重要的是:当您说“它不起作用”时,到底发生了什么。
猜你喜欢
  • 1970-01-01
  • 2011-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-20
  • 1970-01-01
相关资源
最近更新 更多