Sign in Join
Wiki copytemporary

FPSpreadsheet/pl: what changed

Revision 2 to 3. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11> **Warning:** **Ta strona została przetłumaczona w dniu 2021-01-27 i może nie być aktualna. Dlatego skorzystaj także z witryny angielskiej**
22
33Biblioteka fpSpreadsheet oferuje wygodny sposób generowania i czytania arkuszy kalkulacyjnych w różnych formatach. Biblioteka jest napisana w bardzo elastyczny sposób, z możliwością łatwego rozszerzenia do obsługi dowolnej liczby formatów.
44
55Zrzut ekranu spready demo programu dostarczonego z fpspreadsheet przedstawiający plik XLS:
66
77> **Note:** **Możesz także pobrać program spready demo za pomocą komendy: svn checkout <http://svn.code.sf.net/p/lazarus-ccr/svn/applications/spready>**
88
99![](/wiki-images/b/b7/Fpsgrid.png)
1010
1111## Dokumentacja
1212
1313Ta strona wiki zawiera najnowszą wersję development/trunk FPSpreadsheet dostępną za pośrednictwem subversion. Zobacz sekcję Wersje stabilne aby zapoznać się z dokumentacją dotyczącą stabilnej wersji, którą możesz także pobrać.
1414
1515## API Documentation
1616
1717### Dokumentacja API
1818
1919Plik pomocy w formacie CHM można znaleźć w folderze *docs* pakietu instalacyjnego FPSpreadsheet. Jeśli jeszcze nie zainstalowałeś pakietu, wykonaj następujące czynności: [<http://svn.code.sf.net/p/lazarus-ccr/svn/components/fpspreadsheet/docs/fpspreadsheet-api.chm>](http://svn.code.sf.net/p/lazarus-ccr/svn/components/fpspreadsheet/docs/fpspreadsheet-api.chm) aby pobrać *fpspreadsheet-api.chm*.
2020
2121Drugi plik CHM dostępny w folderze *docs*, *fpspreadsheet-wiki.chm*, to migawka stron wiki związanych z FPSpreadsheet, spakowana w pojedynczy plik pomocy.
2222
2323### Podstawy
2424
2525Najmniejsze elementy w arkuszu kalkulacyjnym to **cells** (komórki) zawierające dane. Komórki mogą zawierać różne typy danych, takie jak ciągi, liczby, daty, godziny, wartości logiczne lub formuły. Ponadto komórki mogą zawierać informacje o formatowaniu, tj. Styl czcionki, kolor tła, wyrównanie tekstu itp.
2626
2727Komórki są ułożone w strukturę przypominającą siatkę, zwaną **worksheet** (arkuszem roboczym) lub **spreadsheet** (arkuszem kalkulacyjnym), składającą się z **rows** (wierszy) i **columns** (kolumn). Każda komórka ma unikalny adres podany w indeksie wiersza i kolumny.
2828
2929Arkusze są połączone w **workbook** (skoroszyt), który reprezentuje dokument aplikacji arkusza kalkulacyjnego. Skoroszyt przechowuje również informacje, które są potrzebne dla wszystkich arkuszy roboczych, tj. lista czcionek, listy formatu komórek i liczb itp.
3030
3131FPSpreadsheet ma tę samą strukturę - zawiera `TCell`, `TsWorksheet` i `TsWorkbook`.
3232
3333#### Skoroszyt
3434
3535Klasa `TsWorkbook` jest główną klasą widoczną dla użytkownika. Zapewnia metody odczytu danych i zapisywania do plików. Wszechstronna struktura biblioteki zapewnia dostęp do różnych popularnych formatów plików, takich jak Excel *.xls* lub *.xlsx*, a także OpenOffice/LibreOffice *.ods*.
3636
3737Format pliku jest określony przez typ `TsSpreadsheetFormat` zdefiniowany w module `fpstypes`
3838
3939``` pascal
4040type
4141 TsSpreadsheetFormat = (sfExcel2, sfExcel5, sfExcel8, sfExcelXML, sfOOXML,
4242 sfOpenDocument, sfCSV, sfHTML, sfWikiTable_Pipes, sfWikiTable_WikiMedia, sfUser);
4343```
4444
4545gdzie:
4646
4747- `sfExcel2`, `sfExcel5`, `sfExcel8` oznacza wersje binarnego formatu xls używanego przez program Excel („BIFF” = „Binary Interchange File Format”), przy czym `sfExcel8` jest najnowszym formatem.
4848
4949- `sfOOXML` odpowiada nowszemu formatowi xlsx wprowadzonemu przez Excel2007
5050- `sfExcelXML` to format xml, który został wprowadzony przez Microsoft w Office XP i 2003. Niezbyt popularny.
5151- `sfOpenDocument` to format arkusza kalkulacyjnego używany przez OpenOffice/LibreOffice; Domyślnie pliki mają rozszerzenie *.ods*.
5252- `sfCSV` odnosi się do plików tekstowych rozdzielanych przecinkami (domyślne rozszerzenie *.csv*); mogą one być czytelne dla dowolnego edytora tekstu i dla wszystkich arkuszy kalkulacyjnych, ale nie zawierają informacji o formatowaniu.
5353- `sfHTML` oznacza standardowy format HTML używany w przeglądarkach internetowych.
5454- `sfWikiTable_Pipes` i `sfWikiTable_WikiMedia` to format używany przez tabele w witrynach wiki.
5555- `sfUser` jest potrzebny do zarejestrowania formatu zdefiniowanego przez użytkownika. Nie ma planów wdrożenia „starych” formatów plików, takich jak Excel3.0/4.0 czy Lotus. Możliwe jest jednak utworzenie własnych klas czytania i pisania, aby rozszerzyć funkcjonalność FPSpreadsheet - zobacz sekcję poniżej o Dodawanie nowych formatów plików
5656
5757Podczas stosowania FPSpreadsheet pierwszym zadaniem jest utworzenie instancji skoroszytu:
5858
5959``` pascal
6060var
6161 MyWorkbook: TsWorkbook;
6262begin
6363 MyWorkbook := TsWorkbook.Create;
6464 ...
6565```
6666
6767Czytanie plików arkuszy kalkulacyjnych odbywa się (między innymi) metodami skoroszytowymi
6868
6969- `procedure ReadFromFile(AFileName: string):`\
7070 Czyta plik o podanej nazwie i automatycznie rozpoznaje poprawny format pliku.
7171- `procedure ReadFromFile(AFileName: string; AFormat: TsSpreadsheetFormat):`\
7272 Odczytuje plik, ale zakłada, że ​​format pliku jest określony przez `AFormat`.
7373
7474Do zapisywania do pliku można użyć następujących metod skoroszytu:
7575
7676- `procedure WriteToFile(const AFileName: string; const AFormat: TsSpreadsheetFormat; const AOverwriteExisting: Boolean = False)`:\
7777 Zapisuje skoroszyt do podanego pliku przy użyciu podanego formatu arkusza kalkulacyjnego. Jeśli plik już istnieje, zostanie on automatycznie nadpisany, jeśli `AOverwriteExisting` ma wartość `true`:
7878- `procedure WriteToFile(const AFileName: String; const AOverwriteExisting: Boolean = False)`:\
7979 tak samo, ale format pliku jest określany na podstawie podanego rozszerzenia pliku (w przypadku xls Excela używana jest najnowsza wersja `sfExcel8`).
8080
8181Po wywołaniu tych metod warto przyjrzeć się właściwości `ErrorMsg` skoroszytu, w której gromadzone są komunikaty z powodu błędów lub ostrzeżeń, które mogły wystąpić podczas odczytu/zapisu. Ta właściwość zwraca wielowierszowy ciąg, który jest najlepiej wyświetlany w komponencie memo; jeśli wszystko było w porządku, jest to pusty ciąg.
8282
8383Uwaga: PSpreadsheets zapewnia wyspecjalizowane moduły do odczytu i zapisu w każdym formacie pliku. Te moduły nie są dostępne automatycznie, musisz je jawnie dodać do klauzuli **uses**. FPSpreadsheet zgłosi „nieobsługiwany format pliku”, jeśli nie zostanie znaleziony żaden pasujący moduł do odczytu/zapisu. Oto lista nazw takich modułów:
8484
8585- *xlsbiff2*, *xlsbiff5* i *xlsbiff8* la binarnych formatów plików xls odpowiednio `sfExcel2`, `sfExcel5` i `sfExcel8`,
8686- *xlsxOOXML* dla formatu pliku xlsx `sfOOXML` programu Excel 2007 i nowszych,
8787- *xlsXML* dla formatu xml programów Excel XP i 2003,
8888- *fpsopendocument* dla formatu pliku `sfOpenDocument` programów OpenOffice/LibreOffice,
8989- *fpsCSV* dla plików tekstowych z wartościami oddzielonymi przecinkami (csv),
9090- *fpsHTML* dla plików HTML,
9191- *wikitables* dla `sfWikiTable_Pipes` i `sfWikiTable_WikiMedia`,
9292- lub po prostu dodaj *fpsallformats*, aby uzyskać obsługę odczytu/zapisu dla wszystkich obsługiwanych formatów plików.
9393
9494#### Arkusz roboczy
9595
9696Skoroszyt zawiera listę instancji `TsWorksheet`. Odpowiadają one zakładkom, które widzisz w programie Excel lub Open/LibreOffice. Podczas czytania pliku arkusza kalkulacyjnego poszczególne arkusze są tworzone automatycznie zgodnie z zawartością pliku. Kiedy arkusz kalkulacyjny jest tworzony ręcznie, aby zapisać go w pliku, arkusz roboczy musi zostać utworzony przez *dodanie* go do skoroszytu:
9797
9898``` pascal
9999var
100100 MyWorkbook: TsWorkbook;
101101 MyWorksheet: TsWorksheet;
102102begin
103103 MyWorkbook := TsWorkbook.Create;
104104 MyWorksheet := MyWorkbook.AddWorksheet('My_Table');
105105 // 'My_Table' to „nazwa” arkusza
106106 ...
107107```
108108
109109Dostęp do już istniejących arkuszy roboczych można uzyskać przy użyciu metod `TsWorkbook`
110110
111111- `function GetFirstWorksheet: TsWorksheet`: pobiera pierwszy arkusz ze skoroszytu.
112112- `function GetWorksheetByIndex(AIndex: Cardinal): TsWorksheet`: zwraca arkusz z podanym indeksem (począwszy od 0).
113113- `function GetWorksheetByName(AName: String): TsWorksheet`: zwraca arkusz o podanej nazwie, która była używana podczas dodawania arkusza.
114114
115115Liczbę już istniejących arkuszy można sprawdzić wywołując metodę `GetWorksheetCount`.
116116
117117#### Komórka
118118
119119Wreszcie arkusz roboczy zapewnia dostęp do komórek. Nowo utworzony arkusz, jak w powyższym przykładzie, jest pusty i nie zawiera żadnych komórek. Komórki są dodawane przez przypisanie do nich danych lub atrybutów za pomocą jednej z metod `WriteXXXX` arkusza. Jak już wspomniano, komórka jest adresowana przez indeks wiersza i kolumny, do których należy. Jak zwykle, indeksy wierszy i kolumn zaczynają się od 0. W związku z tym komórka „A1” należy do wiersza 0 i kolumny 0. Należy zauważyć, że indeksy wierszy i kolumn są zawsze podawane w tej kolejności, która *różni się od konwencji stosowanej w* `TStringGrid`. Poniższy przykład tworzy komórkę pod adresem A1 i umieszcza w niej liczbę `1.0`.
120120
121121``` pascal
122122var
123123 MyWorkbook: TsWorkbook;
124124 MyWorksheet: TsWorksheet;
125125begin
126126 MyWorkbook := TsWorkbook.Create;
127127 MyWorksheet := MyWorkbook.AddWorksheet('My_Table');
128128 MyWorksheet.WriteNumber(0, 0, 1.0); //„A1” ma rząd=0 i kolumnę=0
129129 ...
130130```
131131
132132Możliwy jest również bezpośredni dostęp do komórek za pomocą metod skoroszytu `FindCell(ARow, ACol)` lub `GetCell(ARow, ACol)`. Obie funkcje istnieją również w wersji przeciążonej, do której można przekazać adres komórki w notacji Excela: `FindCell(ACellStr: String)` lub `GetCell(ACellStr: String)`. Należy pamiętać, że te funkcje zwracają wskaźnik `pointer` do danej komórki (typ `PCell`). Nie zapomnij odwołać się do wskaźników! Różnica między `FindCell` i `GetCell` polega na tym, że pierwsza zwraca wartość `nil`, jeśli komórka jeszcze nie istnieje, a druga tworzy pustą komórkę w tym przypadku.
133133
134134``` pascal
135135if MyWorksheet.FindCell('A1') = nil then
136136 WriteLn('Komórka A1 nie istnieje.');
137137```
138138
139139##### Podstawowy rekord TCell
140140
141141Oto deklaracja typu danych komórki:
142142
143143``` pascal
144144type
145145 TCell = record
146146 { Lokalizacja komórki }
147147 Worksheet: TsWorksheet;
148148 Col: Cardinal; // od zera
149149 Row: Cardinal; // od zera
150150
151151 { Indeks formatu zapisu }
152152 FormatIndex: Integer;
153153
154154 { Flagi stanu }
155155 Flags: TsCellFlags; // (cfHasComment, cfMerged, cfHyperlink, ...)
156156
157157 { Zawartość komórki }
158158 UTF8StringValue: String; // ciąg nie może być częścią rekordu wariantowego
159159 case ContentType: TCellContentType of // który musi znajdować się na końcu deklaracji
160160 cctEmpty : (); // nie ma żadnych danych
161161 cctFormula : (); // UTF8StringValue znajduje się poza rekordem wariantowym
162162 cctNumber : (Numbervalue: Double);
163163 cctUTF8String : (); // FormulaValue znajduje się poza rekordem wariantowym
164164 cctDateTime : (DateTimevalue: TDateTime);
165165 cctBool : (BoolValue: boolean);
166166 cctError : (ErrorValue: TsErrorValue);
167167 end;
168168 PCell = ^TCell;
169169```
170170
171171Pole `ContentType` wskazuje, jaki typ danych jest przechowywany w komórce:
172172
173173``` pascal
174174type
175175 TCellContentType = (cctEmpty, cctFormula, cctNumber, cctUTF8String, cctDateTime, cctBool, cctError);
176176```
177177
178178Zgodnie z tym polem odpowiednie dane można znaleźć w polach
179179
180180- `NumberValue` (dla `ContentType=cctNumber`), lub
181181- `UTF8StringValue` (dla `ContentType=cctUTF8String`), lub
182182- `DateTimeValue` (dla `ContentType=cctDateTime`), lub
183183- `BoolValue` (dla `ContentType=cctBool`), tj. `TRUE` lub `FALSE`, lub
184184- `ErrorValue` (dla `ContentType=cctError`).
185185
186186Ze względu na użycie rekordu wariantu większość z tych wartości zachodzi na siebie, tj. modyfikacja `NumberValue` wpływa również na inne wartości. Dlatego zawsze bierz pod uwagę wartość `ContentType` podczas bezpośredniego dostępu do rekordu `TCell` (metody arkusza omówione poniżej uwzględniają to automatycznie).
187187
188188Pole `Flags` mówi, czy z komórką są powiązane dodatkowe dane, które nie są zawarte w rekordzie komórki, zwykle w celu zaoszczędzenia pamięci:
189189
190190``` pascal
191191type
192192 TsCellFlag = (cfHasComment, cfHyperlink, cfMerged, cfHasFormula, cf3dFormula);
193193 TsCellFlags = set of TsCellFlag;
194194```
195195
196196- `cfHasComment`: Rekord komentarza można znaleźć w `Comments` arkusza.
197197- `cfHyperlink`: Komórka zawiera hiperłącze przechowywane w `Hyperlinks` arkusza.
198198- `cfMerged`: Komórka należy do scalonego bloku i rozciąga się na kilka komórek.
199199- `cfHasFormula`: Komórka jest powiązana z formułą, która jest przechowywana w `Formulas` arkusza.
200200- `cf3dFormula`: Formuła skojarzona z komórką zawierającą elementy odwołujące się do innych arkuszy tego samego skoroszytu.
201201
202202> **Note:** Po obliczeniu formuły lub po odczytaniu pliku, formuła komórki w `ContentType` jest konwertowana na wynik. Wówczas obecność formuły można wykryć tylko przez wywołanie funkcji `HasFormula(cell)` dla odpytywanej komórki (`cell: PCell`) w module *fpsUtils*; ta funkcja sprawdza obecność elementu `cfHasFormula` we flagach komórki.
203203
204204##### Jak dodawać i czytać dane do/z komórki
205205
206206Dodawanie wartości do komórki jest najłatwiejsze przy użyciu jednej z metod arkusza `WriteXXXX`. Najważniejsze z nich to:
207207
208208``` pascal
209209type
210210 TsWorksheet = class
211211 ...
212212 { Zapisywanie wartości walutowych }
213213 function WriteCurrency(ARow, ACol: Cardinal; AValue: Double;
214214 ANumFormat: TsNumberFormat = nfCurrency; ADecimals: Integer = 2;
215215 ACurrencySymbol: String = '?'; APosCurrFormat: Integer = -1;
216216 ANegCurrFormat: Integer = -1): PCell; overload;
217217 procedure WriteCurrency(ACell: PCell; AValue: Double;
218218 ANumFormat: TsNumberFormat = nfCurrency; ADecimals: Integer = -1;
219219 ACurrencySymbol: String = '?'; APosCurrFormat: Integer = -1;
220220 ANegCurrFormat: Integer = -1); overload;
221221 function WriteCurrency(ARow, ACol: Cardinal; AValue: Double;
222222 ANumFormat: TsNumberFormat; ANumFormatString: String): PCell; overload;
223223 procedure WriteCurrency(ACell: PCell; AValue: Double;
224224 ANumFormat: TsNumberFormat; ANumFormatString: String); overload;
225225
226226 { Zapisywanie wartości daty/czasu }
227227 function WriteDateTime(ARow, ACol: Cardinal; AValue: TDateTime): PCell; overload;
228228 procedure WriteDateTime(ACell: PCell; AValue: TDateTime); overload;
229229 function WriteDateTime(ARow, ACol: Cardinal; AValue: TDateTime;
230230 ANumFormat: TsNumberFormat; ANumFormatStr: String = ''): PCell; overload;
231231 procedure WriteDateTime(ACell: PCell; AValue: TDateTime;
232232 ANumFormat: TsNumberFormat; ANumFormatStr: String = ''); overload;
233233 function WriteDateTime(ARow, ACol: Cardinal; AValue: TDateTime;
234234 ANumFormatStr: String): PCell; overload;
235235 procedure WriteDateTime(ACell: PCell; AValue: TDateTime;
236236 ANumFormatStr: String); overload;
237237
238238 { Zapisywanie wartości liczbowych }
239239 function WriteNumber(ARow, ACol: Cardinal; ANumber: double): PCell; overload;
240240 procedure WriteNumber(ACell: PCell; ANumber: Double); overload;
241241 function WriteNumber(ARow, ACol: Cardinal; ANumber: double;
242242 ANumFormat: TsNumberFormat; ADecimals: Byte = 2): PCell; overload;
243243 procedure WriteNumber(ACell: PCell; ANumber: Double;
244244 ANumFormat: TsNumberFormat; ADecimals: Byte = 2); overload;
245245 function WriteNumber(ARow, ACol: Cardinal; ANumber: double;
246246 ANumFormat: TsNumberFormat; ANumFormatString: String): PCell; overload;
247247 procedure WriteNumber(ACell: PCell; ANumber: Double;
248248 ANumFormat: TsNumberFormat; ANumFormatString: String); overload;
249249
250250 { Zapisywanie ciągów typu string }
251251 function WriteText(ARow, ACol: Cardinal; AText: ansistring;
252252 ARichTextParams: TsRichTextParams = nil): PCell; overload;
253253 procedure WriteText(ACell: PCell; AText: String;
254254 ARichTextparams: TsRichTextParams = nil); overload;
255255
256256 // stare metody typu string, jak "WriteUTF8Text" są teraz przestarzałe
257257 ...
258258```
259259
260260Niektóre z tych metod istnieją w przeciążonych wersjach, w których parametry formatowania komórki można dodać razem z wartością komórki. Odpowiednio jak do zapisu, istnieje również kilka metod arkusza `worksheet` do odczytu wartości komórek:
261261
262262``` pascal
263263type
264264 TsWorksheet = class
265265 ...
266266 { Odczytywanie zawartości komórki jako ciągu }
267267 function ReadAsText(ARow, ACol: Cardinal): string; overload;
268268 function ReadAsText(ACell: PCell): string; overload;
269269 function ReadAsText(ACell: PCell; AFormatSettings: TFormatSettings): string; overload;
270270
271271 { Odczytywanie zawartości komórki jako liczby }
272272 function ReadAsNumber(ARow, ACol: Cardinal): Double; overload;
273273 function ReadAsNumber(ACell: PCell): Double; overload;
274274 function ReadNumericValue(ACell: PCell; out AValue: Double): Boolean;
275275
276276 { Odczytywanie zawartości komórki jako wartości daty/czasu }
277277 function ReadAsDateTime(ARow, ACol: Cardinal; out AResult: TDateTime): Boolean; overload;
278278 function ReadAsDateTime(ACell: PCell; out AResult: TDateTime): Boolean; overload;
279279 ...
280280```
281281
282282##### Indeks do formatu komórki
283283
284284`FormatIndex` jest to indeks rekordu formatu komórki. Opisuje on atrybuty formatowania komórki. Te rekordy są zbierane przez wewnętrzną listę skoroszytu i są zdefiniowane w następujący sposób:
285285
286286``` pascal
287287type
288288 TsCellFormat = record
289289 FontIndex: Integer;
290290 TextRotation: TsTextRotation;
291291 HorAlignment: TsHorAlignment;
292292 VertAlignment: TsVertAlignment;
293293 Border: TsCellBorders;
294294 BorderStyles: TsCellBorderStyles;
295295 Background: TsFillPattern;
296296 NumberFormatIndex: Integer;
297297 NumberFormat: TsNumberFormat;
298298 NumberFormatStr: String;
299299 BiDiMode: TsBiDiMode; // bdDefault, bdLTR {kierunek pisania od lewej do prawej}, bdRTL {od prawej do lewej)
300300 Protection: TsCellProtection; // cpLockCell, cpHideFormulas
301301 UsedFormattingFields: TsUsedFormattingFields;
302302 //uffTextRotation, uffFont, uffBold, uffBorder, uffBackground, uffNumberFormat, uffWordWrap, uffHorAlign, uffVertAlign, uffBiDi
303303 end;
304304```
305305
306306- `FontIndex`: czcionka tekstu jako określenie indeksu na liście czcionek skoroszytu
307307- `TextRotation`: określa, czy tekst komórki jest zapisywany poziomo czy pionowo
308308- `HorAlignment`: tekst wyrównany do lewej, wyśrodkowany w poziomie lub wyrównany do prawej
309309- `VertAlignment`: tekst wyrównany do góry, na dole lub wyśrodkowany w pionie
310310- `Border`: zestaw flag wskazujących, że - jeśli są ustawione - linia graniczna jest rysowana przy lewej, górnej, prawej lub dolnej krawędzi komórki. Linie są rysowane zgodnie ze standardami `BorderStyles`, które określają styl linii i kolor obramowania.
311311- `Background`: rekord określający wypełnienie tła komórki (styl wzoru, kolor wzoru i kolor tła - patrz rozdział na temat tła komórki poniżej).
312312- `NumberFormat` i `NumberFormatStr` określają sposób formatowania wartości liczbowych lub daty/czasu (np. liczba miejsc dziesiętnych, długi lub krótki format daty itp.).
313313- Podczas formatowania komórki uwzględniane są tylko te atrybuty formatu, dla których flaga jest ustawiona w `UsedFormattingFields`. Jeśli flaga nie jest dołączona, odpowiedni atrybut jest ignorowany i zastępowany jego wartością domyślną.
314314
315315Aby określić format dla danej komórki, wywołaj odpowiednią metodę arkusza `WriteXXXX`, aby pobrać format wywołaj `ReadXXXX`. Te metody zwykle pobierają wskaźnik do komórki jako parametr, ale istnieją również przeciążone wersje, które akceptują indeks wierszy i kolumn. Ponadto style formatowania można również zastosować bezpośrednio do komórki za pomocą [[Helper types|rekordu pomocniczego]] zaimplementowanego w module *fpsCell*.
316316
317317Aby uzyskać bardziej szczegółowy opis, zobacz formatowanie komórek poniżej.
318318
319319#### Kolumny i wiersze
320320
321321Rekordy kolumn i wierszy są dodawane do każdej kolumny i wiersza o właściwościach innych niż domyślne:
322322
323323``` pascal
324324type
325325 TCol = record
326326 Col: Cardinal;
327327 Width: Single;
328328 ColWidthType: TsColWidthType; // = (cwtDefault, cwtCustom)
329329 FormatIndex: Integer;
330330 Options: TsColRowOptions; // set of [croHidden, croPageBreak]
331331 end;
332332 PCol = ^TCol;
333333
334334 TRow = record
335335 Row: Cardinal;
336336 Height: Single;
337337 RowHeightType: TsRowHeightType; // = (rhtDefault, rhtCustom, rhtAuto)
338338 FormatIndex: Integer;
339339 Options: TsColRowOptions; // set of [croHidden, croPageBreak]
340340 Hidden: Boolean;
341341 PageBreak: Boolean;
342342 end;
343343 PRow = ^TRow;
344344```
345345
346346##### Szerokość kolumny / wysokość wiersza
347347
348348**Szerokość kolumn** i **Wysokość wierszy** można określić w różnych jednostkach zdefiniowanych przez typ `TsSizeUnits = (suChars, suLines, suMillimeters, suCentimeters, suPoints, suInches)`. `suChars` odnosi się do znaków liczby `0` mieszczących się w szerokości kolumny - w ten sposób Excel definiuje szerokości kolumn. `suLines` to liczba linii tekstu mieszczących się na wysokości wiersza. Obie jednostki są oparte na rozmiarze znaku domyślnej czcionki skoroszytu. Pozostałe jednostki to konwencjonalne jednostki długości fizycznej (1 cm = 10 mm, 1 cal = 25,4 mm = 72 punkty). Akceptowane są wartości ułamkowe. Skoroszyt i arkusze robocze przechowują wewnętrznie długości w milimetrach (`MyWorkbook.Units`).
349349
350350Aplikacje pakietu Office zazwyczaj automatycznie dostosowują wysokość wierszy zgodnie z czcionką lub rotacją tekstu w zawartości komórki. Ten przypadek jest identyfikowany przez `RowHeightType` o wartości `rhtAuto`. Ponieważ arkusz nie może bardzo dokładnie obliczyć rozmiaru tekstu, automatyczne wysokości wierszy nie są zapisywane przez FPSpreadsheet; są one zastępowane przez **domyślną wysokość wiersza**. Domyślna wysokość wiersza jest również używana, jeśli wiersz jest pusty, tj. gdy nie zawiera żadnych komórek danych. Jej wartość można zmienić, wywołując metodę `WriteDefaultRowHeight()` arkusza lub używając właściwości arkusza `DefaultRowHeight`. W `WriteDefaultRowHeight()` jednostki muszą być określone, podczas gdy w `DefaultRowHeight` zakłada się, że są to linie. Podobnie, **domyślną szerokość kolumny** można określić za pomocą funkcji `WriteDefaultColWidth()` lub właściwości `DefaultColWidth` (w znakach).
351351
352352W celu przekroczenia automatycznych i domyślnych wysokości wierszy wywołaj metodę arkusza `WriteRowHeight()`. Te rekordy wierszy są identyfikowane przez `RowHeightType` o wartości `rhtCustom`. W ten sam sposób szerokość kolumn można ustawić na określoną wartość, wywołując `WriteColWidth()`. `ColWidthType` tych kolumn to `cwtCustom`.
353353
354354Wysokość/szerokość konkretnego wiersza/kolumny można pobrać za pomocą metod `GetRowHeight` lub `GetColWidth`. Zwróć uwagę, że te metody zwracają domyślne wysokości wierszy/szerokości kolumn, jeśli nie ma rekordów `TRow`/`TCol`.
355355
356356``` pascal
357357type TsWorksheet = class
358358 ...
359359 { Ustaw wysokość wiersza }
360360 procedure WriteRowHeight(ARowIndex: Cardinal; AHeight: Single; AUnits: TsSizeUnits);
361361 { Ustaw szerokość kolumny }
362362 procedure WriteColWidth(AColIndex: Cardinal; AWidth: Single; AUnits: TsSizeUnits);
363363 { Ustaw domyślną wysokość wiersza }
364364 procedure WriteDefaultRowHeight(AHeight: Single; AUnits: TsSizeUnits);
365365 { Ustaw domyślną szerokość kolumny }
366366 procedure WriteDefaultColWidth(AWidth: Single; AUnits: TsSizeUnits);
367367
368368 { Zwróć wysokość wiersza }
369369 function GetRowHeight(ARowIndex: Cardinal; AUnits: TsSizeUnits): Single;
370370 { Zwróć szerokość kolumny }
371371 function GetColWidth(AColIndex: Cardinal; AUnits: TsSizeUnits): Single;
372372 { Zwróć domyślną wysokość wiersza }
373373 function ReadDefaultRowHeight(AUnits: TsSizeUnits): Single;
374374 { Zwróć domyślną szerokość kolumny }
375375 function ReadDefaultColWidth(AUnits: TsSizeUnits): Single;
376376
377377 property DefaultRowHeight: Single; // w liniach tekstu
378378 property DefaultColWidht: Single; // w liczbie znaków
379379```
380380
381381Istnieją również przeciążone wersje tych metod, które nie wymagają parametru `AUnits`. W tym przypadku wysokości wierszy są określane jako liczba linii tekstu, a szerokości kolumn są określane jako liczba znaków. Zauważ, że te warianty pochodzą z poprzednich wersji i są teraz przestarzałe.
382382
383383##### Formaty kolumn i wierszy
384384
385385Element `FormatIndex` formatu rekordów wierszy i kolumn ma zastosowanie do całego wiersza lub całej kolumny. Razem z komórkami te formaty są przechowywane jako rekordy `TsCellFormat` na wewnętrznej liście skoroszytów. `FormatIndex` jest indeksem właściwości formatu na tej liście. Zobacz szczegóły w sekcji Formatowanie komórek. **Formaty wierszy i kolumn** są stosowane głównie do pustych komórek, ale po dodaniu nowej komórki automatycznie otrzyma ona format wiersza lub kolumny. (Jeśli zarówno wiersz, jak i kolumna mają różne formaty, zostanie użyty format wiersza).
386386
387387Tutaj jest lista metod arkusza dostępna dla formatowania kolumn i wierszy:
388388
389389``` Pascal
390390type TsWorksheet = class
391391 // Przypisuje format do kolumny lub wiersza
392392 procedure WriteColFormatIndex(ACol: Cardinal; AFormatIndex: Integer);
393393 procedure WriteRowFormatIndex(ARow: Cardinal; AFormatIndex: Integer);
394394
395395 // Odczytuje format kolumny lub wiersza
396396 function GetColFormatIndex(ACol: Cardinal): Integer;
397397 function GetRowFormatIndex(ARow: Cardinal): Integer;
398398
399399 // Zwraca czcionkę przypisaną do kolumny lub wiersza
400400 function ReadColFont(ACol: PCol): TsFont;
401401 function ReadRowFont(ARow: PRow): TsFont;
402402
403403 // Sprawdza, czy jakakolwiek kolumna lub wiersz ma specjalny format
404404 function HasRowFormats: Boolean;
405405 function HasColFormats: Boolean;
406406```
407407
408408##### Hidden columns / rows
409409
410410Adding the flag `croHidden` to the row's or column's `Options` hides the row or column in the Office application (or in TsWorksheetGrid). The following worksheet methods are helpers to handle **row/column visibility**:
411411
412412``` pascal
413413type TsWorksheet = class
414414 ...
415415 { Hide column/row }
416416 procedure HideCol(ACol: Cardinal);
417417 procedure HideRow(ARow: Cardinal);
418418
419419 { Show a previously hidden column/row }
420420 procedure ShowCol(ACol: Cardinal);
421421 procedure ShowRow(ARow: Cardinal);
422422
423423 { Check whether column/row is hidden }
424424 function ColHidden(ACol: Cardinal): Boolean;
425425 function RowHidden(ARow: Cardinal): Boolean;
426426```
427427
428428##### Page breaks
429429
430430The flag `croPageBreak` can be added to the row's or column's `Options` in order to force a **page break** before the corresponding row or column when the worksheet is printed by the Office applications. Note that FPSpreadsheet itself does not support printing. The following worksheet methods help with page breaks:
431431
432432``` pascal
433433type TsWorksheet = class
434434 ...
435435 { Enforce a page break before the specified column/row }
436436 procedure AddPageBreakToCol(ACol: Cardinal);
437437 procedure AddPageBreakToRow(ARow: Cardinal);
438438
439439 { Removes a page break previously added to a column/row }
440440 procedure RemovePageBreakFromCol(ACol: Cardinal);
441441 procedure RemovePageBreakFromRow(ARow: Cardinal);
442442
443443 { Checks whether a page break is forced before the specified column/row }
444444 function IsPageBreakCol(ACol: Cardinal): Boolean;
445445 function IsPageBreakRow(ARow: Cardinal): Boolean;
446446```
447447
448448#### Events
449449
450450Worksheets and workbooks fire a series of events such as OnChangeCell, OnChangeFont, etc. The events usually are intended for interaction with the [[FPSpreadsheet tutorial: Writing a mini spreadsheet application|visual spreadsheet controls]]. If you need to attach your own handlers you should make sure that the original handler is called, at least in a gui program using the spreadsheet controls. Or you use the events provided by the visual controls themselves, e.g. [[TsWorksheetGrid|WorksheetGrid]]`.OnEditingDone` instead of `WorksheetGrid.Worksheet.OnChangeCell`.
451451
452452### Formulas
453453
454454Two kinds of formulas are supported by FPSpreadsheet:
455455
456456- **String formulas**: These are written in strings just like in the office applications, for example `"=ROUND(A1+B1,0)"`. They are used internally in the files of Open/LibreOffice and Excel *.xlsx*.
457457- **RPN formulas** are used internally by the binary *.xls* Excel files. They are written in Reverse Polish Notation (RPN), for example: `A1, B1, Add, 0, ROUND`. If a spreadsheet containing formulas is to be saved in a binary Excel format, the RPN formulas required are generated automatically.
458458
459459FPSpreadsheet can convert between string and rpn formulas. Formulas in both types can be calculated.
460460
461461In older versions of FPSpreadsheet, formulas were stored directly in the cell record. This was given up to have parsed formulas available for faster calculation. The formulas are stored in the tree `Formulas` of the worksheet. The formula record contains the row and column index of the cell to which the formula belongs, the string representation of the formula, as well as the parser tree for quick evaluation.
462462
463463FPSpreadsheet supports the majority of the formulas provided by the common spreadsheet applications. However, when reading a file created by these applications, there is always a chance that an unsupported formula is contained. To avoid crashing of fpspreadsheet, reading of formulas is disabled by default; the cell displays only the result of the formula written by the Office application. To activate reading of formulas add the element `boReadformulas` to the workbook's `Options` before opening the file. If an error occurs in this case the reader normally catches the exception, writes the exception message into the workbook's errorlog and continues reading. If you want reading to stop you must add the `boAbortReadingOnFormulaError` to the workbook `Options`.
464464
465465Formulas can link to data in other sheets of the same workbook ("3d formulas") by applying the Excel syntax (see below). External links to spreadsheets in other files are not supported.
466466
467467Calculation of formulas is normally not needed when a file is written by FPSpreadsheet for opening in an Office application because that automatically calculates the formula results. If the same file, however, is openend by an application based on FPSpreadsheet the calculated cells would be empty because the formulas are not automatically calculated by default. To activate calculation of formulas before writing a spreadsheet to file you have to add the option `boCalcBeforeSaving` to the workbook's `Options`.
468468
469469If FPSpreadshet is used in an interactive application (such as the *spready* demo found in the *examples* folder of the FPSpreadsheet installation) it is desirable to calculate formulas automatically whenever formula strings or cell values are changed by the user. This can be achieved by the option `boAutoCalc` in the workbook's `Options`.
470470
471471The most general setting regarding formulas, therefore, is
472472
473473``` pascal
474474 MyWorkbook.Options := MyWorkbook.Options + [boReadFormulas, boCalcBeforeSaving, boAutoCalc];
475475```
476476
477477Calculation of formulas can be triggered manually by calling the method `CalcFormulas` of the worksheet or workbook. The latter is absolutely required when the workbook contains 3d formulas where the result of one cell can affect cells in other sheets. If there are only within-sheet formulas then the worksheet's `CalcFormulas` is sufficient.
478478
479479#### String formulas
480480
481481String formulas are written in the same way as in the Office applications. The worksheet method for creating a string formula is `WriteFormula`:
482482
483483``` pascal
484484var
485485 MyWorksheet: TsWorksheet;
486486//...
487487 MyWorksheet.WriteFormula(0, 1, '=ROUND(A1+B2+1.215,0)');
488488 // By default, use dot as decimal and comma as list separator!
489489```
490490
491491A few notes on **syntax**:
492492
493493- The leading `=` character which identifies formulas in the Office applications is not absolutely necessary here and can be dropped. The formula is stored in the cell record without it.
494494- The case of the formula name is ignored.
495495- Spaces can be added for better readability, but they will be lost when saving.
496496- Strings must be enclosed in double quotes.
497497- The corner points of a cell range must be separated by a colon (":"), e.g. `A1:C3`. Unordered ranges will be rearranged when the formula is parsed, i.e. `C3:A1` becomes `A1:C3`.
498498- Links to other worksheets must follow the Excel syntax which separates the sheetname and cell address by a "!". An single cell, for example, can be linked by `Sheet1!A1`. An range of sheets must be placed before the cell or cell range, e.g. `Sheet1:Sheet2!A1:C3`. Note that the Open/LibreOffice syntax with a separating point and reference to the corner points of the 3d box (i.e., `Sheet1.A1:Sheet2.C3`) is not supported. Note also that the worksheet(s) to which the formula links must exist at the time when the formula is added; otherwise the link will be replaced by the error code `#REF!`, and the formula will not be usable even if the missing sheet is added later.
499499- Normally, floating point numbers must be entered with a dot as decimal separator, and a comma must be used to separate function arguments.
500500- Setting the optional parameter `ALocalized` of the worksheet methods `WriteFormula` to `TRUE`, however, allows to use localized decimal and list separators taken from the workbook's `FormatSettings` - see *spready* demo.
501501
502502``` pascal
503503var
504504 MyWorksheet: TsWorksheet;
505505//...
506506 MyWorksheet.WriteFormula(0, 1, '=ROUND(A1+B2+1,215;0)', true);
507507 // Because of the "true" the formula parser accepts the comma as decimal and the
508508 // semicolon as list separator if the workbook's FormatSettings are set up like this.
509509```
510510
511511Use the worksheet methods `ReadFormula` or `ReadFormulaAsString` to retrieve the string formula assigned to the cell. The pointer to the cell must be given as a parameter. The latter function accepts an additional (boolean) parameter `ALocalized` to use the decimal and list separators of the workbook's `FormatSettings` for creation of the formula string.
512512
513513``` pascal
514514var
515515 MyWorksheet: TsWorksheet;
516516 cell: PCell;
517517//...
518518 cell := MyWorksheet.FindCell(0, 1);
519519 WriteLn('The formula in internal format is ', MyworkSheet.ReadFormula(cell));
520520 WriteLn('The localized formula is ', MyWorksheet.ReadFormulaAsString(cell, true));
521521//-------------------------------------------------------------------
522522// For the previous example, this will result in the following output
523523The formula in internal format is ROUND(A1+B2+1.215,0)
524524The localized formula is ROUND(A1+B2+1,215;0)
525525```
526526
527527#### RPN formulas
528528
529529At application level, string formulas are mainly used, and RPN formulas are of little practical importance. Therefore, documentation of RPN formulas has been removed from this main FPSpreadsheet wiki and can be found in the article [[RPN Formulas in FPSpreadsheet|"RPN Formulas in FPSpreadsheet"]].
530530
531531#### Shared formulas and array formulas
532532
533533- **Shared formulas** are only supported for reading (from Excel files).
534534- **Array formulas** are not supported, currently.
535535
536536#### List of built-in formulas
537537
538538FPSpreadsheet supports more than 80 built-in formulas. In order not to blow up this wiki page too much documentation of these formulas has been moved to the [[FPSpreadsheet: List of formulas|separate document "List of formulas"]].
539539
540540To learn more about the functions available, look at file *testcases_calcrpnformula.inc* in the *tests* folder of the FPSpreadsheet installation where every function is included with at least one sample.
541541
542542#### Extending FPSpreadsheet by user-defined formulas
543543
544544Although the built-in formulas cover most of the applications there may be a need to access a formula which is available in the Office application, but not in FPSpreadsheet. For this reason, the library supports a registration mechanism which allows to add user-defined functions to the spreadsheets. This can be done by calling the procedure `RegisterFunction` from the unit *fpsExprParser*:
545545
546546``` pascal
547547procedure RegisterFunction(const AName: ShortString; const AResultType: Char;
548548 const AParamTypes: String; const AExcelCode: Integer; ACallBack: TsExprFunctionCallBack); overload;
549549
550550procedure RegisterFunction(const AName: ShortString; const AResultType: Char;
551551 const AParamTypes: String; const AExcelCode: Integer; ACallBack: TsExprEventCallBack); overload;
552552```
553553
554554- `AName` specifies the name under which the function will be called in the spreadsheet. It must match the name of the formula in the Office application.
555555- `AResultType` is a character which identifies the data type of the function result:
556556 - `'F'` - floating point number
557557 - `'I'` - integer
558558 - `'D'` - date/time
559559 - `'B'` - boolean
560560 - `'S'` - string
561561 - `'C'` - cell address, e.g. 'A1'
562562 - `'R'` - cell range address, e.g. 'A1:C3'
563563- `AParamTypes` is a string in which each character identifies the data type of the corresponding argument. In addition to the list shown above the following symbols can be used:
564564 - `'?'` - any type
565565 - `'+'` - must be the last character. It means that the preceding character is repeated indefinitely. This allows for an arbitrary argument count. Please note, however, that Excel supports only up to 30 arguments.
566566 - lowercase `'f', 'i', 'd', 'b', 's'` indicate optional parameters of the type explained above. Of course, uppercase symbols cannot follow lower-case symbols.
567567- `AExcelCode` is the identifier of the function in xls files. See "OpenOffice Documentation of the Microsoft Excel File Format", section 3.11, for a list.
568568- `ACallback` identifies which function is called by FPSpreadsheet for calculation of the formula. It can either be a procedure or an event handler.
569569
570570``` pascal
571571type
572572 TsExprFunctionCallBack = procedure (var Result: TsExpressionResult; const Args: TsExprParameterArray);
573573 TsExprFunctionEvent = procedure (var Result: TsExpressionResult; const Args: TsExprParameterArray) of object;
574574```
575575
576576The `TsExpressionResult` is a variant record containing result or argument data of several types:
577577
578578``` pascal
579579type
580580 TsResultType = (rtEmpty, rtBoolean, rtInteger, rtFloat, rtDateTime, rtString,
581581 rtCell, rtCellRange, rtError, rtAny);
582582
583583 TsExpressionResult = record
584584 Worksheet : TsWorksheet;
585585 ResString : String;
586586 case ResultType : TsResultType of
587587 rtEmpty : ();
588588 rtError : (ResError : TsErrorValue);
589589 rtBoolean : (ResBoolean : Boolean);
590590 rtInteger : (ResInteger : Int64);
591591 rtFloat : (ResFloat : TsExprFloat);
592592 rtDateTime : (ResDateTime : TDatetime);
593593 rtCell : (ResRow, ResCol : Cardinal);
594594 rtCellRange : (ResCellRange : TsCellRange);
595595 rtString : ();
596596 end;
597597
598598 TsExprParameterArray = array of TsExpressionResult;
599599```
600600
601601As an example we show here the code for the `CONCATENATE()` formula which joins two or more strings:
602602
603603``` pascal
604604const
605605 INT_EXCEL_SHEET_FUNC_CONCATENATE = 336;
606606...
607607 RegisterFunction('CONCATENATE', 'S', 'S+', INT_EXCEL_SHEET_FUNC_CONCATENATE, @fpsCONCATENATE);
608608
609609procedure fpsCONCATENATE(var Result: TsExpressionResult; const Args: TsExprParameterArray);
610610// CONCATENATE( text1, text2, ... text_n )
611611var
612612 s: String;
613613 i: Integer;
614614begin
615615 s := '';
616616 for i:=0 to Length(Args)-1 do
617617 begin
618618 if Args[i].ResultType = rtError then
619619 begin
620620 Result := ErrorResult(Args[i].ResError);
621621 exit;
622622 end;
623623 s := s + ArgToString(Args[i]);
624624 // "ArgToString" simplifies getting the string from a TsExpressionResult as
625625 // a string may be contained in the ResString and in the ResCell fields.
626626 // There is such a function for each basic data type.
627627 end;
628628 Result := StringResult(s);
629629 // "StringResult" stores the string s in the ResString field of the
630630 // TsExpressionResult and sets the ResultType to rtString.
631631 // There is such a function for each basic data type.
632632end;
633633```
634634
635635There is a worked-out example (*demo_formula_func.pas*) in the folder *examples/other* of the FPSpreadsheet installation. In this demo, four financial functions (`FV()`, `PV()`, `PMT()`, `RATE()`) are added to FPSpreadsheet.
636636
637637#### Unsupported formulas
638638
639639Sometimes it is required to create files for the Office applications with formulas not supported by fpspreadsheet. This is possible to some extent when the workbook option `boIgnoreFormulas` is active. Then any arbitrary formula can be written to a cell, and the formula is not checked and not evaluated. The workbook can be written to an .ods or .xlsx file. The old xls file format cannot be used because the formula would have to be parsed to create the rpn formula needed.
640640
641641In folder *examples/other* you can find the sample project *demo_ignore_formula* which creates an ods file with references to another data file - external references normally are not supported by fpspreadsheet, and thus the ignore-formulas workaround must be used. Note that this example does not work with xlsx because Excel writes information on the external links to separate xml files within the xlsx container.
642642
643643### Cell formatting
644644
645645#### Number and date/time formats
646646
647647Numbers and date/time values can be displayed in a variety of formats. In FPSpreadsheet this can be achieved in two ways:
648648
649649- using **built-in number formats** by specifiying a value for the `NumberFormat` of the cell
650650- using a custom **format string**.
651651
652652Number formats can be specified by these worksheet methods:
653653
654654``` pascal
655655type
656656 TsWorksheet = class
657657 public
658658 // Set number formats alone
659659 function WriteNumberFormat(ARow, ACol: Cardinal; ANumberFormat: TsNumberFormat;
660660 const AFormatString: String = ''): PCell; overload;
661661 procedure WriteNumberFormat(ACell: PCell; ANumberFormat: TsNumberFormat;
662662 const AFormatString: String = ''); overload;
663663
664664 function WriteNumberFormat(ARow, ACol: Cardinal; ANumFormat: TsNumberFormat;
665665 ADecimals: Integer; ACurrencySymbol: String = ''; APosCurrFormat: Integer = -1;
666666 ANegCurrFormat: Integer = -1): PCell; overload;
667667 procedure WriteNumberFormat(ACell: PCell; ANumFormat: TsNumberFormat;
668668 ADecimals: Integer; ACurrencySymbol: String = '';
669669 APosCurrFormat: Integer = -1; ANegCurrFormat: Integer = -1); overload;
670670
671671 function WriteFractionFormat(ARow, ACol: Cardinal; AMixedFraction: Boolean;
672672 ANumeratorDigits, ADenominatorDigits: Integer): PCell; overload;
673673 procedure WriteFractionFormat(ACell: PCell; AMixedFraction: Boolean;
674674 ANumeratorDigits, ADenominatorDigits: Integer); overload;
675675
676676 // Set date/time formats alone
677677 function WriteDateTimeFormat(ARow, ACol: Cardinal; ANumberFormat: TsNumberFormat;
678678 const AFormatString: String = ''): PCell; overload;
679679 procedure WriteDateTimeFormat(ACell: PCell; ANumberFormat: TsNumberFormat;
680680 const AFormatString: String = ''); overload;
681681
682682 // Set cell values and number formats in one call
683683
684684 // number values
685685 function WriteNumber(ARow, ACol: Cardinal; ANumber: double;
686686 AFormat: TsNumberFormat = nfGeneral; ADecimals: Byte = 2;
687687 ACurrencySymbol: String = ''): PCell; overload;
688688 procedure WriteNumber(ACell: PCell; ANumber: Double; AFormat: TsNumberFormat = nfGeneral;
689689 ADecimals: Byte = 2; ACurrencySymbol: String = ''); overload;
690690 function WriteNumber(ARow, ACol: Cardinal; ANumber: double;
691691 AFormat: TsNumberFormat; AFormatString: String): PCell; overload;
692692 procedure WriteNumber(ACell: PCell; ANumber: Double;
693693 AFormat: TsNumberFormat; AFormatString: String); overload;
694694
695695 // date/time values
696696 function WriteDateTime(ARow, ACol: Cardinal; AValue: TDateTime;
697697 AFormat: TsNumberFormat = nfShortDateTime; AFormatStr: String = ''): PCell; overload;
698698 procedure WriteDateTime(ACell: PCell; AValue: TDateTime;
699699 AFormat: TsNumberFormat = nfShortDateTime; AFormatStr: String = ''); overload;
700700 function WriteDateTime(ARow, ACol: Cardinal; AValue: TDateTime;
701701 AFormatStr: String): PCell; overload;
702702 procedure WriteDateTime(ACell: PCell; AValue: TDateTime;
703703 AFormatStr: String); overload;
704704
705705 // currency values
706706 function WriteCurrency(ARow, ACol: Cardinal; AValue: Double;
707707 AFormat: TsNumberFormat = nfCurrency; ADecimals: Integer = 2;
708708 ACurrencySymbol: String = '?'; APosCurrFormat: Integer = -1;
709709 ANegCurrFormat: Integer = -1): PCell; overload;
710710 procedure WriteCurrency(ACell: PCell; AValue: Double;
711711 AFormat: TsNumberFormat = nfCurrency; ADecimals: Integer = -1;
712712 ACurrencySymbol: String = '?'; APosCurrFormat: Integer = -1;
713713 ANegCurrFormat: Integer = -1); overload;
714714 function WriteCurrency(ARow, ACol: Cardinal; AValue: Double;
715715 AFormat: TsNumberFormat; AFormatString: String): PCell; overload;
716716 procedure WriteCurrency(ACell: PCell; AValue: Double;
717717 AFormat: TsNumberFormat; AFormatString: String); overload;
718718 ...
719719```
720720
721721##### Built-in number formats
722722
723723The **built-in formats** are defined by the enumeration `TsNumberFormat`. In spite of its name, the elements cover both number and date/time values:
724724
725725``` pascal
726726type
727727 TsNumberFormat = (
728728 // general-purpose for all numbers
729729 nfGeneral,
730730 // numbers
731731 nfFixed, nfFixedTh, nfExp, nfPercentage, nfFraction,
732732 // currency
733733 nfCurrency, nfCurrencyRed,
734734 // dates and times
735735 nfShortDateTime, nfShortDate, nfLongDate, nfShortTime, nfLongTime,
736736 nfShortTimeAM, nfLongTimeAM, nfDayMonth, nfMonthYear, nfTimeInterval,
737737 // other (using format string)
738738 nfCustom);
739739```
740740
741741- **nfGeneral** corresponds to the default formatting showing as many decimals as possible (the number `3.141592654` would be unchanged.)
742742- **nfFixed** limits the decimals. The number of decimal places has to be specified in the call to `WriteNumber`. Example: with 2 decimals, the number `3.141592654` becomes `3.14`.
743743- **nfFixedTh**: similar to `nfFixed`, but adds a thousand separator when the number is displayed as a string: The number `3.141592654` would remain like in the previous example because it is too small to show thousand separators. But the number `314159.2654` would become `314,159.26`, for 2 decimals.
744744- **nfExp** selects exponential presentation, i.e. splits off the exponent. The parameter `ADecimals` in `WriteNumber` determines how many decimal places are used. (The number `3.141592654` becomes `3.14E+00` in case of two decimals).
745745- **nfPercentage** displays the number as a percentage. This means that the value is multiplied by 100, and a percent sign is added. Again, specify in `ADecimals` how many decimal places are to be shown. (The number `3.141592654` is displayed as `314.92%`, in case of 2 decimals).
746746- **nfFraction** presents a number as a fraction. Details (mixed fraction?, maximum digit count for numerator or denominator) for can be specified in the worksheet method `WriteFractionFormat`.
747747- **nfCurrency** displays the number together with a currency symbol, and there are special rules how to display negative values (in brackets, or minus sign before or after the number). The FormatSettings of the workbook are used to define the currency sign and the way numbers are displayed (`FormatSettings.CurrencyString` for the currency symbol, `FormatSettings.CurrencyFormat` for positive, `FormatSettings.NegCurrFormat` for negative values). These settings can be overridden by specifying them in the call to `WriteCurrency` directly.
748748- **nfCurrendyRed** like `nfCurrency`, in addition negative values are displayed in red.
749749- **nfShortDateTime** presents the DateTimeValue of the cell in "short date/time format", i.e. days + two digit months + two digit year + hours + minutes, no seconds. The order of the date parts is taken from the workbook's `FormatSettings`. This applies also to the other date/time formats.
750750- **nfShortDate** creates a date string showing day + two-digit month + two-digit year
751751- **nfShortTime** creates a time string showing hours + minutes.
752752- **nfLongTime**, similar, but includes seconds as well
753753- **nfShortTimeAM**, similar to `nfShortTime`, but uses the AM/PM time format, i.e. hours go up to 12, and AM or PM is added to specify morning or evening/afternoon.
754754- **nfLongTimeAM**, like `nfShortTimeAM`, but includes seconds
755755- **nfTimeInterval**, like `nfLongTime`, but there can be more than 24 hours. The interval can also be expressed in minutes or seconds, if the format strings `[n]:ss`, or `[s]`, respectively, are used.
756756- **nfCustom** allows to specify a dedicated formatting string.
757757
758758As already noted the workbook has a property `FormatSettings` which provides additional information to control the resulting formatting. This is essentially a copy of the `DefaultFormatSettings` declared in the *sysutils* unit (the elements `LongDateFormat` and `ShortDateFormat` are slightly modified to better match the default settings in the main spreadsheet applications). The main purpose of the `FormatSettings` is to add a simple way of localization to the number formats.
759759
760760##### Number format strings
761761
762762In addition to these pre-defined formats, more specialized formatting can be achieved by using the format constant `nfCustom` along with a dedicated **format string**. The format string is constructed according to Excel syntax which is close to the syntax of fpc's `FormatFloat` and `FormatDateTime` commands (accepted as well, see the online-help for these functions).
763763
764764Here is a basic list of the symbols used:
765765
766-<thead>
767-
768-</thead>
769-<tbody>
770-
771-1.2345678 --&gt; <code>'1.2345678'</code></td>
772-
773-<code>'0.0'</code>: 1 --&gt; <code>'1.0'</code><br />
774-<code>'0.0'</code>: 1.2345678 --&gt; <code>'1.2'</code></td>
775-
776-<code>'0.*'</code>: 1.2345678 --&gt; <code>'1.2'</code></td>
777-
778-<code>'0.0??'</code>: 1 --&gt; <code>'1.0 '</code></td>
779-
780-<code>'0.00,'</code>: 1200 --&gt; <code>'1.20'</code></td>
781-
782-<code>'# #/#'</code>: 1.5 --&gt; <code>'1 1/2'</code><br />
783-<code>'# #/16'</code>: 1.5 --&gt; <code>'1 8/16'</code><br />
784-also: see date/time examples below</td>
785-
786-Jan 3, 2012 --&gt; <code>'2012-01-03'</code><br />
787-In this example, the <code>DateSeparator</code> is a dash character (<code>-</code>).</td>
788-
789-Jan 3, 2012 --&gt; <code>'12-01-03'</code></td>
790-
791-Please note that the <code>m</code> code can also be interpreted as the "minutes" of a time value (see below).</td>
792-
793-Jan 3, 2012 --&gt; <code>'2012-1-03'</code></td>
794-
795-Please note that the <code>mm</code> code can also be interpreted as the "minutes" of a time value (see below).</td>
796-
797-Jan 3, 2012 --&gt; <code>'2012-01-03'</code></td>
798-
799-Jan 3, 2012 --&gt; <code>'2012-Jan-03'</code></td>
800-
801-Jan 3, 2012 --&gt; <code>'2012-January-03'</code></td>
802-
803-Jan 3, 2012 --&gt; <code>'2012-01-3'</code></td>
804-
805-Jan 3, 2012 --&gt; <code>'2012-01-03'</code></td>
806-
807-Jan 03, 2012 --&gt; <code>'Tue 2012-01-03'</code></td>
808-
809-Jan 03, 2012 --&gt; <code>'Tuesday 2012-01-03'</code></td>
810-
811-0.25 --&gt; <code>'6:00'</code></td>
812-
813-0.25 --&gt; <code>'06:00'</code></td>
814-
815-1.25 --&gt; <code>'30:00'</code></td>
816-
817-0.25 --&gt; <code>'6:0'</code></td>
818-
819-0.25 --&gt; <code>'6:00'</code></td>
820-
821-1.25 --&gt; <code>'1800:00'</code></td>
822-
823-0.25 --&gt; <code>'06:00:0'</code></td>
824-
825-0.25 --&gt; <code>'06:00:00'</code></td>
826-
827-1.25 --&gt; <code>'108000'</code></td>
828-
829-0.25 --&gt; <code>'6:00:00 AM'</code></td>
830-
831-Jan 3, 2012 --&gt; <code>'2012/01/03'</code> (i.e. the <code>/</code> is not replaced by the <code>DateSeparator</code> of the workbook).</td>
832-
833-Jan 3, 2012 --&gt; <code>'2012/01/03'</code></td>
834-
835-1200 --&gt; <code>'1,200$'</code><br />
836--1200 --&gt; <code>'1,200$'</code><br />
837-0 --&gt; <code>'-'</code></td>
838-
839--1200 --&gt; <code>'(1200)$'</code></td>
840-
841--1200 --&gt; '<code>($ 1200.00)</code>'</td>
842-
843-</tbody>
766+| Symbol | Meaning | Format string: Number --> Output string |
767+|---|---|---|
768+| `General` | Displays all decimal places of the number | `'General'`: · 1.2345678 --> `'1.2345678'` |
769+| `0` | Displays insignificant zeros if a number has less digits than there are zeros in the format. If used for decimal places then the number is rounded to as many decimal places as 0s are found. | `'000'`: 1 --> `'001'` · `'0.0'`: 1 --> `'1.0'` · `'0.0'`: 1.2345678 --> `'1.2'` |
770+| `*` | Like "0" above, but does not display insignificant zeros. | `'0.*'`: 1 --> `'1.'` · `'0.*'`: 1.2345678 --> `'1.2'` |
771+| `?` | Like "0" above, but insignificant zeros are replaced by space characters. Good for aligning decimal points and fractions | `'??0'`: 1 --> `' 1'` · `'0.0??'`: 1 --> `'1.0 '` |
772+| `.` | Decimal separator; will be replaced by the value used in the `DecimalSeparator` of the workbook's `FormatSettings` | `'0.00'`: 8.9 --> `'8.90'` |
773+| `,` | Thousand separator; will be replaced by the value used in the `ThousandSeparator` of the workbook's `FormatSettings`. If at the end of a number formatting sequence the displayed value is divided by 1000. | `'#,##0.00'`: 1200 --> `'1,200.00'` · `'0.00,'`: 1200 --> `'1.20'` |
774+| `E+`, `e+` | Displays a number in exponential format. The digits used for the exponent are defined by the number of zeros added the this symbol. The sign of the exponent is shown for positive and negative exponents. | `'0.00E+00'`: 1200 --> `1.20E+03` |
775+| `E-`, `e-` | Displays a number in exponential format. The digits used for the exponent are defined by the number of zeros added the this symbol. The sign of the exponent is shown only for negative exponents. | `'0.00e-000'`: 1200 --> `1.20e003` |
776+| `%` | Displays the number as a "percentage", i.e. the number is multiplied by 100 and a `%` sign is added. | `'0.0%'`: 0.75 --> `75.0%` |
777+| `/` | This symbol has two meanings: if the cell represents a "number" then the slash indicates formatting as fraction, place holders for numerator and denominator must follow. If the cell represents a "date/time" then the slash indicates the date separator which will be replaced by the `DateSeparator` of the workbook's `FormatSettings` | `'#/#'`: 1.5 --> `'3/2'` · `'# #/#'`: 1.5 --> `'1 1/2'` · `'# #/16'`: 1.5 --> `'1 8/16'` · also: see date/time examples below |
778+| `:` | Separator between hours, minutes and seconds of a date/time value. Will be replaced by the `TimeSeparator` of the workbook's `FormatSettings`. | see examples below |
779+| `yyyy` | Place holder for the year of a date/time value. The year is displayed as a four-digit number. | `'yyyy/mm/dd'`: · Jan 3, 2012 --> `'2012-01-03'` · In this example, the `DateSeparator` is a dash character (`-`). |
780+| `yy` | Place holder for the year of a date/time value. The year is displayed as a two-digit number. | `'yy/mm/dd'`: · Jan 3, 2012 --> `'12-01-03'` |
781+| `m` | Place holder for the month of a date/time value. The month is shown as a number without extra digits. · Please note that the `m` code can also be interpreted as the "minutes" of a time value (see below). | `'yyyy/m/dd'`: · Jan 3, 2012 --> `'2012-1-03'` |
782+| `mm` | Place holder for the month of a date/time value. The month is shown as a two-digit number, i.e. a leading zero is added for January to September. · Please note that the `mm` code can also be interpreted as the "minutes" of a time value (see below). | `'yyyy/mm/dd'`: · Jan 3, 2012 --> `'2012-01-03'` |
783+| `mmm` | Place holder for the month of a date/time value. The month is displayed by its abbreviated name. | `'yyyy/mmm/dd'`: · Jan 3, 2012 --> `'2012-Jan-03'` |
784+| `mmmm` | Place holder for the month of a date/time value. The month is displayed by its full name. | `'yyyy/mmm/dd'`: · Jan 3, 2012 --> `'2012-January-03'` |
785+| `d` | Place holder for the day of a date/time value to be displayed as a number. The day is displayed as a simple number, without adding a leading zero. | `'yyyy/mm/d'`: · Jan 3, 2012 --> `'2012-01-3'` |
786+| `dd` | Place holder for the day of a date/time value to be displayed as a number. `dd` adds a leading zero to single-digit day numbers. | `'yyyy/mm/dd'`: · Jan 3, 2012 --> `'2012-01-03'` |
787+| `ddd` | Place holder for the day of a date/time value. The day is displayed as its abbreviated name. | `'dddd, yyyy/mm/ddd'`: · Jan 03, 2012 --> `'Tue 2012-01-03'` |
788+| `dddd` | Place holder for the day of a date/time value. The day is displayed as its full name. | `'dddd, yyyy/mmmm/dd'`: · Jan 03, 2012 --> `'Tuesday 2012-01-03'` |
789+| `h` | Place holder of the hour part of a date/time value. The hour is displayed as a simple number, without adding a leading zero. | `'h:mm'`: · 0.25 --> `'6:00'` |
790+| `hh` | Place holder of the hour part of a date/time value. The hour is displayed with a leading zero if the hour is less than 10. | `'hh:mm'`: · 0.25 --> `'06:00'` |
791+| `[hh]`, or `[h]` | Displays elapsed time such that the hour part can become greater than 23 | `'[h]:mm'`: · 1.25 --> `'30:00'` |
792+| `m` | Place holder of the minutes part of a date/time value. The minutes are shown as a simple number without adding a leading zero. Note that if the `m` codes are surrounded by date symbols (`y`, `d`) then they are interpreted as "month". | `'h:m'`: · 0.25 --> `'6:0'` |
793+| `mm` | Place holder of the minutes part of a date/time value. Single-digit minutes are displayed with a leading zero. Note that if the `mm` code is surrounded by date symbols (`y`, `d`) then it is interpreted as "month". | `'h:mm'`: · 0.25 --> `'6:00'` |
794+| `[mm]`, or `[m]` | Displays elapsed time such that the minute part can become greater than 59 | `'[mm]:ss'`: · 1.25 --> `'1800:00'` |
795+| `s` | Place holder of the seconds part of a date/time value. The seconds are displayed as a simple number, without adding a leading zero. | `'hh:mm:s'`: · 0.25 --> `'06:00:0'` |
796+| `ss` | Place holder of the seconds part of a date/time value. Single-digit seconds are displayed with a leading zero. | `'hh:mm:ss'`: · 0.25 --> `'06:00:00'` |
797+| `[ss]`, or `[s]` | Displays elapsed time such that the seconds part can become greater than 59 | `'[ss]'`: · 1.25 --> `'108000'` |
798+| `AM/PM`, `am/pm`, `A/P`, or `a/p` | Displays the time in the 12-hour format. | `'hh:mm:ss AM/PM'`: · 0.25 --> `'6:00:00 AM'` |
799+| `"` | The text enclosed by quotation marks is inserted into the formatted strings literally. | `'yyyy"/"mm"/"dd'`: · Jan 3, 2012 --> `'2012/01/03'` (i.e. the `/` is not replaced by the `DateSeparator` of the workbook). |
800+| `\` | The next character of the format string appears in the result string literally. The `\` itself does not show up. | `'yyyy\/mm\/dd'`: · Jan 3, 2012 --> `'2012/01/03'` |
801+| `;` | A format string can contain up to three sections separated by the semicolon. The first section is used for positive numbers, the second section for negative numbers, and the third section for zero numbers. If the third section is missing then a zero value is formatted as specified in the first section. If the second section is missing as well then all values are formatted according to the first section. | `'"#,##0"$"';-#,##0"$";"-"'`: · 1200 --> `'1,200$'` · -1200 --> `'1,200$'` · 0 --> `'-'` |
802+| `(`, and `)` | Sometimes used for currency values to indicate negative numbers, instead of minus sign | `'#,##0"$";(#,##0)"$"'`: · -1200 --> `'(1200)$'` |
803+| `[red]` | The formatted string is displayed in the specified color. Instead of `[red]`, you can use accordingly `[black]`, `[white]`, `[green]`, `[blue]`, `[magenta]`, `[yellow]`, or `[cyan]`. Often used to highlight negative currency values. | `'"$" #,##0.00;[red]("$" #,##0.00)'`: · -1200 --> '`($ 1200.00)`' |
844804
845805#### Colors
846806
847807FPSpreadsheet supports colors for text, cell background, and cell borders. The basic EGA colors are declared in unit *fpstypes* as constants:
848808
849809![](/wiki-images/7/7b/DefaultPalette.png)
850810
851811``` pascal
852812type
853813 TsColor = DWORD;
854814
855815const
856816 scBlack = $00000000;
857817 scWhite = $00FFFFFF;
858818 scRed = $000000FF;
859819 scGreen = $0000FF00;
860820 scBlue = $00FF0000;
861821 scYellow = $0000FFFF;
862822 scMagenta = $00FF00FF;
863823 scCyan = $00FFFF00;
864824 scDarkRed = $00000080;
865825 scDarkGreen = $00008000;
866826 scDarkBlue = $00800000;
867827 scOlive = $00008080;
868828 scPurple = $00800080;
869829 scTeal = $00808000;
870830 scSilver = $00C0C0C0;
871831 scGray = $00808080;
872832 scGrey = scGray; // redefine to allow different spelling
873833
874834 // Identifier for undefined color
875835 scNotDefined = $40000000;
876836
877837 // Identifier for transparent color
878838 scTransparent = $20000000;
879839```
880840
881841The `TsColor` represents the **rgb value** of a color, a single byte being used for the red, green, and blue components. The resulting number is in little endian notation, i.e. the red value comes first in memory: `$00BBGGRR`. (This is directly compatible with the color values as defined in the *graphics* unit.)
882842
883843The high order byte is usually zero but is used internally to identify special color values, such as for undefined or transparent colors.
884844
885845> **Note:** In older versions of the library colors were defined as indexes into a color palette. **THIS IS NO LONGER WORKING.**
886846
887847Unit *fpsutils* contains some useful functions for **modification of colors**:
888848
889849- `function GetColorName(AColor: TsColor): String;`\
890850 returns the name of the colors defined above, or a string showing the rgb components for other colors.
891851- `function HighContrastColor(AColor: TsColor): TsColor;`\
892852 returns `scBlack` for a "bright", `scWhite` for a "dark" input color.
893853- `function TintedColor(AColor: TsColor; tint: Double): TsColor;`\
894854 brightens or darkens a color by applying a factor `tint = -1..+1`, where `-1` means "100% darken", `+1` means "100% brighten", and `0` means "no change". The hue of the color is preserved.
895855
896856#### Cell background
897857
898858The cell background can be filled by predefined patterns which are identified by the record `TsFillPattern`:
899859
900860``` pascal
901861type
902862 TsFillPattern = record
903863 Style: TsFillStyle; // fill style pattern as defined below
904864 FgColor: TsColor; // forground color of the fill pattern
905865 BgColor: TsColor; // background color of the fill pattern
906866 end;
907867
908868 TsFillStyle = (fsNoFill, fsSolidFill, fsGray75, fsGray50, fsGray25, fsGray12, fsGray6,
909869 fsStripeHor, fsStripeVert, fsStripeDiagUp, fsStripeDiagDown,
910870 fsThinStripeHor, fsThinStripeVert, fsThinStripeDiagUp, fsThinStripeDiagDown,
911871 fsHatchDiag, fsThinHatchDiag, fsThickHatchDiag, fsThinHatchHor);
912872```
913873
914874- Use the worksheet method `WriteBackground` to assign a fill pattern to a specific cell. Besides the cell address, this method requires the type of the fill pattern (`TsFillStyle`), and the foreground and background colors as specified by their `TsColor` values.
915875- The fill pattern of a particular cell can be retrieved by calling the workbook method `ReadBackground`.
916876- The simplified method `WriteBackgroundColor` can be used to achieve a uniform background color.
917877- **Limitations:**
918878 - OpenDocument files support only uniform fills. The background color is a mixture of the foreground and background rgb components in a ratio defined by the fill pattern.
919879 - BIFF2 files support only a 12.5% black-and-white shaded pattern.
920880
921881``` pascal
922882type
923883 TsWorksheet = class
924884 public
925885 function WriteBackground(ARow, ACol: Cardinal; AStyle: TsFillStyle; APatternColor, ABackgroundColor: TsColor): PCell; overload;
926886 procedure WriteBackground(ACell: PCell; AStyle: TsFillStyle; APatternColor, ABackgroundColor: TsColor); overload;
927887
928888 function WriteBackgroundColor(ARow, ACol: Cardinal; AColor: TsColor): PCell; overload;
929889 procedure WriteBackgroundColor(ACell: PCell; AColor: TsColor); overload;
930890
931891 function ReadBackground(ACell: PCell): TsFillPattern;
932892 function ReadBackgroundColor(ACell: PCell): TsColor; overload;
933893 // ...
934894 end;
935895
936896var
937897 cell: PCell;
938898...
939899 // Example 1: Assign a pattern of thin, horizontal, yellow stripes on a blue background to empty cell A1 (row 0, column 0)
940900 MyWorksheet.WriteBackground(0, 0, fsThinStripeHor, scYellow, scBlue);
941901
942902 // Example 2: Uniform gray background color of cell B1 (row 0, column 1) containing the number 3.14
943903 cell := MyWorksheet.WriteNumber(0, 1, 3.14);
944904 MyWorksheet.WriteBackgroundColor(cell, clSilver);
945905```
946906
947907#### Cell borders
948908
949909Cells can be emphasized by drawing border lines along their edges or diagonal lines. There are four borders plus two diagonals enumerated in the data type `TsCellBorder`:
950910
951911``` pascal
952912type
953913 TsCellBorder = (cbNorth, cbWest, cbEast, cbSouth, dbDiagUp, dbDiagDown);
954914 TsCellBorders = set of TsCellBorder;
955915```
956916
957917In order to show a border line add the corresponding border to the cell's set `Borders` (type `TsCellBorders`, see above). In this way, each cell edge can be handled separately. Use the worksheet method `WriteBorders` for this purpose. This example adds top and bottom borders to the edges A1 and B1:
958918
959919``` pascal
960920 MyWorksheet.WriteBorders(0, 0, [cbNorth, cbSouth]); // A1: row 0, column 0
961921 MyWorksheet.WriteBorders(0, 1, [cbNorth, cbSourth]); // B1: row 0, column 1
962922```
963923
964924Lines usually are drawn as thin, solid, black lines. But it is possible to modify **line style** and **color** of each line. For this purpose, the cell provides an array of `TsCellBorderStyle` records:
965925
966926``` pascal
967927type
968928 TsLineStyle = (lsThin, lsMedium, lsDashed, lsDotted, lsThick, lsDouble, lsHair,
969929 lsMediumDash, lsDashDot, lsMediumDashDot, lsDashDotDot, lsMediumDashDotDot, lsSlantDashDot);
970930
971931 TsCellBorderStyle = record
972932 LineStyle: TsLineStyle;
973933 Color: TsColor;
974934 end;
975935
976936 TsCellBorderStyles = array[TsCellBorder] of TsCellBorderStyle;
977937
978938 TsWorksheet = class
979939 public
980940 function WriteBorderStyle(ARow, ACol: Cardinal; ABorder: TsCellBorder; AStyle: TsCellBorderStyle): PCell; overload;
981941 procedure WriteBorderStyle(ACell: PCell; ABorder: TsCellBorder; AStyle: TsCellBorderStyle); overload;
982942
983943 function WriteBorderStyle(ARow, ACol: Cardinal; ABorder: TsCellBorder; ALineStyle: TsLineStyle; AColor: TsColor): PCell; overload;
984944 procedure WriteBorderStyle(ACell: PCell; ABorder: TsCellBorder; ALineStyle: TsLineStyle; AColor: TsColor); overload;
985945
986946 function WriteBorderColor(ARow, ACol: Cardinal; ABorder: TsCellBorder; AColor: TsColor): PCell; overload;
987947 proceure WriteBorderColor(ACell: PCell; ABorder: TsCellBorder; AColor: TsColor): PCell; overload;
988948
989949 function WriteBorderLineStyle(ARow, ACol: Cardinal; ABorder: TsCellBorder; ALineStyle: TsLineStyle): PCell; overload;
990950 procedure WriteBorderLineStyle(ACell: PCell; ABorder: TsCellBorder; ALineStyle: TsLineStyle): PCell; overload;
991951
992952 function WriteBorderStyles(ARow, ACol: Cardinal; const AStyles: TsCellBorderStyles): PCell; overload;
993953 procedure WriteBorderStyles(ACell: PCell; const AStyles: TsCellBorderStyles); overload;
994954
995955 function WriteBorders(ARow, ACol: Cardinal; ABorders: TsCellBorders): PCell; overload
996956 procedure WriteBorders(ACell: PCell; ABorders: TsCellBorders); overload
997957
998958 function ReadCellBorders(ACell: PCell): TsCellBorders;
999959 function ReadCellBorderStyle(ACell: PCell; ABorder: TsCellBorder): TsCellBorderStyle;
1000960 function ReadCellBorderStyles(ACell: PCell): TsCellBorderStyles;
1001961 ...
1002962 end;
1003963```
1004964
1005965The style of a given cell border can be specified by the following methods provided by the worksheet:
1006966
1007967- **WriteBorderStyle** assigns a cell border style record to one border of the cell. There are two overloaded versions of this method: one takes an entire `TsCellBorderStyle` record, the other one takes the individual record elements.
1008968- **WriteBorderColor** changes the color of a given border without affecting the line style of this border.
1009969- **WriteBorderLineStyle** sets the line style of the border only, but leaves the color unchanged.
1010970- **WriteBorderStyles** sets the border style of all borders of a given cell at once. Useful for copying border styles from one cell to other cells.
1011971
1012972This example adds a thin black border to the top, and a thick blue border to the bottom of cells A1 and B1:
1013973
1014974``` pascal
1015975var
1016976 cellA1, cellB1: PCell;
1017977...
1018978 cellA1 := MyWorksheet.WriteBorders(0, 0, [cbNorth, cbSouth]); // cell A1: row 0, column 0
1019979 MyWorksheet.WriteBorderStyle(cellA1, cbNorth, lsThin, scBlack);
1020980 MyWorksheet.WriteBorderStyle(cellA1, cbSouth, lsThick, scBlue);
1021981
1022982 cellB1 := MyWorksheet.WriteBorders(0, 1, [cbNorth, cbSouth]); // cell B1: row 0, column 1
1023983 MyWorksheet.WriteBorderStyles(cellB1, cellA1^.BorderStyles); // copy all border styles from cell A1 to B1
1024984```
1025985
1026986> **Note:** Diagonal lines are not supported by *sfExcel2* and *sfExcel5* - they are just omitted. *sfExcel8* and *sfOOXML* use the same linestyle and color for both diagonals; when writing the border style of the diagonal-up line is assumed to be valid also for the diagonal-down line. Some writers do not support all the line styles of the `TsLineStyle` enumeration. In this case, appropriate replacement line styles are used.
1027987
1028988#### Fonts
1029989
1030990The cell text can displayed in various fonts. For this purpose, the workbook provides a list of `TsFont` items:
1031991
1032992``` pascal
1033993type
1034994 TsFont = class
1035995 FontName: String;
1036996 Size: Single;
1037997 Style: TsFontStyles;
1038998 Color: TsColor;
1039999 Position: TsFontPosition;
10401000 end;
10411001```
10421002
10431003- The **FontName** corresponds to the name of the font as used by the operational system. In Windows, an example would be "Times New Roman".
10441004- The **FontSize** is given in "points", i.e. units 1/72 inch which are commonly used in Office applications.
10451005- The **FontStyle** is a set of the items `fssBold`, `fssItalic`, `fssStrikeout`, and `fssUnderline` which form the enumeration type `TsFontStyle`. The "normal" font corresponds to an empty set.
10461006- The **Color** determines the foreground color of the text characters given in rgb presentation as discussed above.
10471007- The **Position** is either `fpNormal`, `fpSuperscript`, or `fpSubscript` and indicates whether the font size should be decreased by about 1/3 and the characters should be displaced up (superscript) or down (subscript).
10481008
10491009Every cell is provided with an **index into the font list**.
10501010
10511011In order to assign a particular font to a cell, use one of the following methods of `TsSpreadsheet`:
10521012
10531013``` pascal
10541014type
10551015 TsSpreadsheet = class
10561016 public
10571017 function WriteFont(ARow, ACol: Cardinal; const AFontName: String;
10581018 AFontSize: Single; AFontStyle: TsFontStyles; AFontColor: TsColor): Integer; overload;
10591019 procedure WriteFont(ARow, ACol: Cardinal; AFontIndex: Integer); overload;
10601020 function WriteFontColor(ARow, ACol: Cardinal; AFontColor: TsColor): Integer;
10611021 function WriteFontSize(ARow, ACol: Cardinal; ASize: Integer): Integer;
10621022 function WriteFontStyle(ARow, ACol: Cardinal; AStyle: TsFontStyles): Integer;
10631023 // plus: overloaded versions accepting a pointer to a cell record instead of the row and column index as parameter
10641024 // ...
10651025 end;
10661026```
10671027
10681028- **WriteFont** assigns a font to the cell. If the font does not yet exist in the font list a new entry is created. The function returns the index of the font in the font list. In addition, there is an overloaded version which only takes the font index as a parameter.
10691029- **WriteFontColor** replaces the color of the font that is currently assigned to the cell by a new one. Again, a new font list item is created if the font with the new color does not yet exist. The function returns the index of the font in the list.
10701030- **WriteFontSize** replaces the size of the currently used font of the cell.
10711031- **WriteFontStyle** replaces the style (normal, bold, italic, etc.) of the currently used cell font.
10721032
10731033The workbook's font list contains at least one item which is the **default font** for cells with unmodified fonts. By default, this is 10-point "Arial". Use the workbook method `SetDefaultFont` to assign a different font to the first list item.
10741034
10751035The font at a given index of the font list can be looked up by calling the workbook function `GetFont`. The count of available fonts is returned by `GetFontCount`.
10761036
10771037Here is an **example** which decreases the size of all 10-point "Arial" fonts to 9-point:
10781038
10791039``` pascal
10801040var
10811041 i: Integer;
10821042 font: TsFont;
10831043begin
10841044 for i := 0 to MyWorkbook.GetFontCount-1 do
10851045 begin
10861046 font := MyWorkbook.GetFont(i);
10871047 if (font.FontName = 'Arial') and (font.Size = 10.0) then
10881048 font.Size := 9.0;
10891049 end;
10901050end;
10911051```
10921052
10931053#### Rich-text formatting
10941054
10951055In addition to using a specific font for each cell it is also possible to specify particular font attributes for individual characters or groups of characters in each cell text. Following the Excel notation, we call this feature **Rich-text formatting** (although is has nothing in common with the "rich-text" file format).
10961056
10971057For this purpose, unit *fpstypes* declares the type `TsRichTextParams` which is an array of `TsRichTextParam` records:
10981058
10991059``` pascal
11001060type
11011061 TsRichTextParam = record
11021062 FontIndex: Integer;
11031063 FirstIndex: Integer;
11041064 end;
11051065
11061066 TsRichTextParams = array of TsRichTextParam;
11071067```
11081068
11091069`FontIndex` refers to the index of the font in the workbook's FontList to be used for formatting of the characters beginning at the index `FirstIndex`. Being a string character index the `FirstIndex` is 1-based.
11101070
11111071There are two ways to add "rich-text" formatting to a cell text:
11121072
11131073- Embed corresponding HTML format codes into the cell text. This can be done using the method `WriteTextAsHTML` of the worksheet. In order to add the text "Area (m<sup>2</sup>)" to cell A1, pass the following HTML-coded string to this function
11141074
11151075``` pascal
11161076 MyWorksheet.WriteTextAsHTML(0, 0, 'Area (m<sup>2</sup>');
11171077```
11181078
11191079- Alternatively, the standard text writing method, `WriteText` can be called with an additional parameter specifiying the rich-text formatting parameters to be used directly:
11201080
11211081``` pascal
11221082var
11231083 richTextParams: TsRichTextParams;
11241084 fnt: TsFont;
11251085 cell: PCell;
11261086begin
11271087 SetLength(rtp, 2);
11281088 cell := MyWorksheet.GetFont(0, 0);
11291089 fnt := MyWorksheet.ReadCellFont(cell);
11301090 richTextParams[0].FirstIndex := 8; // The superscript groups begins with "2" which is the (1-based) character #8 of the cell text.
11311091 richTextParams[0].FontIndex := MyWorkbook.AddFont(fnt.FontName, fnt.Size, fnt.Style, fnt.Color, fpSuperscript);
11321092 richTextParams[1].FirstIndex := 9; // Normal font again beginning with character #9.
11331093 richTextParams[1].FontIndex := MyWorksheet.ReadCellFontIndex(0, 0);
11341094 MyWorksheet.WriteUTF8Text(cell, 'Area (m2)', richTextParams);
11351095end;
11361096```
11371097
11381098Use the worksheet method `DeleteRichTextParams` to remove rich-text formatting from a previously formatted cell.
11391099
11401100> **Note:** If the cell is supposed to have a font different from the worksheet's default font then this font must be written to the cell **before** writing the rich-text formatted text. Otherwise the font in the unformatted regions will not be up-to-date.
11411101
11421102#### Text rotation
11431103
11441104Usually text is displayed in the cells horizontally. However, it is also possible to rotate it by 90 degrees in clockwise or counterclockwise directions. In addition, there is also an option to stack horizontal characters vertically above each other.
11451105
11461106If you need this feature use the worksheet method `WriteTextRotation` and specify the text direction by an element of the enumeration type `TsTextRotation`:
11471107
11481108``` pascal
11491109type
11501110 TsTextRotation = (trHorizontal, rt90DegreeClockwiseRotation,
11511111 rt90DegreeCounterClockwiseRotation, rtStacked);
11521112
11531113 TsWorksheet = class
11541114 public
11551115 function WriteTextRotation(ARow, ACol: Cardinal; ARotation: TsTextRotation): PCell; overload;
11561116 procedure WriteTextRotation(ACell: PCell; ARotation: TsTextRotation); overload;
11571117
11581118 function ReadTextRotation(ACell: PCell): TsTextRotation;
11591119 // ...
11601120 end;
11611121
11621122 // example for counter-clockwise rotated text in cell A1:
11631123 WriteTextRotation(0, 0, rt90DegreeCounterClockwizeRotation);
11641124```
11651125
11661126> **Warning:** Finer degrees of rotation which may be supported by some spreadsheet file formats are ignored.
11671127
11681128#### Text alignment
11691129
11701130By default, cell texts are aligned to the left and bottom edges of the cell, except for numbers which are right-aligned. This behavior can be changed by using the worksheet methods `WriteHorAlignment` and `WriteVertAlignment`:
11711131
11721132``` pascal
11731133type
11741134 TsHorAlignment = (haDefault, haLeft, haCenter, haRight);
11751135 TsVertAlignment = (vaDefault, vaTop, vaCenter, vaBottom);
11761136
11771137 TsWorkbook = class
11781138 public
11791139 function WriteHorAlignment(ARow, ACol: Cardinal; AValue: TsHorAlignment): PCell; overload;
11801140 procedure WriteHorAlignment(ACell: PCell; AValue: TsHorAlignment); overload;
11811141 function ReadHorAlignment(ACell: PCell): TsHorAlignment;
11821142
11831143 function WriteVertAlignment(ARow, ACol: Cardinal; AValue: TsVertAlignment): PCell; overload;
11841144 procedure WriteVertAlignment(ACell: PCell; AValue: TsVertAlignment); overload;
11851145 function ReadVertAlignment(ACell: PCell): TsVertAlignment;
11861146 // ...
11871147 end;
11881148
11891149 // Example: Center the text in cell A1 both horizontally and vertically
11901150 MyWorkbook.WriteHorAlignment(0, 0, haCenter);
11911151 MyWorkbook.WriteVertAlignment(0, 0, vaCenter);
11921152```
11931153
11941154#### Word wrap
11951155
11961156Text which is longer than the width of a cell can wrap into several lines by calling the method `WriteWordwrap` of the spreadsheet:
11971157
11981158``` pascal
11991159type
12001160 TsWorksheet = class
12011161 public
12021162 function WriteWordwrap(ARow, ACol: Cardinal; AValue: Boolean): PCell; overload;
12031163 procedure WriteWordwrap(ACell: PCell; AValue: Boolean); overload;
12041164 function ReadWordwrap(ACell: PCell): Boolean;
12051165 //...
12061166 end;
12071167
12081168 // Example: activate wordwrap in cell A1
12091169 MyWorksheet.WriteWordwrap(0, 0, true);
12101170```
12111171
12121172#### Merged cells
12131173
12141174Like the Office applications, FPSpreadsheet supports also to feature of merging cells to a single large cell which is often used as a common header above simlar columns. Simply call `MergeCells` and pass a parameter to specify the cell range to be merged, either an Excel range string (such as `A1:D5`), or the first and last rows and columns:
12151175
12161176``` pascal
12171177 MyWorksheet.MergeCells('A1:D5');
12181178 // or: MyWorksheet.MergeCells(0, 0, 4, 3); // first row, first column, last row, last column
12191179```
12201180
12211181The content and format displayed for a merged range is taken from the upper left corner of the range, cell `A1` in above example. This cell is called the `MergeBase` in the library. Except for this corner cell, there must not be any other cells in the range. If there are their contents and format will be hidden.
12221182
12231183In order to break up a merged range back up into individual cells, use the command `Unmerge` and pass any cell that is within the merged range:
12241184
12251185``` pascal
12261186 MyWorksheet.UnmergeCells('B1');
12271187 // or: MyWorksheet.UnmergeCells(0, 1); // row, column of any cell within the range
12281188```
12291189
12301190Merged cells can be read from/written to all file formats except for `sfCSV`, `sfExcel2` and `sfExcel5` which do not support this feature natively.
12311191
12321192The information which cells are merged is stored in an internal list. Unlike in earlier versions it is no longer possible to access the `MergeBase` from the cell directly. Use the following functions to extract information on merged cells:
12331193
12341194``` pascal
12351195var
12361196 cell, base: PCell;
12371197 r1,c1,r2,c2: Cardinal;
12381198...
12391199 cell := MyWorksheet.FindCell('B1');
12401200 if MyWorksheet.IsMerged(cell) then
12411201 begin
12421202 WriteLn('Cell B1 is merged.');
12431203
12441204 MyWorksheet.FindMergedRange(cell, r1, c1, r2, c2);
12451205 WriteLn('The merged range is ' + GetCellRangeString(r1, c1, r2, c2));
12461206
12471207 base := MyWorksheet.FindMergeBase(cell);
12481208 WriteLn('The merge base is cell ' + GetCellString(base^.Row, base^.Col));
12491209 end;
12501210```
12511211
12521212#### Cell protection
12531213
12541214This is described in a separate section below.
12551215
12561216### Additional data
12571217
12581218#### Cell comments
12591219
12601220Comments can be attached to any cell by calling
12611221
12621222``` pascal
12631223 MyWorksheet.WriteComment(0, 0, 'This is a comment for cell A1');
12641224```
12651225
12661226They are stored in an internal list of the worksheet. Use the corresponding worksheet methods to access comments:
12671227
12681228- If you want to know whether a particular cell contains a comment call the worksheet method `HasComment(cell)`.
12691229- For retrieving a cell comment use the method `ReadComment(cell)`, or its overloaded companion `ReadComment(ARow, ACol)`.
12701230- The total number of comments can be retrieved from `worksheet.Comments.Count`.
12711231
12721232#### Hyperlinks
12731233
12741234Hyperlinks can be attached to cells in order to link cells to other documents or other cells in the same workbook. The general syntax for creating hyperlinks is
12751235
12761236``` pascal
12771237 procedure TWorksheet.WriteHyperlink(ARow, ACol: Cardinal; ATarget: String; ATooltip: String = '');
12781238```
12791239
12801240- The hyperlink target, passed as parameter `ATarget`, must be a fully qualified [URI (Uniform resource identifier)](http://en.wikipedia.org/wiki/Uniform_Resource_Identifier) consisting of a protocol phrase (e.g., [`http://`](http://), [`file:///`](file:///), `mailto:`, etc.) followed by specific information such as web URL, filename, or e-mail address and an optional bookmark identification separated by the character `'#'`. An exception are internal hyperlinks which enable to jump to a cell in the current workbook; they consist of the optional worksheet name and the cell address separated by the character `'!'`.
12811241- The optional `Tooltip` parameter is evaluated by Excel to display it in a hint window if the mouse if above the hyperlink.
12821242
12831243> **Note:** Hyperlinks can be added to empty cells or to cells with content. In the latter case, the displayed content is not changed by the hyperlink; in the former case the cell is converted to a label cell showing the hyperlink target. Be aware that OpenOffice/LibreOffice only does accept hyperlinks with non-text cells.
12841244
12851245**Examples:**
12861246
12871247``` pascal
12881248 // Open the web site www.google.com
12891249 MyWorksheet.WriteText(0, 0, 'Open google');
12901250 MyWorksheet.WriteHyperlink(0, 0, 'http://www.google.com');
12911251
12921252 // Open the local file with the absolute path "C:\readme.txt" (assuming Windows)
12931253 MyWorksheet.WriteHyperlink(1, 0, 'file:///c:\readme.txt');
12941254
12951255 // Open the mail client to send a mail
12961256 MyWorksheet.WriteText('Send mail');
12971257 MyWorksheet.WriteHyperlink(3, 0, 'mailto:somebody@gmail.com?subject=Test');
12981258
12991259 // Jump to a particular cell
13001260 MyWorksheet.WriteText(5, 0, 'Jump to cell A10 on sheet2');
13011261 MyWorksheet.WriteHyperlink(5, 0, '#Sheet2!A10');
13021262
13031263 // Jump to cell A10 on the current sheet and display a popup hint
13041264 MyWorksheet.WriteHyperlink(5, 0, '#A10', 'Go to cell A10');
13051265```
13061266
13071267> **Note:** FPSpreadsheet does not "follow" the links, it only provides a mechanism to get access to the link data. TsWorksheetGrid from the *laz_fpspreadsheet_visual* package, however, fires the event `OnClickHyperlink` if a cell with an external hyperlink is clicked for fractions of a second. In the corresponding event handler, you can, for example, load a target spreadsheet, or open a web browser to display the linked web site. If the link is an internal link to another cell within the same workbook then the grid jumps to the related cell.
13081268
13091269#### Images
13101270
13111271FPSpreadsheet supports embedding of images in worksheets. Use one of the worksheet methods `WriteImage()` to add an image to the worksheet:
13121272
13131273``` pascal
13141274 MyWorksheet.WriteImage(row, col, filename, offsetX, offsetY, scaleX, scaleY);
13151275 MyWorksheet.WriteImage(row, col, stream, offsetX, offsetY, scaleX, scaleY);
13161276 MyWorksheet.WriteImage(row, col, imageindex, offsetX, offsetY, scaleX, scaleY);
13171277```
13181278
13191279The upper/left corner of the image is placed at the upper/left corner of the cell in the specified row and column. The floating point parameters `offsetX`, `offsetY`, `scaleX` and `scaleY` are optional: they define an offset of this image anchor point from the cell corner and a magnification factor. The path to the image file is given as parameter `filename`. Alternatively, overloaded versions can be used which accept a stream in place of the file name or an image index in the workbook's EmbeddedObj list - use `MyWorkbook.FindEmbeddedObj(filename)` to get this index for a previously loaded image file.
13201280
13211281Note that FPSpreadsheet needs to know the image type for successfull picture import. Currently, the types *png*, *jpg*, *tiff*, *bmp*, *gif*, *svg*, *wmf*, *emf*, and *pcx* are supported (Excel2007 cannot read imported *svg* and *pcx* images). Other formats can be registered by writing a function which determines the image size and pixel density, and by registering the new format using the procedure `RegisterImageType` - see unit *fpsImages* for examples:
13221282
13231283``` pascal
13241284type
13251285 TsImageType = integer;
13261286 TGetImageSizeFunc = function (AStream: TStream; out AWidth, AHeight: DWord; out dpiX, dpiY: Double): Boolean;
13271287
13281288function RegisterImageType(AMimeType, AExtension: String; AGetImageSize: TGetImageSizeFunc): TsImageType;
13291289```
13301290
13311291Due to differences in row height and column width calculation between FPSpreadsheet and Office applications it is not possible to position images correctly. If exact image positions are important you should follow these rules:
13321292
13331293- Predefine the widths of all columns at least up to the one containing the right edge of the image.
13341294- Predefine the heights of all rows at least up to the one containing the lower edge of the image.
13351295- If the workbook is to be saved in OpenDocument format add the image after changing column widths and row heights because ods anchors the image to the sheet, not to the cell (like Excel and FPSpreadsheet).
13361296- If the exact size of the image is important make sure that it fits into a single cell.
13371297
13381298### Sorting
13391299
13401300Cells in a worksheet can be sorted for a variety of criteria by calling the `Sort` method of the worksheet. This method takes a `TsSortParams` record and the edges of the cell rectangle to be sorted as parameters; in an overloaded version, the cell rectangle can also be specified by means of an Excel-type range string (e.g. `'A1:G10'`):
13411301
13421302``` pascal
13431303type
13441304 TsWorksheet = class
13451305 // ...
13461306 procedure Sort(const ASortParams: TsSortParams;
13471307 ARowFrom, AColFrom, ARowTo, AColTo: Cardinal); overload;
13481308 procedure Sort(ASortParams: TsSortParams; ARange: String); overload;
13491309 // ...
13501310 end;
13511311```
13521312
13531313The sorting criteria are defined by a record of type `TsSortParams`:
13541314
13551315``` pascal
13561316type
13571317 TsSortParams = record
13581318 SortByCols: Boolean;
13591319 Priority: TsSortPriority; // spNumAlpha ("Numbers first"), or spAlphaNum ("Text first")
13601320 Keys: TsSortKeys;
13611321 end;
13621322
13631323 TsSortKey = record
13641324 ColRowIndex: Integer;
13651325 Options: TsSortOptions; // set of [spDescending, spCaseInsensitive]
13661326 end;
13671327```
13681328
13691329- The boolean value `SortByCols` determines wether sorting occurs along columns (`true`) or rows (`false`). The `ColRowIndex` specified in the sorting keys, accordingly, corresponds to a column or row index, respectively (see below).
13701330- `Priority` determines in mixed content cell ranges whether an ascending sort puts numerical values in front of text values or not. Empty cells are always moved to the end of the sorted column or row. In Excel, the priority is "numbers first" (`spNumAlpha`).
13711331- The array `Keys` specifies multiple sorting parameters. They consist of the index of the column or row to be sorted (`ColRowIndex`) and a set of `Options` for sorting direction (`spoDescending`) and character case (`spCaseInsensitive`). If `Options` is empty, cell comparison is case-sensitive, and cells are arranged in ascending order. If two cells are found to be "equal" on the basis of the first key (`sortParams.Keys[0]`) comparison proceeds with the next conditions in the `Keys` array until a difference is found or all conditions are used up.
13721332
13731333`InitSortParams` is a handy utility to initialize the sorting parameters:
13741334
13751335``` pascal
13761336function InitSortParams(ASortByCols: Boolean = true; ANumSortKeys: Integer = 1;
13771337 ASortPriority: TsSortPriority = spNumAlpha): TsSortParams;
13781338```
13791339
13801340The next code fragment shows a typical sorting call:
13811341
13821342``` pascal
13831343var
13841344 sortParams: TsSortParams;
13851345begin
13861346 sortParams := InitSortParams(true, 2); // sorting along columns, 2 sorting keys
13871347
13881348 // primary sorting key: column 3, ascending, case-insensitive
13891349 sortParams.Keys[0].ColRowIndex := 3;
13901350 sortParams.Keys[0].Options := [ssoCaseInsensitive];
13911351
13921352 // secondary sorting key: colum 1, descending
13931353 sortParams.Keys[1].ColRowIndex := 1;
13941354 sortParams.Keys[1].Options := [ssoDescending];
13951355
13961356 // The sorted block extends between cells A1 (row=0, col=0) and F10 (row=9, col=5)
13971357 MyWorksheet.Sort(sortParams, 0, 0, 9, 5);
13981358 // or: MyWorksheet.Sort(sortParams, 'A1:F10');
13991359end;
14001360```
14011361
14021362### Searching and replacing
14031363
14041364Unit *fpsSearch* implements a **search engine** which can be used to look for specific cell content within a workbook, or to replace the found cell content by some other string.
14051365
14061366**Example:**
14071367
14081368``` pascal
14091369uses
14101370 fpsTypes, fpSpreadsheet, fpsUtils, fpsSearch, fpsAllFormats;
14111371var
14121372 MyWorkbook: TsWorkbook;
14131373 foundWorksheet: TsWorksheet;
14141374 foundRow, foundCol: Cardinal;
14151375 MySearchParams: TsSearchParams;
14161376begin
14171377 MyWorkbook := TsWorkbook.Create;
14181378 try
14191379 MyWorkbook.ReadFromFile(AFileName);
14201380
14211381 // Specify search criteria
14221382 MySearchParams.SearchText := 'Hallo';
14231383 MySearchParams.Options := [soEntireDocument];
14241384 MySearchParams.Within := swWorkbook;
14251385
14261386 // or: MySearchParaams := InitSearchParams('Hallo', [soEntireDocument], swWorkbook);
14271387
14281388 // Create search engine and execute search
14291389 with TsSearchEngine.Create(MyWorkbook) do begin
14301390 if FindFirst(MySearchParams, foundWorksheet, foundRow, foundCol) then begin
14311391 WriteLn('First "', MySearchparams.SearchText, '" found in cell ', GetCellString(foundRow, foundCol), ' of worksheet ', foundWorksheet.Name);
14321392 while FindNext(MySeachParams, foundWorksheet, foundRow, foundCol) do
14331393 WriteLn('Next "', MySearchParams.SearchText, '" found in cell ', GetCellString(foundRow, foundCol), ' of worksheet ', foundWorksheet.Name);
14341394 end;
14351395 Free;
14361396 end;
14371397 finally
14381398 MyWorkbook.Free;
14391399 end;
14401400end;
14411401```
14421402
14431403The search engine provides two methods for **searching**: `FindFirst` and `FindNext`. They are very similar, they only differ in where the search begins. In case of `FindFirst`, the starting cell is determined from the `Options` described below. In case of `FindNext` the search begins at the cell adjacent to the previously found cell. Both methods return the worksheet and row and column indexes of the cell in which the search text is found. If the search is not successful then the function result is `FALSE`, and the `foundWorksheet` is nil. It is clear that the `foundWorksheet` cannot be used for anything else while the search is running.
14441404
14451405The record `TsSearchParams` specifies the criteria used for searching:
14461406
14471407``` pascal
14481408type
14491409 TsSearchParams = record
14501410 SearchText: String;
14511411 Options: TsSearchOptions;
14521412 Within: TsSearchWithin;
14531413 end;
14541414```
14551415
14561416Besides the text to be searched (`SearchText`) it provides a set of options to narrow the search:
14571417
14581418- `soCompareEntireCell`: Compares the `SearchText` with the entire cell content. If not contained in the `Options` then the cell text is compared only partially.
14591419- `soMatchCase`: Perform a case-sensitive search
14601420- `soRegularExpr`: The `SearchText` is considered as a regular expression
14611421- `soAlongRows`: The search engine proceeds first along the rows. If not contained in the `Options` then the search proceeds along the columns.
14621422- `soBackward`: The search begins at the end of the document, or runs backward from the active cell. If not contained in the `Options` then the search starts at the beginning of the document, or runs forward from the active cell.
14631423- `soWrapDocument`: If a search has reached the end of the document the search is resumed at its beginning (or vice versa, if `soBackward` is used).
14641424- `soEntireDocument`: Search begins at the first cell (or last cell if `soBackward` is used). If not contained in the `Options` then the search begins at the active cell of the worksheet. Ignored by `FindNext`.
14651425
14661426The record field `Within` identifies the part of the spreadsheet to be searched:
14671427
14681428- `swWorkbook`: The entire workbook is searched. If the search phrase is not found on the first worksheet (or last worksheet if `soBackward` is used) then the search continues with the next (previous) sheet.
14691429- `swWorksheet`: The search is limited to the currently active worksheet
14701430- `swColumn`: Search is restricted to the column of the active cell
14711431- `swRow`: Search is restricted to the row of the active cell.
14721432
14731433The search params record can be initialized by calling `InitSearchParams` (in unit *fpsutils*) with the record elements as optional parameters. Use the methods `Workbook.ActiveWorksheet` and `Worksheet.SelectCell(ARow, ACol)` to define the active worksheet and the position of the active cell, respectively, if needed by the search.
14741434
14751435In addition to searching the search engine can also be used for **replacing** the found text by another string. Call the functions `ReplaceFirst` or `ReplaceNext` for this purpose. They act like their `FindXXXX` counterparts, therefore, they require a `TsSearchParams` record to specify the search criteria. But in addition to searching, these functions also perform the text replacement according to the specification in a `TsReplaceParams` record:
14761436
14771437``` pascal
14781438type
14791439 TsReplaceParams = record
14801440 ReplaceText: String;
14811441 Options: TsReplaceOptions;
14821442 end;
14831443```
14841444
14851445The `ReplaceText` identifies the string which will replace the found text pattern. The `Options` define a set of criteria how the replacement is done:
14861446
14871447- `roReplaceEntirecell`: Replaces the entire cell text by the `ReplaceText`. If not contained in the `Options` then only the part matching the `SearchText` is replaced.
14881448- `roReplaceAll`: Performs the replacement in all found cells (i.e., simply call `ReplaceFirst` to replace all automatically).
14891449- `roConfirm`: Calls an event handler for the `OnConfirmReplacement` event in which the user must specify whether the replacement is to be performed or not. Note that this event handler is mandatory if `roConfirm` is set.
14901450
14911451Use the function `InitReplaceParams` (in unit *fpsutils*) to initialize the replace parameters record with the provided (but optional) values.
14921452
14931453### Column and row operations
14941454
14951455The worksheet provides these methods for inserting, deleting, hiding or unhiding columns and rows:
14961456
14971457``` pascal
14981458type
14991459 TsWorksheet = class
15001460 ...
15011461 procedure DeleteCol(ACol: Cardinal);
15021462 procedure DeleteRow(ARow: Cardinal);
15031463
15041464 procedure InsertCol(ACol: Cardinal);
15051465 procedure InsertRow(ARow: Cardinal);
15061466
15071467 procedure RemoveCol(ACol: Cardinal);
15081468 procedure RemoveRow(ARow: Cardinal);
15091469
15101470 procedure RemoveAllCols;
15111471 procedure RemoveAllRows
15121472
15131473 procedure HideCol(ACol: Cardinal);
15141474 procedure HideRow(ARow: Cardinal);
15151475
15161476 procedure ShowCol(ACol: Cardinal);
15171477 procedure ShowRow(ARow: Cardinal);
15181478
15191479 function ColHidden(ACol: Cardinal): Boolean;
15201480 function RowHidden(ARow: Cardinal): Boolean;
15211481```
15221482
15231483- When a column or row is **deleted** by `DeleteCol` or `DeleteRow`, any data assigned to this column or row are removed, i., cells, comments, hyperlinks, TCol or TRow records. Data at the right of or below the deleted column/row move to the left or up.
15241484
15251485- `RemoveCol` and `RemoveRow`, in contract, **remove** only the column or row record, i.e. reset column width and row height to their default values. Cell, comment, and hyperlink data are not affected.
15261486
15271487- `RemoveAllCols` **removes all** column records, i.e. resets all column widths; `RemoveAllRows` does the same with the row records and row heights.
15281488
15291489- A column or row is **inserted** before the index specified as parameter of the `InsertXXX` method.
15301490
15311491### Page layout
15321492
15331493#### General
15341494
15351495So far, FPSpreadsheet does not support printing of worksheets, but the Office applications do, and they provide a section of information in their files for this purpose. In FPSpreadsheets this information is available in the `TsPageLayout` class which belongs to the `TsWorksheet` data structure. Its properties and methods combine the most important features from the Excel and OpenDocument worlds.
15361496
15371497``` pascal
15381498type
15391499 TsPageOrientation = (spoPortrait, spoLandscape);
15401500
15411501 TsPrintOption = (poPrintGridLines, poPrintHeaders, poPrintPagesByRows,
15421502 poMonochrome, poDraftQuality, poPrintCellComments, poDefaultOrientation,
15431503 poUseStartPageNumber, poCommentsAtEnd, poHorCentered, poVertCentered,
15441504 poDifferentOddEven, poDifferentFirst, poFitPages);
15451505
15461506 TsPrintOptions = set of TsPrintOption;
15471507
15481508 TsHeaderFooterSectionIndex = (hfsLeft, hfsCenter, hfsRight);
15491509
15501510 TsCellRange = record
15511511 Row1, Col1, Row2, Col2: Cardinal;
15521512 end;
15531513
15541514 TsPageLayout = class
15551515 ...
15561516 public
15571517 ...
15581518 { Methods }
15591519 // embedded header/footer images
15601520 procedure AddHeaderImage(AHeaderIndex: Integer;
15611521 ASection: TsHeaderFooterSectionIndex; const AFilename: String);
15621522 procedure AddFooterImage(AFooterIndex: Integer;
15631523 ASection: TsHeaderFooterSectionIndex; const AFilename: String);
15641524 procedure GetImageSections(out AHeaderTags, AFooterTags: String);
15651525 function HasHeaderFooterImages: Boolean;
15661526
15671527 // Repeated rows and columns
15681528 function HasRepeatedCols: Boolean;
15691529 function HasRepeatedRows: Boolean;
15701530 procedure SetRepeatedCols(AFirstCol, ALastCol: Cardinal);
15711531 procedure SetRepeatedRows(AFirstRow, ALastRow: Cardinal);
15721532
15731533 // print ranges
15741534 function AddPrintRange(ARow1, ACol1, ARow2, ACol2: Cardinal): Integer; overload;
15751535 function AddPrintRange(const ARange: TsCellRange): Integer; overload;
15761536 function GetPrintRange(AIndex: Integer): TsCellRange;
15771537 function NumPrintRanges: Integer;
15781538 procedure RemovePrintRange(AIndex: Integer);
15791539
15801540 { Properties }
15811541 property Orientation: TsPageOrientation read FOrientation write FOrientation;
15821542 property PageWidth: Double read FPageWidth write FPageWidth;
15831543 property PageHeight: Double read FPageHeight write FPageHeight;
15841544 property LeftMargin: Double read FLeftMargin write FLeftMargin;
15851545 property RightMargin: Double read FRightMargin write FRightMargin;
15861546 property TopMargin: Double read FTopMargin write FTopMargin;
15871547 property BottomMargin: Double read FBottomMargin write FBottomMargin;
15881548 property HeaderMargin: Double read FHeaderMargin write FHeaderMargin;
15891549 property FooterMargin: Double read FFooterMargin write FFooterMargin;
15901550 property StartPageNumber: Integer read FStartPageNumber write SetStartPageNumber;
15911551 property ScalingFactor: Integer read FScalingFactor write SetScalingFactor;
15921552 property FitHeightToPages: Integer read FFitHeightToPages write SetFitHeightToPages;
15931553 property FitWidthToPages: Integer read FFitWidthToPages write SetFitWidthToPages;
15941554 property Copies: Integer read FCopies write FCopies;
15951555 property Options: TsPrintOptions read FOptions write FOptions;
15961556 property Headers[AIndex: Integer]: String read GetHeaders write SetHeaders;
15971557 property Footers[AIndex: Integer]: String read GetFooters write SetFooters;
15981558 property RepeatedCols: TsRowColRange read FRepeatedCols;
15991559 property RepeatedRows: TsRowColRange read FRepeatedRows;
16001560 property PrintRange[AIndex: Integer]: TsCellRange read GetPrintRange;
16011561 property FooterImages[ASection: TsHeaderFooterSectionIndex]: TsHeaderFooterImage read GetFooterImages;
16021562 property HeaderImages[ASection: TsHeaderFooterSectionIndex]: TsHeaderFooterImage read GetHeaderImages;
16031563 end;
16041564
16051565 TsWorksheet = class
16061566 ...
16071567 public
16081568 property PageLayout: TsPageLayout;
16091569 ...
16101570 end;
16111571```
16121572
16131573> **Note:** The fact that the `PageLayout` belongs to the worksheet indicates that there can be several page layouts in the same workbook, one for each worksheet.
16141574
16151575- **Orientation** defines the orientation of the printed paper, either portrait or landscape.
16161576
16171577- **Page width** and **page height** refer to the standard orientation of the paper, usually portrait orientation.
16181578
16191579- **Left**, **top**, **right** and **bottom margins** are self-explanatory and are given in millimeters.
16201580
16211581- **HeaderMargin** is understood - like in Excel - as the distance between the paper top edge and the top of the header, and **TopMargin** correspondingly is the distance between the top paper edge and the top of the first table row, i.e. if the header contains several line breaks it can reach into the the table part of the print-out. This is different from OpenDocument files where the header can grow accordingly.
16221582
16231583- **StartPageNumber** should be altered if the print-out should not begin with page 1. This setting requires to add the option `poUseStartPageNumber` to the PageLayout's `Options` - but this is normally done automatically.
16241584
16251585- The **ScalingFactor** is given in percent and can be used to reduce the number of printed pages. Modifying this property clear the option `poFitToPages` from the PageLayout's `Options`.
16261586
16271587- Alternatively to ScalingFactor, you can also use **FitHeightToPages** or **FitWidthToPages**. The option `poFitToPages` must be active in order to override the `ScalingFactor`setting. `FitHeightToPages` specifies the number of pages onto which the entire height of the printed worksheet should fit. Accordingly, `FitWidthToPages` can be used to define the number of pages on which the entire width of the worksheet has to fit. The value `0` has the special meaning of "use as many pages as needed". In this way, the setting "Fit all columns on one page" of Excel, for example, can be achieved by this code:
16281588
16291589``` pascal
16301590 MyWorksheet.PageLayout.Options := MyWorksheet.PageLayout.Options + [poFitPages];
16311591 MyWorksheet.PageLayout.FitWidthToPages := 1; // all columns on one page width
16321592 MyWorksheet.PageLayout.FitHeightToPages := 0; // use as many pages as needed
16331593```
16341594
16351595- **Header rows and columns repeated on every printed page** can be defined by the `RepeatedCols` and `RepeatedRows` records; their elements `FirstIndex` and `LastIndex` refer to the indexes of the first and last column or row, respectively, to be repeated. Use the methods `SetRepeatedCols` and `SetRepeatedRows` to define these numbers. Note that the second parameter for the last index can be omitted to use only a single header row or column.
16361596
16371597- **Print ranges** or **print areas** (using Excel terminology) can be used to restrict printing only to a range of cells. Use the methods `AddPrintRange` to define a cell range for printing: specify the indexes of the left column, top row, right column and bottom row of the range to be printed. A worksheet can contain several print ranges.
16381598
16391599- **Copies** specifies how often the worksheet will be printed.
16401600
16411601- The **Options** define further printing properties, their names are self-explaining. They were defined according to Excel files, some of them do not exist in ODS files and are ignored there.
16421602
16431603#### Headers and footers
16441604
16451605**Header and footer texts** can be composed of left-aligned, centered and right-aligned strings. Add the symbol `&L` to indicate that the following string is to be printed as the left-aligned part; use `&C` accordingly for the centered and `&R` for the right-aligned parts. There are other symbols which will be replaced by their counterparts during printing:
16461606
16471607- `&L`: begins the **left-aligned section** of a header or a footer text definition
16481608- `&C`: begins the **centered section** of a header or a footer text definition
16491609- `&R`: begins the **right-aligned section** of a header or a footer text definition
16501610- `&P`: **page number**
16511611- `&N`: **page count**
16521612- `&D`: current **date** of printing
16531613- `&T`: current **time** of printing
16541614- `&A`: **worksheet name**
16551615- `&F`: **file name** without path
16561616- `&P`: **file path** without file name
16571617- `&G`: embedded **image** - use the methods `AddHeaderImage` or `AddFooterImage` to specify the image file; this also appends the `&G` to the other codes of the current header/footer section. Note that not all image types known by the Office application may be accepted. Currently the image can be *jpeg*, *png*, *gif*, *bmp*, *tiff*, *pcx*, *svg*, *wmf* or *emf*.
16581618- `&B`: **bold** on/off
16591619- `&I`: **italic** on/off
16601620- `&U`: **underlining** on/off
16611621- `&E`: **double-underlining** on/off
16621622- `&S`: **strike-out** on/off
16631623- `&H`: **shadow** on/off
16641624- `&O`: **outline** on/off
16651625- `&X`: **superscript** on/off
16661626- `&Y`: **subscript** on/off
16671627- `&"font"`: begin using of the **font** with the specified name, e.g. `&"Arial"`
16681628- `&number`: begin using of the specified **font size** (in points), e.g. `&16`
16691629- `&Krrggbb`: switch to the **font color** specified to the binary value of the specified color, e.g. use `&KFF0000` for red.
16701630
16711631The arrays `Headers[]`/`Footers[]` provide space for usage of three different headers or footers:
16721632
16731633- `Headers[0]` refers to the header used on the **first page** only, similarly for `Footers[0]`. Instead of index `0` you can use the constant `HEADER_FOOTER_INDEX_FIRST`. Leave this string empty if there is no special first-page header/footer.
16741634- `Headers[1]` refers to the header on pages with **odd page numbers**, similarly for `Footers[1]`. Instead of index `1` you may want to use the constant `HEADER_FOOTER_INDEX_ODD`.
16751635- `Headers[2]` refers to the header on lages with **even page nubmers**, similarly for `Footers[2]`. Instead of index `2` you may want to use the constant `HEADER_FOOTER_INDEX_EVEN`.
16761636
16771637Leave the strings at index 0 and 2 empty if the print-out should always have the same header/footer. You can use the constant `HEADER_FOOTER_INDEX_ALL` for better clarity. Example:
16781638
16791639``` pascal
16801640 MyWorksheet.PageLayout.Headers[HEADER_FOOTER_INDEX_ALL] := '&C&D &T'; // centered "date time" on all pages as header
16811641 MyWorksheet.PageLayout.Footers[HEADER_FOOTER_INDEX_ODD] := '&RPage &P of &N'; // right-aligned "Page .. of ..." on odd pages as footer
16821642 MyWorksheet.PageLayout.Footers[HEADER_FOOTER_INDEX_EVEN] := '&LPage &P of &N'; // dto, but left-aligned on even pages
16831643```
16841644
16851645### Protection
16861646
16871647In the Office applications, workbooks can be protected from unintentional changes by the user. fpspreadsheet is able to read and write the data structures related to protection, but does not enforce them. This means, for example, that cells can be modified by the user although the worksheet is specified as being locked.
16881648
16891649Protection is handled at three levels: workbook protection, worksheet protection and cell protection.
16901650
16911651#### Workbook protection
16921652
16931653`TsWorkbook` contains a set of workbook or document protection options:
16941654
16951655- `bpLockRevision`: specifies that the workbook is locked for revisions
16961656- `bpLockStructure`: if this option is set then worksheets in the workbook cannot be moved, deleted, hidden, unhidden, or renamed, and new worksheets cannot be inserted.
16971657- `bpLockWindows`: indicates that the workbook windows in the Office application are locked. Windows are the same size and position each time the workbook is opened by the Office application.
16981658
16991659In relation to workbook protection is the worksheet option `soPanesProtection` which prevents the panes of a worksheet from being modified if the workbook is protected.
17001660
17011661Depending on the file format, only some of these options might be supported. In these cases, the non-supported options are commonly accepted default values.
17021662
17031663#### Worksheet protection
17041664
17051665`TsWorksheet` houses a similar set of protection options. Whenever an option is included in the set `Protection` of the workbook the corresponding action is not allowed and locked:
17061666
17071667- `spCells`: the cells in the sheet are protected. It depends on the level of cell protection whether a particular cell can be changed or not. By default, no cell can be changed.
17081668- `spDeleteColumns`: deleting of columns is not be allowed
17091669- `spDeleteRows`: it is not possible to delete rows
17101670- `spFormatCells`: formatting of cells is not allowed
17111671- `spFormatColumns`: columns cannot be formatted.
17121672- `spFormatRows`: rows cannot be formatted
17131673- `spInsertColumns`: it is not allowed to insert columns
17141674- `spInsertRows`: rows cannot be inserted
17151675- `spInsertHyperlinks`: it is not possible to insert new hyperlinks
17161676- `spSort`: the worksheet is not allowed to be sorted.
17171677- `spSelectLockedCells`: Cells which are locked cannot be selected any more.
17181678- `spSelectUnlockedCells`: Even cells which are unlocked cannot be selected. Together with `spSelectLockedCells` this means that the selection in the worksheet is frozen.
17191679
17201680These levels of protection become active if the option `soProtected` is added to the worksheet's `Options`, or by calling the worksheet method `Protect(true)`.
17211681
17221682#### Cell protection
17231683
17241684Cell protection becomes active when the worksheet protection is enabled. It is controlled by a set of `TsCellProtection` elements which belong to the cell format record:
17251685
17261686- `cpLockCell`: This option determines whether cell content can be modified by the user. Since it is on by default cells of a protected worksheet normally cannot be edited. In order to unlock some cells for user input the option `cpLockCell` must be removed from the protection of these cells.
17271687- `cpHideFormulas`: prevents formulas from being shown in the Office application.
17281688
17291689Cell protection can be changed by calling the worksheet method `WriteCellProtection`. Conversely, `ReadCellProtection` can be used to retrieve the protection state of a particular cell:
17301690
17311691``` pascal
17321692// query and modifiy the protection state of cell A1 (row=0, col=0)
17331693var
17341694 cell: PCell;
17351695 cellprot: TsCellProtections;
17361696...
17371697 // Find the cell
17381698 cell := worksheet.FindCell(0, 0);
17391699 // query cell protection
17401700 cellprot := worksheet.ReadCellProtection(cell);
17411701 // Unlock the cell for editing, don't change the visibility of formulas
17421702 worksheet.WriteCellProtection(cell, cellprot - [cpLockCell]);
17431703 // Hide formula of the cell and unlock the cell.
17441704 worksheet.WriteCellProtection(cell, [cpHideFormulas]);
17451705```
17461706
17471707#### Passwords
17481708
17491709Workbook and worksheet protection can be secured by passwords. Note that these passwords do not encrypt the file (except for workbook protection in Excel 2007). In the Office applications the user must enter this password to turn off protection or to change protection items. The encrypted password is stored in the `CryptoInfo` record of the wordbook and the worksheets, respectively:
17501710
17511711``` pascal
17521712type
17531713 TsCryptoInfo = record
17541714 PasswordHash: String;
17551715 Algorithm: TsCryptoAlgorithm; // caExcel, caSHA1, caSHA256, etc.
17561716 SaltValue: String;
17571717 SpinCount: Integer;
17581718 end;
17591719```
17601720
17611721> **Warning:** FPSpreadsheet does not perform any hashing calculations, the `CryptoInfo` record is just passed through from reading to writing. This causes problems when different file formats are involved in reading and writing. It is attempted to detect **incompatible combinations**. In these cases, the **password protection is removed**, and an error is logged by the workbook.
17621722
17631723### Loading and saving
17641724
17651725#### Adding new file formats
17661726
17671727FPSpreadsheet is open to any spreadsheet file format. In addition to the built-in file formats which are specified by one of the `sfXXXX` declarations, it is possible to provide dedicated reader and writer units to get access to special file formats.
17681728
17691729- Write a unit implementing a reader and a writer for the new file format. They must inherit from the basic `TsCustomSpreadReader` and `TsCustomWriter`, respectively, - both are implemented in unit *fpsReaderWriter* -, or from one of the more advanced ones belonging to the built-in file formats.
17701730- Register the new reader/writer by calling the function `RegisterSpreadFileFormat` in the `initialization` section of this unit (implemented in unit *fpsRegFileFormats*):
17711731
17721732``` pascal
17731733function RegisterSpreadFormat(AFormat: TsSpreadsheetFormat; AReaderClass: TsSpreadReaderClass; AWriterClass: TsSpreadWriterClass;
17741734 AFormatName, ATechnicalName: String; const AFileExtensions: array of String): TsSpreadFormatID;
17751735```
17761736
17771737- `AFormat` must have the value `sfUser` to register an external file format.
17781738- `AReaderClass` is the class of the reader (or nil, if reading functionality is not implemented).
17791739- `AWriterClass` is the class of the writer (or nil, if writing functionality is not implemented).
17801740- `AFormatName` defines the name of the format as used for example in the filter list of file-open dialogs.
17811741- `ATechnicalName` defines a shorter format name.
17821742- `AFileExtensions` is an array of file extensions used in the files. The first array element denotes the default extension. The extensions must begin with a period as in `.xls`.
17831743- The registration function returns a numerical value (`TsSpreadFormatID`) which can be used as format identifier in the workbook reading and writing functions which exist in overloaded version accepting a numerical value for the format specifier. In contract to the built-in formats the FormatID is negative.
17841744- Finally, in your application, add the new unit to the `uses` clause. This will call the registrations function when the unit is loaded and make the new file format available to FPSpreadsheet.
17851745
17861746#### Stream selection
17871747
17881748Workbooks are loaded and saved by means of the `ReadFromFile` and `WriteToFile` methods, respectively (or by their stream counterparts, `ReadFromStream` and `WriteToStream`).
17891749
17901750By default, the data files are accessed by means of **memory streams** which yields the fastest access to the files. In case of very large files (e.g. tens of thousands of rows), however, the system may run out of memory. There are two methods to defer the memory overflow by some extent.
17911751
17921752- Add the element `boBufStream` to the workbook's `Options`. In this case, a **"buffered" stream** is used for accessing the data. This kind of stream holds a memory buffer of a given size and swaps data to file if the buffer becomes too small.
17931753- Add the element `boFileStream` to the workbook's `Options`. This option avoids memory streams altogether and creates temporary **files** if needed. This is, however, the slowest method of data access.
17941754- If both options are set then `boBufStream` is ignored.
17951755- In practice, however, the effect of the selected streams is not very large if memory is to be saved.
17961756
17971757#### Virtual mode
17981758
17991759Beyond the transient memory usage during reading/writing the main memory consumptions originates in the internal structure of FPSpreadsheet which holds all data in memory. To overcome this limitation, a "virtual mode" has been introduced. In this mode, data are received from a data source (such as a database table) and are passed through to the writer without being collected in the worksheet. It is clear that data loaded in virtual mode cannot be displayed in the visual controls. Virtual mode is good for conversion between different data formats.
18001760
18011761These are the steps required to use this mode:
18021762
18031763- Activate virtual mode by adding the option `boVirtualMode` to the `Options` of the workbook.
18041764- Tell the spreadsheet writer how many rows and columns are to be written. The corresponding worksheet properties are `VirtualRowCount` and `VirtualColCount`.
18051765- Write an event handler for the event `OnWriteCellData` of the worksheet. This handler gets the index of row and column of the cell currently being saved. You have to return the value which will be saved in this cell. You can also specify a template cell that physically exists in the workbook from which the formatting style is copied to the destination cell. Please be aware that when exporting a database, you are responsible for advancing the dataset pointer to the next database record when writing of a row is complete.
18061766- Call the `WriteToFile` method of the workbook.
18071767
18081768Virtual mode also works for reading spreadsheet files.
18091769
18101770The folder *example/other* contains a worked out sample project demonstrating virtual mode using random data. More realistic database examples are in *example/db_import_export* and in the chapter on converting a large database table using virtual mode.
18111771
18121772### Dataset export
18131773
18141774FPC contains a set of units that allow you to export datasets to various formats (XML, SQL statements, DBF files,...). There is a master package that allows you to choose an export format at design time or run time (Lazarus package lazdbexport).
18151775
18161776FPSpreadsheet has `TFPSExport` which plugs into this system. It allows you to export the contents of a dataset to a new spreadsheet (*.xls*, *.xlsx*, *.ods*, wikitable format) file into a table on the first sheet by default. In addition, if `MultipleSheets` is set to `TRUE` it is possible to combine several sheets into individual worksheets in the same file. You can optionally include the field names as header cells on the first row using the `HeaderRow` properties in the export settings. The export component tries to find the number format of the cells according to the dataset field types.
18171777
18181778For more complicated exports, you need to manually code a solution (see examples below) but for simple data transfer/dynamic exports at user request, this unit will probably be sufficient.
18191779
18201780A simple example of how this works:
18211781
18221782``` pascal
18231783uses
18241784...
18251785fpsexport
18261786...
18271787var
18281788 Exp: TFPSExport;
18291789 ExpSettings: TFPSExportFormatSettings;
18301790 TheDate: TDateTime;
18311791begin
18321792 FDataset.First; //assume we have a dataset called FDataset
18331793 Exp := TFPSExport.Create(nil);
18341794 ExpSettings := TFPSExportFormatSettings.Create(true);
18351795 try
18361796 ExpSettings.ExportFormat := efXLS; // choose file format
18371797 ExpSettings.HeaderRow := true; // include header row with field names
18381798 Exp.FormatSettings := ExpSettings; // apply settings to export object
18391799 Exp.Dataset:=FDataset; // specify source
18401800 Exp.FileName := 'c:\temp\datadump.xls';
18411801 Exp.Execute; // run the export
18421802 finally
18431803 Exp.Free;
18441804 ExpSettings.Free;
18451805 end;
18461806```
18471807
18481808#### Export to DBF
18491809
18501810You can save the information from Excel to dbf rather easily. Here is the example from forum. Please note that this example is supposed to work with Win1251 encoding by default. To get more information please refer to this thread [1](http://forum.lazarus.freepascal.org/index.php/topic,41636.0.html)
18511811
18521812``` pascal
18531813procedure TForm1.ExportToDBF(AWorksheet: TsWorksheet; AFileName: String);
18541814var
18551815 i: Integer;
18561816 f: TField;
18571817 r, c: Cardinal;
18581818 cell: PCell;
18591819begin
18601820 DbfGlobals.DefaultCreateCodePage := 1251; //default encoding of the dbf
18611821 DbfGlobals.DefaultOpenCodePage := 1251; //default encoding of the dbf
18621822 if Dbf1.Active then Dbf1.Close;
18631823 if FileExists(AFileName) then DeleteFile(AFileName);
18641824
18651825 Dbf1.FilePathFull := ExtractFilePath(AFileName);
18661826 Dbf1.TableName := ExtractFileName(AFileName);
18671827 Dbf1.TableLevel := 25; // DBase IV: 4 - most widely used; or 25 = FoxPro supports nfCurrency
18681828 Dbf1.LanguageID := $C9; //russian language by default
18691829 Dbf1.FieldDefs.Clear;
18701830 //below are the fields in excel
18711831 Dbf1.FieldDefs.Add('fam', ftString);
18721832 //add other fields you want to save
18731833
18741834 Dbf1.CreateTable;
18751835 Dbf1.Open;
18761836
18771837 for f in Dbf1.Fields do
18781838 f.OnGetText := @DbfGetTextHandler;
18791839
18801840 // Skip row 0 which contains the headers
18811841 for r := 1 to AWorksheet.GetLastRowIndex do begin
18821842 Dbf1.Append;
18831843 for c := 0 to Dbf1.FieldDefs.Count-1 do begin
18841844 f := Dbf1.Fields[c];
18851845 cell := AWorksheet.FindCell(r, c);
18861846 if cell = nil then
18871847 f.Value := NULL
18881848 else
18891849 case cell^.ContentType of
18901850 cctUTF8String: f.AsString := UTF8ToCP1251(cell^.UTF8StringValue);
18911851 cctNumber: f.AsFloat := cell^.NumberValue;
18921852 cctDateTime: f.AsDateTime := cell^.DateTimeValue;
18931853 else f.AsString := UTF8ToCP1251(AWorksheet.ReadAsText(cell));
18941854 end;
18951855 end;
18961856 Dbf1.Post;
18971857 end;
18981858end;
18991859
19001860//This procedure is called so the text in the cells could be correctly dispayed on WorkSheetGrid on the form, otherwise '?' symbols showing
19011861procedure TForm1.DbfGetTextHandler(Sender: TField; var AText: string; DisplayText: Boolean);
19021862begin
19031863 if DisplayText then
19041864 AText := CP1251ToUTF8(Sender.AsString);
19051865end;
19061866```
19071867
19081868## Visual controls for FPSpreadsheet
19091869
19101870The package **laz_fpspreadsheet_visual** implements a series of controls which simiplify creation of visual GUI applications:
19111871
19121872- **TsWorkwookSource** links the controls to a workbook and notifies the controls of changes in the workbook.
19131873- **[[TsWorksheetGrid]]** implements a grid control with editing and formatting capabilities; it can be applied in a similar way to TStringGrid.
19141874- **TsWorkbookTabControl** provides a tab sheet for each worksheet of the workbook. It is the ideal container for a [[TsWorksheetGrid]].
19151875- **TsWorksheetIndicator**: a combobox which lists all worksheets of the workbook.
19161876- **TsCellEdit** corresponds to the editing line in Excel or Open/LibreOffice. Direct editing in the grid, however, is possible as well.
19171877- **TsCellIndicator** displays the name of the currently selected cell; it can be used for navigation purposes by entering a cell address string.
19181878- **TsCellCombobox** offers to pick cell properties for a selection of formatting attributes: font name, font size, font color, background color.
19191879- **TsSpreadsheetInspector** is a tool mainly for debugging; it displays various properties of workbook, worksheet, cell value and cell formatting, similar to the ObjectInspector of Lazarus. It is read-only, though.
19201880- Various standard actions are provided in the unit **fpsActions**. Applied to menu or toolbar, they simplify typical formatting and editing tasks without having to write a line of code.
19211881- **TsWorkbookChartSource** interfaces a workbook with the [[TAChart]] library. It defines the cell ranges from which a Chart series can get its data. There is also an older component, [[TsWorksheetChartSource]], which requires all cells to be from the same worksheet. For this reason, it has not been fully integrated into the environment of FPSpreadsheet controls and will be removed from the library in the future.
19221882
19231883See the [[FPSpreadsheet tutorial: Writing a mini spreadsheet application]] for more information and a tutorial, and see demo projects for examples of the application of these components.
19241884
19251885## Examples
19261886
19271887Please see [[FPSpreadsheet: Examples]] for a variety of code examples.
19281888
19291889## Download
19301890
19311891### Subversion
19321892
19331893You can download FPSpreadsheet using the subversion software and the following command line:
19341894
19351895``` bash
19361896svn checkout https://svn.code.sf.net/p/lazarus-ccr/svn/components/fpspreadsheet fpspreadsheet
19371897```
19381898
19391899#### SVN change log
19401900
19411901- Implementation of conditional formats for ods, xlsx and Excel xml.
19421902- Implementation of meta data for ods, xlsx and Excel xml.
19431903
19441904#### Incompatible changes
19451905
19461906- Removed the deprecated worksheet properties DefaultRowHeight and DefaultColWidth. Use the corresponding Read/Write routines instead (ReadDefaultColWidth(units), WriteDefaultColWidth(units)).
19471907
19481908### Stable releases
19491909
19501910You can find all releases of FPSpreadsheet on [sourceforge](https://sourceforge.net/projects/lazarus-ccr/files/FPSpreadsheet/).
19511911
19521912#### Version 1.12
19531913
19541914###### Change log (with respect to v1.10x)
19551915
19561916- **Hide** (and unhide) rows and columns.
19571917- Enforce **Page breaks** before rows and columns during printing by the Office applications.
19581918- Full support (reading and writing) of the **ExcelXML** xml format (Excel 2003 and XP).
19591919- Support of the color of worksheet tabs (Worksheet.TabColor) in xls biff8, xlsx and ods formats. The property is ignored by the visual WorkbookTabControl, though.
19601920- Add TsWorksheetIndicator to visual controls.
19611921
19621922#### Version 1.10.1
19631923
19641924This is the latest stable release.
19651925
19661926###### Change log (with respect to v1.8x)
19671927
19681928- **Workbook, worksheet and cell protection** (read/write in BIFF2/BIFF5/BIFF8/OOXML/ODS, write in ExcelXML).
19691929- New package **laz_fpspreadsheet_crypto** to decipher the encryption for worksheet-protection in xls files. Requires DCPcrypt.
19701930- TsWorksheetGrid can **display embedded images**.
19711931- **Drag and drop** in TsWorksheetGrid
19721932- New, **highDPI-aware** component palette icons.
19731933- New workbook optiond **boAbortReadingOnFormulaError** and **boIgnoreFormulas**.
19741934- Formulas with **references to other sheets**, i.e. `'=Sheet1!A1+Sheet2!A2'`
19751935
19761936###### Incompatible changes
19771937
19781938- The field **FormulaValue** has been removed from the cell record. The cell formula now can be retrieved by calling `Worksheet.ReadFormula(cell)`.
19791939
19801940#### Version 1.8
19811941
19821942###### Change log (with respect to v1.6x)
19831943
19841944- **"Rich-text" formatting** of label cells, i.e. assignment different fonts to groups of characters within the cell text. For this purpose, HTML codes (such as `<B>...</B>`) can be embedded in the cell text to identify the parts with different font (--\> `TsWorksheet.WriteTextAsHTML`).
19851945- **Searching** for cells with specified content in worksheet or workbook.
19861946- Support for reading and writing of **HTML format**
19871947- Support for writing of the **ExcelXML format** (Excel XP and 2003)
19881948- Ability to use **user-provided file reader/writer classes** to extend FPSpreadsheet to new file formats.
19891949- Readers and writers now support all the **line styles** of Excel8 and OOXML.
19901950- xls, xlsx and ods readers/writers now support the **active worksheet** and **selected cell**.
19911951- Ability to write to/read from the system's **clipboard** for copy & paste using the visual controls.
19921952- Support for **print ranges** and **repeated header rows and columns** in the Office applications.
19931953- Support for **embedded images** (currently only writing to xlsx and ods, no reading).
19941954- Improved compatibility of **TsWorksheetGrid** with TStringGrid (`Cells[Col,Row]` property). Standalone application as an advanced StringGrid replacement.
19951955- Support for **Right-to-left mode** in TsWorksheetGrid. In addition to the system-wide RTL mode, there are also parameters `BiDiMode` in the Worksheet and cells allowing to controls text direction at worksheet and cell level individually, like in Excel or LibreOffice Calc.
19961956- Support of several **units** for specification of column widths and row heights.
19971957- The library now supports **localization** using po files. Translations are welcome.
19981958- **Zoom factor** read and written by the worksheet, and applied by the TsWorksheetGrid.
19991959- Support of **column and row formats**
20001960- Support of **hidden** worksheets
20011961
20021962###### Incompatible changes
20031963
20041964- VirtualMode was changed in order to be able to treat worksheets of the same workbook differently. `VirtualRowCount` and `VirtualColCount` are now properties of the worksheet, and similarly, the event handler `OnWriteCellData`. In older versions, these properties had belonged to the workbook.
20051965- The worksheet methods `ReadAsUTF8Text` and `WriteUTF8Text` have been renamed to `ReadAsText` and `WriteText`, respectively. The old ones are still available and marked as deprecated; they will be removed in later versions.
20061966- The public properties of `TsWorksheetGrid` using a `TRect` as parameter were modified to use the Left, Top, Right, Bottom values separately.
20071967- The `PageLayout` is a class now, no longer a record. As a consequence, some array properties cannot be set directly any more, use the corresponding methods instead.
20081968- Most of the predefined color constants were marked as deprecated; only the basic EGA colors will remain.
20091969- Unit fpsNumFormatParser is integrated in fpsNumFormat. Old code which "uses" fpsNumFormatParser must "use" fpsNumFormat now.
20101970- The source files of the laz_fpspreadsheet, laz_fpspreadsheet_visual and laz_fpspreadsheetexport_visual packages have been moved to separate folders in order to resolve some occasional compilation issues. Projects which do not use the packages but the path to the sources must adapt the paths.
20111971
20121972#### Version 1.6
20131973
20141974###### Change log (with respect to v1.4.x)
20151975
20161976- TsWorkbookChartSource is a new component which facilitates creation of charts from non-contiguous spreadsheet data in various worksheets. It interfaces to a workbook via tha WorkbookSource component. In the long run, it will replace the older TsWorksheetChartSource which required contiguous x/y data blocks in the same worksheet.
20171977- Major reconstruction of the cell record resulting in strong reduction of memory consumption per cell (from about 160 bytes per cell down to about 50)
20181978- Implementation of a record helper for the TCell which simplifies cell formatting (no need to set a bit in UsedFormattingFields any more, automatic notification of visual controls)
20191979- Comments in cells
20201980- Background fill patterns
20211981- Hyperlinks
20221982- Enumerators for worksheet's internal AVLTrees for faster iteration using a for-in loop.
20231983- Formatting of numbers as fractions.
20241984- Improved number format parser for better recognition of Excel-like number formats.
20251985- Page layout (page margins, headers, footer, used for only when printing in the Office applications - no direct print support in fpspreadsheet!)
20261986- Improved color management: no more palettes, but direct rgb colors. More pre-defined colors.
20271987- A snapshot of the wiki documentation is added to the library as chm help file.
20281988
20291989###### Incompatible changes
20301990
20311991- All type declarations and constants are moved from fpspreadsheet.pas to the new unit **fpstypes.pas**. Therefore, most probably, this unit has to be added to the uses clause.
20321992- Because fpspreadsheet supports now **background** fill patterns the cell property `BackgroundColor` has been replaced by `Background`. Similarly, the `UsedFormattingFields` flag `uffBackgroundColor` is called `uffBackground` now.
20331993- Another `UsedFormattingFields` flag has been dropped: **`uffBold`**. It is from the early days of fpspreadsheet and has become obsolete since the introduction of full font support. For achieving a bold type-face, now call `MyWorksheet.WriteFont(row, col, BOLD_FONTINDEX)`, or `Myworksheet.WriteFontStyle(row, col, [fssBold])`.
20341994- **Iteration through cells** using the worksheet methods `GetFirstCell` and `GetNextCell` has been removed - it failed if another iteration of this kind was called within the loop. Use the new for-in syntax instead.
20351995- Support for **shared formulas** has been reduced. The field `SharedFormulaBase` has been deleted from the TCell record, and methods related to shared formulas have been removed from TsWorksheet. Files containing shared formulas can still be read, the shared formulas are converted to multiple normal formulas.
20361996- The **color palettes** of previous versions have been abandoned. `TsColor` is now a `DWord` representing the rgb components of a color (just like TColor does in the *graphics* unit), it is not an index into a color palette any more. The values of pre-defined colors, therefore, have changed, their names, however, are still existing. The workbook functions for palette access have become obsolete and were removed.
20371997
20381998#### Version 1.4
20391999
20402000###### Change log (with respect to v1.2.x)
20412001
20422002- Full support for **string formulas**; calculation of RPN and string formulas for all built-in formulas either directly or by means of registration mechanism. Calculation occurs when a workbook is saved (activate workbook option `boCalcBeforeSaving`) or when cell content changes (active workbook option `boAutoCalc`).
20432003- **Shared formulas** (reading for sfExcel5, sfExcel8, sfOOXML; writing for sfExcel2, sfExcel5, sfExcel8).
20442004- Significant **speed-up** of writing of large spreadsheets for the xml-based formats (ods and xlsx), speed up for biff2; **speedtest demo** program
20452005- **VirtualMode** allowing to read and write very large spreadsheet files without loading entire document representation into memory. Formatting of cells in VirtualMode.
20462006- Demo program for database export using virtual mode and TFPSExport.
20472007- Added db export unit allowing programmatic exporting datasets using **TFPSExport**. Similar export units are e.g. [[fpdbfexport]], [[fpXMLXSDExport]].
20482008- Reader for **xlsx** files, now fully supporting the same features as the other readers.
20492009- Reader/writer for **CSV files** based on [[CsvDocument]].
20502010- **Wikitables writer** supports now most of the fpspreadsheet formatting options (background color, font style, font color, text alignment, cell borders/line styles/line colors, merged cells, column widths, row heights); new "wikitablemaker" demo
20512011- **Insertion and deletion of rows and columns** into a worksheet containing data.
20522012- Implementation of **sorting** of a worksheet.
20532013- Support of **diagonal "border" lines**
20542014- **Logging of non-fatal error messages** during reading/writing (TsWorksheet.ErrorMsg)
20552015- **Merged** cells
20562016- **Registration** of currency strings for automatic conversion of strings to **currency values**
20572017- A set of **visual controls** (TsWorkbookSource, TsWorkbookTabControl, TsSpreadsheetInspector, TsCellEdit, TsCellIndicator, TsCellCombobox, in addition to the already-existing TsWorksheetGrid) and pre-defined standard actions to facilitate [[FPSpreadsheet tutorial: Writing a mini spreadsheet application|creation of GUI applications]].
20582018- **Overflow cells** in TsWorksheetGrid: label cells with text longer than the cell width extend into the neighboring cell(s).
20592019
20602020###### Incompatible changes
20612021
20622022- The option `soCalcBeforeSaving` now belongs to the workbook, no longer to the worksheet, and has been renamed to `boCalcBeforeSaving` (it controls automatic calculation of formulas when a workbook is saved).
20632023- The workbook property `ReadFormulas` is replaced by the option flag `boReadFormulas`. This means that you have to add this flag to the workbook's `Options` in order to activate reading of formulas.
20642024- With full support of string formulas some features related to RPN formulas were removed:
20652025 - The field `RPNFormulaResult` of TCell was dropped, as well as the element `cctRPNFormula` in the `TsContentType` set.
20662026 - Sheet function identifiers were removed from the `TsFormulaElement` set, which was truncated after `fekParen`.
20672027 - To identify a sheet function, its name must be passed to the function `RPNFunc` (instead of using the now removed `fekXXXX` token). In the array notation of the RPN formula, a sheet function is identified by the new token `fekFunc`.
20682028 - The calling convention for registering user-defined functions was modified. It now also requires the Excel ID of the function (see "OpenOffice Documentation of Microsoft Excel Files", section 3.11, or unit *xlsconst* containing all token up to ID 200 and some above).
20692029 - Code related to RPN formulas was moved to a separate unit, `fpsRPN`. Add this unit to the uses clause if you need RPN features.
20702030
20712031#### Wiki documentation of old releases
20722032
20732033This wiki page is work in progress and updated whenever a new feature is added; therefore, its state corresponds to the svn trunk version of the package. If you work with an older stable version please use these "historic" wiki versions:
20742034
20752035- Version 1.12: \[<http://wiki.lazarus.freepascal.org/index.php?title=FPSpreadsheet&oldid=118771> <https://wiki.lazarus.freepascal.org/index.php?title=FPSpreadsheet&oldid=136886>}
20762036- Version 1.10.1: [<http://wiki.lazarus.freepascal.org/index.php?title=FPSpreadsheet&oldid=118771>](http://wiki.lazarus.freepascal.org/index.php?title=FPSpreadsheet&oldid=118771)
20772037- Version 1.10: [wiki.lazarus.freepascal.org/index.php?title=FPSpreadsheet&oldid=118441](http://wiki.lazarus.freepascal.org/index.php?title=FPSpreadsheet&oldid=118441)
20782038- Version 1.8: [wiki.lazarus.freepascal.org/index.php?title=FPSpreadsheet&oldid=107616](http://wiki.lazarus.freepascal.org/index.php?title=FPSpreadsheet&oldid=107616)
20792039- Version 1.6.2: [wiki.lazarus.freepascal.org/index.php?title=FPSpreadsheet&oldid=100723](http://wiki.lazarus.freepascal.org/index.php?title=FPSpreadsheet&oldid=100723)
20802040- Version 1.6: [wiki.lazarus.freepascal.org/index.php?title=FPSpreadsheet&oldid=91469](http://wiki.lazarus.freepascal.org/index.php?title=FPSpreadsheet&oldid=91469)
20812041- Version 1.4: [wiki.lazarus.freepascal.org/index.php?title=FPSpreadsheet&oldid=85299](http://wiki.lazarus.freepascal.org/index.php?title=FPSpreadsheet&oldid=85299)
20822042- Version 1.2 and 1.2.1: [wiki.lazarus.freepascal.org/index.php?title=FPSpreadsheet&oldid=81375](http://wiki.lazarus.freepascal.org/index.php?title=FPSpreadsheet&oldid=81375)
20832043
20842044## Installation
20852045
20862046- If you only need non-GUI components: in Lazarus: Package/Open Package File, select **laz_fpspreadsheet.lpk**, click Compile. Now the package is known to Lazarus (and should e.g. show up in Package/Package Links). Now you can add a dependency on `laz_fpspreadsheet` in your project options and `fpspreadsheet` to the uses clause of the project units that need to use it.
20872047- If you also want GUI components ([[TsWorksheetGrid]] and [[TsWorksheetChartSource]]): Package/Open Package File, select **laz_fpspreadsheet_visual.lpk**, click Compile, then click Use, Install and follow the prompts to rebuild Lazarus with the new package. Drop needed grid/chart components on your forms as usual.
20882048- If you want to have a GUI component for dataset export: Package/Open Package File, select **laz_fpspreadsheetexport_visual.lpk**, click Compile, then click, Use, Install and follow the prompts to rebuild Lazarus with the new package. Drop needed export components from the **Data Export** tab on your forms as usual.
20892049- FPSpreadsheet is developed with the latest stable fpc version (currently fpc 3.0.2). We only occasionally check older versions.
20902050- The basic spreadsheet functionality works with Lazarus versions back to version 1.0. Some visual controls or demo programs, however, require newer versions. Please update your Lazarus if you have an older version and experience problems.
20912051
20922052### Compiler options
20932053
20942054Here is a list of **conditional defines** which can be activated in order to tweak some operating modes of the packages and/or make it compilable with older Lazarus/FPC versions:
20952055
20962056- `FPS_DONT_USE_CLOCALE`: In Unix systems, the unit `clocale` is automatically added to the uses clause of *fpspreadsheet.pas*. This unit sets up localization settings needed for locale-dependent number and date/time formats. However, this adds a dependence on the C library to the package [2](http://lazarus-ccr.sourceforge.net/docs/rtl/clocale/index.html). If this is not wanted, define `FPS_DONT_USE_CLOCALE`.
20972057- `FPS_VARISBOOL`: fpspreadsheet requires the function VarIsBool which was introduced by fpc 2.6.4. If an older FPC versions is used define `FPS_VARISBOOL`. Keep undefined for the current FPC version.
20982058- `FPS_LAZUTF8`: fpspreadsheet requires some functions from the unit LazUTF8 which were introduced by Lazarus 1.2. If an older Lazarus version is used define `FPS_LAZUTF8`. Keep undefined for the current Lazarus version.
20992059
21002060All these defines are collected in the include file *fps.inc*.
21012061
21022062## Support and Bug Reporting
21032063
21042064The recommended place to discuss FPSpreadsheet and obtain support is asking in the [Lazarus Forum](http://forum.lazarus.freepascal.org/index.php?board=49.0).
21052065
21062066Bug reports should be sent to the [Lazarus/Free Pascal Bug Tracker](http://bugs.freepascal.org/); please specify the "Lazarus-CCR" project.
21072067
21082068## Current Progress
21092069
21102070### Progress by supported cell content
21112071
2112-<thead>
2113-
2114-sheets</th>
2115-
2116-support</th>
2117-
2118-support</th>
2119-
2120-Formula</th>
2121-
2122-Formula</th>
2123-
2124-references</th>
2125-
2126-formats</th>
2127-
2128-</thead>
2129-<tbody>
2130-
2131-</tbody>
2072+| Format | Multiple · sheets | Unicode | Reader · support | Writer · support | Text | Number | String · Formula | RPN · Formula | 3D cell · references | Date/Time | Comments | Hyperlinks | Images +++ | Protection | Conditional · formats |
2073+|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2074+| CSV files | No | Yes + | Working ++ | Working ++ | Working ++ | Working ++ | N/A | N/A | N/A | Working ++ | N/A | N/A | N/A | N/A | N/A |
2075+| Excel 2.x | No | No * | Working ** | Working | Working | Working | Working | Working *** | N/A | Working | Working | N/A | N/A | Working | N/A |
2076+| Excel 5.0 (Excel 5.0 and 95) | Yes | No * | Working ** | Working | Working | Working | Working | Working *** | Working | Working | Working | N/A | N/A | Working | N/A |
2077+| Excel 8.0 (Excel 97- 2003) | Yes | Yes | Working ** | Working | Working | Working | Working | Working *** | Working | Working | Reading only | Working | Not working | Working | Not working |
2078+| Excel 2003/XML | Yes | Yes | Working ** | Working | Working | Working | Working *** | Working | Working | Working | Working | Working | N/A | Working | Working |
2079+| Excel OOXML | Yes | Yes | Working ** | Working | Working | Working | Working *** | Working | Working | Working | Working | Working | Writing only | Working | Working ++++ |
2080+| OpenDocument | Yes | Yes | Working ** | Working | Working | Working | Working *** | Working | Working | Working | Working | Working | Working | Working | Working |
2081+| HTML | No | Yes | Working ++ | Working ++ | Working ++ | Working ++ | N/A | N/A | N/A | Working ++ | N/A | Working | Not working | N/A | N/A |
2082+| Wikitable files (Mediawiki) | No | Yes | planned | Working ++ | Working ++ | Working ++ | N/A | N/A | N/A | Working ++ | N/A | N/A | Not working | N/A | N/A |
21322083
21332084(+) Depends on file.\
21342085(++) No "true" number format support because the file does not containg number formatting information. But the number format currently used in the spreadsheet understood.\
21352086(+++) Only very basic image support: no transformations, no cropping, no image manipulation.\
21362087(++++) Extended OOXML formatting options not supported.\
21372088(*) In formats which don't support Unicode the data is stored by default as ISO 8859-1 (Latin 1). You can change the encoding in TsWorkbook.Encoding. Note that FPSpreadsheet offers UTF-8 read and write routines, but the data might be converted to ISO when reading or writing to the disk. Be careful that characters which don't fit selected encoding will be lost in those operations. The remarks here are only valid for formats which don't support Unicode.\
21382089(**) Some cell could be returned blank due to missing or non ready implemented number and text formats.\
21392090(***) This is the format in which the formulas are written to file (determined by design of the file format).\
21402091(****) Writing of all formats is supported. Some rare custom formats, however, may not be recognized correctly. BIFF2 supports only built-in formats by design.
21412092
21422093### Progress of the formatting options
21432094
21442095The following formatting options are available:
21452096
2146-<thead>
2147-
2148-alignment</th>
2149-
2150-rotation</th>
2151-
2152-text</th>
2153-
2154-support</th>
2155-
2156-ground</th>
2157-
2158-wrap</th>
2159-
2160-size</th>
2161-
2162-format</th>
2163-
2164-cells</th>
2165-
2166-layout</th>
2167-
2168-ranges</th>
2169-
2170-images</th>
2171-
2172-format</th>
2173-
2174-cols/rows</th>
2175-
2176-breaks</th>
2177-
2178-</thead>
2179-<tbody>
2180-
2181-(Excel 5.0 and 95)</td>
2182-
2183-(Excel 97 - XP)</td>
2184-
2185-</tbody>
2097+| Format | Text · alignment | Text · rotation | Font | Rich · text | Border | Color · support | Back · ground | Word · wrap | Col&Row · size | Number · format | Merged · cells | Page · layout | Print · ranges | Header/footer · images | Column/row · format | Hide · cols/rows | Page · breaks |
2098+|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2099+| CSV files | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A |
2100+| Excel 2.x | Working * | N/A | Working | N/A | Working | Working | Working** | N/A | Working | Working | N/A | Working | N/A | N/A | Working | N/A | Working |
2101+| Excel 5.0 · (Excel 5.0 and 95) | Working | Working | Working | Working | Working | Working | Working | Working | Working | Working | N/A | Working | Working | N/A | Working | Working | Working |
2102+| Excel 8.0 · (Excel 97 - XP) | Working | Working | Working | Working | Working | Working | Working | Working | Working | Working | Working | Working | Working | Not working | Working | Working | Working |
2103+| Excel 2003/XML | Working | Working | Working | Working | Working | Working | Working | Working | Working | Working | Working | Working | Working | N/A | Working | Wworking | Working |
2104+| Excel OOXML (xlsx) | Working | Working | Working | Working | Working | Working | Working | Working | Working | Working | Working | Working | Working | Writing only | Working | Working | Working |
2105+| OpenDocument | Working | Working | Working | Working | Working | Working | Working*** | Working | Working | Working | Working | Working | Working | Working | Working | Working | |
2106+| HTML (+) | Working | bugs | Working | Working | bugs | Working | Working | Writing only | Writing only | N/A | Working | N/A | N/A | Not working | Writing only | to be done | N/A |
2107+| Wikitable (Mediawiki) | Writing only | N/A | Writing only | Not working | Writing only | Writing only | | Writing only | Writing only | N/A | Writing only | N/A | N/A | Not working | Writing only | to be done | N/A |
21862108
21872109(N/A) Feature is not available for this format intrinsically.\
21882110(*) BIFF2 supports only horizontal text alignment, vertical alignment is ignored.\
21892111(**) BIFF2 does not support a background color; a dotted black&white background is used instead.\
21902112(***) OpenDocument supports only uniform backgrounds; a fill color interpolated between foreground and background colors is written instead.\
21912113(****) Only uniform background color, no fill styles.\
21922114(+) HTML reader does not support styles. Since the writer does use styles these files are not read back correctly.
21932115
21942116### Progress of workbook/worksheet user-interface options
21952117
21962118Some additional options were added to interface the file contents with the `TsWorksheetGrid`:
21972119
21982120| Format | Hide grid lines | Hide headers | Frozen Panes | Active sheet/cell | Zooming | BiDi mode | Tab color |
21992121|----|----|----|----|----|----|----|----|
22002122| Excel 2.x | Working | Working | not working | N/A | N/A | N/A | N/A |
22012123| Excel 5.0 (Excel 5.0 and 95) | Working | Working | Working | Working | Working | N/A | N/A |
22022124| Excel 8.0 (Excel 97 - XP) | Working | Working | Working | Working | Working | Working | Working |
22032125| Excel2003/XML | Working | Working | Working | Working | Working \|\| class="working\|Working | N/A | |
22042126| Excel OOXML | Working | Working | Working | Working | Working | Working | Working |
22052127| OpenDocument | Working | Working | Working | Working | Working | Working | Working |
22062128| HTML | Writing only | Writing only | N/A | N/A | N/A | not working | N/A |
22072129
22082130### To do list
22092131
22102132Note: this list is provisional, maintained by developers and can change without notice. If you are interested in contributing, please feel free to get in touch and submit a patch - thanks!
22112133
22122134- Find out why BIFF2 files are corrupt when saved with frozen rows/cols activated.
22132135- Add row and column formats
22142136- Add reading support for wikitable (Mediawiki) files
22152137- xls reader crashes for some incorrectly written xls files (which Excel can read), see [<http://forum.lazarus.freepascal.org/index.php/topic,25624.0.html>](http://forum.lazarus.freepascal.org/index.php/topic,25624.0.html).
22162138- Improve color support: due to palette support colors may change from file to file currently.
22172139- Add embedded images.
22182140- Fix writing of cell comments to BIFF8 files.
22192141
22202142**Long-term:**
22212143
22222144- Provide a more common user interface to fpspreadsheet (setter/getter and properties instead of Read*/Write* methods, MyWorksheet.Cells\[ARow, ACol\]), make TCell a class, avoid the pointers PCell.
22232145- Store formatting in a format list of the workbook, not in the cell, to reduce memory usage.
22242146- Use BIFF8 file-wide string storage instead of storing strings in cells (should reduce memory usage in case of many duplicate strings)
22252147- Redo ooxml and ods readers based upon SAX/TXmlReader instead of DOM to reduce memory usage of large files.
22262148- Add an fpspreadsheetexport unit and component on "Data Export" tab similar to [[fpdbfexport]] FPSpreadsheetexport demo preferably with all export formats component. Find a way to register export format to all formats (look into how lazreport pdf export performs a similar procedure).
22272149
22282150## Changelog
22292151
22302152Changes in the development version that have not yet been released are already documented on this page.
22312153
22322154- 2 June 2020:\
22332155 **Version 1.12** based on revision 7479
22342156- 13 August 2018:\
22352157 **Version 1.10.1** bug fix release, based on revision 6598.
22362158
22372159- 6 July 2018:\
22382160 **Version 1.10** release, based on svn revision 6547.
22392161- 16 June 2017:\
22402162 **Version 1.8.3**. Fixes compilation with Lazarus 1.8. New, highDPI-aware component palette icons
22412163- 11 April 2017:\
22422164 **Version 1.8.2**, based on svn revision 5832. Fixes writing distorted images due to incorrect row height calculation.
22432165- 2 March 2017:\
22442166 **Version 1.8**, based on svn revision 5781.
22452167- 13 April 2016:\
22462168 **Version 1.6.2** released, based on svn revision 4619. Fixes integer overflow in formulas ([Issue \#29999](https://bugs.freepascal.org/view.php?id=29999)).
22472169- 28 June 2015:\
22482170 **Version 1.6** released, based on svn release 4106. Improved memory consumption, comments, hyperlinks, background fill patterns, cell enumerator, fraction number format, page layout, modified color management, offline wiki version included.
22492171- 13 March 2015:\
22502172 **Version 1.4.3** released. Fixes formula calculation in worksheet grid.
22512173- 31 January 2015:\
22522174 **Version 1.4.2** released. Fixes incomplete reading of ods files with repeated cells ([Issue \#0027389](https://bugs.freepascal.org/view.php?id=0027389))
22532175- 26 January 2015:\
22542176 **Version 1.4.1** released. A bugfix release for 1.4 that fixes incorrect streaming of TsWorksheetGrid and reading errors of biff5 and biff8 readers.
22552177- 31 December 2014:\
22562178 **Version 1.4** released (based on subversion revision 3856 with full formula support, xlsx reader, csv reader and writer, wikitables writer, speed enhancement, virtual mode, db export component, row and column insertion/deletion, sorting, merged cells, visual controls in addition to (improved) fpspreadsheet grid.
22572179- 3 September 2014:\
22582180 **Version 1.2.1** released. This is a bugfix release for 1.2 that fixes a bug in spreadsheetGrid ([Issue \#26521](https://bugs.freepascal.org/view.php?id=26521))
22592181- 26 June 2014:\
22602182 **Version 1.2** released (based on subversion revision 3241) with fpsgrid improvements, date/time cell support for .xls, .ods, vastly improved cell formatting support, improved formula support, unit tests.
22612183- Jan 2013:\
22622184 **Version 1.1** released with all improvements up to revision 2621
22632185- Nov 2011:\
22642186 Released **version 1.0**, which includes OO XML generation support with bold formatting supported and also a lot of improvements from the last years
22652187- Jan 2009:\
22662188 Implemented a cross-platform support for OLE file. Now Excel 5.0 files can be created in any operating system. Adds read support for Excel 2.1
22672189- Feb 2008:\
22682190 **Initial commit** to lazarus-ccr with write support for Excel 2.1, Excel 5.0 (Windows only) and experimental OOXML and OpenDocument
22692191
22702192## License
22712193
22722194LGPL with static linking exception. This is the same license as is used in the Lazarus Component Library.
22732195
22742196## References
22752197
22762198### Wiki links
22772199
22782200- [[Office Automation]]
22792201- [[CsvDocument]]
22802202- [[FPSpreadsheet: Examples]]
22812203- [[RPN Formulas in FPSpreadsheet|RPN formulas in FPSpreadsheet]]
22822204- [[FPSpreadsheet: List of formulas]]
22832205- [[FPSpreadsheet tutorial: Writing a mini spreadsheet application]]
22842206
22852207### External Links
22862208
22872209- [Microsoft OLE Document Format](http://sc.openoffice.org/compdocfileformat.pdf)
22882210- [Excel file format description](http://sc.openoffice.org/excelfileformat.pdf)
22892211- Excel xls and PowerPoint ppt file dumper written in Python - very handy to list all contents of BIFF files (e.g. ./xls-dump.py file.xls) - [<http://cgit.freedesktop.org/libreoffice/contrib/mso-dumper/>](http://cgit.freedesktop.org/libreoffice/contrib/mso-dumper/). A similar application is the "BIFFExplorer" which can be found in the *applications* folder of ccr.
22902212- Icons used in the demo programs:
22912213 - [silk icons](http://www.famfamfam.com/lab/icons/silk/)
22922214 - [fugue icons](http://p.yusukekamiyamane.com/)
22932215
22942216---
22952217*From the Free Pascal wiki, page "FPSpreadsheet/pl", as it stood on 2021-08-14 after a change by FTurtle, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history