Difference between revisions of "FPSpreadsheet/ru"

From Free Pascal wiki
Jump to navigationJump to search
Line 105: Line 105:
  
 
Количество уже существующих рабочих листов можно запросить, вызвав <tt>GetWorksheetCount</tt>.
 
Количество уже существующих рабочих листов можно запросить, вызвав <tt>GetWorksheetCount</tt>.
 +
 +
==== Cell ====
 +
The worksheet, finally, gives access to the cells. A newly created worksheet, as in above example, is empty and does not contain any cells. Cells are added by assigning data or attributes to them by one of the <tt>WriteXXXX</tt> methods of the worksheet. As already mentioned, a cell is addressed by the index of the row and column to which it belongs. As usual, row and column indexes start at 0. Therefore, cell "A1" belongs to row 0 and column 0. It should be noted that row and column index are always specified in this order, this is ''different from the convention of ''<tt>TStringGrid</tt>. The following example creates a cell at address A1 and puts the number <tt>1.0</tt> in it.
 +
<syntaxhighlight>
 +
var
 +
  MyWorkbook: TsWorkbook;
 +
  MyWorksheet: TsWorksheet;
 +
begin
 +
  MyWorkbook := TsWorkbook.Create;
 +
  MyWorksheet := MyWorkbook.AddWorksheet('My_Table');
 +
  MyWorksheet.WriteNumber(0, 0, 1.0);  // "A1" has row=0 and col=0
 +
  ...
 +
</syntaxhighlight>
 +
 +
It is also possible to access cells directly by means of the methods <tt>FindCell(ARow, ACol)</tt> or <tt>GetCell(ARow, ACol)</tt> of the workbook. Both funtions exist also in an overloaded version to which the cell address can be passed in Excel notation: <tt>FindCell(ACellStr: String)</tt> or <tt>GetCell(ACellStr: String)</tt>. Please be aware that these functions return a <tt>pointer</tt> to the cell data (type <tt>PCell</tt>). Don't forget to dereference the pointers! The difference between <tt>FindCell</tt> and <tt>GetCell</tt> is that the former one returns <tt>nil</tt>, if a cell does not yet exist, while the latter one creates an empty cell in this case.
 +
 +
<syntaxhighlight>
 +
if MyWorksheet.FindCell('A1') = nil then
 +
  WriteLn('Cell A1 does not exist.');
 +
</syntaxhighlight> 
 +
 +
===== The basic TCell record =====
 +
This is the declaration of the cell's data type:
 +
<syntaxhighlight>
 +
type
 +
  TCell = record
 +
    { Location of the cell }
 +
    Worksheet: TsWorksheet;
 +
    Col: Cardinal; // zero-based
 +
    Row: Cardinal; // zero-based
 +
 +
    { Index of format record }
 +
    FormatIndex: Integer;
 +
 +
    { Status flags }
 +
    Flags: TsCellFlags;        // (cfHasComment, cfMerged, cfHyperlink, ...)
 +
 +
    { Cell content }
 +
    UTF8StringValue: String;  // strings cannot be part of a variant record
 +
    case ContentType: TCellContentType of  // must be at the end of the declaration
 +
      cctEmpty      : ();      // has no data at all
 +
      cctFormula    : ();      // UTF8StringValue is outside the variant record
 +
      cctNumber    : (Numbervalue: Double);
 +
      cctUTF8String : ();      // FormulaValue is outside the variant record
 +
      cctDateTime  : (DateTimevalue: TDateTime);
 +
      cctBool      : (BoolValue: boolean);
 +
      cctError      : (ErrorValue: TsErrorValue);
 +
  end;
 +
  PCell = ^TCell;
 +
</syntaxhighlight>
 +
 +
The field <tt>ContentType</tt> indicates which data type is stored in the cell:
 +
<syntaxhighlight>
 +
type
 +
  TCellContentType = (cctEmpty, cctFormula, cctNumber, cctUTF8String, cctDateTime, cctBool, cctError);
 +
</syntaxhighlight>
 +
 +
According to this field the corresponding data can be found in the fields
 +
* <tt>NumberValue</tt> (for <tt>ContentType=cctNumber</tt>), or
 +
* <tt>UTF8StringValue</tt> (for <tt>ContentType=cctUTF8String</tt>), or
 +
* <tt>DateTimeValue</tt> (for <tt>ContentType=cctDateTime</tt>), or
 +
* <tt>BoolValue</tt> (for <tt>ContentType=cctBool</tt>), i.e. <tt>TRUE</tt> or <tt>FALSE</tt>, or
 +
* <tt>ErrorValue</tt> (for <tt>ContentType=cctError</tt>).
 +
 +
Due to usage of a variant record most of these values are overlapping, i.e. modification of <tt>NumberValue</tt> affects also the other values. Therefore, always respect the <tt>ContentType</tt> when accessing the <tt>TCell</tt> record directly (the worksheet methods discussed below consider this automatically).
 +
 +
The field <tt>Flags</tt> tells whether additional data are associated with the cell which are not included in the cell record usually to save memory:
 +
<syntaxhighlight>
 +
type
 +
  TsCellFlag = (cfHasComment, cfHyperlink, cfMerged, cfHasFormula, cf3dFormula);
 +
  TsCellFlags = set of TsCellFlag;
 +
</syntaxhighlight>
 +
 +
* <tt>cfHasComment</tt>: A [[#comments|comment]] record can be found in the <tt>Comments</tt> of the worksheet.
 +
* <tt>cfHyperlink</tt>: The cell is contains a [[#hyperlink|hyperlink]] stored in the <tt>Hyperlinks</tt> of the worksheet.
 +
* <tt>cfMerged</tt>: The cell belongs to a [[#Merged_cells|merged block]] and extends across several cells.
 +
* <tt>cfHasFormula</tt>: The cell is associated with a [[#formulas|formula]] which is stored in the <tt>Formulas</tt> of the worksheet.
 +
* <tt>cf3dFormula</tt>: The formula associated with the cell contains elements referencing other sheets of the same workbook.
 +
 +
{{Note|After calculation of a formula or after reading of a file, the <tt>ContentType</tt> of the formula cell is converted to that of the result. Then the presence of a formula can only be detetected by calling the function <tt>HasFormula(cell)</tt> for the cell to be queried (<tt>cell: PCell</tt>) in unit ''fpsUtils''; this function checks the presence of the element <tt>cfHasFormula</tt> in the cell flags.}}
 +
 +
===== How to add and read data to/from a cell =====
 +
Adding values to a cell is most easily accompished by using one of the <tt>WriteXXXX</tt> methods of the worksheet. The most important ones are:
 +
 +
<syntaxhighlight>
 +
type
 +
  TsWorksheet = class
 +
    ...
 +
    { Writing of currency values }
 +
    function WriteCurrency(ARow, ACol: Cardinal; AValue: Double;
 +
      ANumFormat: TsNumberFormat = nfCurrency; ADecimals: Integer = 2;
 +
      ACurrencySymbol: String = '?'; APosCurrFormat: Integer = -1;
 +
      ANegCurrFormat: Integer = -1): PCell; overload;
 +
    procedure WriteCurrency(ACell: PCell; AValue: Double;
 +
      ANumFormat: TsNumberFormat = nfCurrency; ADecimals: Integer = -1;
 +
      ACurrencySymbol: String = '?'; APosCurrFormat: Integer = -1;
 +
      ANegCurrFormat: Integer = -1); overload;
 +
    function WriteCurrency(ARow, ACol: Cardinal; AValue: Double;
 +
      ANumFormat: TsNumberFormat; ANumFormatString: String): PCell; overload;
 +
    procedure WriteCurrency(ACell: PCell; AValue: Double;
 +
      ANumFormat: TsNumberFormat; ANumFormatString: String); overload;
 +
 +
    { Writing of date/time values }
 +
    function WriteDateTime(ARow, ACol: Cardinal; AValue: TDateTime): PCell; overload;
 +
    procedure WriteDateTime(ACell: PCell; AValue: TDateTime); overload;
 +
    function WriteDateTime(ARow, ACol: Cardinal; AValue: TDateTime;
 +
      ANumFormat: TsNumberFormat; ANumFormatStr: String = ''): PCell; overload;
 +
    procedure WriteDateTime(ACell: PCell; AValue: TDateTime;
 +
      ANumFormat: TsNumberFormat; ANumFormatStr: String = ''); overload;
 +
    function WriteDateTime(ARow, ACol: Cardinal; AValue: TDateTime;
 +
      ANumFormatStr: String): PCell; overload;
 +
    procedure WriteDateTime(ACell: PCell; AValue: TDateTime;
 +
      ANumFormatStr: String); overload;
 +
 +
    { Writing of number values }
 +
    function WriteNumber(ARow, ACol: Cardinal; ANumber: double): PCell; overload;
 +
    procedure WriteNumber(ACell: PCell; ANumber: Double); overload;
 +
    function WriteNumber(ARow, ACol: Cardinal; ANumber: double;
 +
      ANumFormat: TsNumberFormat; ADecimals: Byte = 2): PCell; overload;
 +
    procedure WriteNumber(ACell: PCell; ANumber: Double;
 +
      ANumFormat: TsNumberFormat; ADecimals: Byte = 2); overload;
 +
    function WriteNumber(ARow, ACol: Cardinal; ANumber: double;
 +
      ANumFormat: TsNumberFormat; ANumFormatString: String): PCell; overload;
 +
    procedure WriteNumber(ACell: PCell; ANumber: Double;
 +
      ANumFormat: TsNumberFormat; ANumFormatString: String); overload;
 +
 +
    { Writing of string values }
 +
    function WriteText(ARow, ACol: Cardinal; AText: ansistring;
 +
      ARichTextParams: TsRichTextParams = nil): PCell; overload;
 +
    procedure WriteText(ACell: PCell; AText: String;
 +
      ARichTextparams: TsRichTextParams = nil); overload;
 +
 +
    // the old string methods "WriteUTF8Text" are deprecated now
 +
    ...
 +
</syntaxhighlight>
 +
 +
Some of these methods exist in overloaded versions in which [[#cell_formatting|cell formatting parameters]] can be added together with the cell value. Correspondingly to writing, there is also a number of <tt>worksheet</tt> methods for reading the cell values:
 +
 +
<syntaxhighlight>
 +
type
 +
  TsWorksheet = class
 +
    ...
 +
    { Reading cell content as a string }
 +
    function  ReadAsText(ARow, ACol: Cardinal): string; overload;
 +
    function  ReadAsText(ACell: PCell): string; overload;
 +
    function  ReadAsText(ACell: PCell; AFormatSettings: TFormatSettings): string; overload;
 +
 +
    { Reading cell content as a number }
 +
    function  ReadAsNumber(ARow, ACol: Cardinal): Double; overload;
 +
    function  ReadAsNumber(ACell: PCell): Double; overload;
 +
    function  ReadNumericValue(ACell: PCell; out AValue: Double): Boolean;
 +
 +
    { Reading cell content as a date/time value }
 +
    function  ReadAsDateTime(ARow, ACol: Cardinal; out AResult: TDateTime): Boolean; overload;
 +
    function  ReadAsDateTime(ACell: PCell; out AResult: TDateTime): Boolean; overload;
 +
    ...
 +
</syntaxhighlight>
 +
 +
===== Index to Cell format =====
 +
<tt>FormatIndex</tt> is the index of the <span id="id_cellformatrecord">cell format record</span>. It describes the formatting attributes of a cell. These records are collected by an internal list of the workbook and are defined like this:
 +
<syntaxhighlight>
 +
type
 +
  TsCellFormat = record
 +
    FontIndex: Integer;
 +
    TextRotation: TsTextRotation;
 +
    HorAlignment: TsHorAlignment;
 +
    VertAlignment: TsVertAlignment;
 +
    Border: TsCellBorders;
 +
    BorderStyles: TsCellBorderStyles;
 +
    Background: TsFillPattern;
 +
    NumberFormatIndex: Integer;
 +
    NumberFormat: TsNumberFormat;
 +
    NumberFormatStr: String;
 +
    BiDiMode: TsBiDiMode;          // bdDefault, bdLTR {left-to-right}, bdRTL {right-to-left)
 +
    Protection: TsCellProtection;  // cpLockCell, cpHideFormulas
 +
    UsedFormattingFields: TsUsedFormattingFields;
 +
      //uffTextRotation, uffFont, uffBold, uffBorder, uffBackground, uffNumberFormat, uffWordWrap, uffHorAlign, uffVertAlign, uffBiDi
 +
  end;             
 +
</syntaxhighlight>
 +
 +
* <tt>FontIndex</tt>: text font by specifying the index in the workbook's font list
 +
* <tt>TextRotation</tt>: specifies whether the cell text is written horizontally or vertically
 +
* <tt>HorAlignment</tt>: left-aligned, horizontally centered, or right-aligned text
 +
* <tt>VertAlignment</tt>: top, bottom or vertically centered text
 +
* <tt>Border</tt>: a set of flags indicating that - if set - a border line is drawn at the left, top, right, or bottom cell edge. The lines are drawn according to the <tt>BorderStyles</tt> which define the linestyle and color of the border.
 +
* <tt>Background</tt>: a record defining the background fill of a cell (pattern style, pattern color, and background color - see chapter on [[#Cell_background|cell background]] below).
 +
* <tt>NumberFormat</tt> and <tt>NumberFormatStr</tt> specify how number or date/time values are formatted (e.g., number of decimal places, long or short date format, etc.).
 +
* Only those format attributes for which a flag is set in the <tt>UsedFormattingFields</tt> are considered when formatting a cell. If a flag is not included then the corresponding attribute is ignored and replaced by its default value.
 +
 +
For specifying a format for a given cell call the corresponding the worksheet method <tt>WriteXXXX</tt>, for retrieving a format call <tt>ReadXXXX</tt>. These methods usually get a pointer to the cell as a parameter, but there are also overloaded versions which accept the row and column index. Moreover, formatting styles can also be applied directly to the cell by using a record helper implemented in unit ''fpsCell''.
 +
 +
See [[#Cell_formatting|cell formatting]] below for a more detailed description.
 +
 +
==== Columns and rows ====
 +
Column and row records are added for each column and row having a non-default size:
 +
 +
<syntaxhighlight>
 +
type
 +
  TCol = record
 +
    Col: Cardinal;
 +
    Width: Single;
 +
    ColWidthType: TsColWidthType;    // = (cwtDefault, cwtCustom)
 +
    FormatIndex: Integer;
 +
  end;
 +
  PCol = ^TCol;
 +
 +
  TRow = record
 +
    Row: Cardinal;
 +
    Height: Single;
 +
    RowHeightType: TsRowHeightType;  // = (rhtDefault, rhtCustom, rhtAuto)
 +
    FormatIndex: Integer;
 +
  end;
 +
  PRow = ^TRow;
 +
</syntaxhighlight>
 +
 +
'''Column widths''' and '''row heights''' can be specified in a variety of units defined by the type <tt>TsSizeUnits = (suChars, suLines, suMillimeters, suCentimeters, suPoints, suInches)</tt>. <tt>suChars</tt> refers to the count of <tt>0</tt> characters fitting into the column width - this is the way how Excel defines column widths. <tt>suLines</tt> is the number of lines fitting into the row height. Both units are based on the character size of the workbook's default font. The other units are conventional physical length units (1 cm = 10 mm, 1 inch = 25.4 mm = 72 pt). Fractional values are accepted. The workbook and worksheets store lengths internally in millimeters (<tt>MyWorkbook.Units</tt>).
 +
 +
The Office applications usually adjust the row heights automatically according to the font or text rotation of the cell content. This case is identified by <code>RowHeightType</code> having the value <code>rhtAuto</code>. Since the worksheet cannot calculate text size very accurately automatic row heights are not written by FPSpreadsheet; they are replaced by the '''default row height'''. The default row height is also used if a row is empty, i.e. does not contain any data cells. Its value can be changed by calling the worksheet's <code>WriteDefaultRowHeight()</code> or by using the worksheet property <code>DefaultRowHeight</code>. In <code>WriteDefaultRowHeight</code>, the units must be specified while in <code>DefaultRowHeight</code> they are assumed to be lines. Similarly, the '''default column width''' can be specified by <code>WriteDefaultColWidth()</code> or the property <code>DefaultColWidth</code> (in characters).
 +
 +
In order to overrun automatic and default row heights call the worksheet method <tt>WriteRowHeight()</tt>. These row records are identified by <code>RowHeightType</code> having the value <code>rhtCustom</code>. In the same way the width of columns can be set to a specific value by calling <tt>WriteColWidth()</tt>. <code>ColWidthType</code> of these columns is <code>cwtCustom</code>.
 +
 +
The height/width of a particular row/column can be retrieved by means of the methods <tt>GetRowHeight</tt> or <tt>GetColHeight</tt>. Note that these methods return the default row heights/column widths if there are no <tt>TRow</tt>/<tt>TCol</tt> records.
 +
 +
<syntaxhighlight>
 +
type TsWorksheet = class
 +
  ...
 +
  { Set row height }
 +
  procedure WriteRowHeight(ARowIndex: Cardinal; AHeight: Single; AUnits: TsSizeUnits);
 +
  { Set column width }
 +
  procedure WriteColWidth(AColIndex: Cardinal; AWidth: Single; AUnits: TsSizeUnits);
 +
  { Set default row height }
 +
  procedure WriteDefaultRowHeight(AHeight: Single; AUnits: TsSizeUnits);
 +
  {Set default cokumn width }
 +
  procedure WriteDefaultColWidth(AWidth: Single; AUnits: TsSizeUnits);
 +
 +
  { Return row height }
 +
  function GetRowHeight(ARowIndex: Cardinal; AUnits: TsSizeUnits): Single;
 +
  { Return column width }
 +
  function GetColWidth(AColIndex: Cardinal; AUnits: TsSizeUnits): Single;
 +
  { Return default row height }
 +
  function ReadDefaultRowHeight(AUnits: TsSizeUnits): Single;
 +
  { Return default column width }
 +
  function ReadDefaultColWidth(AUnits: TsSizeUnits): Single;
 +
 +
  property DefaultRowHeight: Single;  // in lines
 +
  property DefaultColWidht: Single;  // in characters
 +
</syntaxhighlight>
 +
 +
There are also overloaded versions of these methods which do not require the <tt>AUnits</tt> parameter. In this case, row heights are defined in terms of line count, and column widths are defined in terms of character count. Note that these variants are from previos versions and are deprecated now.
 +
 +
The <code>FormatIndex</code> element of the row and column records format applied to the entire row or column. Like with cells, these formats are stored as <code>TsCellFormat</code> records in an internal workbook list. '''Row and column formats''' are primarily applied to empty cells, but if a new cell is added it will automatically get the format of the row or column. (If both row and column have different formats then the row format will be used).
  
 
=== Формулы ===
 
=== Формулы ===

Revision as of 00:53, 10 September 2018

Deutsch (de) English (en) español (es) français (fr) polski (pl) русский (ru)

THIS PAGE IS OUTDATED. PLEASE USE THE ENGLISH PAGE.

FpSpreadsheet библиотека предоставляет удобный способ создания и чтения табличных документов в различных форматах. Библиотека написана на очень гибкой основе, и поэтому её можно легко расширять поддержкой любого количества форматов.

Скриншот демонстрационной программы spready, предоставляемой с fpspreadsheet, показывающим файл XLS:


fpsgrid.png


Документация

Эта страница вики включает последнюю версию FPSpreadsheet, доступную через subversion. Пожалуйста, см. раздел Стабильные версии для [получения] документации по стабильной версии, которую вы можете скачать.

Документация по API

Ссылка на API

Файл справки в формате CHM можно найти в папке установки FPSpreadsheet docs . Если вы еще не установили пакет, тогда следуйте сюда хттпс://sourceforge.net/p/lazarus-ccr/svn/HEAD/tree/components/fpspreadsheet/docs/fpspreadsheet-api.chm для получения fpspreadsheet-api.chm.


Второй файл CHM, доступный в папке docs , fpspreadsheet-wiki.chm , представляет собой снимок связанных с FPSpreadsheet страниц вики, объединенных в один файл справки.

Основы

Наименьшими объектами в электронной таблице являются «ячейки», содержащие данные. Ячейки могут содержать различные типы данных, такие как строки, числа, даты, время, логические значения или формулы. Кроме того, ячейки могут содержать информацию о форматировании, то есть стиль шрифта, цвет фона, выравнивание текста и т.д.

Ячейки расположены в сетке, называемой «рабочей таблицей», или «электронной таблицей», состоящей из «строк» и «столбцов». Каждая ячейка имеет уникальный адрес, заданный индексом строки и столбца.

Рабочие листы связаны вместе, формируя «книгу», которая представляет собой документ электронной таблицы приложения. В книге также хранится информация, необходимая для всех листов, то есть список шрифтов, списки сотовых и числовых форматов и т.д.

FPSpreadsheet следует этой же структуре - существует TCell, TsWorksheet и TsWorkbook .

[Рабочая] книга

Класс TsWorkbook является основным классом, видимым для пользователя. Он предоставляет методы для чтения данных и записи в файлы. Универсальная структура библиотеки обеспечивает доступ к различным популярным форматам файлов, таким как Excel .xls или .xlsx, или OpenOffice/LibreOffice .ods.

Формат файла определяется типом TsSpreadsheetFormat, определенным в модуле fpstypes

type
  TsSpreadsheetFormat = (sfExcel2, sfExcel5, sfExcel8, sfExcelXML, sfOOXML, 
    sfOpenDocument, sfCSV, sfHTML, sfWikiTable_Pipes, sfWikiTable_WikiMedia, sfUser);

где

  • sfExcel2, sfExcel5, sfExcel8 означает версии бинарного формата xls, используемые Excel («BIFF» = «Формат файла двоичного обмена»), причем sfExcel8 является самым современным.
  • sfOOXML соответствует новому формату xlsx, представленному Excel2007
  • sfExcelXML - это xml-формат, который был представлен Microsoft для Office XP и 2003. Не очень популярен.
  • sfOpenDocument - формат электронных таблиц, используемый OpenOffice/LibreOffice; по умолчанию файлы имеют расширение .ods.
  • sfCSV</ tt> относится к текстовым файлам с разделителями-запятыми (расширение по умолчанию .csv); они могут быть поняты любым текстовым редактором и всеми программами электронных таблиц, но не содержат информации о форматировании.
  • sfHTML обозначает стандартный формат HTML, используемый в веб-браузерах.
  • sfWikiTable_Pipes и sfWikiTable_WikiMedia - это формат, используемый таблицами в вики-сайтах.
  • sfUser необходим для регистрации пользовательского формата. Планируется внедрение «древних» форматов файлов, таких как Excel3.0/4.0 или Lotus. Тем не менее, вы можете предоставить свои собственные классы чтения и письма для расширения функциональности FPSpreadsheet - см. ниже раздел Добавление новых форматов файлов

При применении fpspreadsheet первая задача - создать экземпляр рабочей книги:

var
  MyWorkbook: TsWorkbook;
begin
  MyWorkbook := TsWorkbook.Create;
  ...


Чтение файлов электронных таблиц выполняется (среди прочего) методами рабочей книги

  • procedure ReadFromFile (AFileName: string):
    Читает файл с заданным именем и автоматически определяет правильный формат файла.
  • procedure ReadFromFile (AFileName: string; AFormat: TsSpreadsheetFormat):
    Читает файл, но предполагает, что формат файла соответствует AFormat .

Для сохранения файла можно использовать следующие методы работы с книгой:

  • procedure WriteToFile (const AFileName: string; const AFormat: TsSpreadsheetFormat; const AOverwriteExisting: Boolean = False):
    Записывает книгу в данный файл с использованием заданного формата электронной таблицы. Если файл уже существует, он автоматически перезаписывается, если AOverwriteExisting - true :
  • procedure WriteToFile (const AFileName: String; const AOverwriteExisting: Boolean = False):
    dto., но формат файла определяется из предоставленного расширения файла (в случае Excel больше xls используется последняя версия, sfExcel8).

После вызова этих методов полезно посмотреть на свойство рабочей книги ErrorMsg, в котором собраны сообщения из-за ошибок или предупреждений, которые могли возникнуть во время чтения/записи. Это свойство возвращает многострочную строку, которая лучше всего отображается в компоненте memo; если все в порядке, это пустая строка.

Примечание. FPSpreadsheets предоставляет специализированные блоки для чтения и записи в каждый формат файла. Эти блоки недоступны автоматически, вы должны явно добавить их в предложение uses. FPSpreadsheet будет жаловаться на «неподдерживаемый формат файла», если запрошенный читатель/писатель не найден. Ниже приведен список названий устройств:

  • xlsbiff2, xlsbiff5 и xlsbiff8 для двоичных форматов файлов xls sfExcel2, sfExcel5 и sfExcel8 , соответственно,
  • xlsOOXML для формата xlsx sfOOXML для Excel 2007 и более поздних версий,
  • xlsXML для XML-формата Excel XP и 2003,
  • fpsopendocument для формата файла sfOpenDocument OpenOffice/LibreOffice,
  • fpsCSV для текстовых файлов с разделенными запятыми значениями (csv),
  • fpsHTML для файлов HTML,
  • wikitables для sfWikiTable_Pipes и sfWikiTable_WikiMedia,
  • или просто добавьте fpsallformats, чтобы получить поддержку чтения/записи для всех поддерживаемых форматов файлов.

Рабочий лист

В книге содержится список экземпляров TsWorksheet. Они соответствуют вкладкам, которые вы видите в Excel или Open/LibreOffice. При чтении файла электронной таблицы рабочие листы создаются автоматически в соответствии с содержимым файла. Когда электронная таблица создается вручную для хранения в файле, рабочий лист должен быть создан путем «добавления» в рабочую книгу:

var
  MyWorkbook: TsWorkbook;
  MyWorksheet: TsWorksheet;
begin
  MyWorkbook := TsWorkbook.Create;
  MyWorksheet := MyWorkbook.AddWorksheet('My_Table');  
    // 'My_Table' - это «имя» рабочего листа
  ...

Доступ к уже имеющимся рабочим листам можно получить с помощью методов TsWorkbook

  • function GetFirstWorksheet: TsWorksheet: извлекает первый рабочий лист книги.
  • Функция GetWorksheetByIndex (AIndex: Cardinal): TsWorksheet: возвращает рабочий лист с заданным индексом (начиная с 0).
  • function GetWorksheetByName (AName: String): TsWorksheet: возвращает рабочий лист с заданным именем, которое было использовано при добавлении рабочего листа.

Количество уже существующих рабочих листов можно запросить, вызвав GetWorksheetCount.

Cell

The worksheet, finally, gives access to the cells. A newly created worksheet, as in above example, is empty and does not contain any cells. Cells are added by assigning data or attributes to them by one of the WriteXXXX methods of the worksheet. As already mentioned, a cell is addressed by the index of the row and column to which it belongs. As usual, row and column indexes start at 0. Therefore, cell "A1" belongs to row 0 and column 0. It should be noted that row and column index are always specified in this order, this is different from the convention of TStringGrid. The following example creates a cell at address A1 and puts the number 1.0 in it.

var
  MyWorkbook: TsWorkbook;
  MyWorksheet: TsWorksheet;
begin
  MyWorkbook := TsWorkbook.Create;
  MyWorksheet := MyWorkbook.AddWorksheet('My_Table');
  MyWorksheet.WriteNumber(0, 0, 1.0);  // "A1" has row=0 and col=0
  ...

It is also possible to access cells directly by means of the methods FindCell(ARow, ACol) or GetCell(ARow, ACol) of the workbook. Both funtions exist also in an overloaded version to which the cell address can be passed in Excel notation: FindCell(ACellStr: String) or GetCell(ACellStr: String). Please be aware that these functions return a pointer to the cell data (type PCell). Don't forget to dereference the pointers! The difference between FindCell and GetCell is that the former one returns nil, if a cell does not yet exist, while the latter one creates an empty cell in this case.

if MyWorksheet.FindCell('A1') = nil then
  WriteLn('Cell A1 does not exist.');
The basic TCell record

This is the declaration of the cell's data type:

type
  TCell = record
    { Location of the cell }
    Worksheet: TsWorksheet;
    Col: Cardinal; // zero-based
    Row: Cardinal; // zero-based

    { Index of format record }
    FormatIndex: Integer;

    { Status flags }
    Flags: TsCellFlags;        // (cfHasComment, cfMerged, cfHyperlink, ...)

    { Cell content }
    UTF8StringValue: String;   // strings cannot be part of a variant record
    case ContentType: TCellContentType of  // must be at the end of the declaration
      cctEmpty      : ();      // has no data at all
      cctFormula    : ();      // UTF8StringValue is outside the variant record
      cctNumber     : (Numbervalue: Double);
      cctUTF8String : ();      // FormulaValue is outside the variant record
      cctDateTime   : (DateTimevalue: TDateTime);
      cctBool       : (BoolValue: boolean);
      cctError      : (ErrorValue: TsErrorValue);
  end;
  PCell = ^TCell;

The field ContentType indicates which data type is stored in the cell:

type
  TCellContentType = (cctEmpty, cctFormula, cctNumber, cctUTF8String, cctDateTime, cctBool, cctError);

According to this field the corresponding data can be found in the fields

  • NumberValue (for ContentType=cctNumber), or
  • UTF8StringValue (for ContentType=cctUTF8String), or
  • DateTimeValue (for ContentType=cctDateTime), or
  • BoolValue (for ContentType=cctBool), i.e. TRUE or FALSE, or
  • ErrorValue (for ContentType=cctError).

Due to usage of a variant record most of these values are overlapping, i.e. modification of NumberValue affects also the other values. Therefore, always respect the ContentType when accessing the TCell record directly (the worksheet methods discussed below consider this automatically).

The field Flags tells whether additional data are associated with the cell which are not included in the cell record usually to save memory:

type 
  TsCellFlag = (cfHasComment, cfHyperlink, cfMerged, cfHasFormula, cf3dFormula);
  TsCellFlags = set of TsCellFlag;
  • cfHasComment: A comment record can be found in the Comments of the worksheet.
  • cfHyperlink: The cell is contains a hyperlink stored in the Hyperlinks of the worksheet.
  • cfMerged: The cell belongs to a merged block and extends across several cells.
  • cfHasFormula: The cell is associated with a formula which is stored in the Formulas of the worksheet.
  • cf3dFormula: The formula associated with the cell contains elements referencing other sheets of the same workbook.
Light bulb  Примечание: After calculation of a formula or after reading of a file, the ContentType of the formula cell is converted to that of the result. Then the presence of a formula can only be detetected by calling the function HasFormula(cell) for the cell to be queried (cell: PCell) in unit fpsUtils; this function checks the presence of the element cfHasFormula in the cell flags.
How to add and read data to/from a cell

Adding values to a cell is most easily accompished by using one of the WriteXXXX methods of the worksheet. The most important ones are:

type
  TsWorksheet = class
    ...
    { Writing of currency values }
    function WriteCurrency(ARow, ACol: Cardinal; AValue: Double;
      ANumFormat: TsNumberFormat = nfCurrency; ADecimals: Integer = 2;
      ACurrencySymbol: String = '?'; APosCurrFormat: Integer = -1;
      ANegCurrFormat: Integer = -1): PCell; overload;
    procedure WriteCurrency(ACell: PCell; AValue: Double;
      ANumFormat: TsNumberFormat = nfCurrency; ADecimals: Integer = -1;
      ACurrencySymbol: String = '?'; APosCurrFormat: Integer = -1;
      ANegCurrFormat: Integer = -1); overload;
    function WriteCurrency(ARow, ACol: Cardinal; AValue: Double;
      ANumFormat: TsNumberFormat; ANumFormatString: String): PCell; overload;
    procedure WriteCurrency(ACell: PCell; AValue: Double;
      ANumFormat: TsNumberFormat; ANumFormatString: String); overload;

    { Writing of date/time values }
    function WriteDateTime(ARow, ACol: Cardinal; AValue: TDateTime): PCell; overload;
    procedure WriteDateTime(ACell: PCell; AValue: TDateTime); overload;
    function WriteDateTime(ARow, ACol: Cardinal; AValue: TDateTime;
      ANumFormat: TsNumberFormat; ANumFormatStr: String = ''): PCell; overload;
    procedure WriteDateTime(ACell: PCell; AValue: TDateTime;
      ANumFormat: TsNumberFormat; ANumFormatStr: String = ''); overload;
    function WriteDateTime(ARow, ACol: Cardinal; AValue: TDateTime;
      ANumFormatStr: String): PCell; overload;
    procedure WriteDateTime(ACell: PCell; AValue: TDateTime;
      ANumFormatStr: String); overload;

    { Writing of number values } 
    function WriteNumber(ARow, ACol: Cardinal; ANumber: double): PCell; overload;
    procedure WriteNumber(ACell: PCell; ANumber: Double); overload;
    function WriteNumber(ARow, ACol: Cardinal; ANumber: double;
      ANumFormat: TsNumberFormat; ADecimals: Byte = 2): PCell; overload;
    procedure WriteNumber(ACell: PCell; ANumber: Double;
      ANumFormat: TsNumberFormat; ADecimals: Byte = 2); overload;
    function WriteNumber(ARow, ACol: Cardinal; ANumber: double;
      ANumFormat: TsNumberFormat; ANumFormatString: String): PCell; overload;
    procedure WriteNumber(ACell: PCell; ANumber: Double;
      ANumFormat: TsNumberFormat; ANumFormatString: String); overload;

    { Writing of string values }
    function WriteText(ARow, ACol: Cardinal; AText: ansistring;
      ARichTextParams: TsRichTextParams = nil): PCell; overload;
    procedure WriteText(ACell: PCell; AText: String;
      ARichTextparams: TsRichTextParams = nil); overload;

    // the old string methods "WriteUTF8Text" are deprecated now
    ...

Some of these methods exist in overloaded versions in which cell formatting parameters can be added together with the cell value. Correspondingly to writing, there is also a number of worksheet methods for reading the cell values:

type
  TsWorksheet = class
    ...
    { Reading cell content as a string }
    function  ReadAsText(ARow, ACol: Cardinal): string; overload;
    function  ReadAsText(ACell: PCell): string; overload;
    function  ReadAsText(ACell: PCell; AFormatSettings: TFormatSettings): string; overload;

    { Reading cell content as a number }
    function  ReadAsNumber(ARow, ACol: Cardinal): Double; overload;
    function  ReadAsNumber(ACell: PCell): Double; overload;
    function  ReadNumericValue(ACell: PCell; out AValue: Double): Boolean;

    { Reading cell content as a date/time value }
    function  ReadAsDateTime(ARow, ACol: Cardinal; out AResult: TDateTime): Boolean; overload;
    function  ReadAsDateTime(ACell: PCell; out AResult: TDateTime): Boolean; overload;
    ...
Index to Cell format

FormatIndex is the index of the cell format record. It describes the formatting attributes of a cell. These records are collected by an internal list of the workbook and are defined like this:

type
  TsCellFormat = record
    FontIndex: Integer;
    TextRotation: TsTextRotation;
    HorAlignment: TsHorAlignment;
    VertAlignment: TsVertAlignment;
    Border: TsCellBorders;
    BorderStyles: TsCellBorderStyles;
    Background: TsFillPattern;
    NumberFormatIndex: Integer;
    NumberFormat: TsNumberFormat;
    NumberFormatStr: String;
    BiDiMode: TsBiDiMode;           // bdDefault, bdLTR {left-to-right}, bdRTL {right-to-left)
    Protection: TsCellProtection;   // cpLockCell, cpHideFormulas
    UsedFormattingFields: TsUsedFormattingFields;
      //uffTextRotation, uffFont, uffBold, uffBorder, uffBackground, uffNumberFormat, uffWordWrap, uffHorAlign, uffVertAlign, uffBiDi
  end;
  • FontIndex: text font by specifying the index in the workbook's font list
  • TextRotation: specifies whether the cell text is written horizontally or vertically
  • HorAlignment: left-aligned, horizontally centered, or right-aligned text
  • VertAlignment: top, bottom or vertically centered text
  • Border: a set of flags indicating that - if set - a border line is drawn at the left, top, right, or bottom cell edge. The lines are drawn according to the BorderStyles which define the linestyle and color of the border.
  • Background: a record defining the background fill of a cell (pattern style, pattern color, and background color - see chapter on cell background below).
  • NumberFormat and NumberFormatStr specify how number or date/time values are formatted (e.g., number of decimal places, long or short date format, etc.).
  • Only those format attributes for which a flag is set in the UsedFormattingFields are considered when formatting a cell. If a flag is not included then the corresponding attribute is ignored and replaced by its default value.

For specifying a format for a given cell call the corresponding the worksheet method WriteXXXX, for retrieving a format call ReadXXXX. These methods usually get a pointer to the cell as a parameter, but there are also overloaded versions which accept the row and column index. Moreover, formatting styles can also be applied directly to the cell by using a record helper implemented in unit fpsCell.

See cell formatting below for a more detailed description.

Columns and rows

Column and row records are added for each column and row having a non-default size:

type
  TCol = record
    Col: Cardinal;
    Width: Single;
    ColWidthType: TsColWidthType;     // = (cwtDefault, cwtCustom)
    FormatIndex: Integer;
  end;
  PCol = ^TCol;

  TRow = record
    Row: Cardinal;
    Height: Single;
    RowHeightType: TsRowHeightType;   // = (rhtDefault, rhtCustom, rhtAuto)
    FormatIndex: Integer;
  end;
  PRow = ^TRow;

Column widths and row heights can be specified in a variety of units defined by the type TsSizeUnits = (suChars, suLines, suMillimeters, suCentimeters, suPoints, suInches). suChars refers to the count of 0 characters fitting into the column width - this is the way how Excel defines column widths. suLines is the number of lines fitting into the row height. Both units are based on the character size of the workbook's default font. The other units are conventional physical length units (1 cm = 10 mm, 1 inch = 25.4 mm = 72 pt). Fractional values are accepted. The workbook and worksheets store lengths internally in millimeters (MyWorkbook.Units).

The Office applications usually adjust the row heights automatically according to the font or text rotation of the cell content. This case is identified by RowHeightType having the value rhtAuto. Since the worksheet cannot calculate text size very accurately automatic row heights are not written by FPSpreadsheet; they are replaced by the default row height. The default row height is also used if a row is empty, i.e. does not contain any data cells. Its value can be changed by calling the worksheet's WriteDefaultRowHeight() or by using the worksheet property DefaultRowHeight. In WriteDefaultRowHeight, the units must be specified while in DefaultRowHeight they are assumed to be lines. Similarly, the default column width can be specified by WriteDefaultColWidth() or the property DefaultColWidth (in characters).

In order to overrun automatic and default row heights call the worksheet method WriteRowHeight(). These row records are identified by RowHeightType having the value rhtCustom. In the same way the width of columns can be set to a specific value by calling WriteColWidth(). ColWidthType of these columns is cwtCustom.

The height/width of a particular row/column can be retrieved by means of the methods GetRowHeight or GetColHeight. Note that these methods return the default row heights/column widths if there are no TRow/TCol records.

type TsWorksheet = class
  ...
  { Set row height }
  procedure WriteRowHeight(ARowIndex: Cardinal; AHeight: Single; AUnits: TsSizeUnits);
  { Set column width }
  procedure WriteColWidth(AColIndex: Cardinal; AWidth: Single; AUnits: TsSizeUnits);
  { Set default row height }
  procedure WriteDefaultRowHeight(AHeight: Single; AUnits: TsSizeUnits);
  {Set default cokumn width }
  procedure WriteDefaultColWidth(AWidth: Single; AUnits: TsSizeUnits);

  { Return row height }
  function GetRowHeight(ARowIndex: Cardinal; AUnits: TsSizeUnits): Single;
  { Return column width }
  function GetColWidth(AColIndex: Cardinal; AUnits: TsSizeUnits): Single;
  { Return default row height }
  function ReadDefaultRowHeight(AUnits: TsSizeUnits): Single;
  { Return default column width }
  function ReadDefaultColWidth(AUnits: TsSizeUnits): Single;

  property DefaultRowHeight: Single;  // in lines
  property DefaultColWidht: Single;   // in characters

There are also overloaded versions of these methods which do not require the AUnits parameter. In this case, row heights are defined in terms of line count, and column widths are defined in terms of character count. Note that these variants are from previos versions and are deprecated now.

The FormatIndex element of the row and column records format applied to the entire row or column. Like with cells, these formats are stored as TsCellFormat records in an internal workbook list. Row and column formats are primarily applied to empty cells, but if a new cell is added it will automatically get the format of the row or column. (If both row and column have different formats then the row format will be used).

Формулы

В FPSpreadsheet поддерживаются два вида формул: строковый и RPN. Строковый вид записываются также как и в офисных приложениях, например, "ROUND (A1 + B1)", а RPN формулы записываются в обратной польской нотации (Reverse Polish Notation (RPN)), например: A1, B1, Add, 0, ROUND

RPN формулы

Пример использования встроенной процедуры

  // Write the formula E1 = ABS(A1)
  SetLength(MyRPNFormula, 2);
  MyRPNFormula[0].ElementKind := fekCell;
  MyRPNFormula[0].Col := 0;
  MyRPNFormula[0].Row := 0;
  MyRPNFormula[1].ElementKind := fekABS;
  MyWorksheet.WriteRPNFormula(0, 4, MyRPNFormula);

  // Write the formula F1 = ROUND(A1, 0)
  SetLength(MyRPNFormula, 3);
  MyRPNFormula[0].ElementKind := fekCell;
  MyRPNFormula[0].Col := 0;
  MyRPNFormula[0].Row := 0;
  MyRPNFormula[1].ElementKind := fekNum;
  MyRPNFormula[1].DoubleValue := 0.0;
  MyRPNFormula[2].ElementKind := fekROUND;
  MyWorksheet.WriteRPNFormula(0, 5, MyRPNFormula);

Встроенные процедуры

ABS - Возвращает абсолютное значение заданного числа. Принимает 1 аргумент. Пример: ABS (-1) = 1

ROUND - Округляет число до заданного числа десятичных знаков. Принимает 2 аргумента, сначало округляемое число, а затем количество десятичных знаков. Второй аргумент по умолчанию равен нулю и может быть отрицательным.

Примеры

Чтобы создать проект, который использует библиотеку fpspreadsheet, необходимо добавить пакет fpspreadsheet_pkg в ваш Lazarus проект или добавить корневой каталог fpspreadsheet в опциях вашего компилятора, если используется другая IDE.

Пример Excel 5

{
excel5demo.dpr

Demonstrates how to write an Excel 5.x file using the fpspreadsheet library

You can change the output format by changing the OUTPUT_FORMAT constant

AUTHORS: Felipe Monteiro de Carvalho
}
program excel5demo;

{$mode delphi}{$H+}

uses
  Classes, SysUtils, fpspreadsheet, fpsallformats, fpspreadsheet_pkg;

const OUTPUT_FORMAT = sfExcel5;

var
  MyWorkbook: TsWorkbook;
  MyWorksheet: TsWorksheet;
  MyFormula: TsRPNFormula;
  MyDir: string;
begin
  // Initialization
  MyDir := ExtractFilePath(ParamStr(0));

  // Create the spreadsheet
  MyWorkbook := TsWorkbook.Create;
  MyWorksheet := MyWorkbook.AddWorksheet('My Worksheet');

  // Write some number cells
  MyWorksheet.WriteNumber(0, 0, 1.0);
  MyWorksheet.WriteNumber(0, 1, 2.0);
  MyWorksheet.WriteNumber(0, 2, 3.0);
  MyWorksheet.WriteNumber(0, 3, 4.0);

  // Write the formula E1 = A1 + B1
  // or, in RPN: A1, B1, +
  SetLength(MyFormula, 3);
  MyFormula[0].ElementKind:=fekCell; {A1}
  MyFormula[0].Col := 0;
  MyFormula[0].Row := 0;
  MyFormula[1].ElementKind:=fekCell; {B1}
  MyFormula[1].Col := 1;
  MyFormula[1].Row := 0;
  MyFormula[2].ElementKind:=fekAdd;;  {+}
  MyWorksheet.WriteRPNFormula(0, 4, MyFormula);

  // Creates a new worksheet
  MyWorksheet := MyWorkbook.AddWorksheet('My Worksheet 2');

  // Write some string cells
  MyWorksheet.WriteUTF8Text(0, 0, 'First');
  MyWorksheet.WriteUTF8Text(0, 1, 'Second');
  MyWorksheet.WriteUTF8Text(0, 2, 'Third');
  MyWorksheet.WriteUTF8Text(0, 3, 'Fourth');

  // Save the spreadsheet to a file
  MyWorkbook.WriteToFile(MyDir + 'test' + STR_EXCEL_EXTENSION, OUTPUT_FORMAT);
  MyWorkbook.Free;
end.


Перебор всех Листов (Worksheets)

var
  MyWorkbook: TsWorkbook;
  MyWorksheet: TsWorksheet;
  i: Integer;
begin
  // Here load MyWorkbook from a file or build it
 
  for i := 0 to MyWorkbook.GetWorksheetCount() - 1 do
  begin
    MyWorksheet := MyWorkbook.GetWorksheetByIndex(i);
    // Do something with MyWorksheet
  end;

Преобразование базы данных в электронную таблицу

Обратите внимание, что это только мета-код, не тестировал.

program db5xls;
 
{$mode delphi}{$H+}
 
uses
  Classes, SysUtils, 
  // add database units
  fpspreadsheet, fpsallformats, fpspreadsheet_pkg;
 
const OUTPUT_FORMAT = sfExcel5;
 
var
  MyWorkbook: TsWorkbook;
  MyWorksheet: TsWorksheet;
  MyDatabase: TSdfDataset;
  MyDir: string;
  i, j: Integer;
begin
  // Initialization
  MyDir := ExtractFilePath(ParamStr(0));
 
  // Open the database
  MyDatabase := TSdfDataset.Create;
  MyDatabase.Filename := 'test.dat';
  // Add table description here
  MyDatabase.Active := True;

  // Create the spreadsheet
  MyWorkbook := TsWorkbook.Create;
  MyWorksheet := MyWorkbook.AddWorksheet('My Worksheet');
 
  // Write the field names
  for i := 0 to MyDatabase.Fields.Count - 1 do
    MyWorksheet.WriteUTF8Text(0, i, MyDatabase.Field[i].FieldName);

  // Write all cells to the worksheet
  MyDatabase.First;
  j := 0;
  while not MyDatabase.EOF do
  begin
    for i := 0 to MyDatabase.Fields.Count - 1 do
      MyWorksheet.WriteUTF8Text(j + 1, i, MyDatabase.Field[i].AsString);

    MyDatabase.Next;
    Inc(j);
  end;

  // Close the database
  MyDatabase.Active := False;
  MyDatabase.Free;

  // Save the spreadsheet to a file
  MyWorkbook.WriteToFile(MyDir + 'test' + STR_EXCEL_EXTENSION, OUTPUT_FORMAT);
  MyWorkbook.Free;
end.

Скачать

Subversion

FPSpreadsheet Вы можете скачать с SourceForge, также можно воспользоваться программным обеспечение subversion, или следующей командой:

svn co https://lazarus-ccr.svn.sourceforge.net/svnroot/lazarus-ccr/components/fpspreadsheet fpspreadsheet

Текущий состояние

Текущее состояние поддерживаемых форматов:

Формат Поддержка нескольких листов Поддержка Unicode Чтение Запись Текст Число Строковая формула RPN формула
Excel 2.x Нет Нет** Работает Работает Работает Работает Не реализовано Работает
Excel 3.0 Нет Нет** Не реализовано Не реализовано Не реализовано Не реализовано Не реализовано Не реализовано
Excel 4.0 Нет Нет** Не реализовано Не реализовано Не реализовано Не реализовано Не реализовано Не реализовано
Excel 5.0 (Excel 5.0 and 95) Да Нет** Работает* Работает Работает Работает Не реализовано Работает
Excel 8.0 (Excel 97, 2000, XP and 2003) Да Да Работает* Работает Работает Работает Не реализовано Не реализовано
Microsoft OOXML Да Да Не реализовано Не реализовано Не реализовано Не реализовано Не реализовано Не реализовано
OpenDocument Да Да Работает Работает Работает Работает Не реализовано Не реализовано

(*) Некоторые ячейки могут быть возвращены пустыми из-за отсутствия реализации некоторых числовых и строковых форматов. (**) В форматах, не поддерживающих Unicode, данные сохраняются в виде ISO 8859-1. Обратите внимание, что при чтении/записи FPSpreadsheet предлагает использовать UTF-8, но эти данные будут преобразованы в ISO при чтении или записи на диск. Будьте осторожны - символы, которые не укладываются в ISO Latin 1, будут потеряны в этих операциях.

Журнал изменений

Январь 2009

  • Реализована это кросс-платформенная поддержка для OLE файлов. Теперь файлы Excel 5.0 могут быть созданы в любой операционной системе.
  • Добавлена поддержка чтения файлов Excel 2.1

Февраль 2008

  • Initial commit to lazarus-ccr with write support for Excel 2.1, Excel 5.0 (Windows only) and experimental OOXML and OpenDocument

Лицензия

LGPL with static linking exception. This is the same license as is used in the Lazarus Component Library.

См. также

Поддержка и багрепорты

Рекомендованное место для обсуждения FPSpreadsheet и получения ответов на ваши вопросы это ветка форума Lazarus Forum.

Багрепорты должны быть отправленны в Lazarus/Free Pascal Bug Tracker; пожалуйста уточните что это "Lazarus-CCR" проект.

Внешние ссылки

--4yma 01:53, 13 April 2010 (CEST)