Почему метод TextRange.InsertSymbol заменяет текст в моем TextRange? - PullRequest
5 голосов
/ 06 июня 2019

В процессе создания слайда через VBA в powerpoint мне нужно вставить «символ Wingdings» в сгенерированный текст, который представляет собой сравнение двух значений.Я сделал этот метод, который работает именно так, как я хочу

Sub formatDifference(header As String, old As Integer, now As Integer, txt As TextRange)
    Dim diff As Integer
    diff = old - now

    With txt
        If (diff > 0) Then
            .InsertSymbol "Wingdings", getArrowCharCode("down")
                                       ' getArrowCharCode is a custom function to get the 
                                       ' char code as an Integer
        ElseIf (diff = 0) Then
            .InsertSymbol "Wingdings", getArrowCharCode("right")
        Else
            .InsertSymbol "Wingdings", getArrowCharCode("up")
        End If

        .InsertBefore header & now & " ("    ' <-- note this line
        .InsertAfter " " & Abs(diff) & ")"
    End With
End Sub

Sub formatDifference, по сути, просто добавляет пункт с маркером в тексте (в примере ниже, процедура вызывается 4 раза додобавить текст без маркера).

Что я не понимаю, так это то, что когда я начинаю текст с какого-то текста, а затем использую метод InsertSymbol, кажется, что текст фактически заменяется вместо добавления символа в конце.Вот пример другого кода:

Sub formatDifference(header As String, old As Integer, now As Integer, txt As TextRange)
    Dim diff As Integer
    diff = old - now

    With txt
        .InsertAfter header & now & " (" ' <-- line moved here
                                         '     it doesn't matter if I use 
                                         '     .Text = "initial text"', 
                                         '     it will do the same thing
        If (diff > 0) Then
            .InsertSymbol "Wingdings", getArrowCharCode("down")
        ElseIf (diff = 0) Then
            .InsertSymbol "Wingdings", getArrowCharCode("right")
        Else
            .InsertSymbol "Wingdings", getArrowCharCode("up")
        End If
        .InsertAfter " " & Abs(diff) & ")"
    End With
End Sub

И вот сравнение двух результатов, которые я получаю из кодов выше (в том же порядке):

Example of the difference the codes make

Мое понимание метода InsertSymbol заключалось в том, что он вставлял бы символ в конце последнего абзаца, но это не похоже на это ... Мой второй пример неисправен или янеправильно понимать описание метода ?


PS Примечание : параметр заголовка содержал символы возврата каретки и перевода строки, поэтому второй захват имеетвсе точки на одной линии, так как эта первая часть, кажется, заменена.

Ответы [ 2 ]

1 голос
/ 14 июля 2019

Документация реализаций InsertSymbol

Microsoft Word Range.InsertSymbol и Selection.InsertSymbol описываются как:

Вставляет aсимвол вместо указанного диапазона.
Если вы не хотите заменять диапазон, используйте метод Свернуть, прежде чем использовать этот метод.

Microsoft Publisher's TextRange.InsertSymbol *Реализация 1015 * описывается следующим образом:

Возвращает объект TextRange, представляющий символ, вставленный вместо указанного диапазона или выделения.
Если вы не хотите заменять диапазон или выделение, используйтеметод Свернуть, прежде чем использовать этот метод.

А затем есть методы Office TextRange2.InsertSymbol и PowerPoint TextRange2.InsertSymbol , описанные как:

Вставка символа из указанного шрифта в диапазон текста, представленного объектом TextRange2.

Сэто означает, что документация PowerPoint реализации TextRange.InsertSymbol немного неточна , включая неверное объяснение («после первого предложения») включенногоПример кода.

InsertSymbol после TextRange

Если вы хотите вставить символ после предоставленного TextRange, я предлагаю следующую функцию-обертку:

Public Function InsertSymbolAfter(newTextRange As PowerPoint.TextRange, _
                           newFontName As String, _
                           newCharNumber As Long, _
                           Optional newUnicode As MsoTriState = msoFalse) As TextRange

    If Right(newTextRange.Text, 1) = vbCr Then
        Set InsertSymbolAfter = newTextRange.Characters(newTextRange.Characters.Count) _
            .InsertSymbol(newFontName, newCharNumber, newUnicode)
        newTextRange.InsertAfter vbCr
    Else
        Set newTextRange = newTextRange.InsertAfter("#")
        Set InsertSymbolAfter = newTextRange _
            .InsertSymbol(newFontName, newCharNumber, newUnicode)
    End If

End Function

Он различает два случая:

  • Если последним символом является vbCR (Chr(13), возврат каретки, CR), символ добавляется до CR (заменяется CR)новым символом и добавлен позже).
  • Во всех других случаях сначала добавляется произвольный символ, а затем заменяется новым символом.

Test

Функция может быть проверена для целых текстовых кадров,абзацы или символы этим:

Private Sub testit()
    Const WingDingsLeft As Long = 231
    Const WingDingsRight As Long = 232
    Const WingDingsUp As Long = 233
    Const WingDingsDown As Long = 234

    With ActivePresentation.Slides(1).Shapes(1).TextFrame
        InsertSymbolAfter(.TextRange, "Wingdings", WingDingsUp)
        InsertSymbolAfter(.TextRange.Paragraphs(1), "Wingdings", WingDingsDown)
        InsertSymbolAfter(.TextRange.Characters(2, 1), "Wingdings", WingDingsRight)
    End With
End Sub
1 голос
/ 10 июля 2019

Я мог бы сделать обходной путь, который, кажется, работает нормально.

Sub AppendSymbol(ByRef orig As TextRange, ByVal fontName As String, ByVal charCode As Integer, Optional ByVal position As Integer = -1)
    Dim strStart, strEnd As String

    If ((position < 0) Or (position >= Len(orig.text))) Then
        orig.Paragraphs(orig.Paragraphs.Count + 1).InsertSymbol fontName, charCode
        'this one just inserts the symbol at the end by forcing a new paragraph
    Else
        strStart = Left(orig.text, position)
        strEnd = Right(orig.text, Len(orig.text) - position)

        orig.Paragraphs(1).InsertSymbol fontName, charCode
        orig.InsertBefore strStart
        orig.InsertAfter strEnd
    End If
End Function

В этом подпункте я в основном копирую исходную строку, заменяю ее символом и затем снова добавляю строку вокруг символа.

Теперь я могу назвать этот Sub следующим образом:

Private Sub displayTotal(ByRef para As TextRange, ByVal prevCompare As Testing)
    Dim arrowDirection As String
    Dim tempDifference As Integer

    tempDifference = p_total - prevCompare.Total
    para.InsertAfter "Number of elements : " & p_total & " ("

    'calling the Sub
    AppendSymbol para, "Wingdings", getWingdingArrowChar(getArrowDirection(tempDifference))

    para.InsertAfter " " & Abs(tempDifference) & ")"
    para.IndentLevel = 2
    para.ParagraphFormat.Bullet = msoFalse
End Sub

Что касается объяснения, Asger , похоже, что-то замышляет.Реализация метода, по-видимому, похожая на Word, потребует, чтобы текстовый диапазон свернулся, прежде чем он сможет добавить символ.

В пользовательском методе выше строка orig.Paragraphs(orig.Paragraphs.Count + 1).InsertSymbol fontName, charCode в основном заставляет текущий абзац свернутьсядобавив после него абзац, поэтому метод InsertSybol затем работает, как и ожидалось.

...