Writer documents primarily contain formatted text that is arranged into paragraphs. Writer methods can operate on words, sentences, paragraphs, and entire text objects. Paragraphs are the most basic organizational unit for formatted text, and methods on paragraphs are often the most reliable, meaning they contain fewer bugs . The paragraphs can be enumerated sequentially using the XEnumerationAccess interface defined in the document's text object. OOo treats tables as a special type of paragraph, and they are returned while enumerating paragraphs (see Listing 6 ).
Sub enumerateParagraphs Dim oEnum 'com.sun.star.container.XEnumerationAccess Dim oPar 'Paragraph of some sort Dim nPars As Integer 'Number of paragraphs Dim nTables As Integer 'Number of tables REM ThisComponent refers to the current OOo document REM Text is a property of ThisComponent for a text document REM The getText() object method returns the same thing. REM createEnumeration() is an object method. oEnum = ThisComponent.Text.createEnumeration() Do While oEnum.hasMoreElements() oPar = oEnum.nextElement() REM The returned paragraph will be a paragraph or a text table If oPar.supportsService("com.sun.star.text.Paragraph") Then nPars = nPars + 1 ElseIf oPar.supportsService("com.sun.star.text.TextTable") Then nTables = nTables + 1 End If Loop MsgBox CStr(nPars) & " Paragraph(s)" & CHR$(13) &_ CStr(nTables) & " Table(s)" & CHR$(13), 0,_ "Paragraph Types In Document" End Sub
Campatibility | Visual Basic for Applications (VBA) supports accessing paragraphs using an index; however, OOo does not. |
While enumerating the paragraphs in a Writer document, both paragraphs and tables are returned. The object method supportsService() is used to determine if a paragraph or a table is returned. Paragraph objects support both the XTextRange interface and the XTextContent interface. TextTable objects, however, support only the XTextContent interface.
Paragraphs contain numerous paragraph-related properties encapsulated in services. The properties that are primarily related to the entire paragraph are encapsulated in the ParagraphProperties service (see Table 5 ).
Property | Description |
---|---|
ParaAdjust | Specify how the paragraph is aligned (or justified). Five values are supported from the com.sun.star.style.ParagraphAdjust enumeration:
|
ParaLastLineAdjust | Adjust the last line if the ParaAdjust is set to BLOCK. |
ParaLineSpacing | Specify the paragraph line spacing. The property is a structure of type com.sun.star.style.LineSpacing, which contains two properties of type Short. The Height property specifies the height and the Mode property specifies how to use the Height property. The Mode property supports values defined in the com.sun.star.style.LineSpacingMode constants group .
|
ParaBackColor | Specify the paragraph background color as a Long Integer. |
ParaBackTransparent | If True, set the paragraph background color to transparent. |
ParaBackGraphicURL | Specify the URL of the paragraph background graphic. |
ParaBackGraphicFilter | Specify the name of the graphic filter for the paragraph background graphic. |
ParaBackGraphicLocation | Specify the position of the background graphic using the enumeration sun.star.style.GraphicLocation:
|
ParaExpandSingleWord | If True, single words may be stretched . |
ParaLeftMargin | Specify the left paragraph margin in 0.01 mm as a Long Integer. |
ParaRightMargin | Specify the right paragraph margin in 0.01 mm as a Long Integer. |
ParaTopMargin | Specify the top paragraph margin in 0.01 mm as a Long Integer. The distance between two paragraphs is the maximum of the bottom margin of the previous paragraph and the top margin of the next paragraph. |
ParaBottomMargin | Specify the bottom paragraph margin in 0.01 mm as a Long Integer. The distance between two paragraphs is the maximum of the bottom margin of the previous paragraph and the top margin of the next paragraph. |
ParaLineNumberCount | If True, this paragraph is included in line numbering. |
ParaLineNumberStartValue | Specify the start value for line numbering as a Long Integer. |
PageDescName | Setting this string causes a page break to occur before the paragraph. The new page uses the specified page style name. |
PageNumberOffset | Specify a new page number if a page break occurs. |
ParaRegisterModeActive | If True, and if the paragraph's page style also has the register mode set to True, the register mode is active for this paragraph. If register mode is active, each line has the same height. |
ParaTabStops | Specify the tab stops for this paragraph. This is an array of structures of type com.sun.star.style.TabStop. Each structure contains the following properties:
|
ParaStyleName | Specify the name of the current paragraph style. |
DropCapFormat | Structure that determines if the first characters of the paragraph use dropped capital letters . The com.sun.star.style. DropCapFormat contains the following properties:
|
DropCapWholeWord | If True, the DropCapFormat is applied to the entire first word. |
ParaKeepTogether | If True, prevents a page or column break after this paragraph-for example, to prevent a title from being the last line on a page or column. |
ParaSplit | If False, prevents the paragraph from splitting into two pages or columns . |
NumberingLevel | Specify the numbering level of the paragraph. |
NumberingRules | Specify the numbering rules applied to this paragraph. This object implements the com.sun.star.container.XIndexReplace interface. |
NumberingStartValue | Specify the start value for numbering if ParaIsNumberingRestart is True. |
ParaIsNumberingRestart | Specify if numbering restarts at the current paragraph (see NumberingStartValue). |
NumberingStyleName | Specify the name of the style for numbering (see ParaLineNumberCount). |
ParaOrphans | Specify the minimum number of lines at the bottom of a page if the paragraph spans more than one page. |
ParaWidows | Specify the minimum number of lines at the top of a page if the paragraph spans more than one page. |
ParaShadowFormat | Specify the paragraph shadow format as a com.sun.star.table.ShadowFormat:
|
LeftBorder | Specify the left border as a com.sun.star.table.BorderLine:
|
RightBorder | Specify the right border (see Left Border). |
TopBorder | Specify the top border (see Left Border). |
BottomBorder | Specify the bottom border (see Left Border). |
BorderDistance | Specify the distance from the border to the object (in 0.01 mm). |
LeftBorderDistance | Specify the distance from the left border to the object (in 0.01 mm). |
RightBorderDistance | Specify the distance from the right border to the object (in 0.01 mm). |
TopBorderDistance | Specify the distance from the top border to the object (in 0.01 mm). |
Bottom BorderDistance | Specify the distance from the bottom border to the object (in 0.01 mm). |
BreakType | Specify the type of break that is applied at the start of the paragraph. This is an enumeration of type com.sun.star.style.BreakType with the following values:
|
DropCapCharStyleName | Specify the name of the character style for drop caps. |
ParaFirstLineIndent | Specify the indent for the first line in a paragraph. |
ParalsAutoFirstLinelndent | If True, the first line is indented automatically. |
ParalsHyphenation | If True, automatic hyphenation is applied. |
ParaHyphenationMaxHyphens | Specify the maximum number of consecutive hyphens for each word contained in the current paragraph. |
ParaHyphenationMaxLeadingChars | Specify the maximum number of characters to remain before a hyphen character. |
ParaHyphenationMaxTrailingChars | Specify the maximum number of characters to remain after a hyphen character. |
ParaVertAlignment | Specify the vertical alignment of the paragraph. This is a constant group of type com.sun.star.text.ParagraphVertAlign with valid values:
|
ParaUserDefinedAttributes | Stores XML attributes that are saved and restored from the automatic styles inside XML files. The object implements the com.sun.star.container.XNameContainer interface. |
NumberingIsNumber | If True, the numbering of a paragraph is a number but has no symbol. This is void if the paragraph is not part of a paragraph numbering sequence. |
ParalsConnectBorder | If True, paragraph borders are merged with the previous paragraph if the borders are identical. This property may be void. |
Tip | The Paragraph service is not the only service that supports the ParagraphProperties service. Other services, especially those that are also a text range, also support paragraph properties. Techniques used to modify paragraph properties in paragraphs apply to these services as well. |
Tip | Paragraph properties are usually set using paragraph styles-at least they should be. |
Many of the properties in Table 5 are structures; they require special care if you want to modify them, because a structure is copied by value rather than by reference. For example, the ParaLineSpacing property is a structure. Although the code in Listing 7 looks correct, it fails; this usage is a very common error committed by OOo Basic programmers.
oPar.ParaLineSpacing.Mode = com.sun.star.style.LineSpacing.LEADING
The code in Listing 7 fails because the code "oPar.ParaLineSpacing" made a copy of the structure. The Mode is set, but it is set only on the copy, leaving the original intact. The code in Listing 8 demonstrates the proper way to modify the value of a structure when it is used as a property. A copy of the structure is stored in the variable v, which is then modified and copied back.
v = oPar.ParaLineSpacing v.Mode = com.sun.star.style.LineSpacing.LEADING oPar.ParaLineSpacing = v
To insert a page break, set the PageDescName property to the name of the page style to use after the page break. This style may be the same as the current page style; it is the act of setting the PageDescName property-not changing it to a new value-that causes a page break to occur. The page style name must exist in the document or a page break is not inserted. When you insert a page break, you can also set a new page number by setting the PageNumberOffset property to the new page number. See Listing 9 .
Sub SetPageBreakAtEndFromEnumeration Dim oEnum 'com.sun.star.container.XEnumerationAccess Dim oParTest 'Paragraph of some sort Dim oPar 'Last Paragraph object REM Find the last paragraph oEnum = ThisComponent.Text.createEnumeration() Do While oEnum.hasMoreElements() oParTest = oEnum.nextElement() If oParTest.supportsService("com.sun.star.text.Paragraph") Then oPar = oParTest End If Loop REM Note that this does not actually change the page style name oPar.PageDescName = oPar.PageStyleName REM Set the new page number to be 7 oPar.PageNumberOffset = 7 End Sub
Tip | It's rare to insert a page break while enumerating paragraphs. It is more common to insert a page break using a text cursor or a text range. You can use any service that supports paragraph properties to insert a page break. |
While writing this book, I formatted code examples using paragraph styles. One benefit is that this forces uniformity in the spacing around the macro examples. Unfortunately, I occasionally make a mistake and use the wrong styles. A macro is the perfect tool to verify some level of consistency. Table 6 describes the styles that I use for formatting code examples.
Style | Description |
---|---|
_code one line | Used for a single line of code. There is extra space above and below the paragraph. |
_code first line | First line of code in an example that uses more than one line. There is extra space above, but not below, the paragraph. |
_code last line | Last line of code in an example that uses more than one line. There is extra space below, but not above, the paragraph. |
_code | Line of code that is neither first nor last. There is no extra space above or below the paragraph. |
This example makes excellent use of enumerating paragraphs. As the paragraphs are traversed, each paragraph is compared to the paragraph that precedes it. It's easy to set the paragraph style by setting the ParaStyleName property. The macro in Listing 10 shows the complete code.
Sub CleanCodeStyles() CleanCodeStyles_enumerate("_code first line", "_code",_ "_code last line", "_code one line") End Sub Sub CleanCodeStyles_enumerate(firstStyle$, midStyle$, lastStyle$, onlyStyle$) Dim oEnum 'com.sun.star.container.XEnumerationAccess Dim oPrevPar 'Paragraph of some sort Dim oCurPar 'Last Paragraph object Dim sPrevStyle As String 'Previous style Dim sCurStyle As String 'Current style oEnum = ThisComponent.Text.createEnumeration() Do While oEnum.hasMoreElements() oCurPar = oEnum.nextElement() REM Determine the paragraph style of the current paragraph If oCurPar.supportsService("com.sun.star.text.Paragraph") Then sCurStyle = oCurPar.ParaStyleName End If REM I do this because the call below fails if oPrevPar is Empty REM I call this a bug. Note that this is safe to do because REM sPrevStyle is "" when oPrevPar is empty. If IsEmpty(oPrevPar) Then oPrevPar = oCurPar CleanCodeStyles_worker(firstStyle$, midStyle$, lastStyle$, onlyStyle$,_ oPrevPar, oCurPar, sPrevStyle, sCurStyle) sPrevStyle = sCurStyle sCurStyle = "" oPrevPar = oCurPar Loop CleanCodeStyles_worker(firstStyle$, midStyle$, lastStyle$, onlyStyle$,_ oPrevPar, oCurPar, sPrevStyle, sCurStyle End Sub Sub CleanCodeStyles_worker(firstStyle$, midStyle$, lastStyle$, onlyStyle$,_ oPrevPar, oCurPar, sPrevStyle$, sCurStyle$) If sCurStyle = firstStyle$ Then REM Current style is the first style. REM See if the previous style was also one of these! Select Case sPrevStyle Case onlyStyle$ sCurStyle = midStyle$ oCurPar.ParaStyleName = sCurStyle oPrevPar.ParaStyleName = firstStyle$ Case lastStyle$ sCurStyle = midStyle$ oCurPar.ParaStyleName = sCurStyle oPrevPar.ParaStyleName = midStyle$ Case firstStyle$, midStyle$ sCurStyle = midStyle$ oCurPar.ParaStyleName = sCurStyle End Select Elself sCurStyle = midStyle$ Then REM Current style is the mid style. REM See if the previous style was also one of these! Select Case sPrevStyle Case firstStyle$, midStyle$ REM Do nothing! Case onlyStyle$ REM The last style was an only style, but it comes before a mid! oPrevPar.ParaStyleName = firstStyle$ Case lastStyle$ oPrevPar.ParaStyleName = midStyle$ Case Else sCurStyle = firstStyle$ oCurPar.ParaStyleName = sCurStyle End Select ElseIf sCurStyle = lastStyle$ Then Select Case sPrevStyle Case firstStyle$, midStyle$ REM Do nothing! Case onlyStyle$ REM The last style was an only style, but it comes before a mid! oPrevPar.ParaStyleName = firstStyle$ Case lastStyle$ oPrevPar.ParaStyleName = midStyle$ Case Else sCurStyle = firstStyle$ oCurPar.ParaStyleName = sCurStyle End Select ElseIf sCurStyle = onlyStyle$ Then Select Case sPrevStyle Case firstStyle$, midStyle$ sCurStyle = midStyle$ oCurPar.ParaStyleName = sCurStyle Case lastStyle$ sCurStyle = lastStyle$ oCurPar.ParaStyleName = sCurStyle oPrevPar.ParaStyleName = midStyle$ Case onlyStyle$ sCurStyle = lastStyle$ oCurPar.ParaStyleName = sCurStyle oPrevPar.ParaStyleName = firstStyle$ End Select Else Select Case sPrevStyle Case firstStyle$ oPrevPar.ParaStyleName = onlyStyle$ Case midStyle$ oPrevPar.ParaStyleName = lastStyle$ End Select End If End Sub
Paragraphs contain numerous character-related properties. Like the paragraph-specific properties, these properties are optional and are encapsulated in services. The properties that are primarily related to characters are found the CharacterProperties service (see Table 7 ).
Property | Description |
---|---|
CharFontName | Specify the name of the font in western text. This may be a comma-separated list of names . |
CharFontStyleName | Specify the name of the font style. |
CharFontFamily | Specify the name of the font family as specified in com.sun.star.awt.FontFamily constant group.
|
CharFontCharSet | Specify the text encoding of the font using the com.sun.star.awt.CharSet constant group. The values are self-explanatory: DONTKNOW, ANSI, MAC, IBMPC_437 (IBM PC character set number 437), IBMPC_850, IBMPC_860, IBMPC_86, IBMPC_863, IBMPC_865, SYSTEM, and SYMBOL. |
CharFontPitch | Specify the character font pitch using the com.sun.star.awt.FontPitch constant group. The values are self-explanatory: DONTKNOW, FIXED, and VARIABLE. |
CharColor | Specify the text color as a Long Integer. |
CharEscapement | Specify the Short Integer representing the percentage of raising or lowering for superscript/subscript characters. Negative values lower the characters. |
CharHeight | Specify the character height in points as a decimal number. |
CharUnderline | Specify the character underline type using the com.sun.star.awt.FontUnderline constant group.
|
CharWeight | Specify the font weight using the com.sun.star.awt.FontWeight constant group.
|
CharPosture | Specify the character posture using the com.sun.star.awt.FontSlant enumeration with values:
|
CharAutoKerning | Set to True to use the kerning tables for the current font. Automatic kerning adjusts the spacing between certain pairs of characters to improve readability. |
CharBackColor | Specify the text background color as a Long Integer. |
CharBackTransparent | If True, the text background color is transparent. |
CharCaseMap | Specify how characters should be displayed using the com.sun.star.style.CaseMap constant group. This does not change the actual text-only the way it is displayed.
|
CharCrossedOut | If True, the characters have a line through them. |
CharFlash | If True, the characters are displayed flashing. |
CharStrikeout | Specify character strikeout using the com.sun.star.awt.FontStrikeout constant group:
|
CharWordMode | If True, white spaces (spaces and tabs) ignore the CharStrikeout and CharUnderline properties. |
CharKerning | Specify the character kerning value as a Short Integer. |
CharLocale | Specify the character locale as a com.star.lang.Locale structure. |
CharKeepTogether | If True, OOo tries to keep the character range on the same line. If a break must occur, it occurs before the characters. |
CharNoLineBreak | If True, OOo ignores a line break in the character range. If a break must occur, it occurs after the characters so it is possible that they will cross a border. |
CharShadowed | If True, the characters are formatted and displayed with a shadow effect. |
CharFontType | Specify the fundamental technology of the font using the com.sun.star.awt.FontType constant group.
|
CharStyleName | Specify the name of the font style as a string. |
CharContoured | If True, characters are formatted and displayed with a contour (3-D outline) effect. |
CharCombinelsOn | If True, text is formatted and displayed using two lines. The CharCombinePrefix string precedes the text in full size, and the CharCombineSuffix follows the text in full size. |
CharCombinePrefix | Specify the prefix (usually parentheses) used with the CharCombinelsOn property. |
CharCombineSuffix | Specify the suffix (usually parentheses) used with the CharCombinelsOn property. |
CharEmphasize | Specify the type and position of emphasis marks in Asian texts using the com.sun.star.text.FontEmphasis constant group:
|
CharRelief | Specify the relief value from the com.sun.star.text.FontRelief constant group:
|
RubyText | Specify the text that is set as ruby. "Ruby Text" acts as an annotation and is associated with a "Ruby Base." This is typically used in Asian writing systems, providing a helper for uncommonly used writing characters that are not easily recognizable, especially by children. For example, in Japanese writing, the phonetic Hiragana alphabet is used to pair phonetic "helper" readings (called Furigana or Yomigana in Japanese) with the Chinese character counterpart . |
RubyAdjust | Specify the ruby text adjustment using the com.sun.star.text.RubyAdjust enumeration:
|
RubyCharStyleName | Specify the name of the character style that is applied to RubyText. |
RubylsAbove | If True, the Ruby is printed above the text (right if the text is vertical). |
CharRotation | Specify the rotation of a character in degrees as a Short Integer. Not all implementations support all values. |
CharRotationIsFitToLine | If True, OOo tries to fit the rotated text to the surrounding line height. |
CharScaleWidth | Specify the scaling for superscript and subscript as a percentage using a Short Integer. |
HyperLinkURL | Specify the URL of a hyperlink (if set) as a String. |
HyperLinkTarget | Specify the name of the target for a hyperlink (if set) as a String. |
HyperLinkName | Specify the name of the hyperlink (if set) as a String. |
VisitedCharStyleName | Specify the character style for visited hyperlinks as a String. |
UnvisitedCharStyleName | Specify the character style name for unvisited hyperlinks as a String. |
CharEscapementHeight | Specify the additional height used for subscript or superscript characters as an Integer percent. For subscript characters the value is negative. |
CharNoHyphenation | If True, the word cannot be hyphenated at the character. |
CharUnderlineColor | Specify the color of the underline as a Long Integer. |
CharUnderlineHasColor | If True, the CharUnderlineColor is used for an underline. |
CharStyleNames | An array of character style names applied to the text. The order is not necessarily relevant. |
Tip | Many of the properties are represented by a value in a constant group. Constant groups associate meaningful names to constant values. For example, the CharFontFamily accepts the value com.sun.star.awt.FontFamily.ROMAN to specify a Roman font with serifs. A value of 3 may also be used. In almost all cases, the first value is 0, the second value is 1, and so on. Code that uses the descriptive names is easier to read and understand. |
Tip | When a property supports a DONTKNOW value, the property is usually used as a hint to perform certain operations more efficiently or to find a close replacement value if the requested value is not available. For example, if a particular font is not available, you can use the CharFontFamily to choose a font of the correct type. |
The code in Listing 11 demonstrates modifying the character properties by modifying the FontRelief property and then changing it back.
Sub ViewFontRelief Dim oEnum 'com.sun.star.container.XEnumerationAccess Dim oPar 'Paragraph of some sort Dim i% 'General Counting variable Dim s$ oEnum = ThisComponent.Text.createEnumeration() Do While oEnum.hasMoreElements() oPar = oEnum.nextElement() REM The returned paragraph will be a paragraph or a text table If oPar.supportsService("com.sun.star.text.Paragraph") Then i = i + 1 oPar.CharRelief = i MOD 3 End If Loop MsgBox "The document now uses NONE, EMBOSSED, and ENGRAVED character relief" oEnum = ThisComponent.Text.createEnumeration() Do While oEnum.hasMoreElements() oPar = oEnum.nextElement() REM The returned paragraph will be a paragraph or a text table If oPar.supportsService("com.sun.star.text.Paragraph") Then i = i + 1 oPar.CharRelief = com.sun.star.text.FontRelief.NONE End If Loop End Sub
It is not unusual for a paragraph to contain text with dissimilar formatting-for example, a single word may be displayed in bold in the middle of a sentence that is displayed in the font's normal state. Just as you can enumerate the paragraphs in a document, you can enumerate the text sections in a paragraph. Text within each enumerated portion uses the same properties and is of the same type. Table 8 lists the properties directly supported by the TextPortion service. The TextPortion service exports the TextRange service so it also supports the paragraph properties in Table 5 and the character properties in Table 7.
Property | Description |
---|---|
TextPortionType | String containing the type of the text portion. Valid content type names are:
|
ControlCharacter | Short Integer containing the control character if the text portion contains a ControlCharacter. |
Bookmark | If the text content is a bookmark, this is a reference to the bookmark. The property implements the com.sun.star.text.XTextContent interface. |
IsCollapsed | If True, the text portion is a point. |
IsStart | If True, the text portion is a start portion if two portions are needed to include an object. For example, a DocmentlndexMark has a start and end text portion surrounding the text to be indexed. |
Tip | An object that supports paragraph or character properties typically provides a way to enclose a range of text. If a specific property changes value in the text range, it usually isn't available to be set. For example, a text range can contain more than one paragraph. If all of the contained paragraphs in the text range do not support the same paragraph style, the paragraph style property is not available to the text range. If, however, the text range is reduced to contain only paragraphs that support a single paragraph style, the paragraph style property will be available to that text range. |
The macro in Listing 12 demonstrates enumerating the text content inside a paragraph. It displays the paragraph number and the included text portion types in a dialog. The paragraph number is calculated and is not a property of the paragraph.
Sub EnumerateTextSections Dim oParEnum 'Paragraph enumerator Dim osecEnum 'Text section enumerator Dim oPar 'Current paragraph Dim oParSection 'Current section Dim nPars As Integer 'Number of paragraphs Dim s$ oParEnum = ThisComponent.Text.createEnumeration() Do While oParEnum.hasMoreElements() oPar = oParEnum.nextElement() If oPar.supportsService("com.sun.star.text.Paragraph") Then nPars = nPars + 1 oSecEnum = oPar.createEnumeration() s = s & nPars & ":" Do While oSecEnum.hasMoreElements() oParSection = oSecEnum.nextElement() s = s & oParSection.TextPortionType & ":" Loop s = s & CHR$(10) If nPars MOD 10 = 0 Then MsgBox s, 0, "Paragraph Text Sections" s = "" End If End If Loop MsgBox s, 0, "Paragraph Text Sections" End Sub