InStr()无法识别智能报价

时间:2018-01-18 20:01:57

标签: vba ms-word ms-office word-vba

我有一个像这样的代码:

Sub MoveToBeginningSentence()
    Application.ScreenUpdating = False
    Dim selectedWords As Range
    Dim selectedText As String
    Const punctuation As String = " & Chr(145) & "
    On Error GoTo ErrorReport
     ' Cancel macro when there's no text selected

    Selection.Cut
    Selection.MoveLeft Unit:=wdSentence, Count:=1, Extend:=wdMove
    Selection.MoveRight Unit:=wdCharacter, Count:=1, Extend:=wdExtend
    Set selectedWords = Selection.Range
    selectedText = selectedWords
    If InStr(selectedText, punctuation) = 0 Then
        Selection.MoveLeft Unit:=wdSentence, Count:=1, Extend:=wdMove
        Selection.Paste
    Else
        Selection.MoveLeft Unit:=wdSentence, Count:=1, Extend:=wdMove
        Selection.Paste
        Selection.Paste
        Selection.Paste
        Selection.Paste
    End If

ErrorReport:

End Sub

基本上,它帮助我将我选择的任何文本移动到Word中句子的开头。如果没有引号,则粘贴一次。如果有引号,请粘贴4次。

问题在于是否有任何引用,它只会粘贴一次。如果我将宏设置为检测任何其他字符,它将正常工作。但每次我试图强迫它检测智能报价时,它都会失败。

有没有办法解决它?

3 个答案:

答案 0 :(得分:1)

使用Selection对象总是有点意义;总的来说,使用Range对象更好。你只能有一个选择;您可以根据需要拥有尽可能多的范围。

因为您的代码使用了Selection对象,所以它并不是100%清楚代码的作用。基于我的最佳猜测,我将以下示例放在一起,如果它不完全正确,您可以调整它。

一开始,我会检查选择中是否有某些内容,或者它是一个闪烁的插入点。如果未选择任何文本,则宏结束。这比调用错误处理更好,然后不处理任何事情:如果代码中出现其他问题,你就不会知道它们。

Range对象被实例化以供选择 - 不需要" cut"它,正如你将进一步看到的那样。基于此,整个句子也被分配给Range对象。拾取句子的文本,然后句子的范围是"折叠"到它的起点。 (想象一下,就像按下键盘上的左箭头一样。)

现在检查句子的文本是否有字符Chr(145)。如果不存在,则在句子的开头添加原始选择的文本(包括格式)。如果它在那里,那么它会被添加四次。

最后,删除原始选择。

Sub MoveToBeginningSentence()
    Application.ScreenUpdating = False
    Dim selectedText As String
    Dim punctuation As String
    punctuation = Chr(145)  ' ‘ "smart" apostrophe
    Dim selRange As word.Range
    Dim curSentence As word.Range
    Dim i As Long

   ' Cancel macro when there's no text selected
   If Selection.Type = wdSelectionIP Then Exit Sub

    Set selRange = Selection.Range
    Set curSentence = selRange.Sentences(1)
    selectedText = curSentence.Text
    curSentence.Collapse wdCollapseStart
    If InStr(selectedText, punctuation) = 0 Then
        curSentence.FormattedText = selRange.FormattedText
    Else
        For i = 1 To 4
            curSentence.FormattedText = selRange.FormattedText
            curSentence.Collapse wdCollapseEnd
        Next
    End If
    selRange.Delete
End Sub

答案 1 :(得分:0)

请查看此代码。

Sub MoveToBeginningSentence()
    ' 19 Jan 2018

    Dim Rng As Range
    Dim SelText As String
    Dim Repeats As Integer
    Dim i As Integer

    With Selection.Range
        SelText = .Text                     ' copy the selected text
        Set Rng = .Sentences(1)             ' identify the current sentence
    End With

    If Len(SelText) Then                    ' Skip when no text is selected
        With Rng
            Application.ScreenUpdating = False
            Selection.Range.Text = ""       ' delete the selected text
            Repeats = IIf(IsQuote(.Text), 4, 1)
            If Repeats = 4 Then .MoveStart wdCharacter, 1
            For i = 1 To Repeats
                .Text = SelText & .Text
            Next i
            Application.ScreenUpdating = True
        End With
    Else
        MsgBox "Please select some text.", _
               vbExclamation, "Selection is empty"
    End If
End Sub

Private Function IsQuote(Txt As String) As Boolean
    ' 19 Jan 2018

    Dim Quotes
    Dim Ch As Long
    Dim i As Long

    Quotes = Array(34, 147, 148, -24143, -24144)
    Ch = Asc(Txt)
'    Debug.Print Ch                      ' read ASCII code of first character
    For i = 0 To UBound(Quotes)
        If Ch = Quotes(i) Then Exit For
    Next i
    IsQuote = (i <= UBound(Quotes))
End Function

采用的方法是使用ASC()函数识别所选句子的第一个字符。对于正常的引号,这将是34.在我的测试中,我提出了-24143和-24144(打开和关闭)。我无法识别Chr(145),但发现MS说明卷曲引号分别是Chr(147)和Chr(148)。因此我添加了一个检查所有这些功能的函数。如果在函数中启用行Debug.Print Ch,则实际找到的字符代码将打印到即时窗口。您可以向数组Quotes添加更多字符代码。

代码本身并不考虑单词之间的空格。也许Word会照顾到这一点,也许你不需要它。

答案 2 :(得分:-1)

您需要提供InStr作为第一个参数的起始位置:

If InStr(1, selectedText, punctuation) = 0 Then

另外

Const punctuation As String = " & Chr(145) & "

将搜索space-ampersand-space-Chr(145)-space-ampersand-space。如果要搜索智能引号字符,请使用

Const punctuation As String = Chr(145)

希望有所帮助。