Text frames, text sections and page styles can be formatted to have columns. The width of columns is relative since the absolute width of the object is unknown in the model. The layout formatting is responsible for calculating the actual widths of the columns.

Columns are applied using the property TextColumns. It expects a com.sun.star.text.TextColumns service that has to be created by the document factory. The interface com.sun.star.text.XTextColumns refines the characteristics of the text columns before applying the created TextColumns service to the property TextColumns.

Consider the following example to see how to work with text columns:

/** This method demonstrates the XTextColumns interface and how to insert a blank paragraph
using the XRelativeTextContentInsert interface
*/
protected void TextColumnsExample() {
try {
// Go to the end of the doucment
mxDocCursor.gotoEnd(false);
// insert a new paragraph
mxDocText.insertControlCharacter(mxDocCursor, ControlCharacter.PARAGRAPH_BREAK, false);
// insert the string 'I am a fish.' 100 times
for (int i = 0 ; i < 100 ; ++i) {
mxDocText.insertString(mxDocCursor, "I am a fish.", false);
}
// insert a paragraph break after the text
mxDocText.insertControlCharacter(mxDocCursor, ControlCharacter.PARAGRAPH_BREAK, false);
// Get the XParagraphCursor interface of our text cursor
XParagraphCursor xParaCursor = (XParagraphCursor) UnoRuntime.queryInterface(
XParagraphCursor.class, mxDocCursor);
// Jump back before all the text we just inserted
xParaCursor.gotoPreviousParagraph(false);
xParaCursor.gotoPreviousParagraph(false);
// Insert a string at the beginning of the block of text
mxDocText.insertString(mxDocCursor, "Fish section begins:", false);
// Then select all of the text
xParaCursor.gotoNextParagraph(true);
xParaCursor.gotoNextParagraph(true);
// Create a new text section and get it's XNamed interface
XNamed xSectionNamed = (XNamed) UnoRuntime.queryInterface(
XNamed.class, mxDocFactory.createInstance("com.sun.star.text.TextSection"));
// Set the name of our new section (appropiately) to 'Fish'
xSectionNamed.setName("Fish");
// Create the TextColumns service and get it's XTextColumns interface
XTextColumns xColumns = (XTextColumns) UnoRuntime.queryInterface(
XTextColumns.class, mxDocFactory.createInstance("com.sun.star.text.TextColumns"));
// We want three columns
xColumns.setColumnCount((short) 3);
// Get the TextColumns, and make the middle one narrow with a larger margin
// on the left than the right
TextColumn[] aSequence = xColumns.getColumns ();
aSequence[1].Width /= 2;
aSequence[1].LeftMargin = 350;
aSequence[1].RightMargin = 200;
// Set the updated TextColumns back to the XTextColumns
xColumns.setColumns(aSequence);
// Get the property set interface of our 'Fish' section
XPropertySet xSectionProps = (XPropertySet) UnoRuntime.queryInterface(
XPropertySet.class, xSectionNamed);
// Set the columns to the Text Section
xSectionProps.setPropertyValue("TextColumns", xColumns);
// Get the XTextContent interface of our 'Fish' section
mxFishSection = (XTextContent) UnoRuntime.queryInterface(
XTextContent.class, xSectionNamed);
// Insert the 'Fish' section over the currently selected text
mxDocText.insertTextContent(mxDocCursor, mxFishSection, true);
// Get the wonderful XRelativeTextContentInsert interface
XRelativeTextContentInsert xRelative = (XRelativeTextContentInsert)
UnoRuntime.queryInterface(XRelativeTextContentInsert.class, mxDocText);
// Create a new empty paragraph and get it's XTextContent interface
XTextContent xNewPara = (XTextContent) UnoRuntime.queryInterface(XTextContent.class,
mxDocFactory.createInstance("com.sun.star.text.Paragraph"));
// Insert the empty paragraph after the fish Text Section
xRelative.insertTextContentAfter(xNewPara, mxFishSection);
} catch (Exception e) {
e.printStackTrace(System.out);
}
}

The text columns property consists of com.sun.star.text.TextColumn structs. The Width elements of all structs in the TextColumns sequence make up a sum, that is provided by the method getReferenceValue() of the XTextColumns interface. To determine the metric width of an actual column, the reference value and the columns width element have to be calculated using the metric width of the object (page, text frame, text section) and a rule of three, for example:

The column margins (LeftMargin, and RightMargin elements of the struct) are inside of the column. Their values do not influence the column width. They just limit the space available for the column content.

The default column setting in OpenOffice.org creates columns with equal margins at inner columns, and no left margin at the leftmost column and no right margin at the rightmost column. Therefore, the relative width of the first and last column is smaller than those of the inner columns. This causes a limitation of this property: Setting the text columns with equal column content widths and equal margins is only possible when the width of the object (text frame, text section) can be determined. Unfortunately this is impossible when the width of the object depends on its environment itself.