Tengo un código así:

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

Básicamente, me ayuda a mover cualquier texto que haya seleccionado al comienzo de la oración en Word. Si no hay comillas, pegue una vez. Si hay una comilla, pegue 4 veces.

El problema es independientemente de si hay alguna cita allí o no, solo se pegará una vez. Si configuro la macro para detectar cualquier otro personaje, funcionará bien. Pero cada vez que trato de obligarlo a detectar citas inteligentes, fallará.

Hay alguna manera de arreglarlo?

0
nguyen long 18 ene. 2018 a las 23:01

3 respuestas

La mejor respuesta

Trabajar con el objeto Selection siempre es un poco confuso; en general, es mejor trabajar con un objeto Range. Solo puede tener una Selección; puedes tener tantos rangos como necesites.

Debido a que su código usa el objeto Selección, no está 100% claro qué hace el código. Basado en mi mejor conjetura, armé el siguiente ejemplo que puedes ajustar si no es exactamente correcto.

Al principio, verifico si hay algo en la selección o si es un punto de inserción parpadeante. Si no se selecciona texto, la macro finaliza. Esto es mejor que invocar el manejo de errores, luego no manejar nada: si surgen otros problemas en su código, no los conocerá.

Se crea una instancia de un objeto Range para la selección; no es necesario "cortarlo", como verá más adelante. En base a esto, la oración completa también se asigna a un objeto Range. Se recoge el texto de la oración, luego el Rango de la oración se "contrae" a su punto de partida. (Piense en esto como presionar la flecha izquierda del teclado).

Ahora se verifica el texto de la oración para el carácter Chr (145). Si no está allí, el texto de la selección original (incluido el formato) se agrega al comienzo de la oración. Si está allí, se agrega cuatro veces.

Finalmente, se elimina la selección original.

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
Cindy Meister 19 ene. 2018 a las 15:48

Debe proporcionar InStr con la posición inicial como primer parámetro:

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

Además

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

Va a buscar space-ampersand-space-Chr(145)-space-ampersand-space. Si desea buscar el carácter de comillas inteligentes, use

Const punctuation As String = Chr(145)

Espero que eso ayude.

-1
xidgel 18 ene. 2018 a las 22:31

Por favor revisa este código.

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

El enfoque adoptado es identificar el primer carácter de la oración seleccionada utilizando la función ASC (). Para una comilla normal que sería 34. En mi prueba se me ocurrió -24143 y -24144 (apertura y cierre). No pude identificar Chr (145) pero encontré MS indicando que las comillas son Chr (147) y Chr (148) respectivamente. Por lo tanto, agregué una función que los verifica a todos. Si habilita la línea Debug.Print Ch en la función, el código de caracteres realmente encontrado se imprimirá en la ventana inmediata. Puede agregar más códigos de caracteres a la matriz Quotes.

El código en sí mismo no considera espacios entre palabras. Quizás Word se encargará de eso, y quizás no lo necesites.

0
Variatus 19 ene. 2018 a las 02:34