Macro to convert text to math formula

Dear Libreoffice community,

I am searching for a macro to replace a text with a formula object in a writer document.

The document contains for example ${54} over {16}$ and should be replaced by a correspondig Formula Object. I know I can select the formula an click “Insert> Object > Formula” but with a great number of formulas doing it by hand is tedious.

Any ideas for a macro to automate this process?

Thank you for your efforts in advance

Add the Formula icon to the toolbar? That’s what I did.

Thank you for the idea. What you describe is nearly the same process I use now. But the documents in question contain more then 100 formulas per document. So an automatic process would be nice.

I would suggest to use marker characters different from any character usually occurring in our texts - and also “parenthesing” in the sense that start marker and end marker are different.
For my example I chose (U+266F) and (U+203C).
Then I wrote a piece of framework (distinguishing by positions in TextFrames, TextTables, and the Text body itself) and a loop going through the occurrences of strings accepted by the RegEx ♯.+?‼.
For every finding the marker characters were replaced with spaces. The remaining string was selected and this way passed to the dispatcher command .uno:InsertObjectStarMath.
For unknown reasons this doesn’t work reliably. In specific formula strings occurring inside TextTable or TextFrame were sometimes converted (obscure context in proceeding), but often not - and I failed trying to find clear conditions distinguishing the cases. Findings occurring in ordinary table cells without nesting seem to be converted, but
The formula string (simple examples!) found in the BodyText, generally were treated correctly, but since there is much darkness, I wouldn’t expect this to be expectable …

It’s obviously a mess again. I haven’t the nerve now to spend another hour with what would be needed to omit the use of any dipatch command. See attached example.
makeFormulasFromMarkedTextPortions_0.odt

PS Another test with V7.0.0.0.beta1 also gave irreproducibkle results, but now sometimes converted the same formula (kind of a vector) correctly from a table cell, but not at all from the text body.
You may do the steps needed to omit the diapatcher, and report your success here.

=== Edit 2020-07-03 about 22:00UTC ===
Ignore the previous suggestions. The reworked macro works perfectly. (afaidt)

Sub makeFormulasFromMarkedTextAsNewOleObjects(Optional pDoc, Optional pScope, Optional pRegex As String)
If IsMissing(pDoc) Then pDoc = ThisComponent
If IsMissing(pScope) Then pScope = "fbt" REM Body, Frames, TextTables
pScope = Ucase(pScope)
fOK = InStr(pScope, "F")>0
tOK = InStr(pScope, "T")>0
bOK = InStr(pScope, "B")>0
If IsMissing(pRegEx) Then pRegEx = "♯.+?‼" REM Used in the example. LeadIn and LeadOut may be chosen differently.
seDe = pDoc.createSearchDescriptor         REM You need to do it in the code.
With seDe
 .SearchRegularExpression = True
 .SearchString = pRegEx
End With
fi = pDoc.FindNext(pDoc.Text.Start, seDe)
REM The findings are only ordered predictably interior per text object.  
While NOT IsNull(fi)
 posF = IsObject(fi.TextFrame) REM Nesting: Also True if the Frame is inside a TexTable cell or another Frame.
 posT = IsObject(fi.TextTable) REM Nesting: Also True if the TextTable is inside a Frame or a cell of another TextTable.
 posB = NOT (posF OR posT)
 If (fOK AND posF) OR (tOK AND posT) OR (bOK AND posB) Then
  foStr =  Mid(fi.String, 2, Len(fi.String) - 2)
  fi.String = ""
  mathOle = pDoc.createInstance("com.sun.star.text.TextEmbeddedObject")
  mathOle.CLSID = "078B7ABA-54FC-457F-8551-6147e776a997"
  mathOle.AnchorType = com.sun.star.text.TextContentAnchorType.AS_CHARACTER
  fi.Text.insertTextContent(fi, mathOle, False)
  mathOle.EmbeddedObject.Component.Formula = foStr
End If
 fi = pDoc.FindNext(fi.End, seDe)
Wend
End Sub

avoids all the problems I had previously. It is also demonstrated in the new attachment.
makeFormulasFromMarkedTextPortions_1.odt

Really great, thanks to you for your efforts. As my Basics skills are not up to the task, I don’t think that I im able to go the described path. However I found a workaround with the use of a little bash scripting.
Maybe to someone my process can be useful. I will write it in an Answer below, some parts maybe adapted into the macro.

Thanks for your comment.
As I see from your answer you still use the dollar sign as “LeadIn” and as “LeadOut” as well. I cannot align me with this decision. Instead I insist stubbornly on using a pair of different and otherwise rarely occurring characters as a kind of parentheses.
However, readers who don’t accept my advice can simply change the RegEx hardcoded in my macro to their preference. That’s bad, but I can bear with them.

Finally, I found the bits of information I still missed when I first posted my answer. As so often the famous “Useful Macro Information” by Andrew Pitonyak had it.

The reworked macro does away with the dispatcher, and solves the task perfectly as far as I can see. I will append this macro and a reworked demo containing it to my answer.

Really nice, thanks a lot.
I changed the Regex (also stubborn on this end ;-), but as native german speaker the $ character is rarerly used, and this way the notion is aligned with the inline notion of latex) and it works without any problems.
Thanks again for your time and effort, I really appreciate it.

I’m also a German, but not a LaTex user. Anyway: I suffered more than once from problems with unpaired characters used as markers and therefore strictly deprecate them. It should really be better to use two parentehesing charcters. In addition the MathML formula itself may contain next to every everyday character, probably as a literal. Therefore I favoured very special characters, now easily usable since LibO introduced the Alt+X trick. The alternative isn’t a doller sign, biut e.g. two combinations of literals otherwise not ocurring in the unniverse (§$ and $§ might do).
(You won’t convince me insofar. More stubborn than you, I bet.)
If you actually use the macro more often, I would be interested in your experiences.
If I should start to use it myself, i would surely also be interested in the counterpart (OLE formula to ordinary text, and in harmonizing format settings for formulas.

I clearly understand the reasoning behind picking the markers in a range that would never occur in a formula or text. Maybe in some weeks I will change my mind.
The backwards conversion, seems interesting, but for my current workflow it would only be a “nonessential” feature as I am used to read the formulas as texts and the conversion is one of the latest steps in my process. And as such could be revoked easily.
For now I have just time for some small tests, beginning in August (next school year) I think I will use it to greater extend and will be happy to share my experience.

Quoting @ricciflowing: "I clearly understand the reasoning behind picking the markers in a range that would never occur in a formula or text. Maybe in some weeks I will change my mind. "
I was sure concerning the first statement and hopeful concerning the second :wink: .
Since you seem to be a teacher, and I also am (retired), I would be interested in the workflow you apply when creating texts with formulas.
If you once visit München (by accident or otherwise) you should contact me for a Edelstoff or something you prefer.

Visiting München could take a while. But if your going to visit Stralsund feel free to contact me (the local brewery once won many Worldchampionship title, so I think beverage wise we are covered).

Concerning my workflow: The first reason I like writing the in-text-version of formulas better is that in this way I don’t switch context between writer and the formula editor (At least for me selecting the formula and opening the editor most of the times removed the part of the document with the formula out of my view). As a former latex user I am very used to seeing the formulas this way.
The second an maybe more important reason is that I build an Calc-Table to generate questions for the “Tägliche Übung” (using & to add the content of different cells). This way I can generate many different worksheets and don’t have to think about say choosing 10 different fractions for 5 Worksheets.

See http://psilosoph.de/riflostral/ricciflowing.txt.html

The current process is not entirely based macro and is only tested on linux (but may be adapted to Windows).

  1. I create a macro to select all formula text like: ${54} over {16}$. Therefore I use the macro recorder and open the “Find and Replace” menu and check the regex-box. The search I used is (?<=$).*?(?=$).
  2. I create to keyboard shortcuts one for inserting a formula object and the second for the macro from step 1.
  3. I use xdotool to run the both keyboard shortcuts after another with a little bit delay between it (as with no delay some formulas will not be inserted).
  4. I do a find and replace to erase the leftover $-markers.

I hope this is of use to someone.