In OpenOffice.org, styles provide a method of grouping formatting information. For example, a paragraph style defines the font, character size , margins, and many other formatting options. Changing the style changes every paragraph that was formatted using the style. The interface com.sun.star.style.XStyleFamiliesSupplier provides access to the styles used by a document. The macro in Listing 20 displays the names of all styles in the current document; Figure 9 shows the results for one of my documents.
Sub DisplayAllStyles Dim oFamilies 'Families is interface com.sun.star.container.XNameAccess Dim oFamilyNames 'Names of family types. Array of string Dim oStyleNames 'Names of styles. Array of string Dim oStyles 'Styles is interface com.sun.star.container.XNameAccess Dim oStyle 'An individual style Dim s As String 'Utility string variable Dim n As Integer 'Index variable Dim i As Integer 'Index variable oFamilies = ThisComponent.StyleFamilies oFamilyNames = oFamilies.getElementNames() REM First, display the style types and the number REM of each style type. For n = LBound(oFamilyNames) To UBound(oFamilyNames) oStyles = oFamilies.getByName(oFamilyNames(n)) s = s & oStyles.getCount() & " " & oFamilyNames(n) & CHR$(10) Next MsgBox s, 0, "Style Families" REM Now, display all of the different style names For n = LBound(oFamilyNames) To UBound(oFamilyNames) s = "" oStyles = oFamilies.getByName(oFamilyNames(n)) oStyleNames = oStyles.getElementNames() For i = LBound(oStyleNames) To UBound (oStyleNames) s=s + i + " : " + oStyleNames(i) + CHR$(10) If ((i + 1) Mod 30 = 0) Then MsgBox s,0,oFamilyNames(n) s = "" End If Next i If Len(s) <> 0 Then MsgBox s,0,oFamilyNames(n) Next n End Sub
The different document types contain different types of styles. Figure 9 shows the style families in a Writer document. Calc documents contain the style families CellStyles and PageStyles; Impress documents contain the style families Graphics and Default; Draw documents contain the style family Graphic. Although each style type is different, they do have similarities. For example, each style implements both the com.sun. star.style. Style service and the com.sun.star.style.XStyle interface. The common methods and properties provide very rudimentary functionality (see Table 11 ).
Method or Property | Description |
---|---|
isUserDefined() | Is this style user -defined? If not, it is included with OOo. |
isInUse() | Is this style used in the document? |
getParentStyle() | What is the parent style? |
setParentStyle( name ) | Set the parent style. |
IsPhysical | Is the style physically created? |
FollowStyle | Style name applied to the next paragraph. For example, while using a heading style I might want the next paragraph to be regular text. |
DisplayName | Name of the style as displayed in the user interface. |
IsAutoUpdate | If the properties of an object using this style are changed (for example, if I change the font), are these changes automatically updated to the style? |
Table 11 shows methods and properties that can be used to answer the common question, "How do I obtain a list of styles that are currently used by a document?" See Listing 21 and Figure 10 .
Sub DisplayAllUsedParagraphStyles Dim oStyles 'Styles is interface com.sun.star.container.XNameAccess Dim oStyle 'An individual style Dim s As String 'Utility string variable Dim i As Integer 'Index variable oStyles = ThisComponent.StyleFamilies.getByName("ParagraphStyles") REM If getCount() says that there are 10 styles, this means from 0 to 9 For i = 1 To oStyles.getCount() oStyle = oStyles.getByIndex(i-1) If oStyle.isInUse() Then s = s & oStyle.DisplayName & CHR$(10) Next MsgBox s,0,"Paragraph Styles In Use" End Sub
Note | Listing 20 accesses styles by name; Listing 21 accesses styles by index. Notice that when getCount() returns 10, there are 10 items present, indexed 0 through 9. |
Initially, I was confused by the results shown in Figure 10 because it included paragraph styles that I thought I wasn't using. I assumed that I had made a mistake while writing my document, so I started looking for these accidentally used styles. To find the incorrectly styled text, I started with the Find & Replace dialog (Edit Find & Replace). If you check the box labeled "Search for Styles," all of the styles used in the document become available in the "Search for" drop-down box. I used this method to search for the style "Text body" (shown in Figure 10), but it was not found in the document. After some moments of confusion-in this case, roughly five minutes-I realized that I had not found a bug in OpenOffice.org, but rather I had uncovered an interesting behavior of which I had not been previously aware. When a style is used in a document, the parent style is listed as used even if it is not directly used. For example, in my document, the style "Table Contents" uses "Text body" as the parent style.
The different style types contain methods and properties appropriate for their type. See http://api.openoffice.org/docs/common/ref/com/sun/star/style/module-ix.html for the common services, interfaces, structs, and constants related to styles. The types shown in the style module are the base on which the other styles are built. For example, the two services com.sun.star.text.TextPageStyle and com.sun.star.sheet.TablePageStyle both have the service com.sun.star.style.PageStyle in common. To get a feel for a style it is frequently expedient to start by inspecting the object.
MsgBox vObj.dbg_methods MsgBox vObj.dbg_supportedInterfaces MsgBox vObj.dbg_properties
The style objects, like many other objects, implement the XPropertySet interface. The macro in Listing 22 uses this interface to display a list of properties contained in the "_body text" paragraph style. Listing 22 does not display the value of each property; it only displays the name of each property. It is an interesting exercise to modify Listing 22 to also display the value of each property that is a standard data type-a property may be a complex object.
Sub StyleProperties Dim oStyles 'Styles is interface com.sun.star.container.XNameAccess Dim s As String 'Utility string variable Dim i As Integer 'Index variable Dim Props 'Array of properties REM Each style supports the com.sun.star.beans.XPropertySet interface REM This supports the method getPropertySetInfo(), which allows REM an enumeration of the contained properties. REM Get properties returns an array of com.sun.star.beans.Property oStyles = ThisComponent.StyleFamilies.getByName("ParagraphStyles") Props = oStyles.getByName("_body text").getPropertySetInfo().getProperties() For i = 0 To UBound(Props) 'For each property s = s & Props(i).Name & CHR$(10) 'Include the property name and new line If (i+1) MOD 30 = 0 Then 'If the string becomes too large MsgBox s,0,"Style Properties" 'display the current string s = "" 'Reset the list End If Next REM In case the entire list was not printed. If Len(s) <> 0 Then MsgBox s,0,"Style Properties" End Sub
In my experience, it's rare to access and inspect styles. It's even less common to modify a style from a macro. There are times, however, when this is done. For example, the page size is defined by the current page style. Use the current controller to determine the current page style, and then use that to determine the page dimensions. Listing 23 displays the size of the page, the margins, and the current cursor position on the page. Figure 11 shows the results.
Sub PrintPageInformation Dim oViewCursor 'Current view cursor Dim oStyle 'Current page style Dim lHeight As Long 'Page height from Page Style in 1/100 mm Dim lWidth As Long 'Page width from Page Style in 1/100 mm Dim s As String 'Temporary string variable REM The current controller interfaces with the human - that's you! REM Well, we hope you are human anyway. REM Obtain the current view cursor from the controller. It is REM the thing that knows where the current cursor is, after all. oViewCursor = ThisComponent.CurrentController.getViewCursor() REM That view cursor knows a lot of things, including the REM current page style. Use the page style name to get REM a reference to the current page style. s = oViewCursor.PageStyleName oStyle = ThisComponent.StyleFamilies.getByName("PageStyles").getByName(s) s = "Page Style = " & s & CHR$(10) lHeight = oStyle.Height 'Page height in 1/100 mm lWidth = oStyle.Width 'Page width in 1/100 mm REM Page dimensions in mm, inches, and picas. s = s & "Page size is " & CHR$(10) &_ " " & CStr(lWidth / 100.0) & " mm By " &_ " " & CStr(lHeight / 100.0) & " mm" & CHR$(10) &_ " " & CStr(lWidth / 2540.0) & " inches By " &_ " " & CStr(lHeight / 2540.0) & " inches" & CHR$(10) &_ " " & CStr(lWidth *72.0 / 2540.0) & " picas By " &_ " " & CStr(lHeight *72.0 / 2540.0) & " picas" & CHR$(10) Dim dCharHeight As Double 'Character height in inches Dim iCurPage As Integer 'Current page Dim dXCursor As Double 'Distance from cursor to left in inches Dim dYCursor As Double 'Distance from cursor to top in inches Dim dXRight As Double 'Distance from cursor to right in inches Dim dYBottom As Double 'Distance from cursor to bottom in inches Dim dBottom As Double 'Bottom margin in inches Dim dLeft As Double 'Left margin in inches Dim dRight As Double 'Right margin in inches Dim dTop As Double 'Top margin in inches dCharHeight = oViewCursor.CharHeight / 72.0 'Convert points to inches iCurPage = oViewCursor.getPage() 'Page number s = s & "Current page = " & iCurPage & CHR$(10) dBottom = oStyle.BottomMargin / 2540.0 : dLeft = oStyle.LeftMargin / 2540.0 dRight = oStyle.RightMargin / 2540.0 : dTop = oStyle.TopMargin / 2540.0 s = s & "Margin (inches): Left= " & dLeft & " Right= " & dRight & CHR$(10) s = s & "Margin (inches): Top= " & dTop & " Bottom= " & dBottom & CHR$(10) Dim v REM Cursor's coordinates relative to the top left position of the page REM Return type is com.sun.star.awt.Point REM Units are in twips. Convert them to inches. v = oViewCursor.getPosition() REM Place the cursor as the distance to the margin and then add the margin. REM For the vertical height add half the character height. I should REM probably do this for the character width as well for horizontal. dYCursor = v.Y/2540.0 + dTop + dCharHeight / 2 dYBottom = (lHeight - v.Y)/2540.0 - dTop - dCharHeight / 2 dXCursor = v.X/2540.0 + dLeft dXRight = (lWidth - v.X)/2540.0 - dLeft s=s &"Cursor is "&Format(dXCursor, "0.##") & " inches from left "&CHR$(10) s=s &"Cursor is "&Format(dXRight, "0.##") & " inches from right "&CHR$(10) s=s &"Cursor is "&Format(dYCursor, "0.##") & " inches from top "&CHR$(10) s=s &"Cursor is "&Format(dYBottom, "0.##") & " inches from bottom "&CHR$(10) s=s &"Char height = " & Format(dCharHeight, "0.####") & " inches"&CHR$(10) MsgBox s, 0, "Page information" End Sub
Calc documents are composed of spreadsheets. Each sheet can use a different page style. The macro in Listing 23 obtains the current page style using the view cursor. To obtain the style from a Calc document, use the active sheet.
REM Use the currently active sheet to obtain the page style. REM In a Calc document, the current controller knows which sheet REM is active. Print "Style = " & ThisComponent.CurrentController.getActiveSheet().PageStyle