Working with properties
The following routines all deal with properties. They are revised routines from my RevealCodes macro, and the main routine which demonstrates calling some of the other routines displays the changes in "codes" for the current paragraph.
fnNotIn
The following routine compares two arrays or property beans, and returns an array of property beans for those items which are in array mProp1 but not in mProp2, or where the value is different.
function fnNotIn(mProp1, mProp2)
'Returns an array of the properties in mProp1 not found in mProp2
dim mNotIn()
n1 = uBound(mProp1)
n2 = uBound(mProp2)
if n2 < 0 then
fnNotIn = mProp1
else
for i = 0 to n1
sName1 = mProp1(i).name
bNotFound = true
for j = 0 to n2
sName2 = mProp2(j).name
if sName1 = sName2 then
bNotFound = not fnEqualValues(mProp1(i).value, mProp2(j).value)
exit for
elseif sName2 > sName1 then
exit for
end if
next
if bNotFound then subAddThisProperty(mNotIn(), mProp1(i))
next
fnNotIn = mNotIn()
end if
end function
fnEqualValues
This routine is not strictly dealing with properties but is called by fnNotIn, so is included here. The function is recursive so will only work in OpenOffice.org 1.1.1 or greater. Compares two values of the same type and returns whether they are equal or not. Currently it doesn't work for structs or objects (if you know how to do this please edit this page!)
function fnEqualValues(vValue1, vValue2) as boolean
'Returns true if the values are equal
if varType(vValue1) <> varType(vValue2) then
fnEqualValues = false
elseif isArray(vValue1) then
nUpperBound1 = uBound(vValue1)
nUpperBound2 = uBound(vValue2)
if nUpperBound1 <> nUpperBound2 then
fnEqualValues = false
elseif nUpperBound1 = -1 then
fnEqualValues = true
else
fnEqualValues = true
for i = 0 to nUpperBound1
if not fnEqualValues(vValue1(i), vValue2(i)) then
fnEqualValues = false
exit for
end if
next
end if
elseif isUNOstruct(vValue1) then
fnEqualValues = true 'Assume true as I don't know how to compare them
else
select case varType(vValue1)
case 2-5,7, 8, 11 'numbers, date, string boolean
fnEqualValues = (vValue1 = vValue2)
case 9 'object ???
fnEqualValues = true 'Assume true as I don't know how to compare them
case else
fnEqualValues = true
end select
end if
end function
subAddThisProperty
This routine adds a property bean to the end of a one dimensional array.
sub subAddThisProperty(mProperties, mProperty)
nNext = uBound(mProperties) + 1
redim preserve mProperties(nNext)
set mProperties(nNext) = mProperty
end sub
fnDirectProperties
Returns an array of property beans of directly applied properties to a text range (should work for other types of objects but has not been tested).
![]() |
This routine may require a workaround for Issue 103670 . See the Talk page. |
function fnDirectProperties(oTextRange)
'Returns an array of property beans of directly applied properties
oProperties = oTextRange.getPropertySetInfo.getProperties
nProperties = uBound(oProperties)
dim mDirectProperties()
for i = 0 to nProperties
sName = oProperties(i).name
if oTextRange.getPropertyState(sName) <> com.sun.star.beans.PropertyState.DEFAULT_VALUE and _
((oProperties(i).attributes and com.sun.star.beans.PropertyAttribute.READONLY) = 0) then
nTypeClass = oProperties(i).type.typeClass
subAddProperty( mDirectProperties(),sName, oTextRange.getPropertyValue(sName))
end if
next
fnDirectProperties = mDirectProperties()
end function
fnPropertyValues
Returns an array of strings for the property names and their values. You could think of this as being a form of introspection.
function fnPropertyValues(mProperties)
'returns an array of strings for the property names and their values
nProperties = Ubound(mProperties)
if nProperties < 0 then
fnPropertyValues = array("")
exit function
end if
dim mPropertyValues(nProperties)
for i = 0 to nProperties
mPropertyValues(i) = fnPropertyValue(mProperties(i))
next
fnPropertyValues = mPropertyValues()
end function
fnPropertyValue
Returns the concatenation of a property name and its value as a string
function fnPropertyValue(aProperty) as string
'Returns the concatentaion of a property name and its value as a string
if isNull(aProperty) or isEmpty(aProperty) then
fnPropertyValue = ""
msgbox "Oops!"
else
sName = aProperty.name
vValue = aProperty.Value
fnPropertyValue = sName & ": " & fnConvString(vValue)
end if
end function
fnConvString
Converts a variables value to a string. Currently if the variable is a struct or object it simply returns "Struct" or "Object". (If you know a better way please edit this page!)
function fnConvString(vValue) as string
'Converts a variant to a string
if isArray(vValue) then
nUpperBound = uBound(vValue)
if nUpperBound = 0 then
fnConvString = ""
else
s = "{"
for i = 0 to nUpperBound
s = s & fnConvString(vValue(i)) & ","
next
nLen = len(s)
if nLen > 1 then
fnConvString = left(s, len(s) - 1) & "}"
end if
end if
elseif isUNOstruct(vValue) then
fnConvString = "Struct"
else
select case varType(vValue)
case 0, 2 to 5,7 'empty, numbers, date
fnConvString = cstr(vValue)
case 8 'string
fnConvString = vValue
case 9 'object ???
fnConvString = "Object"
case 11 'boolean
if vValue then
fnConvString = "True"
else
fnConvString = "False"
end if
case else
fnConvString = ""'vValue
msgbox varType(vValue)
end select
end if
end function
subAddProperty
This routine calls fnNewProperty to create new property bean, assign a name and optionally a value, and adds the new property bean to a one dimensional array.
sub subAddProperty(mProperties, sName, optional vValue)
nNext = uBound(mProperties) + 1
redim preserve mProperties(nNext)
if isMissing(vValue) then
mProperties(nNext) = fnNewProperty(sName)
else
mProperties(nNext) = fnNewProperty(sName, vValue)
end if
end sub
fnNewProperty
Create new property bean, assign a name and optionally a value, returns the new property bean.
function fnNewProperty(sName, optional vValue)
aProperty = createUnoStruct("com.sun.star.beans.PropertyValue")
aProperty.Name = sName
if not isMissing(vValue) then
aProperty.Value = vValue
end if
fnNewProperty = aProperty
end function
Example - Displaying 'codes' of a paragraph
This example demonstrates calling fnDirectProperties, fnNotIn, and fnPropertyValues defined above. It shows how the above codes could be used in a "reveal codes" type macro. The join statement is just a quick and dirty way of creating a string out of an array of strings for displaying in the messagebox.
sub main
oParagraph = fnGetCurrentParagraph
mParaProperties = fnDirectProperties(oParagraph)
msgbox join(fnPropertyValues(mParaProperties), chr(10)), 0 , "Paragraph properties"
oPortionEnum = oParagraph.createEnumeration
i = 0
while oPortionEnum.hasMoreElements
i = i + 1
oPortion = oPortionEnum.nextElement
mCurProperties = fnDirectProperties(oPortion)
if i > 1 then
mCloseProperties = fnNotIn(mPrevProperties, mCurProperties)
msgbox join(fnPropertyValues(mCloseProperties), chr(10)), 0 , "Portion " & i & " close properties"
mOpenProperties = fnNotIn(mCurProperties, mPrevProperties)
else
mOpenProperties = mCurProperties
end if
msgbox join(fnPropertyValues(mOpenProperties), chr(10)), 0 , "Portion " & i & " open properties"
set mPrevProperties = mCurProperties
wend
msgbox join(fnPropertyValues(mPrevProperties), chr(10)), 0 , "Portion " & i & " close properties"
end sub
function fnGetCurrentParagraph
'Returns the whole paragraph that the insertion point is in
oVC = thisComponent.getCurrentController.getViewCursor
oCursor = oVC.text.createTextCursorByRange(oVC)
oCursor.gotoStartOfParagraph(false)
oCursor.gotoEndOfParagraph(true)
fnGetCurrentParagraph = oCursor.createEnumeration.nextElement
end function