Обработка математической формулы

Автор Massaraksh7, 17 ноября 2024, 23:20

0 Пользователи и 1 гость просматривают эту тему.

Massaraksh7

Если в параграфе Writer встречается математическая формула, как её распознать? Что-то смотрел свойства параграфа, и не нашёл.
Имею в виду квадратик с Smax
Поясню: мне нужно в скрипте отредактировать параграф, но так, чтобы формула не исчезла.

mikekaganski

Лучше обсуждать не абстрактное "как распознать" (OLE-объект с якорем в абзаце) и скриншот, а пример файла с формулой и скриптом.
С уважением,
Михаил Каганский

Massaraksh7

Хорошо, пытаюсь заменить текст в фигурных скобках на 12345, с сохранением формулы. В лоб не получается. Макрос main.

mikekaganski

#3
Не пользуйтесь Para.String (который, кстати, не имеет отношения к сервису Paragraph, который Вы тестируете) - Вы уничтожаете всё, включая всё форматирование, все привязанные объекты (OLE, изображения, графику), все сноски и т.п.

Если надо что-то вставить - используйте курсор.

Sub findblock
op = "{"
cp = "}"
ParaEnum = ThisComponent.Text.createEnumeration
ipara = 1
While ParaEnum.hasMoreElements() '---Поиск по параграфам
  icell = 0
  icellpara = 0
  Para = ParaEnum.nextElement()
  if Para.supportsService("com.sun.star.text.Paragraph") Then '---Это параграф
1:   txt = Para.String
     p1 = Instr(txt,op)
     p2 = Instr(txt,cp)
     if p1>0 and p2>0 and p2>p1 then
        cursor = ThisComponent.getText().createTextCursorByRange(Para.getStart())
        cursor.goRight(1, true) ' select the first character
        cursor.String = "" ' or cursor.setString("") - i.e., remove the first character
        cursor.goRight(p1 - 1, false) ' move to the next position
        ' the paragraph string doesn't include objects, that cursor stops at
        do
          cursor.collapseToEnd()
          cursor.goRight(1, true)
        loop while cursor.String <> "{"
        cursor.goRight(p2 - p1, true) ' select the placeholder at this position
        while Right(cursor.String, 1) <> "}"
          cursor.goRight(1, true)
        wend
        cursor.String = "12345" ' replace the placeholder
        goto 1
     endif
  end if
ipara = ipara + 1 
Wend
End Sub

Это не тот курсор, который видит пользователь; но этот курсор перемещается (невидимо) так же, как и видимый курсор. Поэтому он имеет остановки там, где есть объекты (которых нет в строке) - поэтому придётся уточнить позицию найденных символов (как это сделано в коде).
С уважением,
Михаил Каганский

Massaraksh7


mikekaganski

Кстати, в моём коде есть проблема - он предполагает, что курсор перемещается как минимум по тем же позициям, что и буквы в строке. Но это может быть не так - например, если в абзаце есть поля, или там есть сложные символы типа эмоджи. Поэтому 'cursor.goRight(p1 - 1, false) ' move to the next position' и 'cursor.goRight(p2 - p1, true) ' select the placeholder at this position' следует уничтожить, чтобы курсор аккуратно перемещался к открывающей и закрывающей скобкам, не обращая внимания на длину текста.

В принципе обратная проблема есть и в Вашей части кода: Вы проверяете, есть ли скобки в тексте, предполагая, что эти скобки могут быть только началом / концом текста-заместителя. Но если они появятся как часть содержимого поля - будет ой.
С уважением,
Михаил Каганский

bigor

А через поиск/замену нельзя сделать?
Поддержать наш форум можно здесь

mikekaganski

С уважением,
Михаил Каганский

sokol92

Альтернативный путь для использования текстового курсора - разбивать параграф на части (TextPortion).
Sub FindBlock2()
  Dim oPar As Object, oPortion As Object
  For Each oPar In ThisComponent.Text
    If oPar.supportsService("com.sun.star.text.Paragraph") Then
      For Each oPortion In oPar
        If oPortion.TextPortionType="Text" Then
          If oPortion.String Like "*{*}*" Then         
            oPortion.String="MyString"
          End If 
        End if
      Next oPortion
    End If 
  Next oPar
End Sub

См. также раздел "Enumerating text sections (paragraph portions)" книги Питоньяка OOME_4_1.odt.
Владимир.

mikekaganski

Единственное - контролировать, что порции не ломаются. Скажем, если Вы готовите свои шаблоны вручную в Writer, то когда Вы через месяц замените символ в Вашей заготовке {abc} на {adc}, то символ d станет отдельной порцией (из-за функции, которая устанавливает изменённому тексту идентификатор для улучшения сравнения).
С уважением,
Михаил Каганский

sokol92

Цитата: mikekaganski от 18 ноября 2024, 14:56Единственное - контролировать, что порции не ломаются
Иногда возникает задача замены текста именно внутри порций - например, многие пользователи Calc мечтают о функции замены текста, которая сохраняет "индивидуальное" форматирование внутри ячеек. Лет 5 уже собираюсь написать эффективный вариант такой функции...  :)
Владимир.

Massaraksh7

Цитата: mikekaganski от 18 ноября 2024, 13:35Но если они появятся как часть содержимого поля - будет ой.
В документации пользователя будет прямой запрет на это, поэтому - нестрашно.
Цитата: mikekaganski от 18 ноября 2024, 13:35Кстати, в моём коде есть проблема
Там ещё первый символ параграфа удаляется. Но это всё мелочи - главное, что я понял принцип. И почитаю ещё документацию по курсорам.

mikekaganski

Цитата: Massaraksh7 от 18 ноября 2024, 18:14Там ещё первый символ параграфа удаляется
Это я специально делал. Даже комментарий написал. Потому что затупил, подумал, что в бейсике нумерация символов с 0.
С уважением,
Михаил Каганский

sokol92

Цитата: mikekaganski от 18 ноября 2024, 18:18подумал, что в бейсике нумерация символов с 0.
Offtop. Это Бурбаки виноват(ы). До него (них) натуральные числа начинались с 1.  :)
См. также здесь.
Владимир.

Massaraksh7

Цитата: mikekaganski от 18 ноября 2024, 14:56то когда Вы через месяц замените символ в Вашей заготовке {abc} на {adc}, то символ d станет отдельной порцией (
А это вполне реальная ситуация, поэтому с порциями могут быть проблемы.