The documentation of MRI mentions a useful tool called diff: if you can change a certain property through the GUI but the macro recorder doesn’t record this change then you can still find out the name of the changed property by using diff, which points you to the property that has been changed and that you need to use.
However, it requires python UNO bridge for LibreOffice, which may be a bit awkward to set up. For those who don’t want to bother themselves with python (like me), it may be more convenient to have such a diff macro in LibreOffice Basic. Therefore, I wrote such a macro, which I want to share here in the hope that it may be useful to other people, as well. The entire macro is based on Andrew Pitonyak’s book: OpenOffice.org Macros Explained, Third Edition.
How to use the macro
Create two instances (Obj1 and Obj2) of the same object of type Type and modify the properties in question in only one of them. Then call Diff_obj (Obj1, Obj2, Type, 0). After a sufficient run a message box will show a list of the different properties of the two objects. In the code below I compared to charts (with different data ranges).
The macro contains recursive function calls because some properties are objects themselves, having other properties, which again may be objects with properties and so on. However, some of these “chains” seem to be infinite, making it necessary to limit the steps made in the object hierarchy, which is done by introducing maxDepth.
I wrote comments in the code. For some more information on the function myGetPropertyValue please refer to Function to return properties of an object rather than their names.
In order to run the macro, you will need a library called “TestLib” and it also has to be loaded (double click on its name).
I am using Ubuntu 14.04 and LibreOffice 4.2.8.2.
Option Explicit
Dim oLib
Dim maxDepth As Integer
Sub myDiff
Dim chart_1, chart_2 As Object
oLib = GlobalScope.BasicLibraries.getByName("TestLib")
maxDepth = 5
chart_1 = ThisComponent.Sheets(0).Charts(0).EmbeddedObject
chart_2 = ThisComponent.Sheets(0).Charts(1).EmbeddedObject
MsgBox Diff_obj (chart_1, chart_2, "EmbeddedObject", 0), 0, "Different properties"
End Sub
Function IsWhiteSpace (iChar As Integer) As Boolean
Select Case iChar
Case 9, 10, 13, 32, 160 ' The character is tab, CR, LF, space or a non-breaking space.
IsWhiteSpace = True
Case Else
IsWhiteSpace = False
End Select
End Function
Function TrimWhite (s As String) As String ' Remove white spaces from both the front and the end of a string
s = Trim(s)
Do While Len(s) > 0
If Not IsWhiteSpace(ASC(s)) Then Exit Do
s = Right(s, Len(s) - 1)
Loop
Do While Len(s) > 0
If Not IsWhiteSpace(ASC(Right(s, 1))) Then Exit Do
s = Left(s, Len(s) - 1)
Loop
TrimWhite = s
End Function
Sub showMsg (dialMsg As String, Optional dialTitle As String)
If IsMissing (dialTitle) Then
If MsgBox (dialMsg, 1) = 2 Then Stop
Else
If MsgBox (dialMsg, 1, dialTitle) = 2 Then Stop
EndIf
End Sub
Function myGetProperties (oObj As Object, sObjName As String) As Variant
Dim iPos As Integer
Dim sProps As String
On Local Error GoTo NoDBGProperties
REM I have encountered an object that had no properties at all, so the DBG_Properties resulted in an error.
sProps = oObj.DBG_Properties
REM Parse the output of DBG_Properties. It has some introductory information that we do not need.
REM We are only interested in what is after the colon.
iPos = InStr(1, sProps, ":") + 4
If iPos > 0 Then sProps = TrimWhite(Right(sProps, Len(sProps) - iPos))
REM split on the separator characters ("; ")
myGetProperties = Split(sProps, "; ")
Exit Function
NoDBGProperties:
showMsg (Error & Chr$(10) & sObjName, "NoDBGProperties")
End Function
Function myGetPropertyValue (v As Variant, oObj As Object, sPropName As String, sModName As String) As String
Dim oPropInfo
Dim sCode As String
On Local Error GoTo NoProperty
oPropInfo = oObj.getPropertySetInfo()
If oPropInfo.hasPropertyByName (sPropName) Then
v = oObj.getPropertyValue (sPropName)
myGetPropertyValue = sModName
Exit Function
EndIf
NoProperty:
If sModName = "" Then ' the module "MyTest" does not exist
sModName = "MyTest"
sCode = "Option Explicit" & Chr$(10) & "Function getProp (oObj As Object)" & Chr$(10) & "On Local Error GoTo propErr" & Chr$(10) & _
"getProp = oObj." & sPropName & Chr$(10) & "Exit Function" & Chr$(10) & _
"propErr:" & Chr$(10) & "getProp = Error" & Chr$(10) & "End Function"
oLib.insertByName(sModName, sCode)
Endif
v = getProp (oObj)
myGetPropertyValue = sModName
End Function
Function Diff_var (Obj1 As Variant, Obj2 As Variant, ObjName As String, depth As Integer) As String
Dim i, k As Integer
Dim s As String
s = ""
If IsEmpty(Obj1) Then
If Not IsEmpty(Obj2) Then
s = ObjName & Chr$(10)
EndIf
ElseIf VarType(Obj1) >= 8192 Then ' array
k = UBound(Obj1)
If UBound(Obj2) < UBound(Obj1) Then
k = UBound(Obj2)
s = s & "UBound (" & ObjName & ")" & Chr$(10)
Endif
For i = LBound(Obj1) To k
If VarType(Obj1(i)) = 9 Then ' object
s = s & Diff_obj (Obj1(i), Obj2(i), ObjName & "(" & i & ")", depth)
Else
s = s & Diff_var (Obj1(i), Obj2(i), ObjName & "(" & i & ")", depth)
Endif
Next i
ElseIf Not (Obj1 = Obj2) Then
s = ObjName & Chr$(10)
End If
Diff_var = s
End Function
Function Diff_obj (Obj1 As Object, Obj2 As Object, ObjName As String, depth As Integer) As String
Dim i, iPos, m As Integer
Dim s, sPropName, sModName As String
Dim oItems(), v_1, v_2
m = depth + 1
If m = maxDepth Then
Diff_obj = ""
Exit Function
Endif
s = ""
If IsNull(Obj1) Then
If Not IsNull(Obj2) Then
s = ObjName & Chr$(10)
EndIf
Else
oItems = myGetProperties (Obj1, ObjName)
If Not IsNull (oItems) Then
For i = 0 To UBound(oItems)
iPos = InStr(1, oItems(i), " ") + 1
REM The first part of oItems(i) is the type of the property. We are only interested in its name, which stands after the space.
sPropName = Mid(oItems(i), iPos)
sModName = myGetPropertyValue (v_1, Obj1, sPropName, "")
sModName = myGetPropertyValue (v_2, Obj2, sPropName, sModName)
If sModName <> "" Then
oLib.removeByName(sModName)
EndIf
If VarType(v_1) = 9 And VarType(v_2) = 9 Then ' object
s = s & Diff_obj (v_1, v_2, ObjName & "." & sPropName, m)
ElseIf VarType(v_1) = VarType(v_2) Then
s = s & Diff_var (v_1, v_2, ObjName & "." & sPropName, m)
Else
s = s & ObjName & "." & sPropName & Chr$(10)
EndIf
Next i
EndIf
EndIf
Diff_obj = s
End Function