Продолжаем разбираться с OpenOffice Document в Lazarus. Сегодня займемся формированием таблиц документа, научимся создавать и редактировать простые таблицы (без объединенных ячеек, столбцов и т.д.), изменять текст и стили текста внутри ячеек таблицы.
Вначале немного сведений о таблицах OpenOffice.
Структура таблиц OpenDocument подобна структуре таблиц [HTML4] или [XSL], и как и они таблицы могут вкладываться.
Представление таблиц основано на сетке строк и столбцов. Строки имеют больший приоритет чем столбцы. Таблица делится на строки, строки делятся на ячейки. Каждый столбец включает описание столбца, но это описание не содержит ячеек.
Строки таблиц могут быть пустыми, различные строки могут содержать различное количество ячеек. Это не является ошибкой, но различные приложения могут трактовать это различным образом. Неполные строки обычно обрабатываются, как имеющие достаточное количество пустых ячеек. Таким же образом обрабатываются пустые строки. Пустые ячейки обычно занимают пространство пустого абзаца.
Строки и столбцы фигурируют в группах строк и группах столбцов. Эти группы определяют, должны ли повторяться строки или столбцы на следующей странице.
В целом получается, что работа с таблицей в OpenOffice будет немногим сложнее, чем при верстке HTML-страниц. Теперь необходимо определиться со стилями таблицы, которые необходимо описать в content.xml.
1. Стили таблиц, столбцов и строк OpenOffice.
Стиль таблицы
Атрибут table:style-name ссылается на стиль таблицы, т.е. на элемент style:style типа таблица. Стиль таблицы описывает свойства форматирования таблицы, такие как ширина и цвет фона. Стиль таблицы может быть автоматическим или общим стилем.
Например описание стиля таблицы может выглядеть так:
Т.е. таблица имеет фиксированную ширину 12 см. и фоновый цвет — светло-серый. Наиболее часто приходится использовать не абсолютную, а относительную ширину таблицы, заданную в процентах.
Ширина таблицы может быть определена относительно ширины площади на
которой она размещается. В этом случае, ширина определяется в процентах, используя атрибут style:rel-width. В случае примера выше, таблица может быть размещена на всю ширину страницы следующим образом:
Также стиль таблицы может содержать атрибут table:align, определяющий горизонтальное выравнивание таблицы. Атрибут может принимать следующие фиксированные значения:
left — Выравнивание таблицы по левому краю.
center — Выравнивание таблицы по центру.
right — Выравнивание таблицы по правому краю.
margins — Таблица заполняет все пространство между левым и правым полем.
Свойство fo:margin определяет расстояние слева, справа, сверху и снизу в таблице.
Применительно к модулю Lazarus, который я рассматривал в предыдущем посте, функция добавления стиля таблицы в content.xml может выглядеть следующим образом:
function TOoWriter.SetTableStyle(TableStyle: TTableStyle): boolean;
var Node, Root: TDOMNode;
begin
try
Root:=FContent.DocumentElement.GetElementsByTagName('office:automatic-styles').Item[0];
Node:=FContent.CreateElement('style:style');
TDOMElement(Node).SetAttribute('style:name',TableStyle.Name);
TDOMElement(Node).SetAttribute('style:family','table');
Root:=Root.AppendChild(Node);
Node:=FContent.CreateElement('style:table-properties');
case TableStyle.SizeCounter of
tsPercent:TDOMElement(Node).SetAttribute('style:rel-width',CurrToStr(TableStyle.Width));
tsCM:TDOMElement(Node).SetAttribute('style:width',CurrToStr(TableStyle.Width));
end;
case TableStyle.Align of
ttpCenter:TDOMElement(Node).SetAttribute('table:align','center');
ttpLeft:TDOMElement(Node).SetAttribute('table:align','left');
ttpMargins:TDOMElement(Node).SetAttribute('table:align','margins');
ttpRight:TDOMElement(Node).SetAttribute('table:align','right');
end;
TDOMElement(Node).SetAttribute('fo:margin',IntToStr(TableStyle.Margin));
Root.AppendChild(Node);
result:=true;
except
Result:=false
end;
end;
где TTableStyle запись вида:
type
TTablePosition = (ttpCenter, ttpLeft, ttpRight, ttpMargins);
TSizeCounter = (tsPercent, tsCM);
type
TTableStyle = record
Name : string; //название стиля
SizeCounter: TSizeCounter; //размерность % или см.
Width : currency;//ширина таблицы
Align : TTablePosition; //положение таблицы на странице
Margin : integer; //отступы
end;
Стиль столбца
Стиль столбца таблицы хранит информацию о свойствах форматирования столбца, таких как ширина и цвет фона. Он определяется элементом style:style со значением семейства атрибутов table-column и может быть автоматическим или общим стилем.
Стиль столбца определяется с использованием атрибута table:style-name.
Свойства форматирования столбцов могут быть включены в элемент style:table-column-properties.
Каждый столбец таблицы должен иметь фиксированную ширину. Эта ширина
определяется атрибутом style:column-width.
Ширина столбца может также определяться относительно ширины других столбцов. Относительная ширина определяется свойством style:rel-column-width, которое принимает числовое значение, следующее за символом ‘*’. Если rc относительное значение
столбца, rs сумма относительных значений ширины всех столбцов, и ws абсолютная
ширина, доступная для всех этих столбцов, тогда абсолютное значение столбца wc рассчитывается как
wc=rc*ws/rs.
Если Вам необходимо, чтобы ширина столбца изменялась в зависимости от содержимого таблицы, Вы можете использовать атрибут style:use-optimal-column-width, который определяет должна ли ширина столбца
быть автоматически пересчитана, если изменилось содержимое столбца.
В Lazarus функция добавления стиля для столбца может выглядеть следующим образом:
function TOoWriter.SetTableColStyle(TableColRowStyle: TTableColRowStyle):boolean;
var Node, Root: TDOMNode;
begin
try
Root:=FContent.DocumentElement.GetElementsByTagName('office:automatic-styles').Item[0];
Node:=FContent.CreateElement('style:style');
TDOMElement(Node).SetAttribute('style:name',TableColRowStyle.Name);
TDOMElement(Node).SetAttribute('style:family','table-column');
Root:=Root.AppendChild(Node);
Node:=FContent.CreateElement('style:table-column-properties');
if TableColRowStyle.UseOptimalColWidth then
TDOMElement(Node).SetAttribute('style:use-optimal-column-width','true')
else
begin
case TableColRowStyle.SizeCounter of
tsPercent:TDOMElement(Node).SetAttribute('style:column-width',CurrToStr(TableColRowStyle.ColWidth));
tsCM:TDOMElement(Node).SetAttribute('style:rel-column-width',CurrToStr(TableColRowStyle.ColWidth));
end;
end;
Root.AppendChild(Node);
Result:=true;
except
Result:=false
end;
end;
где TTableColRowStyle запись вида:
type
TTableColRowStyle = record
Name: string;
SizeCounter: TSizeCounter; //размерность % или см
ColWidth : currency; //ширина столбца
RowHeight : currency;
UseOptimalColWidth: boolean; //использовать оптимальную ширину столбца
UseOptimalRowWidth: boolean; //использовать оптимальную высоту строки
end;
Стиль ячейки таблицы
Стиль ячейки таблицы хранит свойства форматирования ячейки, такие как:
Цвет фона
Формат числа
Вертикальное выравнивание
Обрамление
Стиль ячейки таблицы может быть автоматическим или общим стилем. Стиль
определяется атрибутом table:style-name. Если ячейка не имеет назначенного стиля ячейки, приложение проверяет, определен ли в текущей строке стиль ячейки по умолчанию. Если текущая строка не имеет стиля ячейки по умолчанию, приложение проверяет, определен ли стиль ячейки по умолчанию в текущем столбце.
Атрибут table:value-type определяет тип значения, размещенного в ячейке. Он может принимать одно из следующих значений:
float, percentage или currency (вещественные, процентный или денежный числовые типы)
date (дата)
time (время)
boolean (логический)
string (текстовый)
Свойство выравнивания по вертикали style:vertical-align используется для определения выравнивания по вертикали текста в ячейке таблицы.
Варианты выравнивания по вертикали:
top — Выравнивает текст по верхнему краю ячейки.
middle — Выравнивает текст по середине ячейки.
bottom — Выравнивает текст по нижнему краю ячейки.
automatic – Выравнивание текста определяется приложением.
Атрибуты обрамления fo:border, fo:border-top, fo:border-bottom, fo:border-left и fo:border-right определяют свойства обрамления ячейки таблицы. По умолчанию атрибут fo:border содержит следующее значение:
0.002cm solid #000000
где 0,002 — толщина линии обрамления
solid — стиль линии обрамления (сплошная)
#000000 — цвет линии обрамления (чёрный)
В Lazarus функция добавления стиля ячейки в content.xml может выглядеть так:
function TOoWriter.SetTableCellStyle(TableCellStyle: TTableCellStyle): boolean;
var Root, Node: TDOMNode;
begin
try
Root:=FContent.DocumentElement.GetElementsByTagName('office:automatic-styles').Item[0];
Node:=FContent.CreateElement('style:style');
TDOMElement(Node).SetAttribute('style:name',TableCellStyle.Name);
TDOMElement(Node).SetAttribute('style:family','table-cell');
Root:=Root.AppendChild(Node);
Node:=FContent.CreateElement('style:table-cell-properties');
if Length(TableCellStyle.border)=0 then
begin
TDOMElement(Node).SetAttribute('fo:border-left',TableCellStyle.border_left);
TDOMElement(Node).SetAttribute('fo:border-right',TableCellStyle.border_right);
TDOMElement(Node).SetAttribute('fo:border-top',TableCellStyle.border_top);
TDOMElement(Node).SetAttribute('fo:border-bottom',TableCellStyle.border_bottom);
end
else
TDOMElement(Node).SetAttribute('fo:border',TableCellStyle.border);
case TableCellStyle.VerticalAlign of
tvAutomatic:TDOMElement(Node).SetAttribute('style:vertical-align','automatic');
tvBottom:TDOMElement(Node).SetAttribute('style:vertical-align','bottom');
tvMiddle:TDOMElement(Node).SetAttribute('style:vertical-align','middle');
tvTop:TDOMElement(Node).SetAttribute('style:vertical-align','top');
end;
Root.AppendChild(Node);
Result:=true;
except
Result:=false;
end;
end;
где TTableCellStyle запись вида:
TVertAlign = (tvTop, tvMiddle, tvBottom, tvAutomatic);
type
TTableCellStyle = record
Name: string;
VerticalAlign : TVertAlign;
border: string;
border_top: string;
border_bottom: string;
border_left: string;
border_right: string;
end;
Теперь рассмотрим как формируются таблицы в документе OpenOffice Writer.
2. Формирование таблицы в OpenOffice Writer.
В общем случае таблица внутри документа может выглядеть следующим образом:
На рисунке представлена часть XML-документа, содержащая таблицу из двух столбцов и трёх строк.
Структура таблицы в content.xml получается следующей:
корневым элементом таблицы выступает элемент table:table, содержащий имя таблицы и название стиля для таблицы. Далее идут дочерние элементы:
table:table-column — определяет столбец для таблицы. Атрибут table:number-columns-repeated определяет количество последовательных столбцов, в которых повторяются ячейки. Он может быть использован для описания двух и более соседних ячеек в одном элементе ячейки, если выполняются следующие условия:
Ячейки имеют одинаковые содержимое и свойства.
Ячейки не объединены горизонтально или вертикально.
В этом случае для задания количества последовательных столбцов, в которых будут повторяться ячейки, должен использоваться атрибут table:number-columns-repeated.
table:table-row — определяет отдельную строку таблицы. В строках располагаются ячейки (элементы table:table-cell).
Содержимое каждой ячейки описывается также как и обычный текстовый абзац, т.е. элементом text:p
В целом, для формирования простой таблицы без объединенных строк и столбцов ничего особенно сложного нет. Поэтому можно приступать к программированию. Итак, задачи на сегодня будут следующими:
1. Вставить в документ таблицу с заранее определенными стилями столбца и ячейки.
2. Разработать методы добавления/удаления строк/столбцов таблицы.
3. Разработать методы изменения текстового содержимого ячейки
4. Разработать методы изменения стилей текста внутри ячеек.
Для решения поставленных задач воспользуемся модулем uOpenOffice.
2.1. Стили по умолчанию для таблицы.
Т.к. в большинстве случаев мне для работы требуется использовать таблицы с одинаковым оформлением (думаю, что и большинству из Вас тоже), то можно определить в модуле константы для стилей таблицы, столбца и ячейки и использовать их при формировании документов. У меня эти константы выглядят следующим образом:
const DefoultTablePosition = ttpMargins;
DefoultTableMargin = 1;
DefoultSizeCounter = tsPercent;
DefoultVertAlign = tvMiddle;
DefoultTableWidth = 100;
DefoultTableStyle = 'Defoult_Table';
DefoultColStyle = 'Defoult_Column';
DefoultCellStyle = 'Defoult_Cell';
DefoultCellBorder = '0.002cm solid #000000';
DefoultOptimalWidth = true;
DefoultTextStyle = 'Standard';
В результате применения этих констант новая таблица будет располагаться на всю ширину страницы и иметь стандартное обрамление границ ячеек.
Используя рассмотренные выше функции для добавления стилей в content.xml, можно написать процедуру для формирования дефолтных стилей:
procedure TOoWriter.SetDefoultTableStyles;
var Ts: TTableStyle;
Tw: TTableColRowStyle;
Tc: TTableCellStyle;
begin
Ts.Margin:=DefoultTableMargin;
ts.Align:=DefoultTablePosition;
ts.Width:=DefoultTableWidth;
Ts.SizeCounter:=DefoultSizeCounter;
Ts.Name:=DefoultTableStyle;
Tw.Name:=DefoultColStyle;
Tw.SizeCounter:=DefoultSizeCounter;
Tw.UseOptimalColWidth:=DefoultOptimalWidth;
Tc.Name:=DefoultCellStyle;
Tc.border:=DefoultCellBorder;
Tc.VerticalAlign:=DefoultVertAlign;
SetTableStyle(Ts);
SetTableColStyle(Tw);
SetTableCellStyle(Tc)
end;
2.2. Работа с таблицей.
Теперь определимся как будет происходить работа с самой таблицей. Можно, конечно организовать работу, используя только процедуры и функции работы с XML, но, думаю, что это будет несколько неудобно. Наиболее удобно было бы работать с таблицей OpenOffice также как и с обычным StringGrid’ом. Поэтому в модуле uOpenOffice определен отдельный класс TTable для работы с таблицей. А сама работа происходит следующим образом:
1. Добавляем новую пустую таблицу в документ, используя метод объекта TOoWriter:
function TOoWriter.InsertTable(Cols, Rows: integer;TableName:string):TTable;
var Root, Node: TDOMNode;
i,j:integer;
begin
if CheckDefoultTableStyles then
begin
Root:=FContent.DocumentElement.GetElementsByTagName('office:text').Item[0];
Node:=FContent.CreateElement('table:table');
TDOMElement(Node).SetAttribute('table:name',TableName);
TDOMElement(Node).SetAttribute('table:style-name',DefoultTableStyle);
Root:=Root.AppendChild(Node);
Node:=FContent.CreateElement('table:table-column');
TDOMElement(Node).SetAttribute('table:style-name',DefoultColStyle);
TDOMElement(Node).SetAttribute('table:number-columns-repeated',IntToStr(Cols));
Root:=Root.AppendChild(Node);//Root = table:table-column
//вставляем строки и ячейки
for i:=1 to Rows do
begin
Root:=Root.ParentNode;//Root = table:table
Node:=FContent.CreateElement('table:table-row');
Root:=Root.AppendChild(Node); //Root = table:table-row
for j:=1 to Cols do
begin
Node:=FContent.CreateElement('table:table-cell');
TDOMElement(Node).SetAttribute('table:style-name',DefoultCellStyle);
TDOMElement(Node).SetAttribute('office:value-type','string');
Root:=Root.AppendChild(Node);//Root = table:table-cell
Node:=FContent.CreateElement('text:p');
TDOMElement(Node).SetAttribute('text:style-name','Standard');
Root:=Root.AppendChild(Node).ParentNode.ParentNode;//Root = table:table-row
end;
end;
end
else
begin
SetDefoultTableStyles;
InsertTable(Cols, Rows,TableName);
end;
Result:=GetTable(TableName);
end;
Параметры функции Cols, Rows: integer — определяют количество столбцов и строк для новой таблицы
TableName:string — определяет имя новой таблицы.
В результате функция возвращает объект TTable.
2. Используем методы TTable для работы с таблицей
На текущий момент объект TTable выглядит следующим образом:
type
TTable = class
private
FName : string; //имя таблицы
FDocument : TXMLDocument; //документ в котором расположена таблица
FRootNode : TDOMNode; //корневой элемент таблицы (table:table)
FColCount : integer; //количество столбцов
FRowCount : integer; //количество строк
FDefTextStyle: string; //стиль по умолчанию для текста таблицы
function GetColCount: integer; //получение количества столбцов таблицы
function GetRowCount: integer; //получение количества строк таблицы
procedure SetColCount(AColCount:integer);//установка нового количества столбцов
procedure SetRowCount(ARowCount:integer);//установка нового количества строк
function GetCells(ACol, ARow: Integer): string; //получение содержимого ячейки
procedure SetCells(ACol, ARow: Integer; AValue: string);//запись данных в ячейку
function GetCellNode(ACol, ARow: Integer):TDOMNode;//поиск узла ячейки
function CheckFontName(AFontName: string):boolean; //проверка наличия шрифта в документе
procedure InsertNewFont(AFontName:string);//добавление нового шрифта
public
constructor Create(Document:TXMLDocument; TableName:string);
destructor Destroy;
procedure SetTextStyle(StyleName,FontName:string; FontSize:integer; FontStyles: TFontStyles; TextPosition: TTextPosition);
procedure ApplyTextStyle(ACol, ARow: Integer; AStyle: string);//применение стиля текста к выбраной ячейке
procedure AppendColumn(TextStyle:string);//вставка столбца в конец таблицы
procedure AppendRow(TextStyle:string);//вставка строки в конец таблицы
procedure RemoveRow;//удаление последней строки
procedure RemoveColumn;//удаление последнего столбца
property Name: string read FName;
property RootNode:TDOMNode read FRootNode;
property Cols : integer read GetColCount write SetColCount;
property Rows : integer read GetRowCount write SetRowCount;
property Cell[ACol, ARow: Integer]:string read GetCells write SetCells;
property DefTextStyle:string read FDefTextStyle write FDefTextStyle;
end;
Работа с таблицей происходит точно также, как и со StringGrid’ом за исключением двух методов:
procedure SetTextStyle(StyleName,FontName:string; FontSize:integer; FontStyles: TFontStyles; TextPosition: TTextPosition); procedure ApplyTextStyle(ACol, ARow: Integer; AStyle: string);
Первый метод добавляет в content.xml новый стиль для абзаца, второй — применяет стиль абзаца к ячейке. Чтобы каждый раз не использовать эти методы в работе с таблицей у TTable определено свойство
property DefTextStyle:string read FDefTextStyle write FDefTextStyle;
которое содержит имя стиля, используемого по умолчанию для ячейки таблицы.
Для примера сформируем таблицу, содержащую 3 столбца и 3 строки и посмотрим как используются некоторые свойства и методы TTable.
Пример работы с таблицами в OpenOffice
Открываем Lazarus, подключаем модуль uOpenOffice в uses и в обработчике любого события пишем следующий код:
procedure TMainForm.BitBtn3Click(Sender: TObject);
var Table: TTable;
begin
OoWriter:=TOoWriter.Create; //создали объект TOoWriter
{Добавляем пустую таблицу в документ}
Table:=OoWriter.InsertTable(3{Cols}, 3{Rows}, 'Tablica');
if Assigned(Table)then //таблица создана успешно
begin
{показываем сколько строк и столбцов имеет таблица}
ShowMessage('Cols = '+IntToStr(Table.Cols)+' Rows = '+IntToStr(Table.Rows));
{заполняем ячейки таблицы текстом}
Table.Cell[0,0]:='Столбец 0 строка 0';
Table.Cell[1,0]:='Столбец 1 строка 0';
Table.Cell[2,0]:='Столбец 2 строка 0';
Table.Cell[0,1]:='Столбец 0 строка 1';
Table.Cell[1,1]:='Столбец 1 строка 1';
Table.Cell[2,1]:='Столбец 2 строка 1';
{Добавляем новый стиль оформления абзаца}
Table.SetTextStyle('NewTableStyle','Times New Roman',14,[ftBold,ftItalic],tpCenter);
{применяем стиль к ячейке во втором солбце, второй строки}
Table.ApplyTextStyle(1,1,'NewTableStyle');
{добавляем новый столбец в конец таблицы}
Table.AppendColumn(DefoultTextStyle);
{добавляем новую строку в конец таблицы}
Table.AppendRow(DefoultTextStyle);
{удаляем одну строку}
Table.RemoveRow;
{удаляем два столбца}
Table.RemoveColumn;
Table.RemoveColumn;
{изменяем количество столбцов и строк, используя свойства класса TTable}
Table.Cols:=5;
Table.Rows:=6;
ShowMessage('Cols = '+IntToStr(Table.Cols)+' Rows = '+IntToStr(Table.Rows));
end;
{записываем документ на диск}
OoWriter.GenerateDocument(ExtractFilePath(Application.ExeName)+'document','MyDoc','');
end;
В этом примере я постарался показать как организуется работа с таблицей посредством класса TTable. Как видно из примера, для изменения количества строк и столбцов в таблице можно использовать как методы, так и свойства — всё зависит от ситуации. В результате выполнения этого примера у Вас должна получиться таблица следующего вида:
Резюмируем
На текущий момент, используя uOpenOffice можно сформировать простой текстовый документ OpenOffice Writer. При этом основные файлы, входящие в состав документа формируются автоматически. От разработчика требуется только определить необходимые нестандартные стили оформления документа.
Объект TOoWriter умеет:
1. Добавлять описание шрифтов документа
2. Добавлять новые стили оформления абзацев текста
3. Вставлять текст в конец документа
4. Заменять текст в строках
5. Добавлять простые таблицы в документ
Объект TTable умеет:
1. Добавлять/удалять строки/столбцы в таблице
2. Добавлять и использовать стили оформления текста в ячейках таблицы
В целом, для формирования простого документа без «наворотов» достаточно :). Скачать последнюю версию модуля uOpenOffice можно со страницы Исходников




скажите, а у вас есть материалы по работе с Lazarus в ексель, импорт експорт стринг грида?
Василий, к сожалению, таких материалов не сохранилось
Подскажите где взять документацию по работе с ODTProc.
разработка ведется на SourceForfge — http://sourceforge.net/p/odfproc/home/Home/ Видимо, там можно получить самую последнюю информацию о проекте