Text Tables


Writer documents act as a text-tables supplier, so you can directly retrieve text tables from Writer documents. Although text tables are enumerated as text content along with paragraphs (see Listing 6), tables are more typically obtained by name or by index (see Listing 37 and Figure 1 ).


Figure 1: Tables contained in a document, by index and named access.
Listing 37: LookAtAIITables is found in the Writer module in this chapter's source code files as SC13.sxw.
start example
 Sub LookAtAIITables   Dim oTables  'All of the text tables   Dim s$       'Work string   Dim i%       'Index variable   oTables = ThisComponent.TextTables   REM First, access the tables based on index.   s = "Tables By Index" & CHR$(10)   For i = 0 To oTables.getCount() - 1     s = s & "Table " & (i+1) & " = " & oTables(i).Name & CHR$(10)   Next   s = s & CHR$(10) & CHR$(10) & "Text Tables By Name" & CHR$(10)   s = s & Join(oTables.getElementNames(), CHR$(10))   MsgBox s, 0, "Tables" End Sub 
end example
 
Tip  

Most named text content is retrieved, created, inserted, and disposed of in the same way. Learn to do this using tables and you'll be ready to use other named text content-bookmarks, for example.

As with most text content, tables must be created by the document before they are inserted into the document. The macro in Listing 38 inserts a table named "SampleTable" if it does not exist, and removes it if it does.

Listing 38: InsertDeleteTable is found in the Writer module in this chapter's source code files as SC13.sxw.
start example
 Sub InsertDeleteTable   Dim oTable       'Newly created table to insert   Dim oTables      'All of the text tables   Dim oInsertPoint 'Where the table will be inserted   Dim sTableName as String   sTableName = "SampleTable"   oTables = ThisComponent.TextTables   If oTables.hasByName(sTableName) Then     oTable = oTables.getByName(sTableName)     REM Although this seems like the correct way to remove text content,     REM what if the table is not inserted into the primary document's     REM text object? oTable.dispose() may be safer to use.     ThisComponent.Text.removeTextContent(oTable) Else     REM Let the document create the text table.     oTable = ThisComponent.createInstance( "com.sun.star.text.TextTable" )     oTable.initialize(2, 3) 'Two rows, three columns     REM If there is a bookmark named "InsertTableHere", then insert     REM the table at that point. If this bookmark does not exist,     REM then simply choose the very end of the document.     If ThisComponent.getBookmarks().hasByName("InsertTableHere") Then       oInsertPoint =_         ThisComponent.getBookmarks().getByName("InsertTableHere").getAnchor()     Else       oInsertPoint = ThisComponent.Text.getEnd()     End If     REM Now insert the text table at the end of the document.     REM Note that the text object from the oInsertPoint text     REM range is used rather than the document text object.     oInsertPoint.getText().insertTextContent(oInsertPoint , oTable, False)     REM The setData() object method works ONLY with numerical data.     REM The setDataArray() object method, however, also allows strings.     oTable.setDataArray(Array(Array(0, "One", 2), Array(3, "Four", 5)))     oTable.setName(sTableName)   End If End Sub 
end example
 
Tip  

In general, it is better to set table properties before inserting the table into the document. This prevents screen flicker as the object is modified and then redrawn on the screen. Due to a bug in OOo 1.1.0, if Listing 38 is modified to set the data before inserting the table, the table name is modified and it contains an extra garbage character at the end. Be warned , however, that some text content, such as text field masters, cannot change their names after they have been inserted into a document.

The macro in Listing 38 demonstrates many useful techniques:

  • A named text content is found and obtained. Notice that finding the table and the bookmark are very similar processes.

  • A bookmark is used.

  • A text table is created, initialized , and inserted at a location marked by a bookmark.

  • Text content is deleted, but perhaps dispose() should have been used.

  • A table is initialized with data.

  • The table name is set.

Using the Correct Text Object

It is very important that you use the correct text object. It is possible that the text object in a text section or table cell is not the same as the text object returned by the document. Each text range is associated with a specific text object. Attempting to use object methods from one text object to operate on a text range associated with a different text object causes an error. In Listing 38, a table is removed, with the single line shown in Listing 39 .

Listing 39: What if the table is not contained in the document's text object?
start example
 ThisComponent.Text.removeTextContent(oTable) 
end example
 

The code in Listing 39 assumes that the table is contained in the document's text object. If the table is not contained in the primary document's text object, the code in Listing 39 will fail. Although Listing 39 will rarely fail, it will undoubtedly fail at the worst possible time. The macro works because the sample document was designed so that the table is inserted into the primary document's text object. Either solution shown in Listing 40 may be a better solution for deleting the table.

Listing 40: Two safe methods to delete the table.
start example
 oTable.getAnchor().getText().removeTextContent(oTable) oTable.dispose() 
end example
 

The second time that a text object is used in Listing 38, it is obtained from the anchor returned from a bookmark-this is safe. See Listing 41 .

Listing 41: A safe way to get a text object.
start example
 oInsertPoint.getText().insertTextContent(oInsertPoint , oTable, False) 
end example
 

If the text range oInsertPoint is not contained in the document's text object, attempting to insert the table using the document's text object will fail. Only you can decide how careful you need to be when accessing text objects. Consider the selected text framework. What text object is used to create text cursors and to compare text cursors ? Can you make the code more robust?

Methods and Properties

The methods supported by text tables are very similar to the methods supported by spreadsheets contained in Calc documents (see Chapter 14, "Calc Documents"). Table 18 summarizes the object methods supported by text tables.

Table 18: Object methods supported by text tables.

Method

Description

autoFormat(name)

Apply the specified auto-format name to the table.

createCursorByCellName(name)

XTextTableCursor positioned at the specified cell.

createSortDescriptor()

Array of PropertyValues that specify the sort criteria.

dispose()

Destroy a text object, which also removes it from the document.

getAnchor()

Return a text range identifying where the table is anchored. This method allows text content to be added easily before or after a text table.

getCellByName(name)

Return an XCell based on the cell name, such as "B3".

getCellByPosition(col, row)

Numbering starts at zero. This has difficulties with complex tables.

getCellNames()

String array of cell names contained in the table.

getCellRangeByName(name)

XCellRange based on cell name, such as A1:B4. Fails if the name identifies a cell that has been split.

getCellRangeByPosition(left, top, right, bottom)

XCellRange based on numeric range.

getColumnDescriptions()

Array of strings describing the columns. Fails for complex tables.

getColumns()

XTableColumns object enumerates columns by index. Also supports insertByIndex(idx, count) and remove ByIndex(idx, count).

getData()

Get numerical data as a nested sequence of values (arrays in an array). Fails for complex tables.

getDataArray()

Same as getData() but may contain String or Double.

getName()

Get the table name as a string.

getRowDescriptions()

Array of strings describing the rows. Fails for complex tables.

getRows()

XTableRows object enumerates rows by index. Also supports insertByIndex(idx, count) and remove ByIndex(idx, count).

initialize(rows, cols)

Set the numbers of rows and columns. Must be done before the table is inserted (see Listing 4).

setColumnDescriptions(string())

Set the column descriptions from an array of strings.

setData(Double())

Set numerical data as a nested sequence of values. Fails for complex tables.

setDataArray(array())

Same as setData() but may contain String or Double.

setName(name)

Set the table name.

setRowDescriptions(string())

Set the row descriptions from an array of strings.

sort(array())

Sort the table based on a sort descriptor.

Text table objects also support a variety of properties (see Table 19 ). Text tables support many of the same properties that are supported by paragraphs (see Table 5).

Table 19: Properties supported by the com.sun.star.text.TextTable service.

Property

Description

BreakType

Specify the type of break that is applied at the start of the table (see the BreakType attribute in Table 5).

LeftMargin

Specify the left table margin in 0.01 mm as a Long Integer. Set the HoriOrient property to something other than FULL.

RightMargin

Specify the right table margin in 0.01 mm as a Long Integer. Set the HoriOrient property to something other than FULL.

HoriOrient

Specify the horizontal orientation using the com.sun.star.text.HoriOrientation constants. The default value is com.sun.star.text.HoriOrientation.FULL.

  • NONE = 0 - No alignment is applied.

  • RIGHT = 1 - The object is aligned at the right side.

  • CENTER = 2 - The object is aligned at the middle.

  • LEFT = 3 - The object is aligned at the left side.

  • INSIDE = 4 - (Not yet supported)

  • OUTSIDE = 5 - (Not yet supported)

  • FULL = 6 - The object uses the full space (for text tables only).

  • LEFT_AND_WIDTH = 7 - The left offset and the width of the object are defined.

KeepTogether

If True, prevents page or column breaks between this table and the following paragraph or text table.

Split

If False, the table will not split across two pages.

PageDescName

If this string is set, a page break occurs before the paragraph, and the new page uses the given page style name (see PageDescName in Table 5).

PageNumberOffset

If a page break occurs, specify a new page number (see Page NumberOffset in Table 5).

RelativeWidth

Specify the width of the table relative to its environment as a Short Integer.

IsWidthRelative

If True, the relative width is valid.

RepeatHeadline

If True, the first row of the table is repeated on every new page.

ShadowFormat

Specify the type, color , and size of the shadow (see ParaShadowFormat in Table 5).

TopMargin

Specify the top table margin in 0.01 mm as a Long Integer.

BottomMargin

Specify the bottom table margin in 0.01 mm as a Long Integer.

BackTransparent

If True, the background color is transparent.

Width

Specify the absolute table width as a Long Integer -this is a read-only property.

ChartRowAsLabel

If True, the first row is treated as axis labels if a chart is created.

ChartColumnAsLabel

If True, the first column is treated as axis labels if a chart is created.

TableBorder

Specify the table borders in a com.sun.star.table.TableBorder structure. The structure contains numerous complicated properties:

  • The properties TopLine, BottomLine, LeftLine, RightLine, HorizontalLine, and VeriticalLine are all structures of type BorderLine as described by the LeftBorder property in Table 5.

  • The Distance property contains the distance between the lines and other contents.

  • You can turn each border property on or off by setting one of the following properties to True or False: IsTopLineValid, IsBottomLineValid, IsLeftLineValid, IsRightLineValid, IsHorizontalLineValid, IsVerticalLineValid, and IsDistanceValid.

TabIeColumnSeparators

Specify the width of each column with an array of table column separators. Each separator is a com.sun.star.text.TableColumnSeparator structure.

  • Position is a Short Integer that defines the position of a cell separator.

  • IsVisible determines if the separator is visible.

The width of a cell is defined by the position of the separator between adjacent cells. When two cells are merged, the separator is hidden, not removed.

The Position values are relative to the text table TabIeColumnRelativeSum property. This property is valid for a table only if every row has the same structure. If they do not, obtain the separators from the individual row objects.

TabIeColumnRelativeSum

Specify the sum of the column-width values used in TabIeColumnSeparators as a Short Integer.

BackColor

Specify the paragraph background color as a Long Integer.

BackGraphicURL

Specify the URL of the paragraph background graphic.

BackGraphicFilter

Specify the name of the graphic filter for the paragraph background graphic.

BackGraphicLocation

Specify the position of a background graphic (see ParaBackGraphicLocation in Table 5).

Simple and Complex Tables

Simply speaking, a text table is a set of rows and columns of text. All of the tables in this book are represented using simple text tables. OOo supports both simple and complex tables. As their name implies, in simple tables the table cells are laid out in a simple grid (see Table 20 ). Each column is labeled alphabetically starting with the letter A, and each row is labeled numerically starting with the number 1. The object method getCellByName() uses this name to return the specified cell. A similar object method, getCellByPosition(), returns the cell based on the column and row number. The column and row number are zero-based numbers, so requesting (1, 2) returns the cell named "B3".

Table 20: Rows are labeled numerically; columns are labeled alphabetically.

A1

B1

C1

A2

B2

C2

A3

B3

C3

OOo supports more than just simple text tables. A text table contains rows, rows contain one or more cells (columns), and cells contain either text content or rows. In other words, adjacent cells may be merged, and individual cells may be merged either horizontally or vertically. The naming convention for complex tables is more complicated than for simple tables (see Table 21 ). In Table 21, the cell named B2 was split horizontally. The new name is a concatenation of the former cell name (B2) and the number of the new column and row index inside the original table cell, separated by dots.

Table 21: When a row or column is split or merged, cell names become more complicated.

Al

B1

C1

D1

A2

B2.1.1

C2

D2

B2.1.2

A3

B3

C3

D3

E3

A4

B4

C4

         
Tip  

Not all object methods work with complex tables. For example, the object methods getData() and setData() cause an exception for complex tables.

Although the object method getCellByName() works as expected for complex tables, getCellByPosition() is not able to return all of the cells because it allows only a column and a row number. Use the getCellNames() object method to return the names of the cells in a table (see Listing 42 ); you can then use the cell names to individually obtain each cell in the table.

Listing 42: Join the array of strings to print the cell names in a table.
start example
 MsgBox Join(oTable.getCellNames(), "") 
end example
 

Tables Contain Cells

The cells in a text table are very versatile objects capable of holding all types of data. The cell objects implement both the XText interface (see Table 2 near the beginning of this chapter) as well as the XCell interface (see Table 22 ).

Table 22: Methods defined by the com.sun.star.table.XCell interface.

Method

Description

getFormula()

The original string typed into the cell, even if it is not a formula.

setFormula(String)

Set the cell's formula. Use setString() from the XText interface to set text.

getValue()

Floating-point (Double) value of the cell.

setValue(Double)

Set the floating-point value of the cell.

getType()

Return a com.sun.star.table.CellContentType enumeration with valid values of EMPTY, VALUE, TEXT, and FORMULA.

getError()

Long Integer error value. If the cell is not a formula, the error value is zero.

Note  

Tables are able to create a text table cursor with methods and properties specifically designed to traverse and select cells, and each individual cell is able to produce a text cursor that is local to the cell text object.

Each cell object posses numerous properties. These properties are generally familiar because they are used in other objects. For example, the BackColor, BackGraphicFilter, BackGraphicLocation, BackGraphicURL, BackTransparent, BorderDistance, BottomBorder, BottomBorderDistance, LeftBorder, LeftBorderDistance, RightBorder, RightBorderDistance, TopBorder, and TopBorderDistance properties are defined for text tables in Table 19 and/or paragraph properties in Table 5. One of the more useful properties that is available only in the cell object, however, is CellName. This is useful to determine the location of the current cursor. The macro in Listing 43 demonstrates a few new manipulations for tables.

  • The text tables, rows, columns, and cells all support the BackColor property. Listing 43 sets the background color of the first row to a light gray, which is commonly used to mark headings.

    Listing 43: SimpleTableManipulations is found in the Writer module in this chapter's source code files as SC13.sxw.

    start example
     Sub SimpleTableManipulations   Dim oTable       'Newly created table to insert   Dim oTables      'All of the text tables   Dim oInsertPoint 'Where the table will be inserted   Dim sTableName as String   sTableName = "SampleTable"   oTables = ThisComponent.TextTables   REM Remove the table if it exists!   If oTables.hasByName(sTableName) Then     ThisComponent.Text.removeTextContent(oTables.getByName(sTableName))   End If   REM Let the document create the text table.   oTable = ThisComponent.createInstance( "com.sun.star.text.TextTable" )   oTable.initialize(4, 3) 'Two rows, three columns   REM If there is a bookmark named "InsertTableHere", then insert   REM the table at that point. If this bookmark does not exist,   REM then simply choose the very end of the document.   If ThisComponent.getBookmarks().hasByName("InsertTableHere") Then     oInsertPoint =_       ThisComponent.getBookmarks().getByName("InsertTableHere").getAnchor()   Else     oInsertPoint = ThisComponent.Text.getEnd()   End If   oInsertPoint.getText().insertTextContent(oInsertPoint , oTable, False)   oTable.setDataArray(Array(Array("Name", "Score", "Test"),_     Array("Bob", 80, "CCW"), Array("Andy" , 80, "CCW"),_     Array("Jean" , 100, "CCI")))   oTable.setName(sTableName)   REM Set the first row to have a gray background.   oTable.getRows().getByIndex(0).BackColor = RGB(235, 235, 235)   REM removeByIndex uses the same arguments as insertByIndex, namely   REM the index at which to insert or remove followed by the number   REM of rows to insert or remove. The following line inserts   REM one row at index 4.   oTable.getRows().insertByIndex(4, 1)   REM Obtain the individual cells and set the values.   oTable.getCellByName("A5").setString("Whil")   oTable.getCellByName("B5").setValue(100)   oTable.getCellByName("C5").setString("Advanced") End Sub 
    end example
     
  • The insertByIndex(index, num) object method is used to insert new rows at the end of a table. Rows can also be inserted into the middle or at the start of a table.

  • Individual cells are retrieved by name; both numeric values and strings are set. Notice that strings are set using setString() rather than setFormula().

Tip  

Although the Web-based OOo documentation makes no distinction between cells contained in text tables and cells contained in spreadsheets, the two cell types do not support the same property set. For example, the CellStyle, CellBackColor, and RotateAngle properties are not supported.

Using a Table Cursor

Although text table cursors implement methods specific to traversing text tables, they are not significantly different from their text cursor counterparts in general functionality. You can select and manipulate ranges of cells, and set cell properties.

Tip  

You cannot obtain a text table from the document and then simply insert it again at another location.

Like text cursors, text table cursor movement methods accept a Boolean argument that indicates if the current selection should be expanded (True) or if the cursor should simply be moved (False). The movement methods also return a Boolean value indicating if the movement was successful. Table 23 contains the methods defined by the XTextTableCursor interface.

Table 23: Methods defined by the com.sun.star.text.XTextTableCursor interface.

Method

Description

getRangeName()

Return the cell range selected by this cursor as a string. For example, "B3:D5".

gotoCellByName(String, boolean)

Move the cursor to the cell with the specified name; return Boolean.

goLeft(n, boolean)

Move the cursor left n cells; return Boolean.

goRight(n, boolean)

Move the cursor right n cells; return Boolean.

goUp(n, boolean)

Move the cursor up n cells; return Boolean.

goDown(n, boolean)

Move the cursor down n cells; return Boolean.

gotoStart(boolean)

Move the cursor to the top left cell.

gotoEnd(boolean)

Move the cursor to the bottom right cell.

mergeRange()

Merge the selected range of cells; return True for success.

splitRange(n, boolean)

Create n (an integer) new cells in each cell selected by the cursor. For the Boolean, specify True to split horizontally, False for vertically. Returns True on success.

Text table cursors are used to split and merge table cells. In general, I consider this to be the primary use of a text table cursor. You can use text table cursors to move around the table by using the methods in Table 23. The macro in Listing 44 obtains the table cell names, creates a cell cursor that contains the first table cell, and then moves the cursor to the last cell in the table. A cell range is created based on the range name, and then the entire table is selected by the current controller.

Listing 44: Select an entire table using a cursor. This may fail for a complex table.
start example
 oCellNames = oTable.getCellNames() oCursor = oTable.createCursorByCellName(oCellNames(0)) oCursor.gotoCellByName(oCellNames(UBound(oCellNames())), True) oRange = oTable.getCellRangeByName(oCursor.getRangeName()) 'This may fail! Thiscomponent.getCurrentController.select(oRange) 
end example
 

Listing 44 demonstrates how to select all cells in a table by using a table cell cursor. You can then manipulate the entire table using the cursor. It may fail, however, in selecting the entire table in the current view. Table cell cursors have no problems with complex tables. The object methods supported by tables, however, do not all support complex tables. A notable example is the object method getCellRangeByName(), as used in Listing 44. This is very unfortunate because the view cursor is able to select text based on a cell range, but the table cannot return a cell range that has a split cell as one of the endpoints. For example, the cell range A1.2.1:C4 fails.

There is no easy method to duplicate an entire text table, either within a document or between documents (at least not as of OOo version 1.1.0). The general solution for such problems is to use the clipboard. First, use the view cursor or current controller to select the object that you want to copy. Then use a dispatcher to copy the object to the clipboard, move the view cursor where the object should be placed, and then use a dispatcher to paste the object from the clipboard.

As you may have guessed, the difficult part in this process is selecting the table with the view cursor. Although numerous people have tried and failed to solve this problem, a brilliant solution was provided by Paolo Mantovani, a contributor on the OOo mailing lists. Paolo starts by noting that selecting an entire table with the current controller places the view cursor at the start of the first cell (see Listing 45 ).

Listing 45: Place the cursor at the start of the first cell in the table.
start example
 ThisComponent.CurrentController.select(oTable) 
end example
 

Although Listing 45 does not entirely solve the problem, it does provide a good start, because the view cursor is in the table at a known position. Paolo then provides a very succinct method to select the entire table (see Listing 46 ).

Listing 46: Select the entire table in the current view.
start example
 ThisComponent.CurrentController.select(oTable) oVCursor.gotoEnd(True)  'Move to the end of the current cell oVCursor.gotoEnd(True)  'Move to the end of the table 
end example
 
Tip  

Remember to carefully test all code dealing with tables. A different solution proposed by Paolo-which failed-was to use goRight() and then goDown() based on the number of rows and columns.

The macro in Listing 47 selects a table by name, copies the table to the clipboard, and then pastes it at the end of the document.

Listing 47: CopyNamedTableToEnd is found in the Writer module in this chapter's source code files as SC 13.sxw.
start example
 Sub CopyNamedTableToEnd(sName As String)   Dim oTable        'Table to copy   Dim oText         'Document's text object   Dim oFrame        'Current frame to use with the dispatcher   Dim oVCursor      'Current view cursor   Dim oDispatcher   'Dispatcher for clipboard commands   oVCursor = ThisComponent.CurrentController.getViewCursor()   oText = ThisComponent.getText()   oFrame = ThisComponent.CurrentController.Frame   oDispatcher = createUnoService("com.sun.star.frame.DispatchHelper")   If NOT ThisComponent.getTextTables().hasByName(sName) Then     MsgBox "Sorry, the document does not contain table " & sName     Exit Sub   End If   oTable = ThisComponent.getTextTables().getByName(sName)   REM Place the cursor in the start of the first cell.   REM This is very easy!   ThisComponent.CurrentController.select(oTable)   oVCursor.gotoEnd(True)  'Move to the end of the current cell.   oVCursor.gotoEnd(True)  'Move to the end of the table.   REM Copy the table to the clipboard.   oDispatcher.executeDispatch(oFrame, ".uno:Copy", " , 0, Array())   REM Move the cursor to the end of the document and then paste the table.   oVCursor.gotoRange(oText.getEnd(), False)   oDispatcher.executeDispatch(oFrame, ".uno:Paste", "", 0, Array()) End Sub 
end example
 



OpenOffice.org Macros Explained
OpenOffice.org Macros Explained
ISBN: 1930919514
EAN: 2147483647
Year: 2004
Pages: 203

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net