Compare Structs and Arrays for equality

Shared Libraries
Forum rules
For sharing working examples of macros / scripts. These can be in any script language supported by OpenOffice.org [Basic, Python, Netbean] or as source code files in Java or C# even - but requires the actual source code listing. This section is not for asking questions about writing your own macros.
Post Reply
JeJe
Volunteer
Posts: 3064
Joined: Wed Mar 09, 2016 2:40 pm

Compare Structs and Arrays for equality

Post by JeJe »

Simple way to compare any two Structs for equality, without testing each member against one another, using an EnumerableMap.

Code: Select all

sub testCompareStructs
dim f1 as new com.sun.star.awt.FontDescriptor
dim f2 as new com.sun.star.awt.FontDescriptor
msgbox compareStructs(f1,f2)
f1.weight = 300
msgbox compareStructs(f1,f2)
end sub

function compareStructs(struct1,struct2)
dim EnMap
EnMap = com.sun.star.container.EnumerableMap.create("string", "any")
EnMap.put("0",  struct1)
compareStructs = EnMap.containsValue(struct2)
end function
Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
JeJe
Volunteer
Posts: 3064
Joined: Wed Mar 09, 2016 2:40 pm

Re: Compare Structs and Arrays for equality

Post by JeJe »

We can also compare arrays using the same function, so I've amended the thread title

Code: Select all


sub testCompareArrays

dim s1(10000)
dim s2(10000)


msgbox compareStructsOrArrays(s1,s2)
s1(500) = thiscomponent
msgbox compareStructsOrArrays(s1,s2)
s2(500) = thiscomponent
msgbox compareStructsOrArrays(s1,s2)

end sub

function compareStructsOrArrays(struct1,struct2)
dim EnMap
EnMap = com.sun.star.container.EnumerableMap.create("string", "any")
EnMap.put("0",  struct1)
compareStructsOrArrays = EnMap.containsValue(struct2)
end function

Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
JeJe
Volunteer
Posts: 3064
Joined: Wed Mar 09, 2016 2:40 pm

Re: Compare Structs and Arrays for equality

Post by JeJe »

We can't compare two user defined types but we could use, as a substitute, an array with named constants for the array indexes.
Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
User avatar
karolus
Volunteer
Posts: 1226
Joined: Sat Jul 02, 2011 9:47 am

Re: Compare Structs and Arrays for equality

Post by karolus »

JeJe wrote: Sun Jan 19, 2025 1:36 pm Simple way to compare any two Structs for equality,…
ROFL

Code: Select all

from com.sun.star.awt import FontDescriptor as fs

def compare( one, other):
    return one == other

def main():
    desc1 = fs()
    desc2 = fs()
    print(compare(desc1,desc2))  #True
    desc2.Weight = 300.0
    print(compare(desc1, desc2))  #False
AOO4, Libreoffice 6.1 on Rasbian OS (on ARM)
Libreoffice 7.4 on Debian 12 (Bookworm) (on RaspberryPI4)
Libreoffice 24.8… flatpak on Debian 12 (Bookworm) (on RaspberryPI4)
JeJe
Volunteer
Posts: 3064
Joined: Wed Mar 09, 2016 2:40 pm

Re: Compare Structs and Arrays for equality

Post by JeJe »

Thanks karolus,

Its simple compared to the alternative in Basic of testing each member and possibly writing a separate function for each struct.

Provided you have a generic function, like mine, which is exactly the same to call as an inbuilt one, then the difference, (needing the function in a loaded library) is slight to negligible.
Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
JeJe
Volunteer
Posts: 3064
Joined: Wed Mar 09, 2016 2:40 pm

Re: Compare Structs and Arrays for equality

Post by JeJe »

It might be possible to compare user defined types [edit: generically, one function for all] using the CoreReflection service, but I couldn't work it out.

Another alternative, instead of an array as a substitute for a user type, is to build a substitute by joining Pair structs together.
I'm not sure there's any advantage over an array though:

Code: Select all

sub TestStructEnum
	struct1 = CreateStructEnum(array(0,1,thiscomponent,3,4,5,6,7,8))
	struct2 = CreateStructEnum(array(0,1,thiscomponent,3,4,5,6,7,8))
	struct3 = CreateStructEnum(array(0,1,thiscomponent,3,4,5,60,7,8))
	msgbox compareStructs(struct1,struct2)
	msgbox compareStructs(struct1,struct3)
	const seconditemname = 2 'set const for accessing index by name
	mri	GetStructEnumValue(struct1,seconditemname)
	
end sub


Function CreateStructEnum(arr)
	dim ub,i
	ub = ubound(arr)
	dim pairs(ub)
	for i = 0 to ub
		pairs(i) = new "com.sun.star.beans.Pair<any,any>" 'first any can be another data type
		pairs(i).first = arr(i)
	next
	for i =  ub -1 to 0 step -1
		pairs(i).second = pairs(i+1)
	next
	CreateStructEnum = pairs(0)
end function

function GetStructEnumValue(struct,v) as any
on local error goto outofrange
	dim n,i
	if v = 0 then
		GetStructEnumValue = struct.first
	else
		n = struct
		for i = 0 to v-1
			n = n.second
		next
		GetStructEnumValue =n.first
	end if
	outofrange:
end function

function compareStructs(struct1,struct2)
	dim EnMap
	EnMap = com.sun.star.container.EnumerableMap.create("string", "any")
	EnMap.put("0",  struct1)
	compareStructs = EnMap.containsValue(struct2)
end function



Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
JeJe
Volunteer
Posts: 3064
Joined: Wed Mar 09, 2016 2:40 pm

Re: Compare Structs and Arrays for equality

Post by JeJe »

Continuing the theme of alternatives to user types, we can also of course also borrow an existing struct if we can find one which has the fields we need.

Code: Select all

option VBAsupport 1

enum MyEnum
firstvalue = 0
secondvalue = 1
thirdvalue = 2
end enum

sub testMystruct
dim mystruct1
mystruct1 = new "com.sun.star.chart.TimeIncrement" 'BORROW A TimeIncrement struct which has 3 Any variables
setstructvalue mystruct1, myEnum.secondvalue, thiscomponent 'our own enum value or constant value for field index
mri getstructvalue(mystruct1,myEnum.secondvalue)
End Sub

function getStructValue(struct, index as long) as any 'Generic function for any struct
dim CR,ACR
CR =createunoservice("com.sun.star.reflection.CoreReflection")
ACR = CR.getType(struct)
getStructValue = ACR.fields(index).get(struct)
end function

function setStructValue(byref struct, index as long,value) 'Generic function for any struct
Dim CR,ACR
CR =createunoservice("com.sun.star.reflection.CoreReflection")
ACR = CR.getType(struct)
 ACR.fields(index).set(struct,value)
end function

Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
mikekaganski
Posts: 14
Joined: Mon Oct 30, 2017 12:39 pm

Re: Compare Structs and Arrays for equality

Post by mikekaganski »

JeJe wrote: Tue Jan 21, 2025 2:54 am It might be possible to compare user defined types [edit: generically, one function for all] using the CoreReflection service
Unfortunately, it isn't. The CoreReflection service is for introspection into UNO; and the user-defined type is a Basic type, with no UNO representation.
LibreOffice 7.6 on Windows 10
JeJe
Volunteer
Posts: 3064
Joined: Wed Mar 09, 2016 2:40 pm

Re: Compare Structs and Arrays for equality

Post by JeJe »

mikekaganski wrote: Fri Jan 31, 2025 10:59 am Unfortunately, it isn't. The CoreReflection service is for introspection into UNO; and the user-defined type is a Basic type, with no UNO representation.
Thanks... all I got with MRI was one field of type ANY and unable to inspect further.

Still, I see little difference between using a variant array with named constants for the indexes and a user type... except you can traverse the items, resize the array, use sort algorithms, and compare them as above - all advantages.
Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
Post Reply