How to change multiple formulas simultaneously, instead of one-by-one

So, I have an odp file with 50-100 formulas. All I would like to do is increase the font size from 12 to 18 and also make all fonts bold. Any way I can do these all at once?

1 Like
Sub changeFormulas_Bold_18pt()
	oDrawPages = ThisComponent.getDrawPages()
	for nDP = 0 to oDrawPages.getCount()-1
		oDP = oDrawPages.getByIndex(nDP)
		for nShape = 0 to oDP.getCount()-1
			oShape = oDP.getByIndex(nShape)
			sShapeType = oShape.getShapeType()
			if sShapeType = "com.sun.star.drawing.OLE2Shape" then
				oModel = oShape.Model
				sImplementationName = oModel.getImplementationName()
				if sImplementationName = "com.sun.star.comp.Math.FormulaDocument" then
					oModel.BaseFontHeight = 18
					oModel.FontMathIsBold = True
					oModel.FontFixedIsBold = True
					oModel.FontFunctionsIsBold = True
					oModel.FontNumbersIsBold = True
					oModel.FontSansIsBold = True
					oModel.FontSerifIsBold = True
					oModel.FontTextIsBold = True
					oModel.FontVariablesIsBold = True
				end if
			end if
		next nShape
	next nDP
End Sub

Could you please elaborate on using this code?
Also, I would need all parts of a formula (variables, text, indexes, etc.) to be bold. How should I alter this code to achieve that effect?

Tools>Macros>Organize>Basic…
Button “Organize…”
The code under “My Macros” is organized in libraries and modules. There is a library named “Standard”. Add a module to “Standard” and paste the code to that module.
Close the Basic editor.
Open the document in question.
Call Tools>Macros>Runn…,navigate to your macro and run it.

Thank you, I will try this. Just to confirm, this is gonna make all the characters (indexes, variables, text, etc.) bold, isn’t it?

I reworked and renamed my little snippet. There are 8 different types of text which can be bold.

1 Like

I did run the code, but it doesn’t seem to do anything. On Basic editor though, running it returns:
“BASIC runtime error.
Property or method not found: getDrawPages”
Are you sure that this is the code I should run through LibreOffice Impress and it would modify all the formulas?

sD1m016c35

I saved the above code under "My Macros > library "DrawPage" > module "MathProps", however, the location does not really matter as long as you can find the routine changeFormulas_Bold_18pt.

Just in case, anybody asks, the following Basic module seems to work with Writer, Calc, Impress, Draw and Math:

REM  *****  BASIC  *****

Sub changeFormulas_Bold_18pt()
	doc = ThisComponent
	sNames = Array("BaseFontHeight", "FontMathIsBold", "FontFixedIsBold", "FontFunctionsIsBold", "FontNumbersIsBold", "FontSansIsBold", "FontSerifIsBold", "FontTextIsBold", "FontVariablesIsBold")
	values = Array(18, True, True, True, True, True, True, True, True)
	changeFormulaProperties doc, sNames, values
End Sub

Sub changeFormulas_Regular_12pt()
	doc = ThisComponent
	sNames = Array("BaseFontHeight", "FontMathIsBold", "FontFixedIsBold", "FontFunctionsIsBold", "FontNumbersIsBold", "FontSansIsBold", "FontSerifIsBold", "FontTextIsBold", "FontVariablesIsBold")
	values = Array(12, False, False, False, False, False, False, False, False)
	changeFormulaProperties doc, sNames, values
End Sub

Sub changeFormulaProperties(doc, sNames, values)
	if doc.supportsService("com.sun.star.formula.FormulaProperties") Then  
		doc.setPropertyValues(sNames, values)
	elseif HasUnoInterfaces(doc, "com.sun.star.drawing.XDrawPageSupplier") Then  
		obj = doc.getDrawPage()
		loopDrawPage obj, sNames, values
	elseif HasUnoInterfaces(doc, "com.sun.star.drawing.XDrawPagesSupplier") Then  
		REM Draw, Impress, Calc
		obj = doc.getDrawPages()
		loopDrawPages obj, sNames, values
	endif
End Sub

Sub loopDrawPages(oDrawPages, sNames, values)
	for nDP = 0 to oDrawPages.getCount()-1
		oDP = oDrawPages.getByIndex(nDP)
		loopDrawPage oDP, sNames, values
	next nDP
End Sub

Sub loopDrawPage(oDP, sNames, values)
	for nShape = 0 to oDP.getCount()-1
		oShape = oDP.getByIndex(nShape)
		REM recurse grouped controls:
		if oShape.supportsService("com.sun.star.drawing.GroupShape") then loopDrawPage oShape, sNames, values
		on error resume next
			setShapeModelProperties oShape, sNames, values
	next nShape
End Sub

Sub setShapeModelProperties(oShape, sNames, values)
	oModel = oShape.Model
	sImplementationName = oModel.ImplementationName
	if sImplementationName = "com.sun.star.comp.Math.FormulaDocument" then
		oModel.setPropertyValues(sNames, values)
	endif
End Sub

All you need to prepare is your own routine with a list of property names in array sNames and a corresponding array of property values. In the above code, changeFormulas_Bold_18pt defines 9 properties, the first one is the font size (short integer 18) and 8 boolean values describing the boldness (True) of different formula contents.
The routine changeFormulas_Regular_12pt resets the same properties to regular fonts of size 12.
ThisComponent refers to the currently active document.
The following list shows 63 properties that may be useful in this context:

(Name)	(Type)
Alignment	short
BaseFontHeight	short
BaseLine	short
BottomMargin	short
CustomFontNameFixed	string
CustomFontNameSans	string
CustomFontNameSerif	string
FontFixedIsBold	boolean
FontFixedIsItalic	boolean
FontFunctionsIsBold	boolean
FontFunctionsIsItalic	boolean
FontMathIsBold	boolean
FontMathIsItalic	boolean
FontNameFunctions	string
FontNameMath	string
FontNameNumbers	string
FontNameText	string
FontNameVariables	string
FontNumbersIsBold	boolean
FontNumbersIsItalic	boolean
FontSansIsBold	boolean
FontSansIsItalic	boolean
FontSerifIsBold	boolean
FontSerifIsItalic	boolean
FontTextIsBold	boolean
FontTextIsItalic	boolean
FontVariablesIsBold	boolean
FontVariablesIsItalic	boolean
Formula	string
GreekCharStyle	short
Identifier	string
IsRightToLeft	boolean
IsScaleAllBrackets	boolean
IsTextMode	boolean
LeftMargin	short
RelativeBracketDistance	short
RelativeBracketExcessSize	short
RelativeFontHeightFunctions	short
RelativeFontHeightIndices	short
RelativeFontHeightLimits	short
RelativeFontHeightOperators	short
RelativeFontHeightText	short
RelativeFractionBarExcessLength	short
RelativeFractionBarLineWeight	short
RelativeFractionDenominatorDepth	short
RelativeFractionNumeratorHeight	short
RelativeIndexSubscript	short
RelativeIndexSuperscript	short
RelativeLineSpacing	short
RelativeLowerLimitDistance	short
RelativeMatrixColumnSpacing	short
RelativeMatrixLineSpacing	short
RelativeOperatorExcessSize	short
RelativeOperatorSpacing	short
RelativeRootSpacing	short
RelativeScaleBracketExcessSize	short
RelativeSpacing	short
RelativeSymbolMinimumHeight	short
RelativeSymbolPrimaryHeight	short
RelativeUpperLimitDistance	short
RightMargin	short
SyntaxVersion	short
TopMargin	short
3 Likes

The LibreOffice developers strongly advise against using ImplementationName. :slightly_smiling_face:
Maybe so:

Sub changeFormulaProperties(doc, sNames, values)
	if doc.supportsService("com.sun.star.formula.FormulaProperties") Then  
		doc.setPropertyValues(sNames, values)
	elseif HasUnoInterfaces(doc, "com.sun.star.drawing.XDrawPageSupplier") Then  
		obj = doc.getDrawPage()
		loopDrawPage obj, sNames, values
	elseif HasUnoInterfaces(doc, "com.sun.star.drawing.XDrawPagesSupplier") Then  
		REM Draw, Impress, Calc
		obj = doc.getDrawPages()
		loopDrawPages obj, sNames, values
	endif
End Sub

2 Likes

Do they?

Sure. I replaced the subroutine.

1 Like

They do. :slightly_smiling_face:

So, I copied this code to the basic editor as well and then closed it. Upon running a new macro
image
First, fourth, fifth and sixth ones one give me this error:

A Scripting Framework error occurred while running the Basic script Standard.Module1.[script name here]

Message: wrong number of parameters! at C:/cygwin64/home/buildslave/source/libo-core/scripting/source/basprov/basscript.cxx:199

Second and third ones run but do nothing.

I really don’t know what to do at this point…

In case anyone wants to see the code (that I copied back from the basic editor):

REM  *****  BASIC  *****

Sub changeFormulas_Bold_18pt()
	doc = ThisComponent
	sNames = Array("BaseFontHeight", "FontMathIsBold", "FontFixedIsBold", "FontFunctionsIsBold", "FontNumbersIsBold", "FontSansIsBold", "FontSerifIsBold", "FontTextIsBold", "FontVariablesIsBold")
	values = Array(18, True, True, True, True, True, True, True, True)
	changeFormulaProperties doc, sNames, values
End Sub

Sub changeFormulas_Regular_12pt()
	doc = ThisComponent
	sNames = Array("BaseFontHeight", "FontMathIsBold", "FontFixedIsBold", "FontFunctionsIsBold", "FontNumbersIsBold", "FontSansIsBold", "FontSerifIsBold", "FontTextIsBold", "FontVariablesIsBold")
	values = Array(12, False, False, False, False, False, False, False, False)
	changeFormulaProperties doc, sNames, values
End Sub

Sub changeFormulaProperties(doc, sNames, values)
	if doc.supportsService("com.sun.star.formula.FormulaProperties") Then  
		doc.setPropertyValues(sNames, values)
	elseif HasUnoInterfaces(doc, "com.sun.star.drawing.XDrawPageSupplier") Then  
		obj = doc.getDrawPage()
		loopDrawPage obj, sNames, values
	elseif HasUnoInterfaces(doc, "com.sun.star.drawing.XDrawPagesSupplier") Then  
		REM Draw, Impress, Calc
		obj = doc.getDrawPages()
		loopDrawPages obj, sNames, values
	endif
End Sub

Sub loopDrawPages(oDrawPages, sNames, values)
	for nDP = 0 to oDrawPages.getCount()-1
		oDP = oDrawPages.getByIndex(nDP)
		loopDrawPage oDP, sNames, values
	next nDP
End Sub

Sub loopDrawPage(oDP, sNames, values)
	for nShape = 0 to oDP.getCount()-1
		oShape = oDP.getByIndex(nShape)
		on error resume next
			setShapeModelProperties oShape, sNames, values
	next nShape
End Sub

Sub setShapeModelProperties(oShape, sNames, values)
	oModel = oShape.Model
	sImplementationName = oModel.ImplementationName
	if sImplementationName = "com.sun.star.comp.Math.FormulaDocument" then
		oModel.setPropertyValues(sNames, values)
	endif
End Sub

The callable macros are changeFormulas_Bold_18pt and changeFormulas_Regular_12pt. The names describe what they do.
Each of the two call changeFormulaProperties with parameters describing what should be applied to all the formulas in the given document.
changeFormulaProperties applies the property values directly in case of a Open Formula Document.
It calls loopDrawPage in case of a single DrawPage (Writer) passing the DrawPage in question.
It calls loopDrawPages passing the collection of DrawPages in case of some other document having many DrawPages.
loopDrawPages calls loopDrawPage one time per DrawPage passing a single DrawPage with each call.
Finally, loopDrawPage calls setShapeModelProperties which actually applies the property values after verifying that a shape actually contains a formula object. With any other kind of shape, the properties would not apply.

1 Like

Usually a good idea, but at this stage it may be useful to upload a (reduced / shortened) copy of your .odp
(Just to make sure your formulas are no embedded pictures…)

1 Like

Update, I realized that the reason the code didn’t work was because the formulas were “grouped” with some other objects. Ungrouping and running it seems to have fixed the problem. Huge thanks for that script.
On a slightly unrelated note, I opened a new impress file created a random formula (a simple one, non decimal fraction, with exponents) and copied it 50-100 times. Afterwards I ran the script, for some reason all but one was converted using the script.
And why does a formula with a font size of 18 does not match the same formula size when created with a text box? It need a font size of 10 to match a math formula of 18.

1 Like

Thank you very much for clarifying what the problem with my code is. I did not consider grouping.
P.S. The fix was easier than I thought. Now the code walks through arbitrary levels of groupings.

One more question on this detail: Is it future safe to use supportsService(“com.sun.star.MyService”) instead of testing for interfaces? I use to think in services rather than interfaces.

Likewise, do you also have any idea as to why there is a discrepancy in font sizes? I set font size to 18, but 18 for text created with the “text box” feature is much larger. What am I missing again?

Right-click the formula object, choose “Original size”.

1 Like