Iterating through document textfields in OOo Writer Basic

Creating a macro - Writing a Script - Using the API (OpenOffice Basic, Python, BeanShell, JavaScript)
Post Reply
sdaau
Posts: 5
Joined: Tue Jan 05, 2010 1:29 am

Iterating through document textfields in OOo Writer Basic

Post by sdaau »

Hi all,

Just wanted to document my version of a script for looping through all textfields in a document, and obtaining some of their values. The script loops through the document, and tries to differentiate between textfields and read some of their values; generates a report text and puts this text in the clipboard in the end (so its ready for pasting elsewhere). Tried in OOO Dev 3.2 / XP.

Cheers!


Note TextToClipboard+ClipboardCopy below, refer to functions from OpenOffice.org Forum :: Copy arbitrary string (text) to Clipboard

Code: Select all

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

'' "The maximum lenght of strings is 65535 bytes in Basic and Python"
'' So don't compose string - write to hidden document. 

Sub viewFields() 
	
	Doc = ThisComponent
	
	'' tstr = "" '' instead of composing a string, we shall write directly into a hidden document
	
	'' create hidden doc
	hDoc = StarDesktop.loadComponentFromURL( "private:factory/swriter", "_blank", 0,_
	   Array( MakePropertyValue( "Hidden", True ) ) )
	
	' Get the text (body) of the document.
	hText = hDoc.getText()
	' Get a cursor that can move over or to any part of the text.
	hCursor = hText.createTextCursor()
	
	' Insert text and paragraph breaks into the text, at the cursor position.
	' hText.insertString( hCursor, "bla", False )	
	
	'' OpenOffice.org Forum :: determining a property value for an object - http://www.oooforum.org/forum/viewtopic.phtml?t=52861
	Dim iMyInterface    As Object ' required to call getPropertySetInfo() 
	Dim hasProperty    As Boolean   ' flag to have property 
   
   	' k = 0
  	Set objText = Doc.GetText() 
   	Set objEnumPar = objText.createEnumeration()
 
	Do While objEnumPar.hasMoreElements()
	    Set objPar = objEnumPar.nextElement()
	    Set objEnumChunks = objPar.createEnumeration()
        tz = objPar.ImplementationName ''SwXParagraph
        tz2 = objPar.LocalName
        tz3 = objPar.ParaStyleName ''
        tstr = "- " + tz + " " + tz2 + " " + tz3 + " " + chr(13)
        hText.insertString( hCursor, tstr, False )
        ' k = Len( tstr ) ' check length when using tstr as storage; will max out at 65535
	    Do While objEnumChunks.hasMoreElements()
	        Set objChunk = objEnumChunks.nextElement()
	        tz = objChunk.ImplementationName '' SwXTextPortion
	        tz2 = objChunk.TextPortionType '' Text, Bookmark, TextField, SoftPageBreak, Frame
	        
	        'If (objChunk.TextPortionType = "TextField") Then
	        '	tz3 = objChunk.TextField.SupportedServiceNames(0) + "::" + objChunk.String  
	        '	tz3 = tz3 + "::" + getIfPropertyExists("SourceName", objChunk.TextField)
	        '	tz3 = tz3 + "::" + getIfPropertyExists("CurrentPresentation", objChunk.TextField)
	        'Else
	        '	tz3 = objChunk.HyperLinkURL
	        'End If
	        
			Select Case objChunk.TextPortionType
				Case  "TextField":
		        	tz3 = objChunk.TextField.SupportedServiceNames(0) + "::" + objChunk.String  
		        	tz3 = tz3 + "::" + getIfPropertyExists("SourceName", objChunk.TextField)
		        	tz3 = tz3 + "::" + getIfPropertyExists("CurrentPresentation", objChunk.TextField)
		        	tz3 = tz3 + "::" + getIfPropertyExists("ReferenceFieldPart", objChunk.TextField) ' these for GetReference
		        	tz3 = tz3 + "::" + getIfPropertyExists("ReferenceFieldSource", objChunk.TextField)
		        	tz3 = tz3 + "::" + getIfPropertyExists("AnchorType", objChunk.TextField)
		        	tz3 = tz3 + "::" + getIfPropertyExists("VariableName", objChunk.TextField) 'below only for SetExpression
		        	tz3 = tz3 + "::" + getIfPropertyExists("SequenceValue", objChunk.TextField)
		        	tz3 = tz3 + "::" + getIfPropertyExists("Content", objChunk.TextField)
				Case  "Bookmark":
		        	tz3 = objChunk.Bookmark.LinkDisplayName + "##" + objChunk.String
		        	tz3 = tz3 + "##" + objChunk.Bookmark.Name + "##" + objChunk.Bookmark.Anchor.HyperLinkTarget
				Case Else
	        		tz3 = objChunk.HyperLinkURL
			End Select
			
	        tstr = "-- " + tz + " " + tz2 + " " + tz3 + " " + chr(13) 
	        hText.insertString( hCursor, tstr, False )
	    Loop
	Loop 
   

	tfEnum = Doc.getTextFields.createEnumeration 
	While tfEnum.hasMoreElements()
		tf = tfEnum.nextElement()
		
		tx2 = tf.ImplementationName '' all are SwXTextField
		tx3 = tf.Anchor.String
		''tx4 = tf.Anchor.HyperLinkURL '' all are empty
		''tx4 = tf.Anchor.HyperLinkName '' all are empty
		''tx4 = tf.Anchor.HyperLinkTarget '' all are empty
		tx4 = getIfPropertyExists("HyperLinkTarget", tf.Anchor) ' just a test
		
		
		tstr = tx2 + " " + tx3 + " '" + tx4 + "'" + chr(13) 
		hText.insertString( hCursor, tstr, False )
		'k = Len( tstr ) 
	wend 
	
	' tfmEnum = Doc.getTextFieldMasters.createEnumeration 
	' OpenOffice.org Forum :: InsertField - http://www.oooforum.org/forum/viewtopic.phtml?p=33231.
	vVal = Doc.getTextFieldMasters()
	vNames = vVal.getElementNames() 
	'You will have names such as:
	'com.sun.star.text.FieldMaster.SetExpression.Illustration
	'com.sun.star.text.FieldMaster.SetExpression.Table
	'com.sun.star.text.FieldMaster.SetExpression.Text
	'com.sun.star.text.FieldMaster.SetExpression.Drawing
	'com.sun.star.text.FieldMaster.User 	
	For i = LBound(vNames) to UBound(vNames) 
	sKey = vNames(i) 
	vTextFieldMaster = vVal.getByName(sKey) 
	If Not IsNull(vTextFieldMaster) Then 
		tcn = getIfPropertyExists("Content", vTextFieldMaster)
		tstr = "tfm: " + sKey + " " + tcn + chr(13) 
		hText.insertString( hCursor, tstr, False )
	End If 
	Next i 
	
	'' TextToClipboard( tstr ) '' no need to call TextToClipboard, since we already have a doc open
	'' simply copy from the open hidden doc, which was filled with the report
	SelectAll( hDoc )
	ClipboardCopy( hDoc )

	hDoc.close( True )
End Sub


Function getIfPropertyExists( propName As String, ByRef objRef ) As String
	tret = "*"
	iMyInterface = objRef.getPropertySetInfo()  ' we need the interface
	hasProperty = iMyInterface.hasPropertyByName(propName)    
	   
	If (hasProperty) Then
		tret = objRef.getPropertyValue(propName) 
	Else
		tret = "No"
	End If	
	getIfPropertyExists() = tret
End Function

'----------
'   Create and return a new com.sun.star.beans.PropertyValue.
' http://www.oooforum.org/forum/viewtopic.phtml?t=5108
' 
Function MakePropertyValue( Optional cName As String, Optional uValue ) As com.sun.star.beans.PropertyValue
   Dim oPropertyValue As New com.sun.star.beans.PropertyValue
   If Not IsMissing( cName ) Then
      oPropertyValue.Name = cName
   EndIf
   If Not IsMissing( uValue ) Then
      oPropertyValue.Value = uValue
   EndIf
   MakePropertyValue() = oPropertyValue
End Function 

Last edited by sdaau on Tue Feb 16, 2010 7:07 pm, edited 2 times in total.
sdaau
Posts: 5
Joined: Tue Jan 05, 2010 1:29 am

Re: Iterating through document textfields in OOO Writer Basic

Post by sdaau »

Just a brief note: the code above will show certain bookmarks ( those that have/contain a range of text) twice, which is mentioned in OpenOffice.org Forum :: Problem sorting an array of bookmarks:
http://www.oooforum.org/forum/viewtopic.phtml?t=27669#108961 wrote:This works the same as for a reference it seems. The start and end position is enumerated in the object, which is very flexible, but not so good for your application, because it means that if anything is selected, then everything will be enumerated twice
So, in brief - for Bookmarks:
  • If looping through Doc.GetText().createEnumeration().nextElement().createEnumeration().nextElement() then picking up BOTH opening AND closing "tag" of bookmark
  • If looping through Doc.GetBookmarks().getByName(Doc.GetBookmarks().ElementNames(i)), only THEN getting each bookmark individually
However, TextFields seem to be ok (not split), either via Doc.GetText().... or via Doc.getTextFields.createEnumeration.nextElement() (as it can be seen in above code)

For an example of looping through Doc.GetBookmarks(), see "Sub showBookmarks" code in OpenOffice.org Forum :: PLS HELP !!! HOW TO VIEW BOOKMARKS

Cheers!
sdaau
Posts: 5
Joined: Tue Jan 05, 2010 1:29 am

Re: Iterating through document textfields in OOO Writer Basic

Post by sdaau »

Just adding a slightly more compact version of the above - and plus included an iterator for shapes / grouped graphics.

Cheers!

Code: Select all

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

' http://www.oooforum.org/forum/viewtopic.phtml?t=10527
sub viewShapes
	
	BasicLibraries.loadLibrary("XrayTool")
	
	Doc = ThisComponent	
	
	tstr$ = "" 		' k = Len( tstr ) ' check length when using tstr as storage; will max out at 65535
	'' create hidden doc
	hDoc = StarDesktop.loadComponentFromURL( "private:factory/swriter", "_blank", 0, Array( MakePropertyValue( "Hidden", True ) ) )
	Set hText = hDoc.getText() ' Get the text (body) of the document.
	Set hCursor = hText.createTextCursor()	' Get a cursor that can move over or to any part of the text.

	
	drPage = Doc.CurrentController.Model.getDrawPage()
	' maybe drPage can be thought of as whole Writer doc as graphics on single page? 
	'xray drPage

	Dim xx, oShape
	For xx = 0 to drPage.Count-1
		oShape = drPage.getByIndex(xx) ' get the shape on the drawing page
		'xray oShape
		tz = oShape.ImplementationName ''SwXTextFrame, SwXTextGraphicObject, SwXShape
		tz2 = oShape.ShapeType '' FrameShape, com.sun.star.drawing.GroupShape
		tz3 = oShape.Name
		tz4 = oShape.Anchor.ImplementationName '' SwXTextRange
		tstr = "- " + tz + " " + tz2 + " " + tz3 + " " + tz4 + chr(13)
		hText.insertString( hCursor, tstr, False )	
	Next

	'msgbox (tstr$)
	SelectAll( hDoc )
	ClipboardCopy( hDoc )
	hDoc.close( True )		
end sub


Sub viewFields()

	Doc = ThisComponent
	
	tstr$ = "" 		' k = Len( tstr ) ' check length when using tstr as storage; will max out at 65535
	'' create hidden doc
	hDoc = StarDesktop.loadComponentFromURL( "private:factory/swriter", "_blank", 0, Array( MakePropertyValue( "Hidden", True ) ) )
	Set hText = hDoc.getText() ' Get the text (body) of the document.
	Set hCursor = hText.createTextCursor()	' Get a cursor that can move over or to any part of the text.


	'' OpenOffice.org Forum :: determining a property value for an object - http://www.oooforum.org/forum/viewtopic.phtml?t=52861
	Dim iMyInterface    As Object ' required to call getPropertySetInfo()
	Dim hasProperty    As Boolean   ' flag to have property
	
	' k = 0
	Set objText = Doc.GetText()
	Set objEnumPar = objText.createEnumeration()

	Do While objEnumPar.hasMoreElements()
		Set objPar = objEnumPar.nextElement()
		Set objEnumChunks = objPar.createEnumeration()
		tz = objPar.ImplementationName ''SwXParagraph
		tstr = "- " + tz + chr(13)
		hText.insertString( hCursor, tstr, False )
		Do While objEnumChunks.hasMoreElements()
			Set objChunk = objEnumChunks.nextElement()
			tz = objChunk.ImplementationName '' SwXTextPortion
			tz2 = objChunk.TextPortionType '' Text, Bookmark, TextField, SoftPageBreak, Frame
			tstr = "-- " + tz + " " + tz2 + " " + chr(13) 
			hText.insertString( hCursor, tstr, False )
		Loop
	Loop 
	
	'msgbox (tstr$)
	SelectAll( hDoc )
	ClipboardCopy( hDoc )
	hDoc.close( True )	
end sub


Sub showGraphObjects

	Dim Doc As Object
	Dim GraphObj As Object

	Doc = ThisComponent 

	'xray Doc
	Set objGos = Doc.getGraphicObjects()
	Set goEnum_NamesArr = objGos.ElementNames   

	Dim i%, istr%, iend% ' as integer
	istr% = LBound(goEnum_NamesArr)
	iend% = UBound(goEnum_NamesArr) 

	rep$ = ""

	'' iterate through all graph objs
	for i% = istr% to iend%
		goName$ = goEnum_NamesArr(i%) ' shorthand string - name
		rep$ = rep$ + i + " " + goName$ + chr(13)
		GraphObj = objGos.getByName(goName$)

	next i%
	
	msgbox (rep$)
   
End Sub



'----------
'   Create and return a new com.sun.star.beans.PropertyValue.
' http://www.oooforum.org/forum/viewtopic.phtml?t=5108
'
Function MakePropertyValue( Optional cName As String, Optional uValue ) As com.sun.star.beans.PropertyValue
	Dim oPropertyValue As New com.sun.star.beans.PropertyValue
	If Not IsMissing( cName ) Then
	   oPropertyValue.Name = cName
	EndIf
	If Not IsMissing( uValue ) Then
	   oPropertyValue.Value = uValue
	EndIf
	MakePropertyValue() = oPropertyValue
End Function 
OpenOffice 3.0 on Windows XP
OpenOffice 3.0 on Ubuntu 9.04 (or 3.1?)
OpenOffice 3.2 on Windows XP
Post Reply