You've already forked lazarus-ccr
fpspreadsheet: Massive reconstruction: remove formatting attributes of TCell record and collect in TCellFormatList. TCell only has index into this list. Introduce record helpers to keep the old syntax. Reduction of memory consumption per cell by 50%.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3894 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@@ -21,6 +21,7 @@ var
|
||||
lRow: TRow;
|
||||
r: Integer;
|
||||
fmt: String;
|
||||
|
||||
begin
|
||||
// Open the output file
|
||||
MyDir := ExtractFilePath(ParamStr(0));
|
||||
|
@@ -10,7 +10,7 @@ program excel8write;
|
||||
{$mode delphi}{$H+}
|
||||
|
||||
uses
|
||||
Classes, SysUtils, fpspreadsheet, fpsRPN, xlsbiff8, fpsTypes;
|
||||
Classes, SysUtils, fpspreadsheet, fpsRPN, xlsbiff8, fpsTypes, fpsHelpers;
|
||||
|
||||
const
|
||||
Str_First = 'First';
|
||||
@@ -66,7 +66,7 @@ begin
|
||||
MyWorksheet.WriteNumber(5, 3, 10);
|
||||
lCell := MyWorksheet.GetCell(5, 3);
|
||||
lCell^.BackgroundColor := scPurple;
|
||||
lCell^.UsedFormattingFields := [uffBackgroundColor];
|
||||
// lCell^.UsedFormattingFields := [uffBackgroundColor];
|
||||
// or: MyWorksheet.WriteBackgroundColor(5, 3, scPurple);
|
||||
MyWorksheet.WriteFontColor(5, 3, scWhite);
|
||||
MyWorksheet.WriteFontSize(5, 3, 12);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<CONFIG>
|
||||
<ProjectOptions>
|
||||
<Version Value="9"/>
|
||||
@@ -40,9 +40,6 @@
|
||||
</Win32>
|
||||
</Options>
|
||||
</Linking>
|
||||
<Other>
|
||||
<CompilerPath Value="$(CompPath)"/>
|
||||
</Other>
|
||||
</CompilerOptions>
|
||||
</Item2>
|
||||
</BuildModes>
|
||||
@@ -100,9 +97,6 @@
|
||||
</Win32>
|
||||
</Options>
|
||||
</Linking>
|
||||
<Other>
|
||||
<CompilerPath Value="$(CompPath)"/>
|
||||
</Other>
|
||||
</CompilerOptions>
|
||||
<Debugging>
|
||||
<Exceptions Count="3">
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<CONFIG>
|
||||
<ProjectOptions>
|
||||
<Version Value="9"/>
|
||||
@@ -40,9 +40,6 @@
|
||||
</Win32>
|
||||
</Options>
|
||||
</Linking>
|
||||
<Other>
|
||||
<CompilerPath Value="$(CompPath)"/>
|
||||
</Other>
|
||||
</CompilerOptions>
|
||||
</Item2>
|
||||
</BuildModes>
|
||||
@@ -59,7 +56,7 @@
|
||||
<PackageName Value="LCL"/>
|
||||
</Item1>
|
||||
</RequiredPackages>
|
||||
<Units Count="2">
|
||||
<Units Count="3">
|
||||
<Unit0>
|
||||
<Filename Value="fpsgrid.lpr"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
@@ -72,6 +69,10 @@
|
||||
<ResourceBaseClass Value="Form"/>
|
||||
<UnitName Value="mainfrm"/>
|
||||
</Unit1>
|
||||
<Unit2>
|
||||
<Filename Value="..\..\fpshelpers.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit2>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
@@ -98,9 +99,6 @@
|
||||
</Win32>
|
||||
</Options>
|
||||
</Linking>
|
||||
<Other>
|
||||
<CompilerPath Value="$(CompPath)"/>
|
||||
</Other>
|
||||
</CompilerOptions>
|
||||
<Debugging>
|
||||
<Exceptions Count="3">
|
||||
|
@@ -7,7 +7,7 @@ uses
|
||||
cthreads,
|
||||
{$ENDIF}{$ENDIF}
|
||||
Interfaces, // this includes the LCL widgetset
|
||||
Forms, mainfrm
|
||||
Forms, mainfrm, fpsHelpers
|
||||
{ you can add units after this };
|
||||
|
||||
{$R *.res}
|
||||
|
@@ -7,7 +7,7 @@ interface
|
||||
uses
|
||||
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
|
||||
ComCtrls, StdCtrls, Grids,
|
||||
fpSpreadsheet, fpspreadsheetgrid, {%H-}fpsallformats;
|
||||
fpspreadsheet, fpspreadsheetgrid, {%H-}fpsallformats;
|
||||
|
||||
type
|
||||
|
||||
|
@@ -25,7 +25,7 @@ begin
|
||||
|
||||
// Open the input file
|
||||
MyDir := ExtractFilePath(ParamStr(0));
|
||||
InputFileName := MyDir + 'test.xlsx';
|
||||
InputFileName := MyDir + 'a.xlsx';
|
||||
if not FileExists(InputFileName) then begin
|
||||
WriteLn('Input file ', InputFileName, ' does not exist. Please run opendocwrite first.');
|
||||
Halt;
|
||||
@@ -56,5 +56,7 @@ begin
|
||||
|
||||
// Finalization
|
||||
MyWorkbook.Free;
|
||||
|
||||
ReadLn;
|
||||
end.
|
||||
|
||||
|
@@ -10,7 +10,7 @@ program ooxmlwrite;
|
||||
{$mode delphi}{$H+}
|
||||
|
||||
uses
|
||||
Classes, SysUtils, fpstypes, fpspreadsheet, fpsallformats;
|
||||
Classes, SysUtils, fpstypes, fpspreadsheet, fpsallformats, fpshelpers;
|
||||
|
||||
var
|
||||
MyWorkbook: TsWorkbook;
|
||||
|
@@ -42,6 +42,7 @@
|
||||
<Unit0>
|
||||
<Filename Value="demo_write_formatting.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="demo_write_formatting"/>
|
||||
</Unit0>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
|
@@ -12,7 +12,8 @@ program demo_write_formatting;
|
||||
{$mode delphi}{$H+}
|
||||
|
||||
uses
|
||||
Classes, SysUtils, fpsTypes, fpspreadsheet, xlsbiff8, fpsopendocument;
|
||||
Classes, SysUtils,
|
||||
fpsTypes, fpspreadsheet, xlsbiff8, fpsopendocument, fpscell;
|
||||
|
||||
var
|
||||
MyWorkbook: TsWorkbook;
|
||||
@@ -30,83 +31,67 @@ begin
|
||||
MyWorksheet.WriteUTF8Text(1, 1, '[]'); // B2
|
||||
MyCell := MyWorksheet.GetCell(1, 1);
|
||||
MyCell^.Border := [];
|
||||
MyCell^.UsedFormattingFields := [uffBorder];
|
||||
|
||||
MyWorksheet.WriteUTF8Text(1, 3, '[N]');// D2
|
||||
MyCell := MyWorksheet.GetCell(1, 3);
|
||||
MyCell^.Border := [cbNorth];
|
||||
MyCell^.UsedFormattingFields := [uffBorder];
|
||||
|
||||
MyWorksheet.WriteUTF8Text(1, 5, '[W]');// F2
|
||||
MyCell := MyWorksheet.GetCell(1, 5);
|
||||
MyCell^.Border := [cbWest];
|
||||
MyCell^.UsedFormattingFields := [uffBorder];
|
||||
|
||||
MyWorksheet.WriteUTF8Text(1, 7, '[E]');// H2
|
||||
MyCell := MyWorksheet.GetCell(1, 7);
|
||||
MyCell^.Border := [cbEast];
|
||||
MyCell^.UsedFormattingFields := [uffBorder];
|
||||
|
||||
MyWorksheet.WriteUTF8Text(1, 9, '[S]');// J2
|
||||
MyCell := MyWorksheet.GetCell(1, 9);
|
||||
MyCell^.Border := [cbSouth];
|
||||
MyCell^.UsedFormattingFields := [uffBorder];
|
||||
|
||||
MyWorksheet.WriteUTF8Text(3, 1, '[N,W]');// B4
|
||||
MyCell := MyWorksheet.GetCell(3, 1);
|
||||
MyCell^.Border := [cbNorth, cbWest];
|
||||
MyCell^.UsedFormattingFields := [uffBorder];
|
||||
|
||||
MyWorksheet.WriteUTF8Text(3, 3, '[N,E]');// D4
|
||||
MyCell := MyWorksheet.GetCell(3, 3);
|
||||
MyCell^.Border := [cbNorth, cbEast];
|
||||
MyCell^.UsedFormattingFields := [uffBorder];
|
||||
|
||||
MyWorksheet.WriteUTF8Text(3, 5, '[N,S]');// F4
|
||||
MyCell := MyWorksheet.GetCell(3, 5);
|
||||
MyCell^.Border := [cbNorth, cbSouth];
|
||||
MyCell^.UsedFormattingFields := [uffBorder];
|
||||
|
||||
MyWorksheet.WriteUTF8Text(3, 7, '[W,E]');// H4
|
||||
MyCell := MyWorksheet.GetCell(3, 7);
|
||||
MyCell^.Border := [cbWest, cbEast];
|
||||
MyCell^.UsedFormattingFields := [uffBorder];
|
||||
|
||||
MyWorksheet.WriteUTF8Text(3, 9, '[W,S]');// J4
|
||||
MyCell := MyWorksheet.GetCell(3, 9);
|
||||
MyCell^.Border := [cbWest, cbSouth];
|
||||
MyCell^.UsedFormattingFields := [uffBorder];
|
||||
|
||||
MyWorksheet.WriteUTF8Text(3, 11, '[E,S]');// L4
|
||||
MyCell := MyWorksheet.GetCell(3, 11);
|
||||
MyCell^.Border := [cbEast, cbSouth];
|
||||
MyCell^.UsedFormattingFields := [uffBorder];
|
||||
|
||||
MyWorksheet.WriteUTF8Text(5, 1, '[N,W,E]');// B6
|
||||
MyCell := MyWorksheet.GetCell(5, 1);
|
||||
MyCell^.Border := [cbNorth, cbWest, cbEast];
|
||||
MyCell^.UsedFormattingFields := [uffBorder];
|
||||
|
||||
MyWorksheet.WriteUTF8Text(5, 3, '[N,W,S]');// D6
|
||||
MyCell := MyWorksheet.GetCell(5, 3);
|
||||
MyCell^.Border := [cbNorth, cbWest, cbSouth];
|
||||
MyCell^.UsedFormattingFields := [uffBorder];
|
||||
|
||||
MyWorksheet.WriteUTF8Text(5, 5, '[N,E,S]');// F6
|
||||
MyCell := MyWorksheet.GetCell(5, 5);
|
||||
MyCell^.Border := [cbNorth, cbEast, cbSouth];
|
||||
MyCell^.UsedFormattingFields := [uffBorder];
|
||||
|
||||
MyWorksheet.WriteUTF8Text(5, 7, '[W,E,S]');// H6
|
||||
MyCell := MyWorksheet.GetCell(5, 7);
|
||||
MyCell^.Border := [cbWest, cbEast, cbSouth];
|
||||
MyCell^.UsedFormattingFields := [uffBorder];
|
||||
|
||||
MyWorksheet.WriteUTF8Text(5, 9, '[N,W,E,S]');// J6
|
||||
MyCell := MyWorksheet.GetCell(5, 9);
|
||||
MyCell^.Border := [cbNorth, cbWest, cbEast, cbSouth];
|
||||
MyCell^.BackgroundColor := scGreen;
|
||||
MyCell^.UsedFormattingFields := [uffBorder, uffBold, uffBackgroundColor];
|
||||
end;
|
||||
|
||||
procedure WriteSecondWorksheet();
|
||||
@@ -121,13 +106,11 @@ begin
|
||||
MyCell := MyWorksheet.GetCell(1, 1);
|
||||
MyCell^.Border := [cbNorth, cbWest, cbSouth];
|
||||
MyCell^.BackgroundColor := scGrey20pct;
|
||||
MyCell^.UsedFormattingFields := [uffBorder, uffBackgroundColor, uffBold];
|
||||
|
||||
MyWorksheet.WriteUTF8Text(1, 2, ' ');
|
||||
MyCell := MyWorksheet.GetCell(1, 2);
|
||||
MyCell^.Border := [cbNorth, cbEast, cbSouth];
|
||||
MyCell^.BackgroundColor := scGrey20pct;
|
||||
MyCell^.UsedFormattingFields := [uffBorder, uffBackgroundColor];
|
||||
|
||||
// Line 2
|
||||
|
||||
@@ -135,13 +118,11 @@ begin
|
||||
MyCell := MyWorksheet.GetCell(2, 1);
|
||||
MyCell^.Border := [cbWest];
|
||||
MyCell^.BackgroundColor := scGrey10pct;
|
||||
MyCell^.UsedFormattingFields := [uffBorder, uffBackgroundColor];
|
||||
|
||||
MyWorksheet.WriteUTF8Text(2, 2, 'R$ 20');
|
||||
MyCell := MyWorksheet.GetCell(2, 2);
|
||||
MyCell^.Border := [cbEast];
|
||||
MyCell^.BackgroundColor := scGrey10pct;
|
||||
MyCell^.UsedFormattingFields := [uffBorder, uffBackgroundColor];
|
||||
|
||||
// Line 3
|
||||
|
||||
@@ -149,13 +130,11 @@ begin
|
||||
MyCell := MyWorksheet.GetCell(3, 1);
|
||||
MyCell^.Border := [cbWest, cbSouth];
|
||||
MyCell^.BackgroundColor := scGrey10pct;
|
||||
MyCell^.UsedFormattingFields := [uffBorder, uffBackgroundColor];
|
||||
|
||||
MyWorksheet.WriteUTF8Text(3, 2, 'R$ 20');
|
||||
MyCell := MyWorksheet.GetCell(3, 2);
|
||||
MyCell^.Border := [cbEast, cbSouth];
|
||||
MyCell^.BackgroundColor := scGrey10pct;
|
||||
MyCell^.UsedFormattingFields := [uffBorder, uffBackgroundColor];
|
||||
end;
|
||||
|
||||
const
|
||||
@@ -171,7 +150,6 @@ begin
|
||||
MyWorkbook := TsWorkbook.Create;
|
||||
|
||||
WriteFirstWorksheet();
|
||||
|
||||
WriteSecondWorksheet();
|
||||
|
||||
// Save the spreadsheet to a file
|
||||
|
@@ -8,7 +8,8 @@ uses
|
||||
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
|
||||
StdCtrls, Menus, ExtCtrls, ComCtrls, ActnList, Spin, Grids,
|
||||
ColorBox, ValEdit,
|
||||
fpstypes, fpspreadsheetgrid, fpspreadsheet, {%H-}fpsallformats;
|
||||
fpstypes, fpspreadsheetgrid, fpspreadsheet,
|
||||
{%H-}fpsallformats;
|
||||
|
||||
type
|
||||
|
||||
@@ -617,6 +618,8 @@ var
|
||||
cell: PCell;
|
||||
decs: Byte;
|
||||
currsym: String;
|
||||
nf: TsNumberFormat;
|
||||
nfs: String;
|
||||
begin
|
||||
currsym := Sender.ClassName;
|
||||
with WorksheetGrid do begin
|
||||
@@ -624,7 +627,8 @@ begin
|
||||
exit;
|
||||
cell := Worksheet.FindCell(GetWorksheetRow(Row), GetWorksheetCol(Col));
|
||||
if (cell <> nil) then begin
|
||||
if cell^.NumberFormat = nfGeneral then begin
|
||||
Worksheet.ReadNumFormat(cell, nf, nfs);
|
||||
if nf = nfGeneral then begin
|
||||
Worksheet.WriteNumberFormat(cell, nfFixed, '0.00');
|
||||
exit;
|
||||
end;
|
||||
@@ -667,13 +671,14 @@ procedure TMainFrm.AcNumFormatExecute(Sender: TObject);
|
||||
const
|
||||
DATETIME_CUSTOM: array[0..4] of string = ('', 'dd/mmm', 'mmm/yy', 'nn:ss', 'nn:ss.zzz');
|
||||
var
|
||||
nf: TsNumberFormat;
|
||||
c, r: Cardinal;
|
||||
cell: PCell;
|
||||
fmt: String;
|
||||
decs: Byte;
|
||||
cs: String;
|
||||
isDateTimeFmt: Boolean;
|
||||
nf, cell_nf: TsNumberFormat;
|
||||
cell_nfs: String;
|
||||
begin
|
||||
if TAction(Sender).Checked then
|
||||
nf := TsNumberFormat((TAction(Sender).Tag - NUMFMT_TAG) div 10)
|
||||
@@ -691,23 +696,24 @@ begin
|
||||
c := GetWorksheetCol(Col);
|
||||
r := GetWorksheetRow(Row);
|
||||
cell := Worksheet.GetCell(r, c);
|
||||
Worksheet.ReadNumFormat(cell, cell_nf, cell_nfs);
|
||||
Worksheet.GetNumberFormatAttributes(cell, decs, cs);
|
||||
if cs = '' then cs := '?';
|
||||
case cell^.ContentType of
|
||||
cctNumber, cctDateTime:
|
||||
if isDateTimeFmt then begin
|
||||
if IsDateTimeFormat(cell^.NumberFormat) then
|
||||
if IsDateTimeFormat(cell_nf) then
|
||||
Worksheet.WriteDateTime(cell, cell^.DateTimeValue, nf, fmt)
|
||||
else
|
||||
Worksheet.WriteDateTime(cell, cell^.NumberValue, nf, fmt);
|
||||
end else
|
||||
if IsCurrencyFormat(nf) then begin
|
||||
if IsDateTimeFormat(cell^.NumberFormat) then
|
||||
if IsDateTimeFormat(cell_nf) then
|
||||
Worksheet.WriteCurrency(cell, cell^.DateTimeValue, nf, decs, cs)
|
||||
else
|
||||
Worksheet.WriteCurrency(cell, cell^.Numbervalue, nf, decs, cs);
|
||||
end else begin
|
||||
if IsDateTimeFormat(cell^.NumberFormat) then
|
||||
if IsDateTimeFormat(cell_nf) then
|
||||
Worksheet.WriteNumber(cell, cell^.DateTimeValue, nf, decs)
|
||||
else
|
||||
Worksheet.WriteNumber(cell, cell^.NumberValue, nf, decs)
|
||||
@@ -1114,6 +1120,7 @@ var
|
||||
s: String;
|
||||
cb: TsCellBorder;
|
||||
r1,r2,c1,c2: Cardinal;
|
||||
fmt: TsCellFormat;
|
||||
begin
|
||||
with CellInspector do
|
||||
begin
|
||||
@@ -1174,30 +1181,33 @@ begin
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (ACell=nil) or not (uffFont in ACell^.UsedFormattingFields)
|
||||
if ACell <> nil
|
||||
then fmt := WorksheetGrid.Workbook.GetCellFormat(ACell^.FormatIndex)
|
||||
else InitFormatRecord(fmt);
|
||||
if (ACell=nil) or not (uffFont in fmt.UsedFormattingFields)
|
||||
then Strings.Add('FontIndex=')
|
||||
else Strings.Add(Format('FontIndex=%d (%s(', [
|
||||
ACell^.FontIndex,
|
||||
WorksheetGrid.Workbook.GetFontAsString(ACell^.FontIndex)]));
|
||||
if (ACell=nil) or not (uffTextRotation in ACell^.UsedFormattingFields)
|
||||
else Strings.Add(Format('FontIndex=%d (%s)', [
|
||||
fmt.FontIndex,
|
||||
WorksheetGrid.Workbook.GetFontAsString(fmt.FontIndex)]));
|
||||
if (ACell=nil) or not (uffTextRotation in fmt.UsedFormattingFields)
|
||||
then Strings.Add('TextRotation=')
|
||||
else Strings.Add(Format('TextRotation=%s', [GetEnumName(TypeInfo(TsTextRotation), ord(ACell^.TextRotation))]));
|
||||
if (ACell=nil) or not (uffHorAlign in ACell^.UsedFormattingFields)
|
||||
else Strings.Add(Format('TextRotation=%s', [GetEnumName(TypeInfo(TsTextRotation), ord(fmt.TextRotation))]));
|
||||
if (ACell=nil) or not (uffHorAlign in fmt.UsedFormattingFields)
|
||||
then Strings.Add('HorAlignment=')
|
||||
else Strings.Add(Format('HorAlignment=%s', [GetEnumName(TypeInfo(TsHorAlignment), ord(ACell^.HorAlignment))]));
|
||||
if (ACell=nil) or not (uffVertAlign in ACell^.UsedFormattingFields)
|
||||
else Strings.Add(Format('HorAlignment=%s', [GetEnumName(TypeInfo(TsHorAlignment), ord(fmt.HorAlignment))]));
|
||||
if (ACell=nil) or not (uffVertAlign in fmt.UsedFormattingFields)
|
||||
then Strings.Add('VertAlignment=')
|
||||
else Strings.Add(Format('VertAlignment=%s', [GetEnumName(TypeInfo(TsVertAlignment), ord(ACell^.VertAlignment))]));
|
||||
if (ACell=nil) or not (uffBorder in ACell^.UsedFormattingFields) then
|
||||
else Strings.Add(Format('VertAlignment=%s', [GetEnumName(TypeInfo(TsVertAlignment), ord(fmt.VertAlignment))]));
|
||||
if (ACell=nil) or not (uffBorder in fmt.UsedFormattingFields) then
|
||||
Strings.Add('Borders=')
|
||||
else begin
|
||||
s := '';
|
||||
if cbNorth in ACell^.Border then s := s + ', cbNorth';
|
||||
if cbSouth in ACell^.Border then s := s + ', cbSouth';
|
||||
if cbEast in ACell^.Border then s := s + ', cbEast';
|
||||
if cbWest in ACell^.Border then s := s + ', cbWest';
|
||||
if cbDiagUp in ACell^.Border then s := s + ', cbDiagUp';
|
||||
if cbDiagDown in ACell^.Border then s := s + ', cbDiagDown';
|
||||
if cbNorth in fmt.Border then s := s + ', cbNorth';
|
||||
if cbSouth in fmt.Border then s := s + ', cbSouth';
|
||||
if cbEast in fmt.Border then s := s + ', cbEast';
|
||||
if cbWest in fmt.Border then s := s + ', cbWest';
|
||||
if cbDiagUp in fmt.Border then s := s + ', cbDiagUp';
|
||||
if cbDiagDown in fmt.Border then s := s + ', cbDiagDown';
|
||||
if s <> '' then Delete(s, 1, 2);
|
||||
Strings.Add('Borders='+s);
|
||||
end;
|
||||
@@ -1209,21 +1219,21 @@ begin
|
||||
else
|
||||
Strings.Add(Format('BorderStyles[%s]=%s, %s', [
|
||||
GetEnumName(TypeInfo(TsCellBorder), ord(cb)),
|
||||
GetEnumName(TypeInfo(TsLineStyle), ord(ACell^.BorderStyles[cbEast].LineStyle)),
|
||||
WorksheetGrid.Workbook.GetColorName(ACell^.BorderStyles[cbEast].Color)
|
||||
GetEnumName(TypeInfo(TsLineStyle), ord(fmt.BorderStyles[cbEast].LineStyle)),
|
||||
WorksheetGrid.Workbook.GetColorName(fmt.BorderStyles[cbEast].Color)
|
||||
]));
|
||||
if (ACell=nil) or not (uffBackgroundColor in ACell^.UsedformattingFields)
|
||||
if (ACell=nil) or not (uffBackgroundColor in fmt.UsedformattingFields)
|
||||
then Strings.Add('BackgroundColor=')
|
||||
else Strings.Add(Format('BackgroundColor=%d (%s)', [
|
||||
ACell^.BackgroundColor,
|
||||
WorksheetGrid.Workbook.GetColorName(Acell^.BackgroundColor)
|
||||
fmt.BackgroundColor,
|
||||
WorksheetGrid.Workbook.GetColorName(fmt.BackgroundColor)
|
||||
]));
|
||||
if (ACell=nil) or not (uffNumberFormat in ACell^.UsedFormattingFields)
|
||||
if (ACell=nil) or not (uffNumberFormat in fmt.UsedFormattingFields)
|
||||
then Strings.Add('NumberFormat=')
|
||||
else Strings.Add(Format('NumberFormat=%s', [GetEnumName(TypeInfo(TsNumberFormat), ord(ACell^.NumberFormat))]));
|
||||
if (ACell=nil) or not (uffNumberFormat in ACell^.UsedFormattingFields)
|
||||
else Strings.Add(Format('NumberFormat=%s', [GetEnumName(TypeInfo(TsNumberFormat), ord(fmt.NumberFormat))]));
|
||||
if (ACell=nil) or not (uffNumberFormat in fmt.UsedFormattingFields)
|
||||
then Strings.Add('NumberFormatStr=')
|
||||
else Strings.Add('NumberFormatStr=' + ACell^.NumberFormatStr);
|
||||
else Strings.Add('NumberFormatStr=' + fmt.NumberFormatStr);
|
||||
if not WorksheetGrid.Worksheet.IsMerged(ACell) then
|
||||
Strings.Add('Merged range=')
|
||||
else
|
||||
@@ -1285,6 +1295,7 @@ var
|
||||
i: Integer;
|
||||
ac: TAction;
|
||||
nf: TsNumberFormat;
|
||||
nfs: String;
|
||||
cell: PCell;
|
||||
r,c: Cardinal;
|
||||
found: Boolean;
|
||||
@@ -1296,17 +1307,17 @@ begin
|
||||
if (cell = nil) or not (cell^.ContentType in [cctNumber, cctDateTime]) then
|
||||
nf := nfGeneral
|
||||
else
|
||||
nf := cell^.NumberFormat;
|
||||
Worksheet.ReadNumFormat(cell, nf, nfs);
|
||||
for i:=0 to ActionList.ActionCount-1 do begin
|
||||
ac := TAction(ActionList.Actions[i]);
|
||||
if (ac.Tag >= NUMFMT_TAG) and (ac.Tag < NUMFMT_TAG + 200) then begin
|
||||
found := ((ac.Tag - NUMFMT_TAG) div 10 = ord(nf));
|
||||
if nf = nfCustom then
|
||||
case (ac.Tag - NUMFMT_TAG) mod 10 of
|
||||
1: found := cell^.NumberFormatStr = 'dd/mmm';
|
||||
2: found := cell^.NumberFormatStr = 'mmm/yy';
|
||||
3: found := cell^.NumberFormatStr = 'nn:ss';
|
||||
4: found := cell^.NumberFormatStr = 'nn:ss.z';
|
||||
1: found := nfs = 'dd/mmm';
|
||||
2: found := nfs = 'mmm/yy';
|
||||
3: found := nfs = 'nn:ss';
|
||||
4: found := nfs = 'nn:ss.z';
|
||||
end;
|
||||
ac.Checked := found;
|
||||
end;
|
||||
|
@@ -116,7 +116,6 @@
|
||||
<Unit3>
|
||||
<Filename Value="sctrls.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="sCtrls"/>
|
||||
</Unit3>
|
||||
<Unit4>
|
||||
<Filename Value="sformatsettingsform.pas"/>
|
||||
@@ -140,12 +139,10 @@
|
||||
<ComponentName Value="CurrencyForm"/>
|
||||
<HasResources Value="True"/>
|
||||
<ResourceBaseClass Value="Form"/>
|
||||
<UnitName Value="sfCurrencyForm"/>
|
||||
</Unit6>
|
||||
<Unit7>
|
||||
<Filename Value="..\..\fpscurrency.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="fpsCurrency"/>
|
||||
</Unit7>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
|
@@ -10,6 +10,13 @@
|
||||
{.$DEFINE FPS_DONT_USE_CLOCALE}
|
||||
|
||||
|
||||
{ In older versions of fpspreadsheet, the formatting fields had belonged to the
|
||||
cell record. This has been given up to reduce memory consumption.
|
||||
For fpc >2.6, however, record helpers allow to get this feature back. In case
|
||||
of older compilers activate the define FPS_NO_RECORD_HELPERS. Note that worksheet
|
||||
methods can only be used to change cell formatting then. }
|
||||
{.$DEFINE FPS_NO_RECORD_HELPERS}
|
||||
|
||||
{ The next defines activate code duplicated from new compiler versions in case
|
||||
an old compiler is used. }
|
||||
|
||||
|
@@ -771,7 +771,7 @@ var
|
||||
fnt: TsFont;
|
||||
fs: TsFontStyles;
|
||||
begin
|
||||
fnt := Workbook.GetFont(ACell^.FontIndex);
|
||||
fnt := Worksheet.ReadCellFont(ACell);
|
||||
fs := fnt.Style;
|
||||
if Checked then
|
||||
Include(fs, FFontStyle)
|
||||
@@ -783,16 +783,21 @@ end;
|
||||
procedure TsFontStyleAction.ExtractFromCell(ACell: PCell);
|
||||
var
|
||||
fnt: TsFont;
|
||||
fmt: PsCellFormat;
|
||||
begin
|
||||
if (ACell = nil) then
|
||||
Checked := false
|
||||
else
|
||||
if (uffBold in ACell^.UsedFormattingFields) then
|
||||
begin
|
||||
Checked := false;
|
||||
exit;
|
||||
end;
|
||||
|
||||
fmt := Workbook.GetPointerToCellFormat(ACell^.FormatIndex);
|
||||
if (uffBold in fmt^.UsedFormattingFields) then
|
||||
Checked := (FFontStyle = fssBold)
|
||||
else
|
||||
if (uffFont in ACell^.UsedFormattingFields) then
|
||||
if (uffFont in fmt^.UsedFormattingFields) then
|
||||
begin
|
||||
fnt := Workbook.GetFont(ACell^.FontIndex);
|
||||
fnt := Workbook.GetFont(fmt^.FontIndex);
|
||||
Checked := (FFontStyle in fnt.Style);
|
||||
end else
|
||||
Checked := false;
|
||||
@@ -818,10 +823,7 @@ end;
|
||||
|
||||
procedure TsHorAlignmentAction.ExtractFromCell(ACell: PCell);
|
||||
begin
|
||||
if (ACell = nil) or not (uffHorAlign in ACell^.UsedFormattingFields) then
|
||||
Checked := false
|
||||
else
|
||||
Checked := ACell^.HorAlignment = FHorAlign;
|
||||
Checked := (ACell <> nil) and (Worksheet.ReadHorAlignment(ACell) = FHorAlign);
|
||||
end;
|
||||
|
||||
|
||||
@@ -844,10 +846,7 @@ end;
|
||||
|
||||
procedure TsVertAlignmentAction.ExtractFromCell(ACell: PCell);
|
||||
begin
|
||||
if (ACell = nil) or not (uffVertAlign in ACell^.UsedFormattingFields) then
|
||||
Checked := false
|
||||
else
|
||||
Checked := ACell^.VertAlignment = FVertAlign;
|
||||
Checked := (ACell <> nil) and (Worksheet.ReadVertAlignment(ACell) = FVertAlign);
|
||||
end;
|
||||
|
||||
|
||||
@@ -870,10 +869,7 @@ end;
|
||||
|
||||
procedure TsTextRotationAction.ExtractFromCell(ACell: PCell);
|
||||
begin
|
||||
if (ACell = nil) or not (uffTextRotation in ACell^.UsedFormattingFields) then
|
||||
Checked := false
|
||||
else
|
||||
Checked := ACell^.TextRotation = FTextRotation;
|
||||
Checked := (ACell <> nil) and (Worksheet.ReadTextRotation(ACell) = FTextRotation);
|
||||
end;
|
||||
|
||||
|
||||
@@ -892,7 +888,7 @@ end;
|
||||
|
||||
procedure TsWordwrapAction.ExtractFromCell(ACell: PCell);
|
||||
begin
|
||||
Checked := (ACell <> nil) and (uffWordwrap in ACell^.UsedFormattingFields);
|
||||
Checked := (ACell <> nil) and Worksheet.ReadWordwrap(ACell);
|
||||
end;
|
||||
|
||||
function TsWordwrapAction.GetWordwrap: Boolean;
|
||||
@@ -936,12 +932,12 @@ begin
|
||||
end;
|
||||
|
||||
procedure TsNumberFormatAction.ExtractFromCell(ACell: PCell);
|
||||
var
|
||||
nf: TsNumberFormat;
|
||||
nfs: String;
|
||||
begin
|
||||
if (ACell = nil) or not (uffNumberFormat in ACell^.UsedFormattingFields) then
|
||||
Checked := false
|
||||
else
|
||||
Checked := (ACell^.NumberFormat = FNumberFormat)
|
||||
and (ACell^.NumberFormatStr = FNumberFormatStr);
|
||||
Worksheet.ReadNumFormat(ACell, nf, nfs);
|
||||
Checked := (ACell <> nil) and (nf = FNumberFormat) and (nfs = FNumberFormatStr);
|
||||
end;
|
||||
|
||||
|
||||
@@ -956,14 +952,15 @@ end;
|
||||
procedure TsDecimalsAction.ApplyFormatToCell(ACell: PCell);
|
||||
var
|
||||
decs: Integer;
|
||||
nf: TsNumberFormat;
|
||||
nfs: String;
|
||||
begin
|
||||
if IsDateTimeFormat(ACell^.NumberFormat) then
|
||||
Worksheet.ReadNumFormat(ACell, nf, nfs);
|
||||
|
||||
if IsDateTimeFormat(nf) then
|
||||
exit;
|
||||
|
||||
if (ACell^.ContentType in [cctEmpty, cctNumber]) and (
|
||||
(not (uffNumberFormat in ACell^.UsedFormattingFields)) or
|
||||
(ACell^.NumberFormat = nfGeneral)
|
||||
) then
|
||||
if (ACell^.ContentType in [cctEmpty, cctNumber]) and (nf <> nfGeneral) then
|
||||
decs := Worksheet.GetDisplayedDecimals(ACell)
|
||||
else
|
||||
decs := FDecimals;
|
||||
@@ -976,16 +973,16 @@ procedure TsDecimalsAction.ExtractFromCell(ACell: PCell);
|
||||
var
|
||||
csym: String;
|
||||
decs: Byte;
|
||||
nf: TsNumberFormat;
|
||||
nfs: String;
|
||||
begin
|
||||
if ACell = nil then begin
|
||||
FDecimals := 2;
|
||||
exit;
|
||||
end;
|
||||
|
||||
if (ACell^.ContentType in [cctEmpty, cctNumber]) and (
|
||||
(not (uffNumberFormat in ACell^.UsedFormattingFields)) or
|
||||
(ACell^.NumberFormat = nfGeneral)
|
||||
) then
|
||||
Worksheet.ReadNumFormat(ACell, nf, nfs);
|
||||
if (ACell^.ContentType in [cctEmpty, cctNumber]) and (nf <> nfGeneral) then
|
||||
decs := Worksheet.GetDisplayedDecimals(ACell)
|
||||
else
|
||||
Worksheet.GetNumberFormatAttributes(ACell, decs, csym);
|
||||
@@ -1029,8 +1026,11 @@ end;
|
||||
procedure TsActionBorders.ExtractFromCell(AWorkbook: TsWorkbook; ACell: PCell);
|
||||
var
|
||||
cb: TsCellBorder;
|
||||
fmt: PsCellFormat;
|
||||
begin
|
||||
if (ACell = nil) or not (uffBorder in ACell^.UsedFormattingFields) then
|
||||
if (ACell <> nil) then
|
||||
fmt := AWorkbook.GetPointerToCellFormat(ACell^.FormatIndex);
|
||||
if (ACell = nil) or not (uffBorder in fmt^.UsedFormattingFields) then
|
||||
for cb in TsCellBorder do
|
||||
begin
|
||||
FBorders[cb].ExtractStyle(AWorkbook, DEFAULT_BORDERSTYLES[cb]);
|
||||
@@ -1039,8 +1039,8 @@ begin
|
||||
else
|
||||
for cb in TsCellBorder do
|
||||
begin
|
||||
FBorders[cb].ExtractStyle(AWorkbook, ACell^.BorderStyles[cb]);
|
||||
FBorders[cb].Visible := cb in ACell^.Border;
|
||||
FBorders[cb].ExtractStyle(AWorkbook, fmt^.BorderStyles[cb]);
|
||||
FBorders[cb].Visible := cb in fmt^.Border;
|
||||
end;
|
||||
end;
|
||||
|
||||
@@ -1072,16 +1072,18 @@ procedure TsCellBorderAction.ApplyFormatToRange(ARange: TsCellRange);
|
||||
procedure ShowBorder(ABorder: TsCellBorder; ACell: PCell;
|
||||
ABorderStyle: TsCellBorderStyle; AEnable: boolean);
|
||||
var
|
||||
brdr: TsCellBorders;
|
||||
fmt: TsCellFormat;
|
||||
begin
|
||||
brdr := ACell^.Border;
|
||||
fmt := Workbook.GetCellFormat(ACell^.FormatIndex);
|
||||
if AEnable then
|
||||
begin
|
||||
Include(brdr, ABorder);
|
||||
Worksheet.WriteBorderStyle(ACell, ABorder, ABorderStyle);
|
||||
Worksheet.WriteBorders(ACell, brdr);
|
||||
// Don't modify the cell directly, this will miss the OnChange event.
|
||||
end;
|
||||
Include(fmt.Border, ABorder);
|
||||
fmt.BorderStyles[ABorder] := ABorderStyle;
|
||||
ACell^.FormatIndex := Workbook.AddCellFormat(fmt);
|
||||
Include(fmt.UsedFormattingFields, uffBorder);
|
||||
end else
|
||||
Exclude(fmt.UsedFormattingFields, uffBorder);
|
||||
Worksheet.ChangedCell(ACell^.Row, ACell^.Col);
|
||||
end;
|
||||
|
||||
var
|
||||
@@ -1139,7 +1141,8 @@ procedure TsCellBorderAction.ExtractFromCell(ACell: PCell);
|
||||
var
|
||||
EmptyCell: TCell;
|
||||
begin
|
||||
if (ACell = nil) or not (uffBorder in ACell^.UsedFormattingFields) then
|
||||
// if (ACell = nil) or not (uffBorder in ACell^.UsedFormattingFields) then
|
||||
if (ACell = nil) or not (uffBorder in Worksheet.ReadUsedFormatting(ACell)) then
|
||||
begin
|
||||
EmptyCell.Row := 0; // silence the compiler...
|
||||
InitCell(EmptyCell);
|
||||
@@ -1288,19 +1291,22 @@ procedure TsFontDialogAction.ExtractFromCell(ACell: PCell);
|
||||
var
|
||||
sfnt: TsFont;
|
||||
fnt: TFont;
|
||||
fmt: PsCellFormat;
|
||||
begin
|
||||
fnt := TFont.Create;
|
||||
try
|
||||
if (ACell = nil) then
|
||||
sfnt := Workbook.GetDefaultFont
|
||||
else
|
||||
if uffBold in ACell^.UsedFormattingFields then
|
||||
sfnt := Workbook.GetFont(1)
|
||||
else
|
||||
if uffFont in ACell^.UsedFormattingFields then
|
||||
sfnt := Workbook.GetFont(ACell^.FontIndex)
|
||||
else
|
||||
sfnt := Workbook.GetDefaultFont;
|
||||
else begin
|
||||
fmt := Workbook.GetPointerToCellFormat(ACell^.FormatIndex);
|
||||
if (uffBold in fmt^.UsedFormattingFields) then
|
||||
sfnt := Workbook.GetFont(1)
|
||||
else
|
||||
if (uffFont in fmt^.UsedFormattingFields) then
|
||||
sfnt := Workbook.GetFont(fmt^.FontIndex)
|
||||
else
|
||||
sfnt := Workbook.GetDefaultFont;
|
||||
end;
|
||||
Convert_sFont_to_Font(Workbook, sfnt, fnt);
|
||||
GetDialog.Font.Assign(fnt);
|
||||
finally
|
||||
@@ -1339,11 +1345,15 @@ begin
|
||||
end;
|
||||
|
||||
procedure TsBackgroundColorDialogAction.ExtractFromCell(ACell: PCell);
|
||||
var
|
||||
fmt: PsCellFormat;
|
||||
begin
|
||||
if (ACell = nil) or not (uffBackgroundColor in ACell^.UsedFormattingFields) then
|
||||
FBackgroundColor := scNotDefined
|
||||
else
|
||||
FBackgroundColor := ACell^.BackgroundColor;
|
||||
FBackgroundColor := scNotDefined;
|
||||
if (ACell <> nil) then begin
|
||||
fmt := Workbook.GetPointerToCellFormat(ACell^.FormatIndex);
|
||||
if (uffBackgroundColor in fmt^.UsedFormattingFields) then
|
||||
FBackgroundColor := fmt^.BackgroundColor;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsBackgroundColorDialogAction.GetDialog: TColorDialog;
|
||||
|
146
components/fpspreadsheet/fpscell.pas
Normal file
146
components/fpspreadsheet/fpscell.pas
Normal file
@@ -0,0 +1,146 @@
|
||||
unit fpsCell;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
{$modeswitch advancedrecords}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, fpstypes, fpspreadsheet;
|
||||
|
||||
type
|
||||
TCellHelper = record helper for TCell
|
||||
private
|
||||
function GetBackgroundColor: TsColor;
|
||||
function GetBorder: TsCellBorders;
|
||||
function GetBorderStyle(ABorder: TsCellBorder): TsCellBorderStyle;
|
||||
function GetCellFormat: TsCellFormat;
|
||||
function GetFont: TsFont;
|
||||
function GetFontIndex: integer;
|
||||
function GetHorAlignment: TsHorAlignment;
|
||||
function GetNumberFormat: TsNumberFormat;
|
||||
function GetNumberFormatStr: String;
|
||||
function GetTextRotation: TsTextRotation;
|
||||
function GetVertAlignment: TsVertAlignment;
|
||||
function GetWordwrap: Boolean;
|
||||
procedure SetBackgroundColor(AValue: TsColor);
|
||||
procedure SetBorder(AValue: TsCellBorders);
|
||||
procedure SetBorderStyle(ABorder: TsCellBorder; AValue: TsCellBorderStyle);
|
||||
procedure SetFontIndex(AValue: Integer);
|
||||
|
||||
protected
|
||||
function GetWorkbook: TsWorkbook;
|
||||
public
|
||||
property BackgroundColor: TsColor read GetBackgroundColor write SetBackgroundColor;
|
||||
property Border: TsCellBorders read GetBorder write SetBorder;
|
||||
property CellFormat: TsCellFormat read GetCellFormat;
|
||||
property Font: TsFont read GetFont;
|
||||
property FontIndex: Integer read GetFontIndex write SetFontIndex;
|
||||
property HorAlignment: TsHorAlignment read GetHorAlignment;
|
||||
property NumberFormat: TsNumberFormat read GetNumberFormat;
|
||||
property NumberFormatStr: String read GetNumberFormatStr;
|
||||
property TextRotation: TsTextRotation read GetTextRotation;
|
||||
property VertAlignment: TsVertAlignment read GetVertAlignment;
|
||||
property Wordwrap: Boolean read GetWordwrap;
|
||||
property Workbook: TsWorkbook read GetWorkbook;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
function TCellHelper.GetBackgroundColor: TsColor;
|
||||
begin
|
||||
Result := Worksheet.ReadBackgroundColor(@self);
|
||||
end;
|
||||
|
||||
function TCellHelper.GetBorder: TsCellBorders;
|
||||
begin
|
||||
Result := Worksheet.ReadCellBorders(@self);
|
||||
end;
|
||||
|
||||
function TCellHelper.GetBorderStyle(ABorder: TsCellBorder): TsCellBorderStyle;
|
||||
begin
|
||||
Result := Worksheet.ReadCellBorderStyle(@self, ABorder);
|
||||
end;
|
||||
|
||||
function TCellHelper.GetCellFormat: TsCellFormat;
|
||||
begin
|
||||
Result := Workbook.GetCellFormat(FormatIndex);
|
||||
end;
|
||||
|
||||
function TCellHelper.GetFont: TsFont;
|
||||
begin
|
||||
Result := Worksheet.ReadCellFont(@self);
|
||||
end;
|
||||
|
||||
function TCellHelper.GetFontIndex: Integer;
|
||||
var
|
||||
fmt: PsCellFormat;
|
||||
begin
|
||||
fmt := Workbook.GetPointerToCellFormat(FormatIndex);
|
||||
Result := fmt^.FontIndex;
|
||||
end;
|
||||
|
||||
function TCellHelper.GetHorAlignment: TsHorAlignment;
|
||||
begin
|
||||
Result := Worksheet.ReadHorAlignment(@Self);
|
||||
end;
|
||||
|
||||
function TCellHelper.GetNumberFormat: TsNumberFormat;
|
||||
var
|
||||
fmt: PsCellFormat;
|
||||
begin
|
||||
fmt := Workbook.GetPointerToCellFormat(FormatIndex);
|
||||
Result := fmt^.NumberFormat;
|
||||
end;
|
||||
|
||||
function TCellHelper.GetNumberFormatStr: String;
|
||||
var
|
||||
fmt: PsCellFormat;
|
||||
begin
|
||||
fmt := Workbook.GetPointerToCellFormat(FormatIndex);
|
||||
Result := fmt^.NumberFormatStr;
|
||||
end;
|
||||
|
||||
function TCellHelper.GetTextRotation: TsTextRotation;
|
||||
begin
|
||||
Result := Worksheet.ReadTextRotation(@Self);
|
||||
end;
|
||||
|
||||
function TCellHelper.GetVertAlignment: TsVertAlignment;
|
||||
begin
|
||||
Result := Worksheet.ReadVertAlignment(@self);
|
||||
end;
|
||||
|
||||
function TCellHelper.GetWordwrap: Boolean;
|
||||
begin
|
||||
Result := Worksheet.ReadWordwrap(@self);
|
||||
end;
|
||||
|
||||
function TCellHelper.GetWorkbook: TsWorkbook;
|
||||
begin
|
||||
Result := Worksheet.Workbook;
|
||||
end;
|
||||
|
||||
procedure TCellHelper.SetBackgroundColor(AValue: TsColor);
|
||||
begin
|
||||
Worksheet.WriteBackgroundColor(@self, AValue);
|
||||
end;
|
||||
|
||||
procedure TCellHelper.SetBorder(AValue: TsCellBorders);
|
||||
begin
|
||||
Worksheet.WriteBorders(@self, AValue);
|
||||
end;
|
||||
|
||||
procedure TCellHelper.SetBorderStyle(ABorder: TsCellBorder;
|
||||
AValue: TsCellBorderStyle);
|
||||
begin
|
||||
Worksheet.WriteBorderStyle(@self, ABorder, AValue);
|
||||
end;
|
||||
|
||||
procedure TCellHelper.SetFontIndex(AValue: Integer);
|
||||
begin
|
||||
Worksheet.WriteFont(@self, AValue);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
@@ -1254,6 +1254,7 @@ var
|
||||
stype: String;
|
||||
r1, c1: Cardinal;
|
||||
cell: PCell;
|
||||
cellfmt: TsCellFormat;
|
||||
begin
|
||||
if Length(Args)=1 then
|
||||
begin
|
||||
@@ -1282,6 +1283,10 @@ begin
|
||||
Result := ErrorResult(errWrongType);
|
||||
exit;
|
||||
end;
|
||||
if cell <> nil then
|
||||
cellfmt := cell^.Worksheet.ReadCellFormat(cell)
|
||||
else
|
||||
InitFormatRecord(cellfmt);
|
||||
|
||||
if stype = 'address' then
|
||||
Result := StringResult(GetCellString(r1, c1, []))
|
||||
@@ -1291,7 +1296,7 @@ begin
|
||||
else
|
||||
if stype = 'color' then
|
||||
begin
|
||||
if (cell <> nil) and (cell^.NumberFormat = nfCurrencyRed) then
|
||||
if (cell <> nil) and (cellfmt.NumberFormat = nfCurrencyRed) then
|
||||
Result := IntegerResult(1)
|
||||
else
|
||||
Result := IntegerResult(0);
|
||||
@@ -1322,20 +1327,20 @@ begin
|
||||
if stype = 'format' then begin
|
||||
Result := StringResult('G');
|
||||
if cell <> nil then
|
||||
case cell^.NumberFormat of
|
||||
case cellfmt.NumberFormat of
|
||||
nfGeneral:
|
||||
Result := StringResult('G');
|
||||
nfFixed:
|
||||
if cell^.NumberFormatStr= '0' then Result := StringResult('0') else
|
||||
if cell^.NumberFormatStr = '0.00' then Result := StringResult('F0');
|
||||
if cellfmt.NumberFormatStr= '0' then Result := StringResult('0') else
|
||||
if cellfmt.NumberFormatStr = '0.00' then Result := StringResult('F0');
|
||||
nfFixedTh:
|
||||
if cell^.NumberFormatStr = '#,##0' then Result := StringResult(',0') else
|
||||
if cell^.NumberFormatStr = '#,##0.00' then Result := StringResult(',2');
|
||||
if cellfmt.NumberFormatStr = '#,##0' then Result := StringResult(',0') else
|
||||
if cellfmt.NumberFormatStr = '#,##0.00' then Result := StringResult(',2');
|
||||
nfPercentage:
|
||||
if cell^.NumberFormatStr = '0%' then Result := StringResult('P0') else
|
||||
if cell^.NumberFormatStr = '0.00%' then Result := StringResult('P2');
|
||||
if cellfmt.NumberFormatStr = '0%' then Result := StringResult('P0') else
|
||||
if cellfmt.NumberFormatStr = '0.00%' then Result := StringResult('P2');
|
||||
nfExp:
|
||||
if cell^.NumberFormatStr = '0.00E+00' then Result := StringResult('S2');
|
||||
if cellfmt.NumberFormatStr = '0.00E+00' then Result := StringResult('S2');
|
||||
nfShortDate, nfLongDate, nfShortDateTime:
|
||||
Result := StringResult('D4');
|
||||
nfLongTimeAM:
|
||||
@@ -1352,7 +1357,7 @@ begin
|
||||
begin
|
||||
Result := StringResult('');
|
||||
if (cell^.ContentType = cctUTF8String) then
|
||||
case cell^.HorAlignment of
|
||||
case cellfmt.HorAlignment of
|
||||
haLeft : Result := StringResult('''');
|
||||
haCenter: Result := StringResult('^');
|
||||
haRight : Result := StringResult('"');
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -74,7 +74,7 @@ type
|
||||
property YFirstCellRow: Cardinal read FYFirstCellRow write SetYFirstCellRow default 0;
|
||||
property XSelectionDirection: TsSelectionDirection read FXSelectionDirection write SetXSelectionDirection;
|
||||
property YSelectionDirection: TsSelectionDirection read FYSelectionDirection write SetYSelectionDirection;
|
||||
end;
|
||||
end deprecated 'Use TsWorkBOOKChartSource instead of TsWorkSHEETChartSource.';
|
||||
|
||||
|
||||
{ TsWorkbookChartSource }
|
||||
|
@@ -2548,39 +2548,45 @@ var
|
||||
s: String;
|
||||
cb: TsCellBorder;
|
||||
r1, r2, c1, c2: Cardinal;
|
||||
fmt: TsCellFormat;
|
||||
begin
|
||||
if (ACell = nil) or not (uffFont in ACell^.UsedFormattingFields)
|
||||
if (ACell <> nil) then
|
||||
fmt := Workbook.GetCellFormat(ACell^.FormatIndex)
|
||||
else
|
||||
InitFormatRecord(fmt);
|
||||
|
||||
if (ACell = nil) or not (uffFont in fmt.UsedFormattingFields)
|
||||
then AStrings.Add('FontIndex=')
|
||||
else AStrings.Add(Format('FontIndex=%d (%s)', [
|
||||
ACell^.FontIndex,
|
||||
Workbook.GetFontAsString(ACell^.FontIndex)
|
||||
fmt.FontIndex,
|
||||
Workbook.GetFontAsString(fmt.FontIndex)
|
||||
]));
|
||||
|
||||
if (ACell=nil) or not (uffTextRotation in ACell^.UsedFormattingFields)
|
||||
if (ACell=nil) or not (uffTextRotation in fmt.UsedFormattingFields)
|
||||
then AStrings.Add('TextRotation=')
|
||||
else AStrings.Add(Format('TextRotation=%s', [
|
||||
GetEnumName(TypeInfo(TsTextRotation), ord(ACell^.TextRotation))
|
||||
GetEnumName(TypeInfo(TsTextRotation), ord(fmt.TextRotation))
|
||||
]));
|
||||
|
||||
if (ACell=nil) or not (uffHorAlign in ACell^.UsedFormattingFields)
|
||||
if (ACell=nil) or not (uffHorAlign in fmt.UsedFormattingFields)
|
||||
then AStrings.Add('HorAlignment=')
|
||||
else AStrings.Add(Format('HorAlignment=%s', [
|
||||
GetEnumName(TypeInfo(TsHorAlignment), ord(ACell^.HorAlignment))
|
||||
GetEnumName(TypeInfo(TsHorAlignment), ord(fmt.HorAlignment))
|
||||
]));
|
||||
|
||||
if (ACell=nil) or not (uffVertAlign in ACell^.UsedFormattingFields)
|
||||
if (ACell=nil) or not (uffVertAlign in fmt.UsedFormattingFields)
|
||||
then AStrings.Add('VertAlignment=')
|
||||
else AStrings.Add(Format('VertAlignment=%s', [
|
||||
GetEnumName(TypeInfo(TsVertAlignment), ord(ACell^.VertAlignment))
|
||||
GetEnumName(TypeInfo(TsVertAlignment), ord(fmt.VertAlignment))
|
||||
]));
|
||||
|
||||
if (ACell=nil) or not (uffBorder in ACell^.UsedFormattingFields) then
|
||||
if (ACell=nil) or not (uffBorder in fmt.UsedFormattingFields) then
|
||||
AStrings.Add('Borders=')
|
||||
else
|
||||
begin
|
||||
s := '';
|
||||
for cb in TsCellBorder do
|
||||
if cb in ACell^.Border then
|
||||
if cb in fmt.Border then
|
||||
s := s + ', ' + GetEnumName(TypeInfo(TsCellBorder), ord(cb));
|
||||
if s <> '' then Delete(s, 1, 2);
|
||||
AStrings.Add('Borders='+s);
|
||||
@@ -2593,24 +2599,24 @@ begin
|
||||
else
|
||||
AStrings.Add(Format('BorderStyles[%s]=%s, %s', [
|
||||
GetEnumName(TypeInfo(TsCellBorder), ord(cb)),
|
||||
GetEnumName(TypeInfo(TsLineStyle), ord(ACell^.BorderStyles[cbEast].LineStyle)),
|
||||
Workbook.GetColorName(ACell^.BorderStyles[cbEast].Color)]));
|
||||
GetEnumName(TypeInfo(TsLineStyle), ord(fmt.BorderStyles[cbEast].LineStyle)),
|
||||
Workbook.GetColorName(fmt.BorderStyles[cbEast].Color)]));
|
||||
|
||||
if (ACell = nil) or not (uffBackgroundColor in ACell^.UsedformattingFields)
|
||||
if (ACell = nil) or not (uffBackgroundColor in fmt.UsedformattingFields)
|
||||
then AStrings.Add('BackgroundColor=')
|
||||
else AStrings.Add(Format('BackgroundColor=%d (%s)', [
|
||||
ACell^.BackgroundColor,
|
||||
Workbook.GetColorName(ACell^.BackgroundColor)]));
|
||||
fmt.BackgroundColor,
|
||||
Workbook.GetColorName(fmt.BackgroundColor)]));
|
||||
|
||||
if (ACell = nil) or not (uffNumberFormat in ACell^.UsedFormattingFields) then
|
||||
if (ACell = nil) or not (uffNumberFormat in fmt.UsedFormattingFields) then
|
||||
begin
|
||||
AStrings.Add('NumberFormat=');
|
||||
AStrings.Add('NumberFormatStr=');
|
||||
end else
|
||||
begin
|
||||
AStrings.Add(Format('NumberFormat=%s', [
|
||||
GetEnumName(TypeInfo(TsNumberFormat), ord(ACell^.NumberFormat))]));
|
||||
AStrings.Add('NumberFormatStr=' + ACell^.NumberFormatStr);
|
||||
GetEnumName(TypeInfo(TsNumberFormat), ord(fmt.NumberFormat))]));
|
||||
AStrings.Add('NumberFormatStr=' + fmt.NumberFormatStr);
|
||||
end;
|
||||
|
||||
if (Worksheet = nil) or not Worksheet.IsMerged(ACell) then
|
||||
|
@@ -849,6 +849,7 @@ var
|
||||
txtalign: TsHorAlignment;
|
||||
r: Cardinal;
|
||||
w, w0: Integer;
|
||||
fmt: PsCellFormat;
|
||||
begin
|
||||
Result := false;
|
||||
cell := FDrawingCell;
|
||||
@@ -856,16 +857,19 @@ begin
|
||||
// Nothing to do in these cases (like in Excel):
|
||||
if (cell = nil) or (cell^.ContentType <> cctUTF8String) then // ... non-label cells
|
||||
exit;
|
||||
if (uffWordWrap in cell^.UsedFormattingFields) then // ... word-wrap
|
||||
|
||||
fmt := Workbook.GetPointerToCellFormat(cell^.FormatIndex);
|
||||
|
||||
if (uffWordWrap in fmt^.UsedFormattingFields) then // ... word-wrap
|
||||
exit;
|
||||
if (uffTextRotation in cell^.UsedFormattingFields) and // ... vertical text
|
||||
(cell^.TextRotation <> trHorizontal)
|
||||
if (uffTextRotation in fmt^.UsedFormattingFields) and // ... vertical text
|
||||
(fmt^.TextRotation <> trHorizontal)
|
||||
then
|
||||
exit;
|
||||
|
||||
txt := cell^.UTF8Stringvalue;
|
||||
if (uffHorAlign in cell^.UsedFormattingFields) then
|
||||
txtalign := cell^.HorAlignment
|
||||
if (uffHorAlign in fmt^.UsedFormattingFields) then
|
||||
txtalign := fmt^.HorAlignment
|
||||
else
|
||||
txtalign := haDefault;
|
||||
PrepareCanvas(ACol, ARow, AState);
|
||||
@@ -1160,6 +1164,7 @@ procedure TsCustomWorksheetGrid.DoPrepareCanvas(ACol, ARow: Integer;
|
||||
var
|
||||
ts: TTextStyle;
|
||||
lCell: PCell;
|
||||
fmt: PsCellFormat;
|
||||
r, c: Integer;
|
||||
fnt: TsFont;
|
||||
style: TFontStyles;
|
||||
@@ -1194,8 +1199,9 @@ begin
|
||||
lCell := Worksheet.FindCell(r, c);
|
||||
if lCell <> nil then
|
||||
begin
|
||||
fmt := Workbook.GetPointerToCellFormat(lCell^.FormatIndex);
|
||||
// Background color
|
||||
if (uffBackgroundColor in lCell^.UsedFormattingFields) then
|
||||
if (uffBackgroundColor in fmt^.UsedFormattingFields) then
|
||||
begin
|
||||
if Workbook.FileFormat = sfExcel2 then
|
||||
begin
|
||||
@@ -1206,8 +1212,8 @@ begin
|
||||
end else
|
||||
begin
|
||||
Canvas.Brush.Style := bsSolid;
|
||||
if lCell^.BackgroundColor < Workbook.GetPaletteSize then
|
||||
Canvas.Brush.Color := Workbook.GetPaletteColor(lCell^.BackgroundColor)
|
||||
if fmt^.BackgroundColor < Workbook.GetPaletteSize then
|
||||
Canvas.Brush.Color := Workbook.GetPaletteColor(fmt^.BackgroundColor)
|
||||
else
|
||||
Canvas.Brush.Color := Color;
|
||||
end;
|
||||
@@ -1217,9 +1223,9 @@ begin
|
||||
Canvas.Brush.Color := Color;
|
||||
end;
|
||||
// Font
|
||||
if (uffFont in lCell^.UsedFormattingFields) then
|
||||
if (uffFont in fmt^.UsedFormattingFields) then
|
||||
begin
|
||||
fnt := Workbook.GetFont(lCell^.FontIndex);
|
||||
fnt := Workbook.GetFont(fmt^.FontIndex);
|
||||
if fnt <> nil then
|
||||
begin
|
||||
Canvas.Font.Name := fnt.FontName;
|
||||
@@ -1233,7 +1239,7 @@ begin
|
||||
Canvas.Font.Size := round(fnt.Size);
|
||||
end;
|
||||
end;
|
||||
if (lCell^.NumberFormat = nfCurrencyRed) and
|
||||
if (fmt^.NumberFormat = nfCurrencyRed) and
|
||||
not IsNaN(lCell^.NumberValue) and (lCell^.NumberValue < 0)
|
||||
then
|
||||
Canvas.Font.Color := Workbook.GetPaletteColor(scRed);
|
||||
@@ -1302,7 +1308,7 @@ begin
|
||||
cell := Worksheet.GetFirstCell;
|
||||
while cell <> nil do
|
||||
begin
|
||||
if (uffBorder in cell^.UsedFormattingFields) then
|
||||
if (uffBorder in Worksheet.ReadUsedFormatting(cell)) then
|
||||
begin
|
||||
c := GetGridCol(cell^.Col);
|
||||
r := GetGridRow(cell^.Row);
|
||||
@@ -1442,6 +1448,7 @@ const
|
||||
var
|
||||
bs: TsCellBorderStyle;
|
||||
cell: PCell;
|
||||
fmt: PsCellFormat;
|
||||
begin
|
||||
if Assigned(Worksheet) then begin
|
||||
// Left border
|
||||
@@ -1459,14 +1466,15 @@ begin
|
||||
|
||||
cell := Worksheet.FindCell(ARow-FHeaderCount, ACol-FHeaderCount);
|
||||
if cell <> nil then begin
|
||||
fmt := Workbook.GetPointerToCellFormat(cell^.FormatIndex);
|
||||
// Diagonal up
|
||||
if cbDiagUp in cell^.Border then begin
|
||||
bs := cell^.Borderstyles[cbDiagUp];
|
||||
if cbDiagUp in fmt^.Border then begin
|
||||
bs := fmt^.Borderstyles[cbDiagUp];
|
||||
DrawBorderLine(0, ARect, drawDiagUp, bs);
|
||||
end;
|
||||
// Diagonal down
|
||||
if cbDiagDown in cell^.Border then begin
|
||||
bs := cell^.BorderStyles[cbDiagDown];
|
||||
if cbDiagDown in fmt^.Border then begin
|
||||
bs := fmt^.BorderStyles[cbDiagDown];
|
||||
DrawborderLine(0, ARect, drawDiagDown, bs);
|
||||
end;
|
||||
end;
|
||||
@@ -1527,6 +1535,7 @@ var
|
||||
rct, saved_rct, temp_rct: TRect;
|
||||
clipArea: Trect;
|
||||
cell: PCell;
|
||||
fmt: PsCellFormat;
|
||||
tmp: Integer = 0;
|
||||
|
||||
function IsPushCellActive: boolean;
|
||||
@@ -1606,9 +1615,10 @@ begin
|
||||
then
|
||||
Continue;
|
||||
// Overflow possible from non-merged, non-right-aligned, horizontal label cells
|
||||
fmt := Workbook.GetPointerToCellFormat(cell^.FormatIndex);
|
||||
if (cell^.MergeBase = nil) and (cell^.ContentType = cctUTF8String) and
|
||||
not (uffTextRotation in cell^.UsedFormattingFields) and
|
||||
(uffHorAlign in cell^.UsedFormattingFields) and (cell^.HorAlignment <> haRight)
|
||||
not (uffTextRotation in fmt^.UsedFormattingFields) and
|
||||
(uffHorAlign in fmt^.UsedFormattingFields) and (fmt^.HorAlignment <> haRight)
|
||||
then
|
||||
Break;
|
||||
// All other cases --> no overflow --> return to initial left cell
|
||||
@@ -1631,9 +1641,10 @@ begin
|
||||
then
|
||||
continue;
|
||||
// Overflow possible from non-merged, horizontal, non-left-aligned label cells
|
||||
fmt := Workbook.GetPointerToCellFormat(cell^.FormatIndex);
|
||||
if (cell^.MergeBase = nil) and (cell^.ContentType = cctUTF8String) and
|
||||
not (uffTextRotation in cell^.UsedFormattingFields) and
|
||||
(uffHorAlign in cell^.UsedFormattingFields) and (cell^.HorAlignment <> haLeft)
|
||||
not (uffTextRotation in fmt^.UsedFormattingFields) and
|
||||
(uffHorAlign in fmt^.UsedFormattingFields) and (fmt^.HorAlignment <> haLeft)
|
||||
then
|
||||
Break;
|
||||
// All other cases --> no overflow --> return to initial right column
|
||||
@@ -1786,6 +1797,7 @@ var
|
||||
txtRot: TsTextRotation;
|
||||
lCell: PCell;
|
||||
justif: Byte;
|
||||
fmt: PsCellFormat;
|
||||
begin
|
||||
if (Worksheet = nil) then
|
||||
exit;
|
||||
@@ -1810,12 +1822,13 @@ begin
|
||||
end;
|
||||
|
||||
// Cells
|
||||
wrapped := (uffWordWrap in lCell^.UsedFormattingFields) or (lCell^.TextRotation = rtStacked);
|
||||
txtRot := lCell^.TextRotation;
|
||||
vertAlign := lCell^.VertAlignment;
|
||||
fmt := Workbook.GetPointerToCellFormat(lCell^.FormatIndex);
|
||||
wrapped := (uffWordWrap in fmt^.UsedFormattingFields) or (fmt^.TextRotation = rtStacked);
|
||||
txtRot := fmt^.TextRotation;
|
||||
vertAlign := fmt^.VertAlignment;
|
||||
if vertAlign = vaDefault then vertAlign := vaBottom;
|
||||
if lCell^.HorAlignment <> haDefault then
|
||||
horAlign := lCell^.HorAlignment
|
||||
if fmt^.HorAlignment <> haDefault then
|
||||
horAlign := fmt^.HorAlignment
|
||||
else
|
||||
begin
|
||||
if (lCell^.ContentType in [cctNumber, cctDateTime]) then
|
||||
@@ -1915,7 +1928,7 @@ procedure TsCustomWorksheetGrid.FixNeighborCellBorders(ACol, ARow: Integer);
|
||||
neighbor := Worksheet.FindCell(NewRow, NewCol);
|
||||
if neighbor <> nil then
|
||||
begin
|
||||
border := neighbor^.Border;
|
||||
border := Worksheet.ReadCelLBorders(neighbor);
|
||||
if AInclude then
|
||||
begin
|
||||
Include(border, ANewBorder);
|
||||
@@ -1928,6 +1941,7 @@ procedure TsCustomWorksheetGrid.FixNeighborCellBorders(ACol, ARow: Integer);
|
||||
|
||||
var
|
||||
cell: PCell;
|
||||
fmt: PsCellFormat;
|
||||
begin
|
||||
if Worksheet = nil then
|
||||
exit;
|
||||
@@ -1936,10 +1950,11 @@ begin
|
||||
if (Worksheet <> nil) and (cell <> nil) then
|
||||
with cell^ do
|
||||
begin
|
||||
SetNeighborBorder(Row, Col-1, cbEast, BorderStyles[cbWest], cbWest in Border);
|
||||
SetNeighborBorder(Row, Col+1, cbWest, BorderStyles[cbEast], cbEast in Border);
|
||||
SetNeighborBorder(Row-1, Col, cbSouth, BorderStyles[cbNorth], cbNorth in Border);
|
||||
SetNeighborBorder(Row+1, Col, cbNorth, BorderStyles[cbSouth], cbSouth in Border);
|
||||
fmt := Workbook.GetPointerToCellFormat(cell^.FormatIndex);
|
||||
SetNeighborBorder(Row, Col-1, cbEast, fmt^.BorderStyles[cbWest], cbWest in fmt^.Border);
|
||||
SetNeighborBorder(Row, Col+1, cbWest, fmt^.BorderStyles[cbEast], cbEast in fmt^.Border);
|
||||
SetNeighborBorder(Row-1, Col, cbSouth, fmt^.BorderStyles[cbNorth], cbNorth in fmt^.Border);
|
||||
SetNeighborBorder(Row+1, Col, cbNorth, fmt^.BorderStyles[cbSouth], cbSouth in fmt^.Border);
|
||||
end;
|
||||
end;
|
||||
|
||||
@@ -2034,8 +2049,7 @@ begin
|
||||
if Assigned(Worksheet) then
|
||||
begin
|
||||
cell := Worksheet.FindCell(GetWorksheetRow(ARow), GetWorksheetCol(ACol));
|
||||
if (cell <> nil) and (uffBackgroundColor in cell^.UsedFormattingFields) then
|
||||
Result := cell^.BackgroundColor;
|
||||
Result := Worksheet.ReadBackgroundColor(cell);
|
||||
end;
|
||||
end;
|
||||
|
||||
@@ -2084,8 +2098,7 @@ begin
|
||||
if Assigned(Worksheet) then
|
||||
begin
|
||||
cell := Worksheet.FindCell(GetWorksheetRow(ARow), GetWorksheetCol(ACol));
|
||||
if (cell <> nil) and (uffBorder in cell^.UsedFormattingFields) then
|
||||
Result := cell^.Border;
|
||||
Result := Worksheet.ReadCellBorders(cell);
|
||||
end;
|
||||
end;
|
||||
|
||||
@@ -2137,8 +2150,7 @@ begin
|
||||
if Assigned(Worksheet) then
|
||||
begin
|
||||
cell := Worksheet.FindCell(GetWorksheetRow(ARow), GetWorksheetCol(ACol));
|
||||
if (cell <> nil) then
|
||||
Result := cell^.BorderStyles[ABorder];
|
||||
Result := Worksheet.ReadCellBorderStyle(cell, ABorder);
|
||||
end;
|
||||
end;
|
||||
|
||||
@@ -2190,17 +2202,10 @@ begin
|
||||
if (Workbook <> nil) then
|
||||
begin
|
||||
fnt := Workbook.GetDefaultFont;
|
||||
if Worksheet <> nil then
|
||||
if (Worksheet <> nil) then
|
||||
begin
|
||||
cell := Worksheet.FindCell(GetWorksheetRow(ARow), GetWorksheetCol(ACol));
|
||||
if (cell <> nil) then
|
||||
begin
|
||||
if (uffBold in cell^.UsedFormattingFields) then
|
||||
fnt := Workbook.GetFont(1)
|
||||
else
|
||||
if (uffFont in cell^.UsedFormattingFields) then
|
||||
fnt := Workbook.GetFont(cell^.FontIndex);
|
||||
end;
|
||||
fnt := Worksheet.ReadCellFont(cell);
|
||||
end;
|
||||
Convert_sFont_to_Font(fnt, FCellFont);
|
||||
Result := FCellFont;
|
||||
@@ -2253,7 +2258,7 @@ begin
|
||||
cell := Worksheet.FindCell(GetWorksheetRow(r), GetWorksheetCol(c));
|
||||
if cell <> nil then
|
||||
begin
|
||||
sFont := Workbook.GetFont(cell^.FontIndex);
|
||||
sFont := Worksheet.ReadCellFont(cell);
|
||||
if (sFont.FontName <> sDefFont.FontName) and (sFont.Size <> sDefFont.Size)
|
||||
and (sFont.Style <> sDefFont.Style) and (sFont.Color <> sDefFont.Color)
|
||||
then
|
||||
@@ -2282,6 +2287,7 @@ var
|
||||
cellR: TRect;
|
||||
flags: Cardinal;
|
||||
r1,c1,r2,c2: Cardinal;
|
||||
fmt: PsCellFormat;
|
||||
begin
|
||||
Result := 0;
|
||||
if ShowHeaders and ((ACol = 0) or (ARow = 0)) then
|
||||
@@ -2292,7 +2298,6 @@ begin
|
||||
lCell := Worksheet.FindCell(ARow-FHeaderCount, ACol-FHeaderCount);
|
||||
if lCell <> nil then
|
||||
begin
|
||||
//if lCell^.MergedNeighbors <> [] then begin
|
||||
if (lCell^.Mergebase <> nil) then
|
||||
begin
|
||||
Worksheet.FindMergedRange(lCell, r1, c1, r2, c2);
|
||||
@@ -2306,15 +2311,16 @@ begin
|
||||
if s = '' then
|
||||
exit;
|
||||
DoPrepareCanvas(ACol, ARow, []);
|
||||
wrapped := (uffWordWrap in lCell^.UsedFormattingFields)
|
||||
or (lCell^.TextRotation = rtStacked);
|
||||
fmt := Workbook.GetPointerToCellFormat(lCell^.FormatIndex);
|
||||
wrapped := (uffWordWrap in fmt^.UsedFormattingFields)
|
||||
or (fmt^.TextRotation = rtStacked);
|
||||
// *** multi-line text ***
|
||||
if wrapped then
|
||||
begin
|
||||
// horizontal
|
||||
if ( (uffTextRotation in lCell^.UsedFormattingFields) and
|
||||
(lCell^.TextRotation in [trHorizontal, rtStacked]))
|
||||
or not (uffTextRotation in lCell^.UsedFormattingFields)
|
||||
if ( (uffTextRotation in fmt^.UsedFormattingFields) and
|
||||
(fmt^.TextRotation in [trHorizontal, rtStacked]))
|
||||
or not (uffTextRotation in fmt^.UsedFormattingFields)
|
||||
then
|
||||
begin
|
||||
cellR := CellRect(ACol, ARow);
|
||||
@@ -2331,14 +2337,14 @@ begin
|
||||
// *** single-line text ***
|
||||
begin
|
||||
// not rotated
|
||||
if ( not (uffTextRotation in lCell^.UsedFormattingFields) or
|
||||
(lCell^.TextRotation = trHorizontal) )
|
||||
if ( not (uffTextRotation in fmt^.UsedFormattingFields) or
|
||||
(fmt^.TextRotation = trHorizontal) )
|
||||
then
|
||||
Result := Canvas.TextHeight(s) + 2*constCellPadding
|
||||
else
|
||||
// rotated by +/- 90°
|
||||
if (uffTextRotation in lCell^.UsedFormattingFields) and
|
||||
(lCell^.TextRotation in [rt90DegreeClockwiseRotation, rt90DegreeCounterClockwiseRotation])
|
||||
if (uffTextRotation in fmt^.UsedFormattingFields) and
|
||||
(fmt^.TextRotation in [rt90DegreeClockwiseRotation, rt90DegreeCounterClockwiseRotation])
|
||||
then
|
||||
Result := Canvas.TextWidth(s) + 2*constCellPadding;
|
||||
end;
|
||||
@@ -2389,7 +2395,7 @@ begin
|
||||
if lCell <> nil then
|
||||
begin
|
||||
Result := TrimToCell(lCell);
|
||||
if lCell^.TextRotation = rtStacked then
|
||||
if Worksheet.ReadTextRotation(lCell) = rtStacked then
|
||||
begin
|
||||
s := Result;
|
||||
Result := '';
|
||||
@@ -2495,7 +2501,7 @@ begin
|
||||
then
|
||||
result := false
|
||||
else
|
||||
ABorderStyle := cell^.BorderStyles[border]
|
||||
ABorderStyle := Worksheet.ReadCellBorderStyle(cell, border)
|
||||
end
|
||||
else
|
||||
// Only neighbor has border, cell has not
|
||||
@@ -2506,7 +2512,7 @@ begin
|
||||
then
|
||||
result := false
|
||||
else
|
||||
ABorderStyle := neighborcell^.BorderStyles[neighborborder]
|
||||
ABorderStyle := Worksheet.ReadCellBorderStyle(neighborcell, neighborborder); //neighborcell^.BorderStyles[neighborborder]
|
||||
end
|
||||
else
|
||||
// Both cells have shared border -> use top or left border
|
||||
@@ -2518,9 +2524,9 @@ begin
|
||||
result := false
|
||||
else
|
||||
if (border in [cbNorth, cbWest]) then
|
||||
ABorderStyle := neighborcell^.BorderStyles[neighborborder]
|
||||
ABorderStyle := Worksheet.ReadCellBorderStyle(neighborcell, neighborborder) //neighborcell^.BorderStyles[neighborborder]
|
||||
else
|
||||
ABorderStyle := cell^.BorderStyles[border];
|
||||
ABorderStyle := Worksheet.ReadCellBorderStyle(cell, border); //cell^.BorderStyles[border];
|
||||
end else
|
||||
Result := false;
|
||||
end;
|
||||
@@ -2608,8 +2614,10 @@ end;
|
||||
-------------------------------------------------------------------------------}
|
||||
function TsCustomWorksheetGrid.HasBorder(ACell: PCell; ABorder: TsCellBorder): Boolean;
|
||||
begin
|
||||
Result := (ACell <> nil) and (uffBorder in ACell^.UsedFormattingfields) and
|
||||
(ABorder in ACell^.Border);
|
||||
if Worksheet = nil then
|
||||
result := false
|
||||
else
|
||||
Result := ABorder in Worksheet.ReadCellBorders(ACell);
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
@@ -3299,6 +3307,9 @@ end;
|
||||
-------------------------------------------------------------------------------}
|
||||
procedure TsCustomWorksheetGrid.Setup;
|
||||
begin
|
||||
if csLoading in ComponentState then
|
||||
exit;
|
||||
|
||||
if (Worksheet = nil) or (Worksheet.GetCellCount = 0) then begin
|
||||
if ShowHeaders then begin
|
||||
ColCount := FInitColCount + 1; //2;
|
||||
@@ -3400,14 +3411,18 @@ var
|
||||
p: Integer;
|
||||
isRotated: Boolean;
|
||||
isStacked: Boolean;
|
||||
tr: TsTextRotation;
|
||||
begin
|
||||
Result := Worksheet.ReadAsUTF8Text(ACell);
|
||||
if (Result = '') or ((ACell <> nil) and (ACell^.ContentType = cctUTF8String))
|
||||
then
|
||||
exit;
|
||||
|
||||
isRotated := (uffTextRotation in ACell^.UsedFormattingFields) and (ACell^.TextRotation <> trHorizontal);
|
||||
isStacked := (uffTextRotation in ACell^.UsedFormattingFields) and (ACell^.TextRotation = rtStacked);
|
||||
tr := Worksheet.ReadTextRotation(ACell);
|
||||
isRotated := (tr <> trHorizontal);
|
||||
isStacked := (tr = rtStacked);
|
||||
// isRotated := (uffTextRotation in ACell^.UsedFormattingFields) and (ACell^.TextRotation <> trHorizontal);
|
||||
// isStacked := (uffTextRotation in ACell^.UsedFormattingFields) and (ACell^.TextRotation = rtStacked);
|
||||
|
||||
// Determine space available in cell
|
||||
if isRotated then
|
||||
@@ -3548,11 +3563,8 @@ begin
|
||||
Result := scNotDefined;
|
||||
if (Workbook <> nil) and (Worksheet <> nil) then begin
|
||||
cell := Worksheet.FindCell(GetWorksheetRow(ARow), GetWorksheetCol(ACol));
|
||||
if (cell <> nil) then begin
|
||||
fnt := Workbook.GetFont(cell^.FontIndex);
|
||||
if fnt <> nil then
|
||||
Result := fnt.Color;
|
||||
end;
|
||||
fnt := Worksheet.ReadCellFont(cell);
|
||||
Result := fnt.Color;
|
||||
end;
|
||||
end;
|
||||
|
||||
@@ -3581,11 +3593,8 @@ begin
|
||||
Result := '';
|
||||
if (Workbook <> nil) and (Worksheet <> nil) then begin
|
||||
cell := Worksheet.FindCell(GetWorksheetRow(ARow), GetWorksheetCol(ACol));
|
||||
if (cell <> nil) then begin
|
||||
fnt := Workbook.GetFont(cell^.FontIndex);
|
||||
if fnt <> nil then
|
||||
Result := fnt.FontName;
|
||||
end;
|
||||
fnt := Worksheet.ReadCellFont(cell);
|
||||
Result := fnt.FontName;
|
||||
end;
|
||||
end;
|
||||
|
||||
@@ -3614,11 +3623,8 @@ begin
|
||||
Result := -1.0;
|
||||
if (Workbook <> nil) and (Worksheet <> nil) then begin
|
||||
cell := Worksheet.FindCell(GetWorksheetRow(ARow), GetWorksheetCol(ACol));
|
||||
if (cell <> nil) then begin
|
||||
fnt := Workbook.GetFont(cell^.FontIndex);
|
||||
if fnt <> nil then
|
||||
Result := fnt.Size;
|
||||
end;
|
||||
fnt := Worksheet.ReadCellFont(cell);
|
||||
Result := fnt.Size;
|
||||
end;
|
||||
end;
|
||||
|
||||
@@ -3647,11 +3653,8 @@ begin
|
||||
Result := [];
|
||||
if (Workbook <> nil) and (Worksheet <> nil) then begin
|
||||
cell := Worksheet.FindCell(GetWorksheetRow(ARow), GetWorksheetCol(ACol));
|
||||
if (cell <> nil) then begin
|
||||
fnt := Workbook.GetFont(cell^.FontIndex);
|
||||
if fnt <> nil then
|
||||
Result := fnt.Style;
|
||||
end;
|
||||
fnt := Worksheet.ReadCellFont(cell);
|
||||
Result := fnt.Style;
|
||||
end;
|
||||
end;
|
||||
|
||||
@@ -3679,8 +3682,7 @@ begin
|
||||
Result := haDefault;
|
||||
if Assigned(Worksheet) then begin
|
||||
cell := Worksheet.FindCell(GetWorksheetRow(ARow), GetWorksheetCol(ACol));
|
||||
if cell <> nil then
|
||||
Result := cell^.HorAlignment;
|
||||
Result := Worksheet.ReadHorAlignment(cell);
|
||||
end;
|
||||
end;
|
||||
|
||||
@@ -3718,8 +3720,7 @@ begin
|
||||
Result := trHorizontal;
|
||||
if Assigned(Worksheet) then begin
|
||||
cell := Worksheet.FindCell(GetWorksheetRow(ARow), GetWorksheetCol(ACol));
|
||||
if (cell <> nil) then
|
||||
Result := cell^.TextRotation;
|
||||
Result := Worksheet.ReadTextRotation(cell);
|
||||
end;
|
||||
end;
|
||||
|
||||
@@ -3747,8 +3748,7 @@ begin
|
||||
Result := vaDefault;
|
||||
if Assigned(Worksheet) then begin
|
||||
cell := Worksheet.FindCell(GetWorksheetRow(ARow), GetWorksheetCol(ACol));
|
||||
if cell <> nil then
|
||||
Result := cell^.VertAlignment;
|
||||
Result := Worksheet.ReadVertAlignment(cell);
|
||||
end;
|
||||
end;
|
||||
|
||||
@@ -3792,8 +3792,7 @@ begin
|
||||
Result := false;
|
||||
if Assigned(Worksheet) then begin
|
||||
cell := Worksheet.FindCell(GetWorksheetRow(ARow), GetWorksheetCol(ACol));
|
||||
if (cell <> nil) and (uffWordwrap in cell^.UsedFormattingFields) then
|
||||
Result := true;
|
||||
Result := Worksheet.ReadWordwrap(cell);
|
||||
end;
|
||||
end;
|
||||
|
||||
@@ -3838,14 +3837,13 @@ end;
|
||||
procedure TsCustomWorksheetGrid.SetBackgroundColor(ACol, ARow: Integer;
|
||||
AValue: TsColor);
|
||||
var
|
||||
c, r: Cardinal;
|
||||
cell: PCell;
|
||||
begin
|
||||
if Assigned(Worksheet) then begin
|
||||
BeginUpdate;
|
||||
try
|
||||
c := GetWorksheetCol(ACol);
|
||||
r := GetWorksheetRow(ARow);
|
||||
Worksheet.WriteBackgroundColor(r, c, AValue);
|
||||
cell := Worksheet.GetCell(GetWorksheetRow(ARow), GetWorksheetCol(ACol));
|
||||
Worksheet.WriteBackgroundColor(cell, AValue);
|
||||
finally
|
||||
EndUpdate;
|
||||
end;
|
||||
@@ -3870,14 +3868,13 @@ end;
|
||||
procedure TsCustomWorksheetGrid.SetCellBorder(ACol, ARow: Integer;
|
||||
AValue: TsCellBorders);
|
||||
var
|
||||
c, r: Cardinal;
|
||||
cell: PCell;
|
||||
begin
|
||||
if Assigned(Worksheet) then begin
|
||||
BeginUpdate;
|
||||
try
|
||||
c := GetWorksheetCol(ACol);
|
||||
r := GetWorksheetRow(ARow);
|
||||
Worksheet.WriteBorders(r, c, AValue);
|
||||
cell := Worksheet.GetCell(GetWorksheetRow(ARow), GetWorksheetCol(ACol));
|
||||
Worksheet.WriteBorders(cell, AValue);
|
||||
FixNeighborCellBorders(ACol, ARow);
|
||||
finally
|
||||
EndUpdate;
|
||||
@@ -3902,11 +3899,14 @@ end;
|
||||
|
||||
procedure TsCustomWorksheetGrid.SetCellBorderStyle(ACol, ARow: Integer;
|
||||
ABorder: TsCellBorder; AValue: TsCellBorderStyle);
|
||||
var
|
||||
cell: PCell;
|
||||
begin
|
||||
if Assigned(Worksheet) then begin
|
||||
BeginUpdate;
|
||||
try
|
||||
Worksheet.WriteBorderStyle(GetWorksheetRow(ARow), GetWorksheetCol(ACol), ABorder, AValue);
|
||||
cell := Worksheet.GetCell(GetWorksheetRow(ARow), GetWorksheetCol(ACol));
|
||||
Worksheet.WriteBorderStyle(cell, ABorder, AValue);
|
||||
FixNeighborCellBorders(ACol, ARow);
|
||||
finally
|
||||
EndUpdate;
|
||||
@@ -3932,14 +3932,15 @@ end;
|
||||
procedure TsCustomWorksheetGrid.SetCellFont(ACol, ARow: Integer; AValue: TFont);
|
||||
var
|
||||
fnt: TsFont;
|
||||
cell: PCell;
|
||||
begin
|
||||
FCellFont.Assign(AValue);
|
||||
if Assigned(Worksheet) then begin
|
||||
fnt := TsFont.Create;
|
||||
try
|
||||
Convert_Font_To_sFont(FCellFont, fnt);
|
||||
Worksheet.WriteFont(GetWorksheetRow(ARow), GetWorksheetCol(ACol),
|
||||
fnt.FontName, fnt.Size, fnt.Style, fnt.Color);
|
||||
cell := Worksheet.GetCell(GetWorksheetRow(ARow), GetWorksheetCol(ACol));
|
||||
Worksheet.WriteFont(cell, fnt.FontName, fnt.Size, fnt.Style, fnt.Color);
|
||||
finally
|
||||
fnt.Free;
|
||||
end;
|
||||
@@ -3962,9 +3963,14 @@ begin
|
||||
end;
|
||||
|
||||
procedure TsCustomWorksheetGrid.SetCellFontColor(ACol, ARow: Integer; AValue: TsColor);
|
||||
var
|
||||
cell: PCell;
|
||||
begin
|
||||
if Assigned(Worksheet) then
|
||||
Worksheet.WriteFontColor(GetWorksheetRow(ARow), GetWorksheetCol(ACol), AValue);
|
||||
begin
|
||||
cell := Worksheet.GetCell(GetWorksheetRow(ARow), GetWorksheetCol(ACol));
|
||||
Worksheet.WriteFontColor(cell, AValue);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsCustomWorksheetGrid.SetCellFontColors(ARect: TGridRect; AValue: TsColor);
|
||||
@@ -3982,9 +3988,14 @@ begin
|
||||
end;
|
||||
|
||||
procedure TsCustomWorksheetGrid.SetCellFontName(ACol, ARow: Integer; AValue: String);
|
||||
var
|
||||
cell: PCell;
|
||||
begin
|
||||
if Assigned(Worksheet) then
|
||||
Worksheet.WriteFontName(GetWorksheetRow(ARow), GetWorksheetCol(ACol), AValue);
|
||||
begin
|
||||
cell := Worksheet.GetCell(GetWorksheetRow(ARow), GetWorksheetCol(ACol));
|
||||
Worksheet.WriteFontName(cell, AValue);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsCustomWorksheetGrid.SetCellFontNames(ARect: TGridRect; AValue: String);
|
||||
@@ -4003,9 +4014,14 @@ end;
|
||||
|
||||
procedure TsCustomWorksheetGrid.SetCellFontSize(ACol, ARow: Integer;
|
||||
AValue: Single);
|
||||
var
|
||||
cell: PCell;
|
||||
begin
|
||||
if Assigned(Worksheet) then
|
||||
Worksheet.WriteFontSize(GetWorksheetRow(ARow), GetWorksheetCol(ACol), AValue);
|
||||
begin
|
||||
cell := Worksheet.GetCell(GetWorksheetRow(ARow), GetWorksheetCol(ACol));
|
||||
Worksheet.WriteFontSize(cell, AValue);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsCustomWorksheetGrid.SetCellFontSizes(ARect: TGridRect;
|
||||
@@ -4025,9 +4041,14 @@ end;
|
||||
|
||||
procedure TsCustomWorksheetGrid.SetCellFontStyle(ACol, ARow: Integer;
|
||||
AValue: TsFontStyles);
|
||||
var
|
||||
cell: PCell;
|
||||
begin
|
||||
if Assigned(Worksheet) then
|
||||
Worksheet.WriteFontStyle(GetWorksheetRow(ARow), GetWorksheetCol(ACol), AValue);
|
||||
begin
|
||||
cell := Worksheet.GetCell(GetWorksheetRow(ARow), GetWorksheetCol(ACol));
|
||||
Worksheet.WriteFontStyle(cell, AValue);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsCustomWorksheetGrid.SetCellFontStyles(ARect: TGridRect;
|
||||
@@ -4073,9 +4094,14 @@ end;
|
||||
|
||||
procedure TsCustomWorksheetGrid.SetHorAlignment(ACol, ARow: Integer;
|
||||
AValue: TsHorAlignment);
|
||||
var
|
||||
cell: PCell;
|
||||
begin
|
||||
if Assigned(Worksheet) then
|
||||
Worksheet.WriteHorAlignment(GetWorksheetRow(ARow), GetWorksheetCol(ACol), AValue);
|
||||
begin
|
||||
cell := Worksheet.GetCell(GetWorksheetRow(ARow), GetWorksheetCol(ACol));
|
||||
Worksheet.WriteHorAlignment(cell, AValue);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsCustomWorksheetGrid.SetHorAlignments(ARect: TGridRect;
|
||||
@@ -4149,9 +4175,14 @@ end;
|
||||
|
||||
procedure TsCustomWorksheetGrid.SetTextRotation(ACol, ARow: Integer;
|
||||
AValue: TsTextRotation);
|
||||
var
|
||||
cell: PCell;
|
||||
begin
|
||||
if Assigned(Worksheet) then
|
||||
Worksheet.WriteTextRotation(GetWorksheetRow(ARow), GetWorksheetCol(ACol), AValue);
|
||||
begin
|
||||
cell := Worksheet.GetCell(GetWorksheetRow(ARow), GetWorksheetCol(ACol));
|
||||
Worksheet.WriteTextRotation(cell, AValue);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsCustomWorksheetGrid.SetTextRotations(ARect: TGridRect;
|
||||
@@ -4171,9 +4202,14 @@ end;
|
||||
|
||||
procedure TsCustomWorksheetGrid.SetVertAlignment(ACol, ARow: Integer;
|
||||
AValue: TsVertAlignment);
|
||||
var
|
||||
cell: PCell;
|
||||
begin
|
||||
if Assigned(Worksheet) then
|
||||
Worksheet.WriteVertAlignment(GetWorksheetRow(ARow), GetWorksheetCol(ACol), AValue);
|
||||
begin
|
||||
cell := Worksheet.GetCell(GetWorksheetRow(ARow), GetWorksheetCol(ACol));
|
||||
Worksheet.WriteVertAlignment(cell, AValue);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsCustomWorksheetGrid.SetVertAlignments(ARect: TGridRect;
|
||||
@@ -4193,9 +4229,14 @@ end;
|
||||
|
||||
procedure TsCustomWorksheetGrid.SetWordwrap(ACol, ARow: Integer;
|
||||
AValue: Boolean);
|
||||
var
|
||||
cell: PCell;
|
||||
begin
|
||||
if Assigned(Worksheet) then
|
||||
Worksheet.WriteWordwrap(GetWorksheetRow(ARow), GetWorksheetCol(ACol), AValue);
|
||||
begin
|
||||
cell := Worksheet.GetCell(GetWorksheetRow(ARow), GetWorksheetCol(ACol));
|
||||
Worksheet.WriteWordwrap(cell, AValue);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsCustomWorksheetGrid.SetWordwraps(ARect: TGridRect;
|
||||
|
@@ -16,7 +16,7 @@ unit fpsRPN;
|
||||
interface
|
||||
|
||||
uses
|
||||
SysUtils, fpstypes, fpspreadsheet;
|
||||
SysUtils, fpstypes;
|
||||
|
||||
type
|
||||
{@@ Pointer to a TPRNItem record
|
||||
|
@@ -37,9 +37,9 @@ const
|
||||
MAX_COL_COUNT = 65535;
|
||||
|
||||
{@@ Name of the default font}
|
||||
DEFAULTFONTNAME = 'Arial';
|
||||
DEFAULT_FONTNAME = 'Arial';
|
||||
{@@ Size of the default font}
|
||||
DEFAULTFONTSIZE = 10;
|
||||
DEFAULT_FONTSIZE = 10;
|
||||
|
||||
{@@ Takes account of effect of cell margins on row height by adding this
|
||||
value to the nominal row height. Note that this is an empirical value
|
||||
@@ -309,7 +309,7 @@ const
|
||||
|
||||
// not sure - but I think the mechanism with scRGBColor is not working...
|
||||
// Will be removed sooner or later...
|
||||
scRGBColor = $FFFF;
|
||||
scRGBColor = $FFFD;
|
||||
|
||||
{@@ Identifier for transparent color }
|
||||
scTransparent = $FFFE;
|
||||
@@ -425,7 +425,9 @@ type
|
||||
end;
|
||||
|
||||
{@@ Record containing all details for cell formatting }
|
||||
TsStyle = record
|
||||
TsCellFormat = record
|
||||
Name: String;
|
||||
ID: Integer;
|
||||
UsedFormattingFields: TsUsedFormattingFields;
|
||||
FontIndex: Integer;
|
||||
TextRotation: TsTextRotation;
|
||||
@@ -439,8 +441,211 @@ type
|
||||
NumberFormatStr: String;
|
||||
end;
|
||||
|
||||
{@@ Pointer to a format record }
|
||||
PsCellFormat = ^TsCellFormat;
|
||||
|
||||
{@@ Specialized list for format records }
|
||||
TsCellFormatList = class(TFPList)
|
||||
private
|
||||
FAllowDuplicates: Boolean;
|
||||
function GetItem(AIndex: Integer): PsCellFormat;
|
||||
procedure SetItem(AIndex: Integer; const AValue: PsCellFormat);
|
||||
public
|
||||
constructor Create(AAllowDuplicates: Boolean);
|
||||
destructor Destroy; override;
|
||||
function Add(const AItem: TsCellFormat): Integer; overload;
|
||||
function Add(AItem: PsCellFormat): Integer; overload;
|
||||
procedure Clear;
|
||||
procedure Delete(AIndex: Integer);
|
||||
function FindIndexOfID(ID: Integer): Integer;
|
||||
function FindIndexOfName(AName: String): Integer;
|
||||
function IndexOf(const AItem: TsCellFormat): Integer; overload;
|
||||
property Items[AIndex: Integer]: PsCellFormat read GetItem write SetItem; default;
|
||||
end;
|
||||
|
||||
procedure InitFormatRecord(out AValue: TsCellFormat);
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
{ Utilities }
|
||||
|
||||
procedure InitFormatRecord(out AValue: TsCellFormat);
|
||||
begin
|
||||
AValue.Name := '';
|
||||
AValue.NumberFormatStr := '';
|
||||
FillChar(AValue, SizeOf(AValue), 0);
|
||||
AValue.BorderStyles := DEFAULT_BORDERSTYLES;
|
||||
AValue.BackgroundColor := TsColor(-1);
|
||||
end;
|
||||
|
||||
|
||||
{ TsCellFormatList }
|
||||
|
||||
constructor TsCellFormatList.Create(AAllowDuplicates: Boolean);
|
||||
begin
|
||||
inherited Create;
|
||||
FAllowDuplicates := AAllowDuplicates;
|
||||
end;
|
||||
|
||||
destructor TsCellFormatList.Destroy;
|
||||
begin
|
||||
Clear;
|
||||
inherited;
|
||||
end;
|
||||
|
||||
function TsCellFormatList.Add(const AItem: TsCellFormat): Integer;
|
||||
var
|
||||
P: PsCellFormat;
|
||||
begin
|
||||
if FAllowDuplicates then
|
||||
Result := -1
|
||||
else
|
||||
Result := IndexOf(AItem);
|
||||
if Result = -1 then begin
|
||||
New(P);
|
||||
P^.Name := AItem.Name;
|
||||
P^.ID := AItem.ID;
|
||||
P^.UsedFormattingFields := AItem.UsedFormattingFields;
|
||||
P^.FontIndex := AItem.FontIndex;
|
||||
P^.TextRotation := AItem.TextRotation;
|
||||
P^.HorAlignment := AItem.HorAlignment;
|
||||
P^.VertAlignment := AItem.VertAlignment;
|
||||
P^.Border := AItem.Border;
|
||||
P^.BorderStyles := AItem.BorderStyles;
|
||||
P^.BackgroundColor := AItem.BackgroundColor;
|
||||
P^.RGBBackgroundColor := AItem.RGBBackgroundColor;
|
||||
P^.NumberFormat := AItem.NumberFormat;
|
||||
P^.NumberFormatStr := AItem.NumberFormatStr;
|
||||
Result := inherited Add(P);
|
||||
end;
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Adds a pointer to a FormatRecord to the list. Allows nil for the predefined
|
||||
formats which are not stored in the file.
|
||||
-------------------------------------------------------------------------------}
|
||||
function TsCellFormatList.Add(AItem: PsCellFormat): Integer;
|
||||
begin
|
||||
if AItem = nil then
|
||||
Result := inherited Add(AItem)
|
||||
else
|
||||
Result := Add(AItem^);
|
||||
end;
|
||||
|
||||
procedure TsCellFormatList.Clear;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
for i:=Count-1 downto 0 do
|
||||
Delete(i);
|
||||
inherited;
|
||||
end;
|
||||
|
||||
procedure TsCellFormatList.Delete(AIndex: Integer);
|
||||
var
|
||||
P: PsCellFormat;
|
||||
begin
|
||||
P := GetItem(AIndex);
|
||||
if P <> nil then
|
||||
Dispose(P);
|
||||
inherited Delete(AIndex);
|
||||
end;
|
||||
|
||||
function TsCellFormatList.GetItem(AIndex: Integer): PsCellFormat;
|
||||
begin
|
||||
Result := inherited Items[AIndex];
|
||||
end;
|
||||
|
||||
function TsCellFormatList.FindIndexOfID(ID: Integer): Integer;
|
||||
var
|
||||
P: PsCellFormat;
|
||||
begin
|
||||
for Result := 0 to Count-1 do
|
||||
begin
|
||||
P := GetItem(Result);
|
||||
if (P <> nil) and (P^.ID = ID) then
|
||||
exit;
|
||||
end;
|
||||
Result := -1;
|
||||
end;
|
||||
|
||||
function TsCellFormatList.FindIndexOfName(AName: String): Integer;
|
||||
var
|
||||
P: PsCellFormat;
|
||||
begin
|
||||
for Result := 0 to Count-1 do
|
||||
begin
|
||||
P := GetItem(Result);
|
||||
if (P <> nil) and (P^.Name = AName) then
|
||||
exit;
|
||||
end;
|
||||
Result := -1;
|
||||
end;
|
||||
|
||||
function TsCellFormatList.IndexOf(const AItem: TsCellFormat): Integer;
|
||||
var
|
||||
P: PsCellFormat;
|
||||
equ: Boolean;
|
||||
b: TsCellBorder;
|
||||
begin
|
||||
for Result := 0 to Count-1 do
|
||||
begin
|
||||
P := GetItem(Result);
|
||||
if (P = nil) then continue;
|
||||
|
||||
if (P^.UsedFormattingFields <> AItem.UsedFormattingFields) then continue;
|
||||
|
||||
if (uffFont in AItem.UsedFormattingFields) then
|
||||
if (P^.FontIndex) <> (AItem.FontIndex) then continue;
|
||||
|
||||
if (uffTextRotation in AItem.UsedFormattingFields) then
|
||||
if (P^.TextRotation <> AItem.TextRotation) then continue;
|
||||
|
||||
if (uffHorAlign in AItem.UsedFormattingFields) then
|
||||
if (P^.HorAlignment <> AItem.HorAlignment) then continue;
|
||||
|
||||
if (uffVertAlign in AItem.UsedFormattingFields) then
|
||||
if (P^.VertAlignment <> AItem.VertAlignment) then continue;
|
||||
|
||||
if (uffBorder in AItem.UsedFormattingFields) then begin
|
||||
if (P^.Border <> AItem.Border) then continue;
|
||||
equ := true;
|
||||
for b in AItem.Border do begin
|
||||
if (P^.BorderStyles[b].LineStyle <> AItem.BorderStyles[b].LineStyle) or
|
||||
(P^.BorderStyles[b].Color <> Aitem.BorderStyles[b].Color)
|
||||
then begin
|
||||
equ := false;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
if not equ then continue;
|
||||
end;
|
||||
|
||||
if (uffBackgroundColor in AItem.UsedFormattingFields) then begin
|
||||
if (P^.BackgroundColor <> AItem.BackgroundColor) then continue;
|
||||
if (AItem.BackgroundColor = scRGBColor) then
|
||||
if (P^.RGBBackgroundColor <> AItem.RGBBackgroundColor) then continue;
|
||||
end;
|
||||
|
||||
if (uffNumberFormat in AItem.UsedFormattingFields) then begin
|
||||
if (P^.NumberFormat <> AItem.NumberFormat) then continue;
|
||||
if (P^.NumberFormatStr <> AItem.NumberFormatStr) then continue;
|
||||
end;
|
||||
|
||||
// If we arrive here then the format records match.
|
||||
exit;
|
||||
end;
|
||||
|
||||
// We get here if no record matches
|
||||
Result := -1;
|
||||
end;
|
||||
|
||||
procedure TsCellFormatList.SetItem(AIndex: Integer; const AValue: PsCellFormat);
|
||||
begin
|
||||
inherited Items[AIndex] := AValue;
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
|
||||
|
@@ -143,7 +143,6 @@ This package is all you need if you don't want graphical components (like grids
|
||||
</Item28>
|
||||
<Item29>
|
||||
<Filename Value="fpstypes.pas"/>
|
||||
<HasRegisterProc Value="True"/>
|
||||
<UnitName Value="fpsTypes"/>
|
||||
</Item29>
|
||||
</Files>
|
||||
|
@@ -131,7 +131,6 @@
|
||||
<Unit3>
|
||||
<Filename Value="bebiffutils.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="beBIFFUtils"/>
|
||||
</Unit3>
|
||||
<Unit4>
|
||||
<Filename Value="behtml.pas"/>
|
||||
@@ -148,6 +147,7 @@
|
||||
<Unit6>
|
||||
<Filename Value="beutils.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="beUtils"/>
|
||||
</Unit6>
|
||||
<Unit7>
|
||||
<Filename Value="mrumanager.pp"/>
|
||||
|
@@ -5,7 +5,7 @@ unit beBIFFGrid;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, Controls, Grids, fpspreadsheet;
|
||||
Classes, SysUtils, Controls, Grids, fpstypes, fpspreadsheet;
|
||||
|
||||
type
|
||||
TBIFFBuffer = array of byte;
|
||||
|
@@ -4,7 +4,7 @@ object MainForm: TMainForm
|
||||
Top = 177
|
||||
Width = 1089
|
||||
Caption = 'BIFF Explorer'
|
||||
ClientHeight = 551
|
||||
ClientHeight = 556
|
||||
ClientWidth = 1089
|
||||
Menu = MainMenu
|
||||
OnCloseQuery = FormCloseQuery
|
||||
@@ -12,10 +12,10 @@ object MainForm: TMainForm
|
||||
OnDestroy = FormDestroy
|
||||
OnShow = FormShow
|
||||
ShowHint = True
|
||||
LCLVersion = '1.3'
|
||||
LCLVersion = '1.5'
|
||||
object Splitter1: TSplitter
|
||||
Left = 419
|
||||
Height = 496
|
||||
Height = 506
|
||||
Top = 27
|
||||
Width = 5
|
||||
end
|
||||
@@ -49,6 +49,7 @@ object MainForm: TMainForm
|
||||
end
|
||||
object ToolButton4: TToolButton
|
||||
Left = 59
|
||||
Height = 25
|
||||
Top = 2
|
||||
Width = 5
|
||||
Caption = 'ToolButton4'
|
||||
@@ -57,17 +58,17 @@ object MainForm: TMainForm
|
||||
end
|
||||
object DetailPanel: TPanel
|
||||
Left = 424
|
||||
Height = 496
|
||||
Height = 506
|
||||
Top = 27
|
||||
Width = 665
|
||||
Align = alClient
|
||||
BevelOuter = bvNone
|
||||
ClientHeight = 496
|
||||
ClientHeight = 506
|
||||
ClientWidth = 665
|
||||
TabOrder = 2
|
||||
object PageControl: TPageControl
|
||||
Left = 0
|
||||
Height = 496
|
||||
Height = 506
|
||||
Top = 0
|
||||
Width = 665
|
||||
ActivePage = PgAnalysis
|
||||
@@ -77,12 +78,12 @@ object MainForm: TMainForm
|
||||
OnChange = PageControlChange
|
||||
object PgAnalysis: TTabSheet
|
||||
Caption = 'Analysis'
|
||||
ClientHeight = 463
|
||||
ClientHeight = 478
|
||||
ClientWidth = 657
|
||||
object AnalysisDetails: TMemo
|
||||
Left = 0
|
||||
Height = 191
|
||||
Top = 272
|
||||
Top = 287
|
||||
Width = 657
|
||||
Align = alBottom
|
||||
Font.CharSet = ANSI_CHARSET
|
||||
@@ -99,7 +100,7 @@ object MainForm: TMainForm
|
||||
Cursor = crVSplit
|
||||
Left = 0
|
||||
Height = 5
|
||||
Top = 267
|
||||
Top = 282
|
||||
Width = 657
|
||||
Align = alBottom
|
||||
ResizeAnchor = akBottom
|
||||
@@ -193,7 +194,7 @@ object MainForm: TMainForm
|
||||
20
|
||||
20
|
||||
20
|
||||
20
|
||||
24
|
||||
)
|
||||
Cells = (
|
||||
16
|
||||
@@ -263,22 +264,22 @@ object MainForm: TMainForm
|
||||
OnClick = GridClick
|
||||
OnSelection = AlphaGridSelection
|
||||
ColWidths = (
|
||||
15
|
||||
15
|
||||
15
|
||||
15
|
||||
15
|
||||
15
|
||||
15
|
||||
15
|
||||
15
|
||||
15
|
||||
15
|
||||
15
|
||||
15
|
||||
15
|
||||
15
|
||||
27
|
||||
16
|
||||
16
|
||||
16
|
||||
16
|
||||
16
|
||||
16
|
||||
16
|
||||
16
|
||||
16
|
||||
16
|
||||
16
|
||||
16
|
||||
16
|
||||
16
|
||||
16
|
||||
16
|
||||
)
|
||||
Cells = (
|
||||
16
|
||||
@@ -355,19 +356,19 @@ object MainForm: TMainForm
|
||||
end
|
||||
object TreePanel: TPanel
|
||||
Left = 0
|
||||
Height = 496
|
||||
Height = 506
|
||||
Top = 27
|
||||
Width = 419
|
||||
Align = alLeft
|
||||
BevelOuter = bvNone
|
||||
ClientHeight = 496
|
||||
ClientHeight = 506
|
||||
ClientWidth = 419
|
||||
Constraints.MinWidth = 275
|
||||
TabOrder = 3
|
||||
object FindPanel: TPanel
|
||||
Left = 0
|
||||
Height = 36
|
||||
Top = 460
|
||||
Top = 470
|
||||
Width = 419
|
||||
Align = alBottom
|
||||
BevelOuter = bvNone
|
||||
@@ -509,10 +510,10 @@ object MainForm: TMainForm
|
||||
end
|
||||
object CbFind: TComboBox
|
||||
Left = 28
|
||||
Height = 28
|
||||
Height = 23
|
||||
Top = 5
|
||||
Width = 183
|
||||
ItemHeight = 20
|
||||
ItemHeight = 15
|
||||
OnChange = CbFindChange
|
||||
OnKeyPress = CbFindKeyPress
|
||||
TabOrder = 0
|
||||
@@ -520,7 +521,7 @@ object MainForm: TMainForm
|
||||
end
|
||||
object BIFFTree: TVirtualStringTree
|
||||
Left = 0
|
||||
Height = 460
|
||||
Height = 470
|
||||
Top = 0
|
||||
Width = 419
|
||||
Align = alClient
|
||||
@@ -583,8 +584,8 @@ object MainForm: TMainForm
|
||||
end
|
||||
object StatusBar: TStatusBar
|
||||
Left = 0
|
||||
Height = 28
|
||||
Top = 523
|
||||
Height = 23
|
||||
Top = 533
|
||||
Width = 1089
|
||||
Panels = <
|
||||
item
|
||||
|
@@ -12,7 +12,7 @@ uses
|
||||
{$else}
|
||||
fpolestorage,
|
||||
{$endif}
|
||||
fpSpreadsheet,
|
||||
fpstypes, fpSpreadsheet,
|
||||
mrumanager, beBIFFGrid, types;
|
||||
|
||||
type
|
||||
@@ -791,7 +791,18 @@ begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
FFormat := sfExcel8;
|
||||
// .xls files can contain several formats. We look into the header first.
|
||||
if Lowercase(ExtractFileExt(AFileName))=STR_EXCEL_EXTENSION then
|
||||
begin
|
||||
valid := GetFormatFromFileHeader(AFileName, FFormat);
|
||||
// It is possible that valid xls files are not detected correctly. Therefore,
|
||||
// we open them explicitly by trial and error - see below.
|
||||
if not valid then
|
||||
FFormat := sfExcel8;
|
||||
valid := true;
|
||||
end else
|
||||
FFormat := sfExcel8;
|
||||
|
||||
while True do begin
|
||||
try
|
||||
LoadFile(AFileName, FFormat);
|
||||
@@ -1169,7 +1180,8 @@ begin
|
||||
$0031, $0231: // Font record
|
||||
begin
|
||||
inc(FFontIndex);
|
||||
data.Index := FFontIndex;
|
||||
if FFontIndex > 3 then data.Index := FFontIndex + 1
|
||||
else data.Index := FFontIndex;
|
||||
end;
|
||||
$0043, $00E0: // XF record
|
||||
begin
|
||||
|
@@ -6,13 +6,16 @@ interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, IniFiles, Forms,
|
||||
fpspreadsheet;
|
||||
fpstypes, fpspreadsheet;
|
||||
|
||||
function CreateIni : TCustomIniFile;
|
||||
procedure ReadFormFromIni(ini: TCustomIniFile; ASection: String; AForm: TCustomForm);
|
||||
procedure WriteFormToIni(ini: TCustomIniFile; ASection: String; AForm: TCustomForm);
|
||||
|
||||
function GetFileFormatName(AFormat: TsSpreadsheetFormat): String;
|
||||
function GetFormatFromFileHeader(const AFileName: TFileName;
|
||||
out SheetType: TsSpreadsheetFormat): Boolean;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
@@ -83,5 +86,76 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function GetFormatFromFileHeader(const AFileName: TFileName;
|
||||
out SheetType: TsSpreadsheetFormat): Boolean;
|
||||
const
|
||||
BIFF2_HEADER: array[0..15] of byte = (
|
||||
$09,$00, $04,$00, $00,$00, $10,$00, $31,$00, $0A,$00, $C8,$00, $00,$00);
|
||||
BIFF58_HEADER: array[0..15] of byte = (
|
||||
$D0,$CF, $11,$E0, $A1,$B1, $1A,$E1, $00,$00, $00,$00, $00,$00, $00,$00);
|
||||
BIFF5_MARKER: array[0..7] of widechar = (
|
||||
'B', 'o', 'o', 'k', #0, #0, #0, #0);
|
||||
BIFF8_MARKER:array[0..7] of widechar = (
|
||||
'W', 'o', 'r', 'k', 'b', 'o', 'o', 'k');
|
||||
var
|
||||
buf: packed array[0..16] of byte;
|
||||
stream: TStream;
|
||||
i: Integer;
|
||||
ok: Boolean;
|
||||
begin
|
||||
buf[0] := 0; // Silence the compiler...
|
||||
|
||||
Result := false;
|
||||
stream := TFileStream.Create(AFileName, fmOpenRead + fmShareDenyNone);
|
||||
try
|
||||
// Read first 16 bytes
|
||||
stream.ReadBuffer(buf, 16);
|
||||
|
||||
// Check for Excel 2#
|
||||
ok := true;
|
||||
for i:=0 to 15 do
|
||||
if buf[i] <> BIFF2_HEADER[i] then
|
||||
begin
|
||||
ok := false;
|
||||
break;
|
||||
end;
|
||||
if ok then
|
||||
begin
|
||||
SheetType := sfExcel2;
|
||||
Exit(True);
|
||||
end;
|
||||
|
||||
// Check for Excel 5 or 8
|
||||
for i:=0 to 15 do
|
||||
if buf[i] <> BIFF58_HEADER[i] then
|
||||
exit;
|
||||
|
||||
// Further information begins at offset $480:
|
||||
stream.Position := $480;
|
||||
stream.ReadBuffer(buf, 16);
|
||||
// Check for Excel5
|
||||
ok := true;
|
||||
for i:=0 to 7 do
|
||||
if WideChar(buf[i*2]) <> BIFF5_MARKER[i] then
|
||||
begin
|
||||
ok := false;
|
||||
break;
|
||||
end;
|
||||
if ok then
|
||||
begin
|
||||
SheetType := sfExcel5;
|
||||
Exit(True);
|
||||
end;
|
||||
// Check for Excel8
|
||||
for i:=0 to 7 do
|
||||
if WideChar(buf[i*2]) <> BIFF8_MARKER[i] then
|
||||
exit(false);
|
||||
SheetType := sfExcel8;
|
||||
Exit(True);
|
||||
finally
|
||||
stream.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
@@ -150,7 +150,7 @@ begin
|
||||
MyCell := MyWorksheet.FindCell(row, col);
|
||||
if MyCell = nil then
|
||||
fail('Error in test code. Failed to get cell.');
|
||||
currentRGB := MyWorkbook.GetPaletteColor(MyCell^.BackgroundColor);
|
||||
currentRGB := MyWorkbook.GetPaletteColor(MyWorksheet.ReadBackgroundColor(MyCell));
|
||||
expectedRGB := MyWorkbook.GetPaletteColor(color);
|
||||
CheckEquals(expectedRGB, currentRGB,
|
||||
'Test unsaved background color, cell ' + CellNotation(MyWorksheet,0,0));
|
||||
@@ -176,7 +176,7 @@ begin
|
||||
if MyCell = nil then
|
||||
fail('Error in test code. Failed to get cell.');
|
||||
color := TsColor(row);
|
||||
currentRGB := MyWorkbook.GetPaletteColor(MyCell^.BackgroundColor);
|
||||
currentRGB := MyWorkbook.GetPaletteColor(MyWorksheet.ReadBackgroundColor(MyCell));
|
||||
expectedRGB := pal[color];
|
||||
CheckEquals(expectedRGB, currentRGB,
|
||||
'Test saved background color, cell '+CellNotation(MyWorksheet,Row,Col));
|
||||
@@ -239,7 +239,7 @@ begin
|
||||
MyCell := MyWorksheet.FindCell(row, col);
|
||||
if MyCell = nil then
|
||||
fail('Error in test code. Failed to get cell.');
|
||||
colorInFile := MyWorkbook.GetFont(MyCell^.FontIndex).Color;
|
||||
colorInFile := MyWorksheet.ReadCellFont(MyCell).Color;
|
||||
currentRGB := MyWorkbook.GetPaletteColor(colorInFile);
|
||||
expectedRGB := MyWorkbook.GetPaletteColor(color);
|
||||
CheckEquals(expectedRGB, currentRGB,
|
||||
@@ -267,7 +267,7 @@ begin
|
||||
fail('Error in test code. Failed to get cell.');
|
||||
color := TsColor(row);
|
||||
expectedRGB := pal[color];
|
||||
colorInFile := MyWorkbook.GetFont(MyCell^.FontIndex).Color;
|
||||
colorInFile := MyWorksheet.ReadCellFont(MyCell).Color;
|
||||
currentRGB := MyWorkbook.GetPaletteColor(colorInFile);
|
||||
|
||||
// Excel2 cannot write the entire palette. The writer had called "FixColor".
|
||||
|
@@ -52,7 +52,7 @@ const
|
||||
CopyTestSheet = 'Copy';
|
||||
|
||||
function InitNumber(ANumber: Double; ABkColor: TsColor): TCell;
|
||||
begin
|
||||
begin (*
|
||||
InitCell(Result);
|
||||
Result.ContentType := cctNumber;
|
||||
Result.Numbervalue := ANumber;
|
||||
@@ -60,11 +60,11 @@ begin
|
||||
begin
|
||||
Result.UsedFormattingFields := Result.UsedFormattingFields + [uffBackgroundColor];
|
||||
Result.BackgroundColor := ABkColor;
|
||||
end;
|
||||
end; *)
|
||||
end;
|
||||
|
||||
function InitString(AString: String; ABkColor: TsColor): TCell;
|
||||
begin
|
||||
begin (*
|
||||
InitCell(Result);
|
||||
Result.ContentType := cctUTF8String;
|
||||
Result.UTF8StringValue := AString;
|
||||
@@ -72,11 +72,11 @@ begin
|
||||
begin
|
||||
Result.UsedFormattingFields := Result.UsedFormattingFields + [uffBackgroundColor];
|
||||
Result.BackgroundColor := ABkColor;
|
||||
end;
|
||||
end; *)
|
||||
end;
|
||||
|
||||
function InitFormula(AFormula: String; ANumberResult: Double; ABkColor: TsColor): TCell;
|
||||
begin
|
||||
begin (*
|
||||
InitCell(Result);
|
||||
Result.FormulaValue := AFormula;
|
||||
Result.NumberValue := ANumberResult;
|
||||
@@ -85,7 +85,7 @@ begin
|
||||
begin
|
||||
Result.UsedFormattingFields := Result.UsedFormattingFields + [uffBackgroundColor];
|
||||
Result.BackgroundColor := ABkColor;
|
||||
end;
|
||||
end; *)
|
||||
end;
|
||||
|
||||
{ IMPORTANT: Carefully check the Test_Copy method if anything is changed here.
|
||||
|
@@ -137,6 +137,7 @@ var
|
||||
row, col: Integer;
|
||||
MyCell: PCell;
|
||||
TempFile: string; //write xls/xml to this file and read back from it
|
||||
fmt: TsCellFormat;
|
||||
begin
|
||||
{// Not needed: use workbook.writetofile with overwrite=true
|
||||
if fileexists(TempFile) then
|
||||
@@ -153,7 +154,8 @@ begin
|
||||
MyCell := MyWorksheet.FindCell(row, col);
|
||||
if MyCell = nil then
|
||||
fail('Error in test code. Failed to get cell.');
|
||||
CheckEquals(uffBold in MyCell^.UsedFormattingFields, false,
|
||||
fmt := MyWorkbook.GetCellFormat(MyCell^.FormatIndex);
|
||||
CheckEquals(false, uffBold in fmt.UsedFormattingFields,
|
||||
'Test unsaved bold attribute, cell '+CellNotation(MyWorksheet,Row,Col));
|
||||
|
||||
// Write out a cell with "bold" formatting style
|
||||
@@ -163,7 +165,8 @@ begin
|
||||
MyCell := MyWorksheet.FindCell(row, col);
|
||||
if MyCell = nil then
|
||||
fail('Error in test code. Failded to get cell.');
|
||||
CheckEquals(uffBold in MyCell^.UsedFormattingFields, true,
|
||||
fmt := MyWorkbook.GetCellFormat(MyCell^.FormatIndex);
|
||||
CheckEquals(true, uffBold in fmt.UsedFormattingFields,
|
||||
'Test unsaved bold attribute, cell '+CellNotation(MyWorksheet,Row, Col));
|
||||
|
||||
TempFile:=NewTempFile;
|
||||
@@ -189,7 +192,8 @@ begin
|
||||
MyCell := MyWorksheet.FindCell(row, col);
|
||||
if MyCell = nil then
|
||||
fail('Error in test code. Failed to get cell.');
|
||||
CheckEquals(uffBold in MyCell^.UsedFormattingFields, false,
|
||||
fmt := MyWorkbook.GetCellFormat(MyCell^.FormatIndex);
|
||||
CheckEquals(false, uffBold in fmt.UsedFormattingFields,
|
||||
'Test saved bold attribute, cell '+CellNotation(MyWorksheet,row,col));
|
||||
|
||||
// Try to read cell with "bold"
|
||||
@@ -197,7 +201,8 @@ begin
|
||||
MyCell := MyWorksheet.FindCell(row, col);
|
||||
if MyCell = nil then
|
||||
fail('Error in test code. Failed to get cell.');
|
||||
CheckEquals(uffBold in MyCell^.UsedFormattingFields, true,
|
||||
fmt := MyWorkbook.GetCellFormat(MyCell^.FormatIndex);
|
||||
CheckEquals(true, uffBold in fmt.UsedFormattingFields,
|
||||
'Test saved bold attribute, cell '+CellNotation(MyWorksheet,row,col));
|
||||
finally
|
||||
MyWorkbook.Free;
|
||||
@@ -240,7 +245,7 @@ begin
|
||||
MyCell := MyWorksheet.FindCell(row, col);
|
||||
if MyCell = nil then
|
||||
fail('Error in test code. Failed to get cell.');
|
||||
font := MyWorkbook.GetFont(MyCell^.FontIndex);
|
||||
font := MyWorksheet.ReadCellFont(MyCell);
|
||||
CheckEquals(SollSizes[row], font.Size,
|
||||
'Test unsaved font size, cell ' + CellNotation(MyWorksheet,0,0));
|
||||
currValue := GetEnumName(TypeInfo(TsFontStyles), integer(font.Style));
|
||||
@@ -274,7 +279,7 @@ begin
|
||||
MyCell := MyWorksheet.FindCell(row, col);
|
||||
if MyCell = nil then
|
||||
fail('Error in test code. Failed to get cell.');
|
||||
font := MyWorkbook.GetFont(MyCell^.FontIndex);
|
||||
font := MyWorksheet.ReadCellFont(MyCell);
|
||||
if abs(SollSizes[row] - font.Size) > 1e-6 then // safe-guard against rounding errors
|
||||
CheckEquals(SollSizes[row], font.Size,
|
||||
'Test saved font size, cell '+CellNotation(MyWorksheet,Row,Col));
|
||||
|
@@ -1,6 +1,7 @@
|
||||
unit formattests;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
{$modeswitch advancedrecords}
|
||||
|
||||
interface
|
||||
{ Formatted date/time/number tests
|
||||
@@ -16,9 +17,8 @@ uses
|
||||
{$ENDIF}
|
||||
// Not using Lazarus package as the user may be working with multiple versions
|
||||
// Instead, add .. to unit search path
|
||||
Classes, SysUtils, fpcunit, testutils, testregistry,
|
||||
fpstypes, fpsallformats, fpspreadsheet, xlsbiff8 {and a project requirement for lclbase for utf8 handling},
|
||||
testsutility;
|
||||
Classes, SysUtils, fpcunit, testutils, testregistry, testsutility,
|
||||
fpstypes, fpsallformats, fpspreadsheet, fpshelpers, xlsbiff8;
|
||||
|
||||
var
|
||||
// Norm to test against - list of strings that should occur in spreadsheet
|
||||
@@ -708,6 +708,8 @@ var
|
||||
Result := GetEnumName(TypeInfo(TsCellBorder), ord(cb))
|
||||
else
|
||||
Result := Result + ', ' + GetEnumName(TypeInfo(TsCellBorder), ord(cb));
|
||||
if Result = '' then
|
||||
Result := 'no borders';
|
||||
end;
|
||||
|
||||
begin
|
||||
@@ -725,10 +727,11 @@ begin
|
||||
maxCol := High(SollBorders);
|
||||
for col := Low(SollBorders) to maxCol do
|
||||
begin
|
||||
MyWorksheet.WriteUsedFormatting(row, col, [uffBorder]);
|
||||
MyCell := MyWorksheet.GetCell(row, col);
|
||||
Include(MyCell^.UsedFormattingFields, uffBorder);
|
||||
MyCell^.Border := SollBorders[col];
|
||||
// It is important for the test to write contents to the cell. Without it
|
||||
// the first cell (col=0) would not even contain a format and would be
|
||||
// dropped by the ods reader resulting in a matching error.
|
||||
MyCell := MyWorksheet.WriteUTF8Text(row, col, GetBordersAsText(SollBorders[col]));
|
||||
MyWorksheet.WriteBorders(MyCell, SollBorders[col]);
|
||||
end;
|
||||
|
||||
TempFile:=NewTempFile;
|
||||
@@ -809,6 +812,7 @@ var
|
||||
TempFile: string; //write xls/xml to this file and read back from it
|
||||
c, ls: Integer;
|
||||
borders: TsCellBorders;
|
||||
borderstyle: TsCellBorderStyle;
|
||||
diagUp_ls: Integer;
|
||||
diagUp_clr: integer;
|
||||
begin
|
||||
@@ -874,7 +878,8 @@ begin
|
||||
fail('Error in test code. Failed to get cell.');
|
||||
for b in borders do
|
||||
begin
|
||||
current := ord(MyCell^.BorderStyles[b].LineStyle);
|
||||
borderStyle := MyWorksheet.ReadCellBorderStyle(MyCell, b);
|
||||
current := ord(borderStyle.LineStyle);
|
||||
// In Excel both diagonals have the same line style. The reader picks
|
||||
// the line style of the "diagonal-up" border. We use this as expected
|
||||
// value in the "diagonal-down" case.
|
||||
@@ -886,7 +891,7 @@ begin
|
||||
end;
|
||||
CheckEquals(expected, current,
|
||||
'Test saved border line style mismatch, cell ' + CellNotation(MyWorksheet, row*2, col*2));
|
||||
current := MyCell^.BorderStyles[b].Color;
|
||||
current := borderStyle.Color;
|
||||
expected := SollBorderColors[c];
|
||||
// In Excel both diagonals have the same line color. The reader picks
|
||||
// the color of the "diagonal-up" border. We use this as expected value
|
||||
@@ -1207,13 +1212,15 @@ begin
|
||||
MyCell := MyWorksheet.FindCell(0, 0);
|
||||
if MyCell = nil then
|
||||
fail('Error in test code. Failed to get word-wrapped cell.');
|
||||
CheckEquals(true, (uffWordWrap in MyCell^.UsedFormattingFields), 'Test unsaved word wrap mismatch cell ' + CellNotation(MyWorksheet,0,0));
|
||||
CheckEquals(true, MyWorksheet.ReadWordwrap(MyCell),
|
||||
'Test unsaved word wrap mismatch cell ' + CellNotation(MyWorksheet,0,0));
|
||||
MyWorksheet.WriteUTF8Text(1, 0, LONGTEXT);
|
||||
MyWorksheet.WriteUsedFormatting(1, 0, []);
|
||||
MyCell := MyWorksheet.FindCell(1, 0);
|
||||
if MyCell = nil then
|
||||
fail('Error in test code. Failed to get word-wrapped cell.');
|
||||
CheckEquals(false, (uffWordWrap in MyCell^.UsedFormattingFields), 'Test unsaved non-wrapped cell mismatch, cell ' + CellNotation(MyWorksheet,0,0));
|
||||
CheckEquals(false, MyWorksheet.ReadWordwrap(MyCell),
|
||||
'Test unsaved non-wrapped cell mismatch, cell ' + CellNotation(MyWorksheet,0,0));
|
||||
TempFile:=NewTempFile;
|
||||
MyWorkBook.WriteToFile(TempFile, AFormat, true);
|
||||
finally
|
||||
@@ -1233,12 +1240,12 @@ begin
|
||||
MyCell := MyWorksheet.FindCell(0, 0);
|
||||
if MyCell = nil then
|
||||
fail('Error in test code. Failed to get word-wrapped cell.');
|
||||
CheckEquals(true, (uffWordWrap in MyCell^.UsedFormattingFields),
|
||||
CheckEquals(true, MyWorksheet.ReadWordwrap(MyCell),
|
||||
'Failed to return correct word-wrap flag, cell ' + CellNotation(MyWorksheet,0,0));
|
||||
MyCell := MyWorksheet.FindCell(1, 0);
|
||||
if MyCell = nil then
|
||||
fail('Error in test code. Failed to get non-wrapped cell.');
|
||||
CheckEquals(false, (uffWordWrap in MyCell^.UsedFormattingFields),
|
||||
CheckEquals(false, MyWorksheet.ReadWordwrap(MyCell),
|
||||
'Failed to return correct word-wrap flag, cell ' + CellNotation(MyWorksheet,0,0));
|
||||
finally
|
||||
MyWorkbook.Free;
|
||||
|
@@ -21,7 +21,7 @@ uses
|
||||
// Not using lazarus package as the user may be working with multiple versions
|
||||
// Instead, add .. to unit search path
|
||||
Classes, SysUtils, testutils, testregistry, testdecorator, fpcunit,
|
||||
fpsallformats, fpspreadsheet,
|
||||
fpsallformats, fpspreadsheet, fpshelpers,
|
||||
xlsbiff8 {and a project requirement for lclbase for utf8 handling},
|
||||
testsutility;
|
||||
|
||||
@@ -202,9 +202,7 @@ begin
|
||||
for i:=0 to Workbook.GetPaletteSize-1 do begin
|
||||
WorkSheet.WriteUTF8Text(i+RowOffset,0,'BACKGROUND COLOR TEST');
|
||||
Cell := Worksheet.GetCell(i+RowOffset, 0);
|
||||
Cell^.BackgroundColor := TsColor(i);
|
||||
if not (uffBackgroundColor in Cell^.UsedFormattingFields) then
|
||||
include (Cell^.UsedFormattingFields,uffBackgroundColor);
|
||||
Worksheet.WriteBackgroundColor(Cell, TsColor(i));
|
||||
WorkSheet.WriteUTF8Text(i+RowOffset,1,'Cell to the left should be '+Workbook.GetColorName(i)+'. Please check.');
|
||||
end;
|
||||
end;
|
||||
|
@@ -40,7 +40,7 @@
|
||||
<PackageName Value="FCL"/>
|
||||
</Item4>
|
||||
</RequiredPackages>
|
||||
<Units Count="21">
|
||||
<Units Count="20">
|
||||
<Unit0>
|
||||
<Filename Value="spreadtestgui.lpr"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
@@ -48,22 +48,18 @@
|
||||
<Unit1>
|
||||
<Filename Value="datetests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="datetests"/>
|
||||
</Unit1>
|
||||
<Unit2>
|
||||
<Filename Value="stringtests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="stringtests"/>
|
||||
</Unit2>
|
||||
<Unit3>
|
||||
<Filename Value="numberstests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="numberstests"/>
|
||||
</Unit3>
|
||||
<Unit4>
|
||||
<Filename Value="manualtests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="manualtests"/>
|
||||
</Unit4>
|
||||
<Unit5>
|
||||
<Filename Value="testsutility.pas"/>
|
||||
@@ -72,7 +68,6 @@
|
||||
<Unit6>
|
||||
<Filename Value="internaltests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="internaltests"/>
|
||||
</Unit6>
|
||||
<Unit7>
|
||||
<Filename Value="formattests.pas"/>
|
||||
@@ -82,12 +77,10 @@
|
||||
<Unit8>
|
||||
<Filename Value="colortests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="colortests"/>
|
||||
</Unit8>
|
||||
<Unit9>
|
||||
<Filename Value="fonttests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="fonttests"/>
|
||||
</Unit9>
|
||||
<Unit10>
|
||||
<Filename Value="optiontests.pas"/>
|
||||
@@ -100,12 +93,10 @@
|
||||
<Unit12>
|
||||
<Filename Value="rpnformulaunit.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="rpnFormulaUnit"/>
|
||||
</Unit12>
|
||||
<Unit13>
|
||||
<Filename Value="formulatests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="formulatests"/>
|
||||
</Unit13>
|
||||
<Unit14>
|
||||
<Filename Value="emptycelltests.pas"/>
|
||||
@@ -131,13 +122,7 @@
|
||||
<Unit19>
|
||||
<Filename Value="sortingtests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="sortingtests"/>
|
||||
</Unit19>
|
||||
<Unit20>
|
||||
<Filename Value="copytests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="copytests"/>
|
||||
</Unit20>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
|
@@ -12,7 +12,7 @@ uses
|
||||
manualtests, testsutility, internaltests, formattests, colortests, fonttests,
|
||||
optiontests, numformatparsertests, formulatests, rpnFormulaUnit,
|
||||
emptycelltests, errortests, virtualmodetests, insertdeletetests,
|
||||
celltypetests, sortingtests, copytests;
|
||||
celltypetests, sortingtests;
|
||||
|
||||
begin
|
||||
{$IFDEF HEAPTRC}
|
||||
|
@@ -375,9 +375,11 @@ procedure TsWikiTableWriter.WriteToStrings_WikiMedia(AStrings: TStrings);
|
||||
var
|
||||
ls: TsLineStyle;
|
||||
clr: TsColor;
|
||||
fmt: PsCellFormat;
|
||||
begin
|
||||
ls := ACell^.BorderStyles[ABorder].LineStyle;
|
||||
clr := ACell^.BorderStyles[ABorder].Color;
|
||||
fmt := Workbook.GetPointerToCellFormat(ACell^.FormatIndex);
|
||||
ls := fmt^.BorderStyles[ABorder].LineStyle;
|
||||
clr := fmt^.BorderStyles[ABorder].Color;
|
||||
Result := Format('border-%s:%s', [BORDERNAMES[ABorder], LINESTYLES[ls]]);
|
||||
if clr <> scBlack then
|
||||
Result := Result + ' ' + FWorkbook.GetPaletteColorAsHTMLStr(clr) + '; ';
|
||||
@@ -403,6 +405,7 @@ var
|
||||
vertalign: TsVertAlignment;
|
||||
r1, c1, r2, c2: Cardinal;
|
||||
isHeader: Boolean;
|
||||
borders: TsCellBorders;
|
||||
begin
|
||||
FWorksheet := Workbook.GetFirstWorksheet();
|
||||
FWorksheet.UpdateCaches;
|
||||
@@ -418,7 +421,7 @@ begin
|
||||
// Default font
|
||||
lStyleStr := '';
|
||||
lFont := FWorkbook.GetDefaultFont;
|
||||
if lFont.FontName <> DEFAULTFONTNAME then
|
||||
if lFont.FontName <> DEFAULT_FONTNAME then
|
||||
lStyleStr := lStyleStr + Format('font-family:%s;', [lFont.FontName]);
|
||||
if fssBold in lFont.Style then
|
||||
lStyleStr := lStyleStr + 'font-weight:bold;';
|
||||
@@ -426,7 +429,7 @@ begin
|
||||
lStyleStr := lStyleStr + 'font-style:italic;';
|
||||
if fssUnderline in lFont.Style then
|
||||
lStyleStr := lStyleStr + 'text-decoration:underline;';
|
||||
if lFont.Size <> DEFAULTFONTSIZE then
|
||||
if lFont.Size <> DEFAULT_FONTSIZE then
|
||||
lStyleStr := lStyleStr + Format('font-size:%.0fpt;', [lFont.Size]);
|
||||
if lStyleStr <> '' then
|
||||
lCurStr := lCurStr + ' style="' + lStyleStr + '"';
|
||||
@@ -480,7 +483,7 @@ begin
|
||||
lFont := FWorkbook.GetDefaultFont;
|
||||
if (uffFont in lCurUsedFormatting) then
|
||||
begin
|
||||
lFont := FWorkbook.GetFont(lCell^.FontIndex);
|
||||
lFont := FWorksheet.ReadCellFont(lCell);
|
||||
if fssBold in lFont.Style then lCurStr := '<b>' + lCurStr + '</b>';
|
||||
if fssItalic in lFont.Style then lCurStr := '<i>' + lCurStr + '</i>';
|
||||
if fssUnderline in lFont.Style then lCurStr := '<u>' + lCurStr + '</u>';
|
||||
@@ -502,7 +505,7 @@ begin
|
||||
// Horizontal alignment
|
||||
if uffHorAlign in lCurUsedFormatting then
|
||||
begin
|
||||
horAlign := lCell^.HorAlignment;
|
||||
horAlign := FWorksheet.ReadHorAlignment(lCell);
|
||||
if horAlign = haDefault then
|
||||
case lCell^.ContentType of
|
||||
cctNumber,
|
||||
@@ -520,7 +523,7 @@ begin
|
||||
// vertical alignment
|
||||
if uffVertAlign in lCurUsedFormatting then
|
||||
begin
|
||||
vertAlign := lCell^.VertAlignment;
|
||||
vertAlign := FWorksheet.ReadVertAlignment(lCell);
|
||||
case vertAlign of
|
||||
vaTop : lStyleStr := lStyleStr + 'vertical-align:top;';
|
||||
vaCenter : lStyleStr := lStyleStr + 'vertical-align:center;';
|
||||
@@ -531,13 +534,14 @@ begin
|
||||
// borders
|
||||
if uffBorder in lCurUsedFormatting then
|
||||
begin
|
||||
if (cbWest in lCell^.Border) then
|
||||
borders := FWorksheet.ReadCellBorders(lCell);
|
||||
if (cbWest in borders) then
|
||||
lStyleStr := lStyleStr + DoBorder(cbWest, lCell);
|
||||
if (cbEast in lCell^.Border) then
|
||||
if (cbEast in borders) then
|
||||
lStyleStr := lStyleStr + DoBorder(cbEast, lCell);
|
||||
if (cbNorth in lCell^.Border) then
|
||||
if (cbNorth in borders) then
|
||||
lStyleStr := lStyleStr + DoBorder(cbNorth, lCell);
|
||||
if (cbSouth in lCell^.Border) then
|
||||
if (cbSouth in borders) then
|
||||
lStyleStr := lStyleStr + DoBorder(cbSouth, lCell);
|
||||
end;
|
||||
|
||||
|
@@ -50,7 +50,7 @@ type
|
||||
constructor Create(AWorkbook: TsWorkbook);
|
||||
procedure ConvertBeforeWriting(var AFormatString: String;
|
||||
var ANumFormat: TsNumberFormat); override;
|
||||
function FindFormatOf(AFormatCell: PCell): Integer; override;
|
||||
function Find(ANumFormat: TsNumberFormat; ANumFormatStr: String): Integer; override; overload;
|
||||
end;
|
||||
|
||||
{ TsSpreadBIFF2Reader }
|
||||
@@ -60,10 +60,12 @@ type
|
||||
WorkBookEncoding: TsEncoding;
|
||||
FFont: TsFont;
|
||||
protected
|
||||
procedure ApplyCellFormatting(ACell: PCell; XFIndex: Word); override;
|
||||
// procedure ApplyCellFormatting(ACell: PCell; XFIndex: Word); override;
|
||||
procedure CreateNumFormatList; override;
|
||||
{
|
||||
procedure ExtractNumberFormat(AXFIndex: WORD;
|
||||
out ANumberFormat: TsNumberFormat; out ANumberFormatStr: String); override;
|
||||
}
|
||||
procedure ReadBlank(AStream: TStream); override;
|
||||
procedure ReadBool(AStream: TStream); override;
|
||||
procedure ReadColWidth(AStream: TStream);
|
||||
@@ -93,7 +95,6 @@ type
|
||||
|
||||
TsSpreadBIFF2Writer = class(TsSpreadBIFFWriter)
|
||||
private
|
||||
function FindXFIndex(ACell: PCell): Word;
|
||||
procedure GetCellAttributes(ACell: PCell; XFIndex: Word;
|
||||
out Attrib1, Attrib2, Attrib3: Byte);
|
||||
{ Record writing methods }
|
||||
@@ -107,11 +108,11 @@ type
|
||||
procedure WriteFonts(AStream: TStream);
|
||||
procedure WriteFormatCount(AStream: TStream);
|
||||
procedure WriteIXFE(AStream: TStream; XFIndex: Word);
|
||||
{
|
||||
procedure WriteXF(AStream: TStream; AFontIndex, AFormatIndex: byte;
|
||||
ABorders: TsCellBorders = []; AHorAlign: TsHorAlignment = haLeft;
|
||||
AddBackground: Boolean = false);
|
||||
procedure WriteXFFieldsForFormattingStyles(AStream: TStream);
|
||||
procedure WriteXFRecords(AStream: TStream);
|
||||
AddBackground: Boolean = false); }
|
||||
// procedure WriteXFFieldsForFormattingStyles(AStream: TStream);
|
||||
protected
|
||||
procedure CreateNumFormatList; override;
|
||||
procedure ListAllNumFormats; override;
|
||||
@@ -121,12 +122,12 @@ type
|
||||
const AValue: Boolean; ACell: PCell); override;
|
||||
procedure WriteError(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
const AValue: TsErrorValue; ACell: PCell); override;
|
||||
procedure WriteFormat(AStream: TStream; AFormatData: TsNumFormatData;
|
||||
AListIndex: Integer); override;
|
||||
procedure WriteLabel(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
const AValue: string; ACell: PCell); override;
|
||||
procedure WriteNumber(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
const AValue: double; ACell: PCell); override;
|
||||
procedure WriteNumFormat(AStream: TStream; ANumFormatData: TsNumFormatData;
|
||||
AListIndex: Integer); override;
|
||||
procedure WriteRow(AStream: TStream; ASheet: TsWorksheet;
|
||||
ARowIndex, AFirstColIndex, ALastColIndex: Cardinal; ARow: PRow); override;
|
||||
procedure WriteRPNFormula(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
@@ -139,6 +140,8 @@ type
|
||||
procedure WriteStringRecord(AStream: TStream; AString: String); override;
|
||||
procedure WriteWindow1(AStream: TStream); override;
|
||||
procedure WriteWindow2(AStream: TStream; ASheet: TsWorksheet);
|
||||
procedure WriteXF(AStream: TStream; AFormatRecord: PsCellFormat;
|
||||
XFType_Prot: Byte = 0); override;
|
||||
public
|
||||
constructor Create(AWorkbook: TsWorkbook); override;
|
||||
{ General writing methods }
|
||||
@@ -158,8 +161,6 @@ var
|
||||
$00FFFF // $07: cyan
|
||||
);
|
||||
|
||||
// However, it looks as if BIFF2 can handle more colors, at least 16 are
|
||||
// compatible with the other formats.
|
||||
|
||||
implementation
|
||||
|
||||
@@ -192,7 +193,7 @@ const
|
||||
{%H-}INT_EXCEL_MACRO_SHEET = $0040;
|
||||
|
||||
type
|
||||
TBIFF2BoolErrRecord = packed record
|
||||
TBIFF2_BoolErrRecord = packed record
|
||||
RecordID: Word;
|
||||
RecordSize: Word;
|
||||
Row: Word;
|
||||
@@ -204,7 +205,7 @@ type
|
||||
ValueType: Byte;
|
||||
end;
|
||||
|
||||
TBIFF2DimensionsRecord = packed record
|
||||
TBIFF2_DimensionsRecord = packed record
|
||||
RecordID: Word;
|
||||
RecordSize: Word;
|
||||
FirstRow: Word;
|
||||
@@ -213,7 +214,7 @@ type
|
||||
LastColPlus1: Word;
|
||||
end;
|
||||
|
||||
TBIFF2LabelRecord = packed record
|
||||
TBIFF2_LabelRecord = packed record
|
||||
RecordID: Word;
|
||||
RecordSize: Word;
|
||||
Row: Word;
|
||||
@@ -224,7 +225,7 @@ type
|
||||
TextLen: Byte;
|
||||
end;
|
||||
|
||||
TBIFF2NumberRecord = packed record
|
||||
TBIFF2_NumberRecord = packed record
|
||||
RecordID: Word;
|
||||
RecordSize: Word;
|
||||
Row: Word;
|
||||
@@ -235,7 +236,7 @@ type
|
||||
Value: Double;
|
||||
end;
|
||||
|
||||
TBIFF2IntegerRecord = packed record
|
||||
TBIFF2_IntegerRecord = packed record
|
||||
RecordID: Word;
|
||||
RecordSize: Word;
|
||||
Row: Word;
|
||||
@@ -246,6 +247,15 @@ type
|
||||
Value: Word;
|
||||
end;
|
||||
|
||||
TBIFF2_XFRecord = packed record
|
||||
RecordID: Word;
|
||||
RecordSize: Word;
|
||||
FontIndex: Byte;
|
||||
NotUsed: Byte;
|
||||
NumFormatIndex_Flags: Byte;
|
||||
HorAlign_Border_BkGr: Byte;
|
||||
end;
|
||||
|
||||
|
||||
{ TsBIFF2NumFormatList }
|
||||
|
||||
@@ -265,30 +275,30 @@ var
|
||||
begin
|
||||
fs := FWorkbook.FormatSettings;
|
||||
cs := fs.CurrencyString;
|
||||
AddFormat( 0, '', nfGeneral);
|
||||
AddFormat( 1, '0', nfFixed);
|
||||
AddFormat( 2, '0.00', nfFixed);
|
||||
AddFormat( 3, '#,##0', nfFixedTh);
|
||||
AddFormat( 4, '#,##0.00', nfFixedTh);
|
||||
AddFormat( 5, '"'+cs+'"#,##0;("'+cs+'"#,##0)', nfCurrency);
|
||||
AddFormat( 6, '"'+cs+'"#,##0;[Red]("'+cs+'"#,##0)', nfCurrencyRed);
|
||||
AddFormat( 7, '"'+cs+'"#,##0.00;("'+cs+'"#,##0.00)', nfCurrency);
|
||||
AddFormat( 8, '"'+cs+'"#,##0.00;[Red]("'+cs+'"#,##0.00)', nfCurrency);
|
||||
AddFormat( 9, '0%', nfPercentage);
|
||||
AddFormat(10, '0.00%', nfPercentage);
|
||||
AddFormat(11, '0.00E+00', nfExp);
|
||||
AddFormat(12, fs.ShortDateFormat, nfShortDate);
|
||||
AddFormat(13, fs.LongDateFormat, nfLongDate);
|
||||
AddFormat(14, 'd/mmm', nfCustom);
|
||||
AddFormat(15, 'mmm/yy', nfCustom);
|
||||
AddFormat(16, AddAMPM(fs.ShortTimeFormat, fs), nfShortTimeAM);
|
||||
AddFormat(17, AddAMPM(fs.LongTimeFormat, fs), nfLongTimeAM);
|
||||
AddFormat(18, fs.ShortTimeFormat, nfShortTime);
|
||||
AddFormat(19, fs.LongTimeFormat, nfLongTime);
|
||||
AddFormat(20, fs.ShortDateFormat + ' ' + fs.ShortTimeFormat, nfShortDateTime);
|
||||
AddFormat( 0, nfGeneral, '');
|
||||
AddFormat( 1, nfFixed, '0');
|
||||
AddFormat( 2, nfFixed, '0.00');
|
||||
AddFormat( 3, nfFixedTh, '#,##0');
|
||||
AddFormat( 4, nfFixedTh, '#,##0.00');
|
||||
AddFormat( 5, nfCurrency, Format('"%s"#,##0;("%s"#,##0)', [cs, cs]));
|
||||
AddFormat( 6, nfCurrencyRed, Format('"%s"#,##0;[Red]("%s"#,##0)', [cs, cs]));
|
||||
AddFormat( 7, nfCurrency, Format('"%s"#,##0.00;("%s"#,##0.00)', [cs, cs]));
|
||||
AddFormat( 8, nfCurrencyRed, Format('"%s"#,##0.00;[Red]("%s"#,##0.00)', [cs, cs]));
|
||||
AddFormat( 9, nfPercentage, '0%');
|
||||
AddFormat(10, nfPercentage, '0.00%');
|
||||
AddFormat(11, nfExp, '0.00E+00');
|
||||
AddFormat(12, nfShortDate, fs.ShortDateFormat);
|
||||
AddFormat(13, nfLongDate, fs.LongDateFormat);
|
||||
AddFormat(14, nfCustom, 'd/mmm');
|
||||
AddFormat(15, nfCustom, 'mmm/yy');
|
||||
AddFormat(16, nfShortTimeAM, AddAMPM(fs.ShortTimeFormat, fs));
|
||||
AddFormat(17, nfLongTimeAM, AddAMPM(fs.LongTimeFormat, fs));
|
||||
AddFormat(18, nfShortTime, fs.ShortTimeFormat);
|
||||
AddFormat(19, nfLongTime, fs.LongTimeFormat);
|
||||
AddFormat(20, nfShortDateTime, fs.ShortDateFormat + ' ' + fs.ShortTimeFormat);
|
||||
|
||||
FFirstFormatIndexInFile := 0; // BIFF2 stores built-in formats to file.
|
||||
FNextFormatIndex := 21; // not needed - there are not user-defined formats
|
||||
FFirstNumFormatIndexInFile := 0; // BIFF2 stores built-in formats to file.
|
||||
FNextNumFormatIndex := 21; // not needed - there are not user-defined formats
|
||||
end;
|
||||
|
||||
|
||||
@@ -313,7 +323,44 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsBIFF2NumFormatList.Find(ANumFormat: TsNumberFormat;
|
||||
ANumFormatStr: String): Integer;
|
||||
var
|
||||
parser: TsNumFormatParser;
|
||||
decs: Integer;
|
||||
dt: string;
|
||||
begin
|
||||
Result := 0;
|
||||
|
||||
parser := TsNumFormatParser.Create(Workbook, ANumFormatStr);
|
||||
try
|
||||
decs := parser.Decimals;
|
||||
dt := parser.GetDateTimeCode(0);
|
||||
finally
|
||||
parser.Free;
|
||||
end;
|
||||
|
||||
case ANumFormat of
|
||||
nfGeneral : exit;
|
||||
nfFixed : Result := IfThen(decs = 0, 1, 2);
|
||||
nfFixedTh : Result := IfThen(decs = 0, 3, 4);
|
||||
nfCurrency : Result := IfThen(decs = 0, 5, 7);
|
||||
nfCurrencyRed : Result := IfThen(decs = 0, 6, 8);
|
||||
nfPercentage : Result := IfThen(decs = 0, 9, 10);
|
||||
nfExp : Result := 11;
|
||||
nfShortDate : Result := 12;
|
||||
nfLongDate : Result := 13;
|
||||
nfShortTimeAM : Result := 16;
|
||||
nfLongTimeAM : Result := 17;
|
||||
nfShortTime : Result := 18;
|
||||
nfLongTime : Result := 19;
|
||||
nfShortDateTime: Result := 20;
|
||||
nfCustom : if dt = 'dm' then Result := 14 else
|
||||
if dt = 'my' then Result := 15;
|
||||
end;
|
||||
end;
|
||||
|
||||
(*
|
||||
function TsBIFF2NumFormatList.FindFormatOf(AFormatCell: PCell): Integer;
|
||||
var
|
||||
parser: TsNumFormatParser;
|
||||
@@ -349,7 +396,7 @@ begin
|
||||
if dt = 'my' then Result := 15;
|
||||
end;
|
||||
end;
|
||||
|
||||
*)
|
||||
|
||||
{ TsSpreadBIFF2Reader }
|
||||
|
||||
@@ -358,7 +405,7 @@ begin
|
||||
inherited Create(AWorkbook);
|
||||
FLimitations.MaxPaletteSize := BIFF2_MAX_PALETTE_SIZE;
|
||||
end;
|
||||
|
||||
(*
|
||||
procedure TsSpreadBIFF2Reader.ApplyCellFormatting(ACell: PCell; XFIndex: Word);
|
||||
var
|
||||
xfData: TXFListData;
|
||||
@@ -396,7 +443,7 @@ begin
|
||||
Exclude(ACell^.UsedFormattingFields, uffBackgroundColor);
|
||||
end;
|
||||
end;
|
||||
|
||||
*)
|
||||
{ Creates the correct version of the number format list.
|
||||
It is for BIFF2 and BIFF3 file formats. }
|
||||
procedure TsSpreadBIFF2Reader.CreateNumFormatList;
|
||||
@@ -404,7 +451,7 @@ begin
|
||||
FreeAndNil(FNumFormatList);
|
||||
FNumFormatList := TsBIFF2NumFormatList.Create(Workbook);
|
||||
end;
|
||||
|
||||
(*
|
||||
{ Extracts the number format data from an XF record indexed by AXFIndex.
|
||||
Note that BIFF2 supports only 21 formats. }
|
||||
procedure TsSpreadBIFF2Reader.ExtractNumberFormat(AXFIndex: WORD;
|
||||
@@ -421,7 +468,7 @@ begin
|
||||
ANumberFormatStr := '';
|
||||
end;
|
||||
end;
|
||||
|
||||
*)
|
||||
procedure TsSpreadBIFF2Reader.ReadBlank(AStream: TStream);
|
||||
var
|
||||
ARow, ACol: Cardinal;
|
||||
@@ -443,14 +490,14 @@ end;
|
||||
but also an ERROR value; BIFF stores them in the same record. }
|
||||
procedure TsSpreadBIFF2Reader.ReadBool(AStream: TStream);
|
||||
var
|
||||
rec: TBIFF2BoolErrRecord;
|
||||
rec: TBIFF2_BoolErrRecord;
|
||||
r, c: Cardinal;
|
||||
xf: Word;
|
||||
cell: PCell;
|
||||
begin
|
||||
{ Read entire record, starting at Row }
|
||||
rec.Row := 0; // to silence the compiler...
|
||||
AStream.ReadBuffer(rec.Row, SizeOf(TBIFF2BoolErrRecord) - 2*SizeOf(Word));
|
||||
AStream.ReadBuffer(rec.Row, SizeOf(TBIFF2_BoolErrRecord) - 2*SizeOf(Word));
|
||||
r := WordLEToN(rec.Row);
|
||||
c := WordLEToN(rec.Col);
|
||||
xf := rec.Attrib1 and $3F;
|
||||
@@ -691,7 +738,7 @@ end;
|
||||
|
||||
procedure TsSpreadBIFF2Reader.ReadLabel(AStream: TStream);
|
||||
var
|
||||
rec: TBIFF2LabelRecord;
|
||||
rec: TBIFF2_LabelRecord;
|
||||
L: Byte;
|
||||
ARow, ACol: Cardinal;
|
||||
XF: Word;
|
||||
@@ -701,7 +748,7 @@ var
|
||||
begin
|
||||
{ Read entire record, starting at Row, except for string data }
|
||||
rec.Row := 0; // to silence the compiler...
|
||||
AStream.ReadBuffer(rec.Row, SizeOf(TBIFF2LabelRecord) - 2*SizeOf(Word));
|
||||
AStream.ReadBuffer(rec.Row, SizeOf(TBIFF2_LabelRecord) - 2*SizeOf(Word));
|
||||
ARow := WordLEToN(rec.Row);
|
||||
ACol := WordLEToN(rec.Col);
|
||||
XF := rec.Attrib1 and $3F;
|
||||
@@ -741,7 +788,7 @@ end;
|
||||
|
||||
procedure TsSpreadBIFF2Reader.ReadNumber(AStream: TStream);
|
||||
var
|
||||
rec: TBIFF2NumberRecord;
|
||||
rec: TBIFF2_NumberRecord;
|
||||
ARow, ACol: Cardinal;
|
||||
XF: Word;
|
||||
value: Double = 0.0;
|
||||
@@ -752,7 +799,7 @@ var
|
||||
begin
|
||||
{ Read entire record, starting at Row }
|
||||
rec.Row := 0; // to silence the compiler...
|
||||
AStream.ReadBuffer(rec.Row, SizeOf(TBIFF2NumberRecord) - 2*SizeOf(Word));
|
||||
AStream.ReadBuffer(rec.Row, SizeOf(TBIFF2_NumberRecord) - 2*SizeOf(Word));
|
||||
ARow := WordLEToN(rec.Row);
|
||||
ACol := WordLEToN(rec.Col);
|
||||
XF := rec.Attrib1 and $3F;
|
||||
@@ -785,11 +832,11 @@ var
|
||||
XF: Word;
|
||||
AWord : Word = 0;
|
||||
cell: PCell;
|
||||
rec: TBIFF2IntegerRecord;
|
||||
rec: TBIFF2_IntegerRecord;
|
||||
begin
|
||||
{ Read record into buffer }
|
||||
rec.Row := 0; // to silence the comiler...
|
||||
AStream.ReadBuffer(rec.Row, SizeOf(TBIFF2NumberRecord) - 2*SizeOf(Word));
|
||||
AStream.ReadBuffer(rec.Row, SizeOf(TBIFF2_NumberRecord) - 2*SizeOf(Word));
|
||||
ARow := WordLEToN(rec.Row);
|
||||
ACol := WordLEToN(rec.Col);
|
||||
XF := rec.Attrib1 and $3F;
|
||||
@@ -969,7 +1016,8 @@ procedure TsSpreadBIFF2Reader.ReadXF(AStream: TStream);
|
||||
4 10H 1 = Cell has right black border
|
||||
5 20H 1 = Cell has top black border
|
||||
6 40H 1 = Cell has bottom black border
|
||||
7 80H 1 = Cell has shaded background }
|
||||
7 80H 1 = Cell has shaded background
|
||||
|
||||
type
|
||||
TXFRecord = packed record
|
||||
FontIndex: byte;
|
||||
@@ -977,60 +1025,80 @@ type
|
||||
NumFormat_Flags: byte;
|
||||
HorAlign_Border_BackGround: Byte;
|
||||
end;
|
||||
}
|
||||
var
|
||||
lData: TXFListData;
|
||||
xf: TXFRecord;
|
||||
rec: TBIFF2_XFRecord;
|
||||
fmt: TsCellFormat;
|
||||
b: Byte;
|
||||
nfdata: TsNumFormatData;
|
||||
i: Integer;
|
||||
begin
|
||||
// Read entire xf record into buffer
|
||||
xf.FontIndex := 0; // to silence the compiler...
|
||||
AStream.ReadBuffer(xf, SizeOf(xf));
|
||||
InitFormatRecord(fmt);
|
||||
fmt.ID := FCellFormatList.Count;
|
||||
|
||||
lData := TXFListData.Create;
|
||||
rec.FontIndex := 0; // to silence the compiler...
|
||||
AStream.ReadBuffer(rec.FontIndex, SizeOf(rec) - 2*SizeOf(word));
|
||||
|
||||
// Font index
|
||||
lData.FontIndex := xf.FontIndex;
|
||||
fmt.FontIndex := rec.FontIndex;
|
||||
if fmt.FontIndex = 1 then
|
||||
Include(fmt.UsedFormattingFields, uffBold)
|
||||
else if fmt.FontIndex > 1 then
|
||||
Include(fmt.UsedFormattingFields, uffFont);
|
||||
|
||||
// Format index
|
||||
lData.FormatIndex := xf.NumFormat_Flags and $3F;
|
||||
// Number format index
|
||||
b := rec.NumFormatIndex_Flags and $3F;
|
||||
i := NumFormatList.FindByIndex(b);
|
||||
if i > -1 then begin
|
||||
nfdata := NumFormatList.Items[i];
|
||||
fmt.NumberFormat := nfdata.NumFormat;
|
||||
fmt.NumberFormatStr := nfdata.FormatString;
|
||||
if nfdata.NumFormat <> nfGeneral then
|
||||
Include(fmt.UsedFormattingFields, uffNumberFormat);
|
||||
end;
|
||||
|
||||
// Horizontal alignment
|
||||
b := xf.HorAlign_Border_Background and MASK_XF_HOR_ALIGN;
|
||||
b := rec.HorAlign_Border_BkGr and MASK_XF_HOR_ALIGN;
|
||||
if (b <= ord(High(TsHorAlignment))) then
|
||||
lData.HorAlignment := TsHorAlignment(b)
|
||||
else
|
||||
lData.HorAlignment := haDefault;
|
||||
begin
|
||||
fmt.HorAlignment := TsHorAlignment(b);
|
||||
if fmt.HorAlignment <> haDefault then
|
||||
Include(fmt.UsedFormattingFields, uffHorAlign);
|
||||
end;
|
||||
|
||||
// Vertical alignment - not used in BIFF2
|
||||
lData.VertAlignment := vaBottom;
|
||||
fmt.VertAlignment := vaDefault;
|
||||
|
||||
// Word wrap - not used in BIFF2
|
||||
lData.WordWrap := false;
|
||||
// -- nothing to do here
|
||||
|
||||
// Text rotation - not used in BIFF2
|
||||
lData.TextRotation := trHorizontal;
|
||||
// -- nothing to do here
|
||||
|
||||
// Borders
|
||||
lData.Borders := [];
|
||||
if xf.HorAlign_Border_Background and $08 <> 0 then
|
||||
Include(lData.Borders, cbWest);
|
||||
if xf.HorAlign_Border_Background and $10 <> 0 then
|
||||
Include(lData.Borders, cbEast);
|
||||
if xf.HorAlign_Border_Background and $20 <> 0 then
|
||||
Include(lData.Borders, cbNorth);
|
||||
if xf.HorAlign_Border_Background and $40 <> 0 then
|
||||
Include(lData.Borders, cbSouth);
|
||||
fmt.Border := [];
|
||||
if rec.HorAlign_Border_BkGr and $08 <> 0 then
|
||||
Include(fmt.Border, cbWest);
|
||||
if rec.HorAlign_Border_BkGr and $10 <> 0 then
|
||||
Include(fmt.Border, cbEast);
|
||||
if rec.HorAlign_Border_BkGr and $20 <> 0 then
|
||||
Include(fmt.Border, cbNorth);
|
||||
if rec.HorAlign_Border_BkGr and $40 <> 0 then
|
||||
Include(fmt.Border, cbSouth);
|
||||
if fmt.Border <> [] then
|
||||
Include(fmt.UsedFormattingFields, uffBorder);
|
||||
|
||||
// Background color not supported, only shaded background
|
||||
if xf.HorAlign_Border_Background and $80 <> 0 then
|
||||
lData.BackgroundColor := 1 // encodes "shaded background = true"
|
||||
else
|
||||
ldata.BackgroundColor := 0; // encodes "shaded background = false"
|
||||
if rec.HorAlign_Border_BkGr and $80 <> 0 then
|
||||
begin
|
||||
fmt.BackgroundColor := 1; // encodes "shaded background = true"
|
||||
Include(fmt.UsedFormattingFields, uffBackgroundColor);
|
||||
end else
|
||||
fmt.BackgroundColor := 0; // encodes "shaded background = false"
|
||||
|
||||
// Add the decoded data to the list
|
||||
FXFList.Add(lData);
|
||||
|
||||
ldata := TXFListData(FXFList.Items[FXFList.Count-1]);
|
||||
// Add the decoded data to the format list
|
||||
FCellFormatList.Add(fmt);
|
||||
end;
|
||||
|
||||
|
||||
@@ -1049,7 +1117,7 @@ begin
|
||||
FreeAndNil(FNumFormatList);
|
||||
FNumFormatList := TsBIFF2NumFormatList.Create(Workbook);
|
||||
end;
|
||||
|
||||
(*
|
||||
function TsSpreadBIFF2Writer.FindXFIndex(ACell: PCell): Word;
|
||||
var
|
||||
lIndex: Integer;
|
||||
@@ -1065,18 +1133,22 @@ begin
|
||||
|
||||
// Carefully check the index
|
||||
if (lIndex < 0) or (lIndex > Length(FFormattingStyles)) then
|
||||
raise Exception.Create('[TsSpreadBIFF2Writer.WriteXFIndex] Invalid index, this should not happen!');
|
||||
raise Exception.Create('[TsSpreadBIFF2Writer.FindXFIndex] Invalid index, this should not happen!');
|
||||
Result := FFormattingStyles[lIndex].Row;
|
||||
end;
|
||||
end;
|
||||
end; *)
|
||||
|
||||
{ Determines the cell attributes needed for writing a cell content record, such
|
||||
as WriteLabel, WriteNumber, etc.
|
||||
The cell attributes contain, in bit masks, xf record index, font index, borders, etc.}
|
||||
procedure TsSpreadBIFF2Writer.GetCellAttributes(ACell: PCell; XFIndex: Word;
|
||||
out Attrib1, Attrib2, Attrib3: Byte);
|
||||
var
|
||||
fmt: PsCellFormat;
|
||||
begin
|
||||
if ACell^.UsedFormattingFields = [] then begin
|
||||
fmt := Workbook.GetPointerToCellFormat(ACell^.FormatIndex);
|
||||
|
||||
if fmt^.UsedFormattingFields = [] then begin
|
||||
Attrib1 := 15;
|
||||
Attrib2 := 0;
|
||||
Attrib3 := 0;
|
||||
@@ -1090,9 +1162,9 @@ begin
|
||||
Attrib1 := Min(XFIndex, $3F) and $3F;
|
||||
|
||||
// 2nd byte:
|
||||
// Mask $3F: Index to FORMAT record
|
||||
// Mask $3F: Index to FORMAT record ("FORMAT" = number format!)
|
||||
// Mask $C0: Index to FONT record
|
||||
Attrib2 := ACell^.FontIndex shr 6;
|
||||
Attrib2 := fmt^.FontIndex shr 6;
|
||||
|
||||
// 3rd byte
|
||||
// Mask $07: horizontal alignment
|
||||
@@ -1102,15 +1174,15 @@ begin
|
||||
// Mask $40: Cell has bottom border
|
||||
// Mask $80: Cell has shaded background
|
||||
Attrib3 := 0;
|
||||
if uffHorAlign in ACell^.UsedFormattingFields then
|
||||
Attrib3 := ord (ACell^.HorAlignment);
|
||||
if uffBorder in ACell^.UsedFormattingFields then begin
|
||||
if cbNorth in ACell^.Border then Attrib3 := Attrib3 or $20;
|
||||
if cbWest in ACell^.Border then Attrib3 := Attrib3 or $08;
|
||||
if cbEast in ACell^.Border then Attrib3 := Attrib3 or $10;
|
||||
if cbSouth in ACell^.Border then Attrib3 := Attrib3 or $40;
|
||||
if uffHorAlign in fmt^.UsedFormattingFields then
|
||||
Attrib3 := ord (fmt^.HorAlignment);
|
||||
if uffBorder in fmt^.UsedFormattingFields then begin
|
||||
if cbNorth in fmt^.Border then Attrib3 := Attrib3 or $20;
|
||||
if cbWest in fmt^.Border then Attrib3 := Attrib3 or $08;
|
||||
if cbEast in fmt^.Border then Attrib3 := Attrib3 or $10;
|
||||
if cbSouth in fmt^.Border then Attrib3 := Attrib3 or $40;
|
||||
end;
|
||||
if uffBackgroundColor in ACell^.UsedFormattingFields then
|
||||
if (uffBackgroundColor in fmt^.UsedFormattingFields) and (fmt^.Backgroundcolor <> scWhite) then
|
||||
Attrib3 := Attrib3 or $80;
|
||||
end;
|
||||
|
||||
@@ -1131,51 +1203,56 @@ end;
|
||||
Is called from all writing methods of cell contents. }
|
||||
procedure TsSpreadBIFF2Writer.WriteCellFormatting(AStream: TStream; ACell: PCell;
|
||||
XFIndex: Word);
|
||||
type
|
||||
TCellFmtRecord = packed record
|
||||
XFIndex_Locked_Hidden: Byte;
|
||||
Format_Font: Byte;
|
||||
Align_Border_BkGr: Byte;
|
||||
end;
|
||||
var
|
||||
b: Byte;
|
||||
rec: TCellFmtRecord;
|
||||
fmt: PsCellFormat;
|
||||
w: Word;
|
||||
begin
|
||||
if ACell^.UsedFormattingFields = [] then
|
||||
fmt := Workbook.GetPointerToCellFormat(ACell^.FormatIndex);
|
||||
rec.XFIndex_Locked_Hidden := 0; // to silence the compiler...
|
||||
FillChar(rec, SizeOf(rec), 0);
|
||||
|
||||
if fmt^.UsedFormattingFields <> [] then
|
||||
begin
|
||||
AStream.WriteByte($0);
|
||||
AStream.WriteByte($0);
|
||||
AStream.WriteByte($0);
|
||||
Exit;
|
||||
// 1st byte:
|
||||
// Mask $3F: Index to XF record
|
||||
// Mask $40: 1 = Cell is locked
|
||||
// Mask $80: 1 = Formula is hidden
|
||||
rec.XFIndex_Locked_Hidden := Min(XFIndex, $3F) and $3F;
|
||||
// AStream.WriteByte(Min(XFIndex, $3F) and $3F);
|
||||
|
||||
// 2nd byte:
|
||||
// Mask $3F: Index to FORMAT record
|
||||
// Mask $C0: Index to FONT record
|
||||
w := fmt^.FontIndex shr 6; // was shl --> MUST BE shr! // ??????????????????????
|
||||
rec.Format_Font := Lo(w);
|
||||
// AStream.WriteByte(b);
|
||||
|
||||
// 3rd byte
|
||||
// Mask $07: horizontal alignment
|
||||
// Mask $08: Cell has left border
|
||||
// Mask $10: Cell has right border
|
||||
// Mask $20: Cell has top border
|
||||
// Mask $40: Cell has bottom border
|
||||
// Mask $80: Cell has shaded background
|
||||
if uffHorAlign in fmt^.UsedFormattingFields then
|
||||
rec.Align_Border_BkGr := ord(fmt^.HorAlignment);
|
||||
if uffBorder in fmt^.UsedFormattingFields then begin
|
||||
if cbNorth in fmt^.Border then rec.Align_Border_BkGr := rec.Align_Border_BkGr or $20;
|
||||
if cbWest in fmt^.Border then rec.Align_Border_BkGr := rec.Align_Border_BkGr or $08;
|
||||
if cbEast in fmt^.Border then rec.Align_Border_BkGr := rec.Align_Border_BkGr or $10;
|
||||
if cbSouth in fmt^.Border then rec.Align_Border_BkGr := rec.Align_Border_BkGr or $40;
|
||||
end;
|
||||
if uffBackgroundColor in fmt^.UsedFormattingFields then
|
||||
rec.Align_Border_BkGr := rec.Align_Border_BkGr or $80;
|
||||
end;
|
||||
|
||||
// 1st byte:
|
||||
// Mask $3F: Index to XF record
|
||||
// Mask $40: 1 = Cell is locked
|
||||
// Mask $80: 1 = Formula is hidden
|
||||
AStream.WriteByte(Min(XFIndex, $3F) and $3F);
|
||||
|
||||
// 2nd byte:
|
||||
// Mask $3F: Index to FORMAT record
|
||||
// Mask $C0: Index to FONT record
|
||||
w := ACell.FontIndex shr 6; // was shl --> MUST BE shr!
|
||||
b := Lo(w);
|
||||
//b := ACell.FontIndex shl 6;
|
||||
AStream.WriteByte(b);
|
||||
|
||||
// 3rd byte
|
||||
// Mask $07: horizontal alignment
|
||||
// Mask $08: Cell has left border
|
||||
// Mask $10: Cell has right border
|
||||
// Mask $20: Cell has top border
|
||||
// Mask $40: Cell has bottom border
|
||||
// Mask $80: Cell has shaded background
|
||||
b := 0;
|
||||
if uffHorAlign in ACell^.UsedFormattingFields then
|
||||
b := ord (ACell^.HorAlignment);
|
||||
if uffBorder in ACell^.UsedFormattingFields then begin
|
||||
if cbNorth in ACell^.Border then b := b or $20;
|
||||
if cbWest in ACell^.Border then b := b or $08;
|
||||
if cbEast in ACell^.Border then b := b or $10;
|
||||
if cbSouth in ACell^.Border then b := b or $40;
|
||||
end;
|
||||
if uffBackgroundColor in ACell^.UsedFormattingFields then
|
||||
b := b or $80;
|
||||
AStream.WriteByte(b);
|
||||
AStream.WriteBuffer(rec, SizeOf(rec));
|
||||
end;
|
||||
|
||||
{
|
||||
@@ -1235,7 +1312,7 @@ end;
|
||||
procedure TsSpreadBIFF2Writer.WriteDimensions(AStream: TStream; AWorksheet: TsWorksheet);
|
||||
var
|
||||
firstRow, lastRow, firstCol, lastCol: Cardinal;
|
||||
rec: TBIFF2DimensionsRecord;
|
||||
rec: TBIFF2_DimensionsRecord;
|
||||
begin
|
||||
{ Determine sheet size }
|
||||
GetSheetDimensions(AWorksheet, firstRow, lastRow, firstCol, lastCol);
|
||||
@@ -1282,7 +1359,7 @@ begin
|
||||
WriteBOF(AStream);
|
||||
WriteFonts(AStream);
|
||||
WriteFormatCount(AStream);
|
||||
WriteFormats(AStream);
|
||||
WriteNumFormats(AStream);
|
||||
WriteXFRecords(AStream);
|
||||
WriteColWidths(AStream);
|
||||
WriteDimensions(AStream, FWorksheet);
|
||||
@@ -1376,6 +1453,86 @@ begin
|
||||
AStream.WriteDWord(0);
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFF2Writer.WriteXF(AStream: TStream;
|
||||
AFormatRecord: PsCellFormat; XFType_Prot: Byte = 0);
|
||||
var
|
||||
rec: TBIFF2_XFRecord;
|
||||
b: Byte;
|
||||
j: Integer;
|
||||
clr: TsColorvalue;
|
||||
begin
|
||||
Unused(XFType_Prot);
|
||||
|
||||
{ BIFF Record header }
|
||||
rec.RecordID := WordToLE(INT_EXCEL_ID_XF);
|
||||
rec.RecordSize := WordToLE(SizeOf(TBIFF2_XFRecord) - 2*SizeOf(word));
|
||||
|
||||
{ Index to FONT record }
|
||||
rec.FontIndex := 0;
|
||||
if (AFormatRecord <> nil) then
|
||||
begin
|
||||
if (uffBold in AFormatRecord^.UsedFormattingFields) then
|
||||
rec.FontIndex := 1
|
||||
else
|
||||
if (uffFont in AFormatRecord^.UsedFormattingFields) then
|
||||
rec.FontIndex := AFormatRecord^.FontIndex;
|
||||
end;
|
||||
|
||||
{ Not used byte }
|
||||
rec.NotUsed := 0;
|
||||
|
||||
{ Number format index and cell flags
|
||||
Bit Mask Contents
|
||||
----- ---- --------------------------------
|
||||
5-0 $3F Index to (number) FORMAT record
|
||||
6 $40 1 = Cell is locked
|
||||
7 $80 1 = Formula is hidden }
|
||||
rec.NumFormatIndex_Flags := 0;
|
||||
if (AFormatRecord <> nil) and (uffNumberFormat in AFormatRecord^.UsedFormattingFields) then
|
||||
begin
|
||||
// The number formats in the FormatList are still in fpc dialect
|
||||
// They will be converted to Excel syntax immediately before writing.
|
||||
j := NumFormatList.Find(AFormatRecord^.NumberFormat, AFormatRecord^.NumberFormatStr);
|
||||
if j > -1 then
|
||||
rec.NumFormatIndex_Flags := NumFormatList[j].Index;
|
||||
|
||||
// Cell flags not used, so far...
|
||||
end;
|
||||
|
||||
{Horizontal alignment, border style, and background
|
||||
Bit Mask Contents
|
||||
--- ---- ------------------------------------------------
|
||||
2-0 $07 XF_HOR_ALIGN – Horizontal alignment (0=General, 1=Left, 2=Centred, 3=Right)
|
||||
3 $08 1 = Cell has left black border
|
||||
4 $10 1 = Cell has right black border
|
||||
5 $20 1 = Cell has top black border
|
||||
6 $40 1 = Cell has bottom black border
|
||||
7 $80 1 = Cell has shaded background }
|
||||
b := 0;
|
||||
if (AFormatRecord <> nil) then
|
||||
begin
|
||||
if (uffHorAlign in AFormatRecord^.UsedFormattingFields) then
|
||||
b := b + byte(AFormatRecord^.HorAlignment);
|
||||
if (uffBorder in AFormatRecord^.UsedFormattingFields) then
|
||||
begin
|
||||
if cbWest in AFormatRecord^.Border then b := b or $08;
|
||||
if cbEast in AFormatRecord^.Border then b := b or $10;
|
||||
if cbNorth in AFormatRecord^.Border then b := b or $20;
|
||||
if cbSouth in AFormatRecord^.Border then b := b or $40;
|
||||
end;
|
||||
if (uffBackgroundColor in AFormatRecord^.UsedFormattingFields) then
|
||||
begin
|
||||
clr := Workbook.GetPaletteColor(AFormatRecord^.BackgroundColor);
|
||||
if clr <> $FFFFFF then
|
||||
b := b or $80;
|
||||
end;
|
||||
end;
|
||||
rec.HorAlign_Border_BkGr:= b;
|
||||
|
||||
{ Write out }
|
||||
AStream.WriteBuffer(rec, SizeOf(rec));
|
||||
end;
|
||||
(*
|
||||
procedure TsSpreadBIFF2Writer.WriteXF(AStream: TStream;
|
||||
AFontIndex, AFormatIndex: byte; ABorders: TsCellBorders = [];
|
||||
AHorAlign: TsHorAlignment = haLeft; AddBackground: Boolean = false);
|
||||
@@ -1449,28 +1606,28 @@ end;
|
||||
|
||||
procedure TsSpreadBIFF2Writer.WriteXFRecords(AStream: TStream);
|
||||
begin
|
||||
WriteXF(AStream, 0, 0); // XF0
|
||||
WriteXF(AStream, 0, 0); // XF1
|
||||
WriteXF(AStream, 0, 0); // XF2
|
||||
WriteXF(AStream, 0, 0); // XF3
|
||||
WriteXF(AStream, 0, 0); // XF4
|
||||
WriteXF(AStream, 0, 0); // XF5
|
||||
WriteXF(AStream, 0, 0); // XF6
|
||||
WriteXF(AStream, 0, 0); // XF7
|
||||
WriteXF(AStream, 0, 0); // XF8
|
||||
WriteXF(AStream, 0, 0); // XF9
|
||||
WriteXF(AStream, 0, 0); // XF10
|
||||
WriteXF(AStream, 0, 0); // XF11
|
||||
WriteXF(AStream, 0, 0); // XF12
|
||||
WriteXF(AStream, 0, 0); // XF13
|
||||
WriteXF(AStream, 0, 0); // XF14
|
||||
WriteXF(AStream, 0, 0); // XF15 - Default, no formatting
|
||||
WriteXFRecord(AStream, 0, 0); // XF0
|
||||
WriteXFRecord(AStream, 0, 0); // XF1
|
||||
WriteXFRecord(AStream, 0, 0); // XF2
|
||||
WriteXFRecord(AStream, 0, 0); // XF3
|
||||
WriteXFRecord(AStream, 0, 0); // XF4
|
||||
WriteXFRecord(AStream, 0, 0); // XF5
|
||||
WriteXFRecord(AStream, 0, 0); // XF6
|
||||
WriteXFRecord(AStream, 0, 0); // XF7
|
||||
WriteXFRecord(AStream, 0, 0); // XF8
|
||||
WriteXFRecord(AStream, 0, 0); // XF9
|
||||
WriteXFRecord(AStream, 0, 0); // XF10
|
||||
WriteXFRecord(AStream, 0, 0); // XF11
|
||||
WriteXFRecord(AStream, 0, 0); // XF12
|
||||
WriteXFRecord(AStream, 0, 0); // XF13
|
||||
WriteXFRecord(AStream, 0, 0); // XF14
|
||||
WriteXFRecord(AStream, 0, 0); // XF15 - Default, no formatting
|
||||
|
||||
// Add all further non-standard/built-in formatting styles
|
||||
ListAllFormattingStyles;
|
||||
WriteXFFieldsForFormattingStyles(AStream);
|
||||
end;
|
||||
|
||||
*)
|
||||
{
|
||||
Writes an Excel 2 BOF record
|
||||
|
||||
@@ -1526,7 +1683,7 @@ begin
|
||||
|
||||
{ BIFF Record header }
|
||||
AStream.WriteWord(WordToLE(INT_EXCEL_ID_FONT));
|
||||
AStream.WriteWord(WordToLE(4 + 1 + Len * Sizeof(AnsiChar)));
|
||||
AStream.WriteWord(WordToLE(4 + 1 + Len * SizeOf(AnsiChar)));
|
||||
|
||||
{ Height of the font in twips = 1/20 of a point }
|
||||
AStream.WriteWord(WordToLE(round(font.Size*20)));
|
||||
@@ -1561,8 +1718,8 @@ begin
|
||||
WriteFont(AStream, i);
|
||||
end;
|
||||
|
||||
procedure TsSpreadBiff2Writer.WriteFormat(AStream: TStream;
|
||||
AFormatData: TsNumFormatData; AListIndex: Integer);
|
||||
procedure TsSpreadBiff2Writer.WriteNumFormat(AStream: TStream;
|
||||
ANumFormatData: TsNumFormatData; AListIndex: Integer);
|
||||
type
|
||||
TNumFormatRecord = packed record
|
||||
RecordID: Word;
|
||||
@@ -1575,7 +1732,7 @@ var
|
||||
rec: TNumFormatRecord;
|
||||
buf: array of byte;
|
||||
begin
|
||||
Unused(AFormatData);
|
||||
Unused(ANumFormatData);
|
||||
|
||||
s := NumFormatList.FormatStringForWriting(AListIndex);
|
||||
len := Length(s);
|
||||
@@ -1748,7 +1905,7 @@ end;
|
||||
procedure TsSpreadBIFF2Writer.WriteBool(AStream: TStream;
|
||||
const ARow, ACol: Cardinal; const AValue: Boolean; ACell: PCell);
|
||||
var
|
||||
rec: TBIFF2BoolErrRecord;
|
||||
rec: TBIFF2_BoolErrRecord;
|
||||
xf: Integer;
|
||||
begin
|
||||
if (ARow >= FLimitations.MaxRowCount) or (ACol >= FLimitations.MaxColCount) then
|
||||
@@ -1781,7 +1938,7 @@ end;
|
||||
procedure TsSpreadBIFF2Writer.WriteError(AStream: TStream;
|
||||
const ARow, ACol: Cardinal; const AValue: TsErrorValue; ACell: PCell);
|
||||
var
|
||||
rec: TBIFF2BoolErrRecord;
|
||||
rec: TBIFF2_BoolErrRecord;
|
||||
xf: Integer;
|
||||
begin
|
||||
if (ARow >= FLimitations.MaxRowCount) or (ACol >= FLimitations.MaxColCount) then
|
||||
@@ -1874,7 +2031,7 @@ const
|
||||
var
|
||||
L: Byte;
|
||||
AnsiText: ansistring;
|
||||
rec: TBIFF2LabelRecord;
|
||||
rec: TBIFF2_LabelRecord;
|
||||
buf: array of byte;
|
||||
var
|
||||
xf: Word;
|
||||
@@ -1937,7 +2094,7 @@ procedure TsSpreadBIFF2Writer.WriteNumber(AStream: TStream; const ARow,
|
||||
ACol: Cardinal; const AValue: double; ACell: PCell);
|
||||
var
|
||||
xf: Word;
|
||||
rec: TBIFF2NumberRecord;
|
||||
rec: TBIFF2_NumberRecord;
|
||||
begin
|
||||
if (ARow >= FLimitations.MaxRowCount) or (ACol >= FLimitations.MaxColCount) then
|
||||
exit;
|
||||
|
@@ -115,21 +115,24 @@ type
|
||||
procedure WriteEOF(AStream: TStream);
|
||||
procedure WriteFont(AStream: TStream; AFont: TsFont);
|
||||
procedure WriteFonts(AStream: TStream);
|
||||
procedure WriteFormat(AStream: TStream; AFormatData: TsNumFormatData;
|
||||
AListIndex: Integer); override;
|
||||
procedure WriteIndex(AStream: TStream);
|
||||
procedure WriteLabel(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
const AValue: string; ACell: PCell); override;
|
||||
procedure WriteNumFormat(AStream: TStream; ANumFormatData: TsNumFormatData;
|
||||
AListIndex: Integer); override;
|
||||
procedure WriteStringRecord(AStream: TStream; AString: String); override;
|
||||
procedure WriteStyle(AStream: TStream);
|
||||
procedure WriteWindow2(AStream: TStream; ASheet: TsWorksheet);
|
||||
{
|
||||
procedure WriteXF(AStream: TStream; AFontIndex: Word;
|
||||
AFormatIndex: Word; AXF_TYPE_PROT, ATextRotation: Byte; ABorders: TsCellBorders;
|
||||
const ABorderStyles: TsCellBorderStyles; AHorAlignment: TsHorAlignment = haDefault;
|
||||
AVertAlignment: TsVertAlignment = vaDefault; AWordWrap: Boolean = false;
|
||||
AddBackground: Boolean = false; ABackgroundColor: TsColor = scSilver);
|
||||
procedure WriteXFFieldsForFormattingStyles(AStream: TStream);
|
||||
procedure WriteXFRecords(AStream: TStream);
|
||||
}
|
||||
procedure WriteXF(AStream: TStream; AFormatRecord: PsCellFormat;
|
||||
XFType_Prot: Byte = 0); override;
|
||||
public
|
||||
{ General writing methods }
|
||||
procedure WriteToFile(const AFileName: string;
|
||||
@@ -274,6 +277,7 @@ const
|
||||
{ XF substructures }
|
||||
|
||||
{ XF substructures --- see xlscommon! }
|
||||
MASK_XF_ORIENTATION = $03;
|
||||
XF_ROTATION_HORIZONTAL = 0;
|
||||
XF_ROTATION_STACKED = 1;
|
||||
XF_ROTATION_90DEG_CCW = 2;
|
||||
@@ -304,7 +308,7 @@ const
|
||||
);
|
||||
|
||||
type
|
||||
TBIFF5DimensionsRecord = packed record
|
||||
TBIFF5_DimensionsRecord = packed record
|
||||
RecordID: Word;
|
||||
RecordSize: Word;
|
||||
FirstRow: Word;
|
||||
@@ -314,7 +318,7 @@ type
|
||||
NotUsed: Word;
|
||||
end;
|
||||
|
||||
TBIFF5LabelRecord = packed record
|
||||
TBIFF5_LabelRecord = packed record
|
||||
RecordID: Word;
|
||||
RecordSize: Word;
|
||||
Row: Word;
|
||||
@@ -323,6 +327,18 @@ type
|
||||
TextLen: Word;
|
||||
end;
|
||||
|
||||
TBIFF5_XFRecord = packed record
|
||||
RecordID: Word;
|
||||
RecordSize: Word;
|
||||
FontIndex: Word;
|
||||
NumFormatIndex: Word;
|
||||
XFType_Prot_ParentXF: Word;
|
||||
Align_TextBreak: Byte;
|
||||
TextOrient_UnusedAttrib: Byte;
|
||||
Border_BkGr1: DWord;
|
||||
Border_BkGr2: DWord;
|
||||
end;
|
||||
|
||||
|
||||
{ TsSpreadBIFF5Writer }
|
||||
|
||||
@@ -393,7 +409,7 @@ begin
|
||||
WriteCodepage(AStream, WorkBookEncoding);
|
||||
WriteWindow1(AStream);
|
||||
WriteFonts(AStream);
|
||||
WriteFormats(AStream);
|
||||
WriteNumFormats(AStream);
|
||||
WritePalette(AStream);
|
||||
WriteXFRecords(AStream);
|
||||
WriteStyle(AStream);
|
||||
@@ -530,7 +546,7 @@ end;
|
||||
}
|
||||
procedure TsSpreadBIFF5Writer.WriteDimensions(AStream: TStream; AWorksheet: TsWorksheet);
|
||||
var
|
||||
rec: TBIFF5DimensionsRecord;
|
||||
rec: TBIFF5_DimensionsRecord;
|
||||
firstCol, lastCol, firstRow, lastRow: Cardinal;
|
||||
begin
|
||||
{ Determine sheet size }
|
||||
@@ -658,8 +674,8 @@ end;
|
||||
* DESCRIPTION: Writes an Excel 5 FORMAT record
|
||||
*
|
||||
*******************************************************************}
|
||||
procedure TsSpreadBiff5Writer.WriteFormat(AStream: TStream;
|
||||
AFormatData: TsNumFormatData; AListIndex: Integer);
|
||||
procedure TsSpreadBiff5Writer.WriteNumFormat(AStream: TStream;
|
||||
ANumFormatData: TsNumFormatData; AListIndex: Integer);
|
||||
type
|
||||
TNumFormatRecord = packed record
|
||||
RecordID: Word;
|
||||
@@ -673,7 +689,7 @@ var
|
||||
rec: TNumFormatRecord;
|
||||
buf: array of byte;
|
||||
begin
|
||||
if (AFormatData = nil) or (AFormatData.FormatString = '') then
|
||||
if (ANumFormatData = nil) or (ANumFormatData.FormatString = '') then
|
||||
exit;
|
||||
|
||||
s := UTF8ToAnsi(NumFormatList.FormatStringForWriting(AListIndex));
|
||||
@@ -684,7 +700,7 @@ begin
|
||||
rec.RecordSize := WordToLE(2 + 1 + len * SizeOf(AnsiChar));
|
||||
|
||||
{ Format index }
|
||||
rec.FormatIndex := WordToLE(AFormatData.Index);
|
||||
rec.FormatIndex := WordToLE(ANumFormatData.Index);
|
||||
|
||||
{ Format string }
|
||||
{ Length in 1 byte }
|
||||
@@ -751,7 +767,7 @@ const
|
||||
var
|
||||
L: Word;
|
||||
AnsiValue: ansistring;
|
||||
rec: TBIFF5LabelRecord;
|
||||
rec: TBIFF5_LabelRecord;
|
||||
buf: array of byte;
|
||||
begin
|
||||
if (ARow >= FLimitations.MaxRowCount) or (ACol >= FLimitations.MaxColCount) then
|
||||
@@ -905,7 +921,7 @@ begin
|
||||
{ Grid line RGB colour }
|
||||
AStream.WriteDWord(DWordToLE(0));
|
||||
end;
|
||||
|
||||
(*
|
||||
{*******************************************************************
|
||||
* TsSpreadBIFF5Writer.WriteXF ()
|
||||
*
|
||||
@@ -981,8 +997,114 @@ begin
|
||||
if cbEast in ABorders then dw2 := dw2 or ((DWord(ABorderStyles[cbEast].LineStyle)+1) shl 6);
|
||||
AStream.WriteDWord(DWordToLE(dw1));
|
||||
AStream.WriteDWord(DWordToLE(dw2));
|
||||
end;
|
||||
end; *)
|
||||
|
||||
procedure TsSpreadBIFF5Writer.WriteXF(AStream: TStream;
|
||||
AFormatRecord: PsCellFormat; XFType_Prot: Byte = 0);
|
||||
var
|
||||
rec: TBIFF5_XFRecord;
|
||||
j: Integer;
|
||||
b: Byte;
|
||||
dw1, dw2: DWord;
|
||||
begin
|
||||
{ BIFF record header }
|
||||
rec.RecordID := WordToLE(INT_EXCEL_ID_XF);
|
||||
rec.RecordSize := WordToLE(SizeOf(TBIFF5_XFRecord) - 2*SizeOf(Word));
|
||||
|
||||
{ Index to font record }
|
||||
rec.FontIndex := 0;
|
||||
if (AFormatRecord <> nil) then begin
|
||||
if (uffBold in AFormatRecord^.UsedFormattingFields) then
|
||||
rec.FontIndex := 1
|
||||
else
|
||||
if (uffFont in AFormatRecord^.UsedFormattingFields) then
|
||||
rec.FontIndex := AFormatRecord^.FontIndex;
|
||||
end;
|
||||
rec.FontIndex := WordToLE(rec.FontIndex);
|
||||
|
||||
{ Index to number format }
|
||||
rec.NumFormatIndex := 0;
|
||||
if (AFormatRecord <> nil) and (uffNumberFormat in AFormatRecord^.UsedFormattingFields)
|
||||
then begin
|
||||
// The number formats in the FormatList are still in fpc dialect
|
||||
// They will be converted to Excel syntax immediately before writing.
|
||||
j := NumFormatList.Find(AFormatRecord^.NumberFormat, AFormatRecord^.NumberFormatStr);
|
||||
if j > -1 then
|
||||
rec.NumFormatIndex := NumFormatList[j].Index;
|
||||
end;
|
||||
rec.NumFormatIndex := WordToLE(rec.NumFormatIndex);
|
||||
|
||||
{ XF type, cell protection and parent style XF }
|
||||
rec.XFType_Prot_ParentXF := XFType_Prot and MASK_XF_TYPE_PROT;
|
||||
if XFType_Prot and MASK_XF_TYPE_PROT_STYLE_XF <> 0 then
|
||||
rec.XFType_Prot_ParentXF := rec.XFType_Prot_ParentXF or MASK_XF_TYPE_PROT_PARENT;
|
||||
|
||||
{ Text alignment and text break }
|
||||
if AFormatRecord = nil then
|
||||
b := MASK_XF_VERT_ALIGN_BOTTOM
|
||||
else
|
||||
begin
|
||||
b := 0;
|
||||
if (uffHorAlign in AFormatRecord^.UsedFormattingFields) then
|
||||
case AFormatRecord^.HorAlignment of
|
||||
haLeft : b := b or MASK_XF_HOR_ALIGN_LEFT;
|
||||
haCenter : b := b or MASK_XF_HOR_ALIGN_CENTER;
|
||||
haRight : b := b or MASK_XF_HOR_ALIGN_RIGHT;
|
||||
haDefault: ;
|
||||
end;
|
||||
// Since the default vertical alignment is vaDefault but "0" corresponds
|
||||
// to vaTop, we alwys have to write the vertical alignment.
|
||||
case AFormatRecord^.VertAlignment of
|
||||
vaTop : b := b or MASK_XF_VERT_ALIGN_TOP;
|
||||
vaCenter : b := b or MASK_XF_VERT_ALIGN_CENTER;
|
||||
vaBottom : b := b or MASK_XF_VERT_ALIGN_BOTTOM;
|
||||
else b := b or MASK_XF_VERT_ALIGN_BOTTOM;
|
||||
end;
|
||||
if (uffWordWrap in AFormatRecord^.UsedFormattingFields) then
|
||||
b := b or MASK_XF_TEXTWRAP;
|
||||
end;
|
||||
rec.Align_TextBreak := b;
|
||||
|
||||
{ Text rotation }
|
||||
rec.TextOrient_UnusedAttrib := 0;
|
||||
if (AFormatRecord <> nil) and (uffTextRotation in AFormatRecord^.UsedFormattingFields)
|
||||
then rec.TextOrient_UnusedAttrib := TEXT_ROTATIONS[AFormatRecord^.TextRotation];
|
||||
|
||||
{ Cell border lines and background area }
|
||||
dw1 := 0;
|
||||
dw2 := 0;
|
||||
if (AFormatRecord <> nil) then
|
||||
begin
|
||||
if (uffBackgroundColor in AFormatRecord^.UsedFormattingFields) then
|
||||
begin
|
||||
// Background color
|
||||
dw1 := dw1 or (FixColor(AFormatRecord^.BackgroundColor) and $0000007F);
|
||||
dw1 := dw1 or (MASK_XF_FILL_PATT_SOLID shl 16);
|
||||
end;
|
||||
// Border lines
|
||||
if (uffBorder in AFormatRecord^.UsedFormattingFields) then
|
||||
begin
|
||||
dw1 := dw1 or (AFormatRecord^.BorderStyles[cbSouth].Color shl 25); // Bottom line color
|
||||
dw2 := (FixColor(AFormatRecord^.BorderStyles[cbNorth].Color) shl 9) or // Top line color
|
||||
(FixColor(AFormatRecord^.BorderStyles[cbWest].Color) shl 16) or // Left line color
|
||||
(FixColor(AFormatRecord^.BorderStyles[cbEast].Color) shl 23); // Right line color
|
||||
if cbSouth in AFormatRecord^.Border then
|
||||
dw1 := dw1 or ((DWord(AFormatRecord^.BorderStyles[cbSouth].LineStyle)+1) shl 22);
|
||||
if cbNorth in AFormatRecord^.Border then
|
||||
dw2 := dw2 or (DWord(AFormatRecord^.BorderStyles[cbNorth].LineStyle)+1);
|
||||
if cbWest in AFormatRecord^.Border then
|
||||
dw2 := dw2 or ((DWord(AFormatRecord^.BorderStyles[cbWest].LineStyle)+1) shl 3);
|
||||
if cbEast in AFormatRecord^.Border then
|
||||
dw2 := dw2 or ((DWord(AFormatRecord^.BorderStyles[cbEast].LineStyle)+1) shl 6);
|
||||
end;
|
||||
end;
|
||||
rec.Border_BkGr1 := dw1;
|
||||
rec.Border_BkGr2 := dw2;
|
||||
|
||||
{ Write out }
|
||||
AStream.WriteBuffer(rec, SizeOf(rec));
|
||||
end;
|
||||
(*
|
||||
procedure TsSpreadBIFF5Writer.WriteXFFieldsForFormattingStyles(AStream: TStream);
|
||||
var
|
||||
i, j: Integer;
|
||||
@@ -1040,7 +1162,52 @@ begin
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFF5Writer.WriteXFRecords(AStream: TStream);
|
||||
var
|
||||
i: Integer;
|
||||
fmt: TsCellFormat;
|
||||
begin
|
||||
// XF0
|
||||
WriteXFRecord(AStream, MASK_XF_TYPE_PROT_STYLE_XF, nil);
|
||||
// XF1
|
||||
WriteXFRecord(AStream, MASK_XF_TYPE_PROT_STYLE_XF, nil);
|
||||
// XF2
|
||||
WriteXFRecord(AStream, MASK_XF_TYPE_PROT_STYLE_XF, nil);
|
||||
// XF3
|
||||
WriteXFRecord(AStream, MASK_XF_TYPE_PROT_STYLE_XF, nil);
|
||||
// XF4
|
||||
WriteXFRecord(AStream, MASK_XF_TYPE_PROT_STYLE_XF, nil);
|
||||
// XF5
|
||||
WriteXFRecord(AStream, MASK_XF_TYPE_PROT_STYLE_XF, nil);
|
||||
// XF6
|
||||
WriteXFRecord(AStream, MASK_XF_TYPE_PROT_STYLE_XF, nil);
|
||||
// XF7
|
||||
WriteXFRecord(AStream, MASK_XF_TYPE_PROT_STYLE_XF, nil);
|
||||
// XF8
|
||||
WriteXFRecord(AStream, MASK_XF_TYPE_PROT_STYLE_XF, nil);
|
||||
// XF9
|
||||
WriteXFRecord(AStream, MASK_XF_TYPE_PROT_STYLE_XF, nil);
|
||||
// XF10
|
||||
WriteXFRecord(AStream, MASK_XF_TYPE_PROT_STYLE_XF, nil);
|
||||
// XF11
|
||||
WriteXFRecord(AStream, MASK_XF_TYPE_PROT_STYLE_XF, nil);
|
||||
// XF12
|
||||
WriteXFRecord(AStream, MASK_XF_TYPE_PROT_STYLE_XF, nil);
|
||||
// XF13
|
||||
WriteXFRecord(AStream, MASK_XF_TYPE_PROT_STYLE_XF, nil);
|
||||
// XF14
|
||||
WriteXFRecord(AStream, MASK_XF_TYPE_PROT_STYLE_XF, nil);
|
||||
|
||||
// XF15 - Default, no formatting
|
||||
WriteXFRecord(AStream, 0, nil);
|
||||
|
||||
// Add all further non-standard format records
|
||||
// The first style was already added --> begin loop with 1
|
||||
for i:=1 to FWorkbook.GetNumFormatRecords-1 do begin
|
||||
fmt := FWorkbook.GetFormatRecord(i);
|
||||
WriteXFRecord(AStream, 0, @fmt);
|
||||
end;
|
||||
|
||||
{
|
||||
// XF0
|
||||
WriteXF(AStream, 0, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, [], DEFAULT_BORDERSTYLES);
|
||||
// XF1
|
||||
@@ -1077,8 +1244,9 @@ begin
|
||||
// Add all further non-standard/built-in formatting styles
|
||||
ListAllFormattingStyles;
|
||||
WriteXFFieldsForFormattingStyles(AStream);
|
||||
}
|
||||
end;
|
||||
|
||||
*)
|
||||
|
||||
{ TsSpreadBIFF5Reader }
|
||||
|
||||
@@ -1340,6 +1508,7 @@ begin
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFF5Reader.ReadXF(AStream: TStream);
|
||||
{
|
||||
type
|
||||
TXFRecord = packed record // see p. 224
|
||||
FontIndex: Word; // Offset 0, Size 2
|
||||
@@ -1349,109 +1518,136 @@ type
|
||||
XFRotation: Byte; // Offset 7, Size 1
|
||||
Border_Background_1: DWord; // Offset 8, Size 4
|
||||
Border_Background_2: DWord; // Offset 12, Size 4
|
||||
end;
|
||||
end; }
|
||||
var
|
||||
lData: TXFListData;
|
||||
xf: TXFRecord;
|
||||
rec: TBIFF5_XFRecord;
|
||||
fmt: TsCellFormat;
|
||||
nfidx: Integer;
|
||||
i: Integer;
|
||||
nfdata: TsNumFormatData;
|
||||
//lData: TXFListData;
|
||||
//xf: TXFRecord;
|
||||
b: Byte;
|
||||
dw: DWord;
|
||||
fill: Word;
|
||||
begin
|
||||
xf.FontIndex := 0; // to silence the compiler...
|
||||
InitFormatRecord(fmt);
|
||||
fmt.ID := FCellFormatList.Count;
|
||||
|
||||
// Read the complete xf record into a buffer
|
||||
AStream.ReadBuffer(xf, SizeOf(xf));
|
||||
|
||||
lData := TXFListData.Create;
|
||||
rec.FontIndex := 0; // to silence the compiler...
|
||||
AStream.ReadBuffer(rec.FontIndex, SizeOf(rec) - 2*SizeOf(Word));
|
||||
|
||||
// Font index
|
||||
lData.FontIndex := WordLEToN(xf.FontIndex);
|
||||
fmt.FontIndex := WordLEToN(rec.FontIndex);
|
||||
if fmt.FontIndex = 1 then
|
||||
Include(fmt.UsedFormattingFields, uffBold)
|
||||
else if fmt.FontIndex > 1 then
|
||||
Include(fmt.UsedFormattingFields, uffFont);
|
||||
|
||||
// Format index
|
||||
lData.FormatIndex := WordLEToN(xf.FormatIndex);
|
||||
// Number format index
|
||||
nfidx := WordLEToN(rec.NumFormatIndex);
|
||||
i := NumFormatList.FindByIndex(nfidx);
|
||||
if i > -1 then begin
|
||||
nfdata := NumFormatList.Items[i];
|
||||
fmt.NumberFormat := nfdata.NumFormat;
|
||||
fmt.NumberFormatStr := nfdata.FormatString;
|
||||
if nfdata.NumFormat <> nfGeneral then
|
||||
Include(fmt.UsedFormattingFields, uffNumberFormat);
|
||||
end;
|
||||
|
||||
// Horizontal text alignment
|
||||
b := xf.Align_TextBreak AND MASK_XF_HOR_ALIGN;
|
||||
b := rec.Align_TextBreak AND MASK_XF_HOR_ALIGN;
|
||||
if (b <= ord(High(TsHorAlignment))) then
|
||||
lData.HorAlignment := TsHorAlignment(b)
|
||||
else
|
||||
lData.HorAlignment := haDefault;
|
||||
begin
|
||||
fmt.HorAlignment := TsHorAlignment(b);
|
||||
if fmt.HorAlignment <> haDefault then
|
||||
Include(fmt.UsedFormattingFields, uffHorAlign);
|
||||
end;
|
||||
|
||||
// Vertical text alignment
|
||||
b := (xf.Align_TextBreak AND MASK_XF_VERT_ALIGN) shr 4;
|
||||
b := (rec.Align_TextBreak AND MASK_XF_VERT_ALIGN) shr 4;
|
||||
if (b + 1 <= ord(high(TsVertAlignment))) then
|
||||
begin
|
||||
lData.VertAlignment := tsVertAlignment(b + 1); // + 1 due to vaDefault
|
||||
fmt.VertAlignment := TsVertAlignment(b + 1); // + 1 due to vaDefault
|
||||
// Unfortunately BIFF does not provide a "default" vertical alignment code.
|
||||
// Without the following correction "non-formatted" cells would always have
|
||||
// the uffVertAlign FormattingField set which contradicts the statement of
|
||||
// not being formatted.
|
||||
if lData.VertAlignment = vaBottom then
|
||||
lData.VertAlignment := vaDefault;
|
||||
end
|
||||
else
|
||||
lData.VertAlignment := vaDefault;
|
||||
|
||||
// Word wrap
|
||||
lData.WordWrap := (xf.Align_TextBreak and MASK_XF_TEXTWRAP) <> 0;
|
||||
|
||||
// Text rotation
|
||||
case xf.XFRotation of
|
||||
XF_ROTATION_HORIZONTAL : lData.TextRotation := trHorizontal;
|
||||
XF_ROTATION_90DEG_CCW : lData.TextRotation := rt90DegreeCounterClockwiseRotation;
|
||||
XF_ROTATION_90DEG_CW : lData.TextRotation := rt90DegreeClockwiseRotation;
|
||||
XF_ROTATION_STACKED : lData.TextRotation := rtStacked;
|
||||
if fmt.VertAlignment = vaBottom then
|
||||
fmt.VertAlignment := vaDefault;
|
||||
if fmt.VertAlignment <> vaDefault then
|
||||
Include(fmt.UsedFormattingFields, uffVertAlign);
|
||||
end;
|
||||
|
||||
// Word wrap
|
||||
if (rec.Align_TextBreak and MASK_XF_TEXTWRAP) <> 0 then
|
||||
Include(fmt.UsedFormattingFields, uffWordwrap);
|
||||
|
||||
// Text rotation
|
||||
case rec.TextOrient_UnusedAttrib and MASK_XF_ORIENTATION of
|
||||
XF_ROTATION_HORIZONTAL : fmt.TextRotation := trHorizontal;
|
||||
XF_ROTATION_90DEG_CCW : fmt.TextRotation := rt90DegreeCounterClockwiseRotation;
|
||||
XF_ROTATION_90DEG_CW : fmt.TextRotation := rt90DegreeClockwiseRotation;
|
||||
XF_ROTATION_STACKED : fmt.TextRotation := rtStacked;
|
||||
end;
|
||||
if fmt.TextRotation <> trHorizontal then
|
||||
Include(fmt.UsedFormattingFields, uffTextRotation);
|
||||
|
||||
// Cell borders and background
|
||||
xf.Border_Background_1 := DWordLEToN(xf.Border_Background_1);
|
||||
xf.Border_Background_2 := DWordLEToN(xf.Border_Background_2);
|
||||
lData.Borders := [];
|
||||
rec.Border_BkGr1 := DWordLEToN(rec.Border_BkGr1);
|
||||
rec.Border_BkGr2 := DWordLEToN(rec.Border_BkGr2);
|
||||
// The 4 masked bits encode the line style of the border line. 0 = no line.
|
||||
// The case of "no line" is not included in the TsLineStyle enumeration.
|
||||
// --> correct by subtracting 1!
|
||||
dw := xf.Border_Background_1 and MASK_XF_BORDER_BOTTOM;
|
||||
dw := rec.Border_BkGr1 and MASK_XF_BORDER_BOTTOM;
|
||||
if dw <> 0 then
|
||||
begin
|
||||
Include(lData.Borders, cbSouth);
|
||||
lData.BorderStyles[cbSouth].LineStyle := TsLineStyle(dw shr 22 - 1);
|
||||
Include(fmt.Border, cbSouth);
|
||||
fmt.BorderStyles[cbSouth].LineStyle := TsLineStyle(dw shr 22 - 1);
|
||||
Include(fmt.UsedFormattingFields, uffBorder);
|
||||
end;
|
||||
dw := xf.Border_Background_2 and MASK_XF_BORDER_LEFT;
|
||||
dw := rec.Border_BkGr2 and MASK_XF_BORDER_LEFT;
|
||||
if dw <> 0 then
|
||||
begin
|
||||
Include(lData.Borders, cbWest);
|
||||
lData.BorderStyles[cbWest].LineStyle := TsLineStyle(dw shr 3 - 1);
|
||||
Include(fmt.Border, cbWest);
|
||||
fmt.BorderStyles[cbWest].LineStyle := TsLineStyle(dw shr 3 - 1);
|
||||
Include(fmt.UsedFormattingFields, uffBorder);
|
||||
end;
|
||||
dw := xf.Border_Background_2 and MASK_XF_BORDER_RIGHT;
|
||||
dw := rec.Border_BkGr2 and MASK_XF_BORDER_RIGHT;
|
||||
if dw <> 0 then
|
||||
begin
|
||||
Include(lData.Borders, cbEast);
|
||||
lData.BorderStyles[cbEast].LineStyle := TsLineStyle(dw shr 6 - 1);
|
||||
Include(fmt.Border, cbEast);
|
||||
fmt.BorderStyles[cbEast].LineStyle := TsLineStyle(dw shr 6 - 1);
|
||||
Include(fmt.UsedFormattingFields, uffBorder);
|
||||
end;
|
||||
dw := xf.Border_Background_2 and MASK_XF_BORDER_TOP;
|
||||
dw := rec.Border_BkGr2 and MASK_XF_BORDER_TOP;
|
||||
if dw <> 0 then
|
||||
begin
|
||||
Include(lData.Borders, cbNorth);
|
||||
lData.BorderStyles[cbNorth].LineStyle := TsLineStyle(dw - 1);
|
||||
Include(fmt.Border, cbNorth);
|
||||
fmt.BorderStyles[cbNorth].LineStyle := TsLineStyle(dw - 1);
|
||||
Include(fmt.UsedFormattingFields, uffBorder);
|
||||
end;
|
||||
|
||||
// Border line colors
|
||||
lData.BorderStyles[cbWest].Color := (xf.Border_Background_2 and MASK_XF_BORDER_LEFT_COLOR) shr 16;
|
||||
lData.BorderStyles[cbEast].Color := (xf.Border_Background_2 and MASK_XF_BORDER_RIGHT_COLOR) shr 23;
|
||||
lData.BorderStyles[cbNorth].Color := (xf.Border_Background_2 and MASK_XF_BORDER_TOP_COLOR) shr 9;
|
||||
lData.BorderStyles[cbSouth].Color := (xf.Border_Background_1 and MASK_XF_BORDER_BOTTOM_COLOR) shr 25;
|
||||
fmt.BorderStyles[cbWest].Color := (rec.Border_BkGr2 and MASK_XF_BORDER_LEFT_COLOR) shr 16;
|
||||
fmt.BorderStyles[cbEast].Color := (rec.Border_BkGr2 and MASK_XF_BORDER_RIGHT_COLOR) shr 23;
|
||||
fmt.BorderStyles[cbNorth].Color := (rec.Border_BkGr2 and MASK_XF_BORDER_TOP_COLOR) shr 9;
|
||||
fmt.BorderStyles[cbSouth].Color := (rec.Border_BkGr1 and MASK_XF_BORDER_BOTTOM_COLOR) shr 25;
|
||||
|
||||
// Background fill style
|
||||
fill := (xf.Border_Background_1 and MASK_XF_BKGR_FILLPATTERN) shr 16;
|
||||
fill := (rec.Border_BkGr1 and MASK_XF_BKGR_FILLPATTERN) shr 16;
|
||||
|
||||
// Background color
|
||||
if fill = 0 then
|
||||
lData.BackgroundColor := scTransparent
|
||||
else
|
||||
lData.BackgroundColor := xf.Border_Background_1 and MASK_XF_BKGR_PATTERN_COLOR;
|
||||
fmt.BackgroundColor := scTransparent
|
||||
else begin
|
||||
fmt.BackgroundColor := rec.Border_BkGr1 and MASK_XF_BKGR_PATTERN_COLOR;
|
||||
Include(fmt.UsedFormattingFields, uffBackgroundColor);
|
||||
end;
|
||||
|
||||
// Add the XF to the list
|
||||
FXFList.Add(lData);
|
||||
FCellFormatList.Add(fmt);
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFF5Reader.ReadFromStream(AStream: TStream; AData: TsWorkbook);
|
||||
@@ -1582,7 +1778,7 @@ end;
|
||||
|
||||
procedure TsSpreadBIFF5Reader.ReadLabel(AStream: TStream);
|
||||
var
|
||||
rec: TBIFF5LabelRecord;
|
||||
rec: TBIFF5_LabelRecord;
|
||||
L: Word;
|
||||
ARow, ACol: Cardinal;
|
||||
XF: WORD;
|
||||
@@ -1592,7 +1788,7 @@ begin
|
||||
rec.Row := 0; // to silence the compiler...
|
||||
|
||||
{ Read entire record, starting at Row, except for string data }
|
||||
AStream.ReadBuffer(rec.Row, SizeOf(TBIFF5LabelRecord) - 2*SizeOf(Word));
|
||||
AStream.ReadBuffer(rec.Row, SizeOf(TBIFF5_LabelRecord) - 2*SizeOf(Word));
|
||||
ARow := WordLEToN(rec.Row);
|
||||
ACol := WordLEToN(rec.Col);
|
||||
XF := WordLEToN(rec.XFIndex);
|
||||
|
@@ -111,7 +111,7 @@ type
|
||||
TsSpreadBIFF8Writer = class(TsSpreadBIFFWriter)
|
||||
private
|
||||
// Writes index to XF record according to cell's formatting
|
||||
procedure WriteXFFieldsForFormattingStyles(AStream: TStream);
|
||||
//procedure WriteXFFieldsForFormattingStyles(AStream: TStream);
|
||||
protected
|
||||
{ Record writing methods }
|
||||
procedure WriteBOF(AStream: TStream; ADataType: Word);
|
||||
@@ -120,12 +120,12 @@ type
|
||||
procedure WriteEOF(AStream: TStream);
|
||||
procedure WriteFont(AStream: TStream; AFont: TsFont);
|
||||
procedure WriteFonts(AStream: TStream);
|
||||
procedure WriteFormat(AStream: TStream; AFormatData: TsNumFormatData;
|
||||
AListIndex: Integer); override;
|
||||
procedure WriteIndex(AStream: TStream);
|
||||
procedure WriteLabel(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
const AValue: string; ACell: PCell); override;
|
||||
procedure WriteMergedCells(AStream: TStream; AWorksheet: TsWorksheet);
|
||||
procedure WriteNumFormat(AStream: TStream; AFormatData: TsNumFormatData;
|
||||
AListIndex: Integer); override;
|
||||
function WriteRPNCellAddress(AStream: TStream; ARow, ACol: Cardinal;
|
||||
AFlags: TsRelFlags): word; override;
|
||||
function WriteRPNCellOffset(AStream: TStream; ARowOffset, AColOffset: Integer;
|
||||
@@ -136,12 +136,15 @@ type
|
||||
procedure WriteStringRecord(AStream: TStream; AString: string); override;
|
||||
procedure WriteStyle(AStream: TStream);
|
||||
procedure WriteWindow2(AStream: TStream; ASheet: TsWorksheet);
|
||||
(*
|
||||
procedure WriteXF(AStream: TStream; AFontIndex: Word;
|
||||
AFormatIndex: Word; AXF_TYPE_PROT, ATextRotation: Byte; ABorders: TsCellBorders;
|
||||
const ABorderStyles: TsCellBorderStyles; AHorAlignment: TsHorAlignment = haDefault;
|
||||
AVertAlignment: TsVertAlignment = vaDefault; AWordWrap: Boolean = false;
|
||||
AddBackground: Boolean = false; ABackgroundColor: TsColor = scSilver);
|
||||
procedure WriteXFRecords(AStream: TStream);
|
||||
*)
|
||||
procedure WriteXF(AStream: TStream; AFormatRecord: PsCellFormat;
|
||||
XFType_Prot: Byte = 0); override;
|
||||
public
|
||||
constructor Create(AWorkbook: TsWorkbook); override;
|
||||
{ General writing methods }
|
||||
@@ -290,7 +293,7 @@ const
|
||||
);
|
||||
|
||||
type
|
||||
TBIFF8DimensionsRecord = packed record
|
||||
TBIFF8_DimensionsRecord = packed record
|
||||
RecordID: Word;
|
||||
RecordSize: Word;
|
||||
FirstRow: DWord;
|
||||
@@ -300,7 +303,7 @@ type
|
||||
NotUsed: Word;
|
||||
end;
|
||||
|
||||
TBIFF8LabelRecord = packed record
|
||||
TBIFF8_LabelRecord = packed record
|
||||
RecordID: Word;
|
||||
RecordSize: Word;
|
||||
Row: Word;
|
||||
@@ -310,7 +313,7 @@ type
|
||||
TextFlags: Byte;
|
||||
end;
|
||||
|
||||
TBIFF8LabelSSTRecord = packed record
|
||||
TBIFF8_LabelSSTRecord = packed record
|
||||
RecordID: Word;
|
||||
RecordSize: Word;
|
||||
Row: Word;
|
||||
@@ -319,6 +322,21 @@ type
|
||||
SSTIndex: DWord;
|
||||
end;
|
||||
|
||||
TBIFF8_XFRecord = packed record
|
||||
RecordID: Word;
|
||||
RecordSize: Word;
|
||||
FontIndex: Word;
|
||||
NumFormatIndex: Word;
|
||||
XFType_Prot_ParentXF: Word;
|
||||
Align_TextBreak: Byte;
|
||||
TextRotation: Byte;
|
||||
Indent_Shrink_TextDir: Byte;
|
||||
UsedAttrib: Byte;
|
||||
Border_BkGr1: DWord;
|
||||
Border_BkGr2: DWord;
|
||||
BkGr3: Word;
|
||||
end;
|
||||
|
||||
|
||||
{ TsSpreadBIFF8Writer }
|
||||
|
||||
@@ -326,7 +344,7 @@ constructor TsSpreadBIFF8Writer.Create(AWorkbook: TsWorkbook);
|
||||
begin
|
||||
inherited Create(AWorkbook);
|
||||
end;
|
||||
|
||||
(*
|
||||
procedure TsSpreadBIFF8Writer.WriteXFFieldsForFormattingStyles(AStream: TStream);
|
||||
var
|
||||
i, j: Integer;
|
||||
@@ -383,7 +401,7 @@ begin
|
||||
lBackgroundColor);
|
||||
end;
|
||||
end;
|
||||
|
||||
*)
|
||||
{*******************************************************************
|
||||
* TsSpreadBIFF8Writer.WriteToFile ()
|
||||
*
|
||||
@@ -449,7 +467,7 @@ begin
|
||||
|
||||
WriteWindow1(AStream);
|
||||
WriteFonts(AStream);
|
||||
WriteFormats(AStream);
|
||||
WriteNumFormats(AStream);
|
||||
WritePalette(AStream);
|
||||
WriteXFRecords(AStream);
|
||||
WriteStyle(AStream);
|
||||
@@ -601,7 +619,7 @@ end;
|
||||
procedure TsSpreadBIFF8Writer.WriteDimensions(AStream: TStream; AWorksheet: TsWorksheet);
|
||||
var
|
||||
firstRow, lastRow, firstCol, lastCol: Cardinal;
|
||||
rec: TBIFF8DimensionsRecord;
|
||||
rec: TBIFF8_DimensionsRecord;
|
||||
begin
|
||||
{ Determine sheet size }
|
||||
GetSheetDimensions(AWorksheet, firstRow, lastRow, firstCol, lastCol);
|
||||
@@ -724,7 +742,7 @@ begin
|
||||
WriteFont(AStream, Workbook.GetFont(i));
|
||||
end;
|
||||
|
||||
procedure TsSpreadBiff8Writer.WriteFormat(AStream: TStream;
|
||||
procedure TsSpreadBiff8Writer.WriteNumFormat(AStream: TStream;
|
||||
AFormatData: TsNumFormatData; AListIndex: Integer);
|
||||
type
|
||||
TNumFormatRecord = packed record
|
||||
@@ -921,7 +939,7 @@ const
|
||||
var
|
||||
L: Word;
|
||||
WideValue: WideString;
|
||||
rec: TBIFF8LabelRecord;
|
||||
rec: TBIFF8_LabelRecord;
|
||||
buf: array of byte;
|
||||
begin
|
||||
if (ARow >= FLimitations.MaxRowCount) or (ACol >= FLimitations.MaxColCount) then
|
||||
@@ -1113,6 +1131,145 @@ end;
|
||||
*
|
||||
*
|
||||
*******************************************************************}
|
||||
procedure TsSpreadBIFF8Writer.WriteXF(AStream: TStream;
|
||||
AFormatRecord: PsCellFormat; XFType_Prot: Byte = 0);
|
||||
var
|
||||
rec: TBIFF8_XFRecord;
|
||||
j: Integer;
|
||||
b: Byte;
|
||||
dw1, dw2: DWord;
|
||||
begin
|
||||
{ BIFF record header }
|
||||
rec.RecordID := WordToLE(INT_EXCEL_ID_XF);
|
||||
rec.RecordSize := WordToLE(SizeOf(TBIFF8_XFRecord) - 2*SizeOf(Word));
|
||||
|
||||
{ Index to font record }
|
||||
rec.FontIndex := 0;
|
||||
if (AFormatRecord <> nil) then begin
|
||||
if (uffBold in AFormatRecord^.UsedFormattingFields) then
|
||||
rec.FontIndex := 1
|
||||
else
|
||||
if (uffFont in AFormatRecord^.UsedFormattingFields) then
|
||||
rec.FontIndex := AFormatRecord^.FontIndex;
|
||||
end;
|
||||
rec.FontIndex := WordToLE(rec.FontIndex);
|
||||
|
||||
{ Index to number format }
|
||||
rec.NumFormatIndex := 0;
|
||||
if (AFormatRecord <> nil) and (uffNumberFormat in AFormatRecord^.UsedFormattingFields)
|
||||
then begin
|
||||
// The number formats in the FormatList are still in fpc dialect
|
||||
// They will be converted to Excel syntax immediately before writing.
|
||||
j := NumFormatList.Find(AFormatRecord^.NumberFormat, AFormatRecord^.NumberFormatStr);
|
||||
if j > -1 then
|
||||
rec.NumFormatIndex := NumFormatList[j].Index;
|
||||
end;
|
||||
rec.NumFormatIndex := WordToLE(rec.NumFormatIndex);
|
||||
|
||||
{ XF type, cell protection and parent style XF }
|
||||
rec.XFType_Prot_ParentXF := XFType_Prot and MASK_XF_TYPE_PROT;
|
||||
if XFType_Prot and MASK_XF_TYPE_PROT_STYLE_XF <> 0 then
|
||||
rec.XFType_Prot_ParentXF := rec.XFType_Prot_ParentXF or MASK_XF_TYPE_PROT_PARENT;
|
||||
|
||||
{ Text alignment and text break }
|
||||
if AFormatRecord = nil then
|
||||
b := MASK_XF_VERT_ALIGN_BOTTOM
|
||||
else
|
||||
begin
|
||||
b := 0;
|
||||
if (uffHorAlign in AFormatRecord^.UsedFormattingFields) then
|
||||
case AFormatRecord^.HorAlignment of
|
||||
haDefault: ;
|
||||
haLeft : b := b or MASK_XF_HOR_ALIGN_LEFT;
|
||||
haCenter : b := b or MASK_XF_HOR_ALIGN_CENTER;
|
||||
haRight : b := b or MASK_XF_HOR_ALIGN_RIGHT;
|
||||
end;
|
||||
// Since the default vertical alignment is vaDefault but "0" corresponds
|
||||
// to vaTop, we alwys have to write the vertical alignment.
|
||||
case AFormatRecord^.VertAlignment of
|
||||
vaTop : b := b or MASK_XF_VERT_ALIGN_TOP;
|
||||
vaCenter : b := b or MASK_XF_VERT_ALIGN_CENTER;
|
||||
vaBottom : b := b or MASK_XF_VERT_ALIGN_BOTTOM;
|
||||
else b := b or MASK_XF_VERT_ALIGN_BOTTOM;
|
||||
end;
|
||||
if (uffWordWrap in AFormatRecord^.UsedFormattingFields) then
|
||||
b := b or MASK_XF_TEXTWRAP;
|
||||
end;
|
||||
rec.Align_TextBreak := b;
|
||||
|
||||
{ Text rotation }
|
||||
rec.TextRotation := 0;
|
||||
if (AFormatRecord <> nil) and (uffTextRotation in AFormatRecord^.UsedFormattingFields)
|
||||
then rec.TextRotation := TEXT_ROTATIONS[AFormatRecord^.TextRotation];
|
||||
|
||||
{ Indentation, shrink, merge and text direction:
|
||||
see "Excel97-2007BinaryFileFormat(xls)Specification.pdf", p281 ff
|
||||
Bits 0-3: Indent value
|
||||
Bit 4: Shrink to fit
|
||||
Bit 5: MergeCell
|
||||
Bits 6-7: Reading direction }
|
||||
rec.Indent_Shrink_TextDir := 0;
|
||||
|
||||
{ Used attributes }
|
||||
rec.UsedAttrib :=
|
||||
MASK_XF_USED_ATTRIB_NUMBER_FORMAT or
|
||||
MASK_XF_USED_ATTRIB_FONT or
|
||||
MASK_XF_USED_ATTRIB_TEXT or
|
||||
MASK_XF_USED_ATTRIB_BORDER_LINES or
|
||||
MASK_XF_USED_ATTRIB_BACKGROUND or
|
||||
MASK_XF_USED_ATTRIB_CELL_PROTECTION;
|
||||
|
||||
{ Cell border lines and background area }
|
||||
|
||||
dw1 := 0;
|
||||
dw2 := 0;
|
||||
rec.BkGr3 := 0;
|
||||
if (AFormatRecord <> nil) and (uffBorder in AFormatRecord^.UsedFormattingFields) then
|
||||
begin
|
||||
// Left and right line colors
|
||||
dw1 := AFormatRecord^.BorderStyles[cbWest].Color shl 16 +
|
||||
AFormatRecord^.BorderStyles[cbEast].Color shl 23;
|
||||
// Border line styles
|
||||
if cbWest in AFormatRecord^.Border then
|
||||
dw1 := dw1 or (DWord(AFormatRecord^.BorderStyles[cbWest].LineStyle)+1);
|
||||
if cbEast in AFormatRecord^.Border then
|
||||
dw1 := dw1 or ((DWord(AFormatRecord^.BorderStyles[cbEast].LineStyle)+1) shl 4);
|
||||
if cbNorth in AFormatRecord^.Border then
|
||||
dw1 := dw1 or ((DWord(AFormatRecord^.BorderStyles[cbNorth].LineStyle)+1) shl 8);
|
||||
if cbSouth in AFormatRecord^.Border then
|
||||
dw1 := dw1 or ((DWord(AFormatRecord^.BorderStyles[cbSouth].LineStyle)+1) shl 12);
|
||||
if cbDiagDown in AFormatRecord^.Border then
|
||||
dw1 := dw1 or $40000000;
|
||||
if cbDiagUp in AFormatRecord^.Border then
|
||||
dw1 := dw1 or $80000000;
|
||||
|
||||
// Top, bottom and diagonal line colors
|
||||
dw2 := FixColor(AFormatRecord^.BorderStyles[cbNorth].Color) +
|
||||
FixColor(AFormatRecord^.BorderStyles[cbSouth].Color) shl 7 +
|
||||
FixColor(AFormatRecord^.BorderStyles[cbDiagUp].Color) shl 14;
|
||||
// In BIFF8 both diagonals have the same color - we use the color of the up-diagonal.
|
||||
|
||||
// Diagonal line style
|
||||
if (AFormatRecord^.Border * [cbDiagUp, cbDiagDown] <> []) then
|
||||
dw2 := dw2 or ((DWord(AFormatRecord^.BorderStyles[cbDiagUp].LineStyle)+1) shl 21);
|
||||
// In BIFF8 both diagonals have the same line style - we use the color of the up-diagonal.
|
||||
end;
|
||||
|
||||
if (AFormatRecord <> nil) and (uffBackgroundColor in AFormatRecord^.UsedFormattingFields) then
|
||||
begin
|
||||
dw2 := dw2 or DWORD(MASK_XF_FILL_PATT_SOLID shl 26);
|
||||
rec.BkGr3 := FixColor(AFormatRecord^.BackgroundColor);
|
||||
end;
|
||||
|
||||
rec.Border_BkGr1 := DWordToLE(dw1);
|
||||
rec.Border_BkGr2 := DWordToLE(dw2);
|
||||
rec.BkGr3 := WordToLE(rec.BkGr3);
|
||||
|
||||
{ Write out }
|
||||
AStream.WriteBuffer(rec, SizeOf(rec));
|
||||
end;
|
||||
|
||||
(*
|
||||
procedure TsSpreadBIFF8Writer.WriteXF(AStream: TStream; AFontIndex: Word;
|
||||
AFormatIndex: Word; AXF_TYPE_PROT, ATextRotation: Byte; ABorders: TsCellBorders;
|
||||
const ABorderStyles: TsCellBorderStyles; AHorAlignment: TsHorAlignment = haDefault;
|
||||
@@ -1222,47 +1379,7 @@ begin
|
||||
AStream.WriteWord(WordToLE(ABackgroundColor))
|
||||
else
|
||||
AStream.WriteWord(0);
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFF8Writer.WriteXFRecords(AStream: TStream);
|
||||
begin
|
||||
// XF0
|
||||
WriteXF(AStream, 0, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, [], DEFAULT_BORDERSTYLES);
|
||||
// XF1
|
||||
WriteXF(AStream, 0, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, [], DEFAULT_BORDERSTYLES);
|
||||
// XF2
|
||||
WriteXF(AStream, 0, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, [], DEFAULT_BORDERSTYLES);
|
||||
// XF3
|
||||
WriteXF(AStream, 0, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, [], DEFAULT_BORDERSTYLES);
|
||||
// XF4
|
||||
WriteXF(AStream, 0, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, [], DEFAULT_BORDERSTYLES);
|
||||
// XF5
|
||||
WriteXF(AStream, 0, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, [], DEFAULT_BORDERSTYLES);
|
||||
// XF6
|
||||
WriteXF(AStream, 0, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, [], DEFAULT_BORDERSTYLES);
|
||||
// XF7
|
||||
WriteXF(AStream, 0, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, [], DEFAULT_BORDERSTYLES);
|
||||
// XF8
|
||||
WriteXF(AStream, 0, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, [], DEFAULT_BORDERSTYLES);
|
||||
// XF9
|
||||
WriteXF(AStream, 0, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, [], DEFAULT_BORDERSTYLES);
|
||||
// XF10
|
||||
WriteXF(AStream, 0, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, [], DEFAULT_BORDERSTYLES);
|
||||
// XF11
|
||||
WriteXF(AStream, 0, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, [], DEFAULT_BORDERSTYLES);
|
||||
// XF12
|
||||
WriteXF(AStream, 0, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, [], DEFAULT_BORDERSTYLES);
|
||||
// XF13
|
||||
WriteXF(AStream, 0, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, [], DEFAULT_BORDERSTYLES);
|
||||
// XF14
|
||||
WriteXF(AStream, 0, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, [], DEFAULT_BORDERSTYLES);
|
||||
// XF15 - Default, no formatting
|
||||
WriteXF(AStream, 0, 0, 0, XF_ROTATION_HORIZONTAL, [], DEFAULT_BORDERSTYLES);
|
||||
|
||||
// Add all further non-standard/built-in formatting styles
|
||||
ListAllFormattingStyles;
|
||||
WriteXFFieldsForFormattingStyles(AStream);
|
||||
end;
|
||||
end;*)
|
||||
|
||||
|
||||
{ TsSpreadBIFF8Reader }
|
||||
@@ -1854,13 +1971,13 @@ var
|
||||
ACol,ARow: Cardinal;
|
||||
XF: WORD;
|
||||
SSTIndex: DWORD;
|
||||
rec: TBIFF8LabelSSTRecord;
|
||||
rec: TBIFF8_LabelSSTRecord;
|
||||
cell: PCell;
|
||||
begin
|
||||
rec.Row := 0; // to silence the compiler...
|
||||
|
||||
{ Read entire record, starting at Row }
|
||||
AStream.ReadBuffer(rec.Row, SizeOf(TBIFF8LabelSSTRecord) - 2*SizeOf(Word));
|
||||
AStream.ReadBuffer(rec.Row, SizeOf(TBIFF8_LabelSSTRecord) - 2*SizeOf(Word));
|
||||
ARow := WordLEToN(rec.Row);
|
||||
ACol := WordLEToN(rec.Col);
|
||||
XF := WordLEToN(rec.XFIndex);
|
||||
@@ -1922,7 +2039,7 @@ procedure TsSpreadBIFF8Reader.ReadXF(const AStream: TStream);
|
||||
else Result := lsDashed;
|
||||
end;
|
||||
end;
|
||||
|
||||
(*
|
||||
type
|
||||
TXFRecord = packed record // see p. 224
|
||||
FontIndex: Word; // Offset 0, Size 2
|
||||
@@ -1936,120 +2053,147 @@ type
|
||||
Border_Background_2: DWord; // Offset 14, Size 4
|
||||
Border_Background_3: DWord; // Offset 18, Size 2
|
||||
end;
|
||||
*)
|
||||
var
|
||||
lData: TXFListData;
|
||||
xf: TXFRecord;
|
||||
rec: TBIFF8_XFRecord;
|
||||
fmt: TsCellFormat;
|
||||
// xf: TXFRecord;
|
||||
b: Byte;
|
||||
dw: DWord;
|
||||
fill: Integer;
|
||||
nfidx: Integer;
|
||||
nfdata: TsNumFormatData;
|
||||
i: Integer;
|
||||
begin
|
||||
xf.FontIndex := 0; // to silence the compiler...
|
||||
InitFormatRecord(fmt);
|
||||
fmt.ID := FCellFormatList.Count;
|
||||
|
||||
rec.FontIndex := 0; // to silence the compiler...
|
||||
// Read entire xf record into a buffer
|
||||
AStream.ReadBuffer(xf, SizeOf(xf));
|
||||
|
||||
lData := TXFListData.Create;
|
||||
AStream.ReadBuffer(rec.FontIndex, SizeOf(rec) - 2*SizeOf(word));
|
||||
|
||||
// Font index
|
||||
lData.FontIndex := WordLEToN(xf.FontIndex);
|
||||
fmt.FontIndex := WordLEToN(rec.FontIndex);
|
||||
if fmt.FontIndex = 1 then
|
||||
Include(fmt.UsedFormattingFields, uffBold)
|
||||
else if fmt.FontIndex > 1 then
|
||||
Include(fmt.UsedFormattingFields, uffFont);
|
||||
|
||||
// Format index
|
||||
lData.FormatIndex := WordLEToN(xf.FormatIndex);
|
||||
// Number format index
|
||||
nfidx := WordLEToN(rec.NumFormatIndex);
|
||||
i := NumFormatList.FindByIndex(nfidx);
|
||||
if i > -1 then begin
|
||||
nfdata := NumFormatList.Items[i];
|
||||
fmt.NumberFormat := nfdata.NumFormat;
|
||||
fmt.NumberFormatStr := nfdata.FormatString;
|
||||
if nfdata.NumFormat <> nfGeneral then
|
||||
Include(fmt.UsedFormattingFields, uffNumberFormat);
|
||||
end;
|
||||
|
||||
// Horizontal text alignment
|
||||
b := xf.Align_TextBreak AND MASK_XF_HOR_ALIGN;
|
||||
b := rec.Align_TextBreak AND MASK_XF_HOR_ALIGN;
|
||||
if (b <= ord(High(TsHorAlignment))) then
|
||||
lData.HorAlignment := TsHorAlignment(b)
|
||||
else
|
||||
lData.HorAlignment := haDefault;
|
||||
begin
|
||||
fmt.HorAlignment := TsHorAlignment(b);
|
||||
if fmt.HorAlignment <> haDefault then
|
||||
Include(fmt.UsedFormattingFields, uffHorAlign);
|
||||
end;
|
||||
|
||||
// Vertical text alignment
|
||||
b := (xf.Align_TextBreak AND MASK_XF_VERT_ALIGN) shr 4;
|
||||
b := (rec.Align_TextBreak AND MASK_XF_VERT_ALIGN) shr 4;
|
||||
if (b + 1 <= ord(high(TsVertAlignment))) then
|
||||
begin
|
||||
lData.VertAlignment := tsVertAlignment(b + 1); // + 1 due to vaDefault
|
||||
fmt.VertAlignment := TsVertAlignment(b + 1); // + 1 due to vaDefault
|
||||
// Unfortunately BIFF does not provide a "default" vertical alignment code.
|
||||
// Without the following correction "non-formatted" cells would always have
|
||||
// the uffVertAlign FormattingField set which contradicts the statement of
|
||||
// not being formatted.
|
||||
if lData.VertAlignment = vaBottom then
|
||||
lData.VertAlignment := vaDefault;
|
||||
end
|
||||
else
|
||||
lData.VertAlignment := vaDefault;
|
||||
if fmt.VertAlignment = vaBottom then
|
||||
fmt.VertAlignment := vaDefault;
|
||||
if fmt.VertAlignment <> vaDefault then
|
||||
Include(fmt.UsedFormattingFields, uffVertAlign);
|
||||
end;
|
||||
|
||||
// Word wrap
|
||||
lData.WordWrap := (xf.Align_TextBreak and MASK_XF_TEXTWRAP) <> 0;
|
||||
if (rec.Align_TextBreak and MASK_XF_TEXTWRAP) <> 0 then
|
||||
Include(fmt.UsedFormattingFields, uffWordwrap);
|
||||
|
||||
// TextRotation
|
||||
case xf.XFRotation of
|
||||
XF_ROTATION_HORIZONTAL : lData.TextRotation := trHorizontal;
|
||||
XF_ROTATION_90DEG_CCW : ldata.TextRotation := rt90DegreeCounterClockwiseRotation;
|
||||
XF_ROTATION_90DEG_CW : lData.TextRotation := rt90DegreeClockwiseRotation;
|
||||
XF_ROTATION_STACKED : lData.TextRotation := rtStacked;
|
||||
case rec.TextRotation of
|
||||
XF_ROTATION_HORIZONTAL : fmt.TextRotation := trHorizontal;
|
||||
XF_ROTATION_90DEG_CCW : fmt.TextRotation := rt90DegreeCounterClockwiseRotation;
|
||||
XF_ROTATION_90DEG_CW : fmt.TextRotation := rt90DegreeClockwiseRotation;
|
||||
XF_ROTATION_STACKED : fmt.TextRotation := rtStacked;
|
||||
end;
|
||||
if fmt.TextRotation <> trHorizontal then
|
||||
Include(fmt.UsedFormattingFields, uffTextRotation);
|
||||
|
||||
// Cell borders
|
||||
xf.Border_Background_1 := DWordLEToN(xf.Border_Background_1);
|
||||
lData.Borders := [];
|
||||
lData.BorderStyles := DEFAULT_BORDERSTYLES;
|
||||
rec.Border_BkGr1 := DWordLEToN(rec.Border_BkGr1);
|
||||
rec.Border_BkGr2 := DWordLEToN(rec.Border_BkGr2);
|
||||
|
||||
// the 4 masked bits encode the line style of the border line. 0 = no line
|
||||
dw := xf.Border_Background_1 and MASK_XF_BORDER_LEFT;
|
||||
dw := rec.Border_BkGr1 and MASK_XF_BORDER_LEFT;
|
||||
if dw <> 0 then
|
||||
begin
|
||||
Include(lData.Borders, cbWest);
|
||||
lData.BorderStyles[cbWest].LineStyle := FixLineStyle(dw);
|
||||
Include(fmt.Border, cbWest);
|
||||
fmt.BorderStyles[cbWest].LineStyle := FixLineStyle(dw);
|
||||
Include(fmt.UsedFormattingFields, uffBorder);
|
||||
end;
|
||||
dw := xf.Border_Background_1 and MASK_XF_BORDER_RIGHT;
|
||||
dw := rec.Border_BkGr1 and MASK_XF_BORDER_RIGHT;
|
||||
if dw <> 0 then
|
||||
begin
|
||||
Include(lData.Borders, cbEast);
|
||||
lData.BorderStyles[cbEast].LineStyle := FixLineStyle(dw shr 4);
|
||||
Include(fmt.Border, cbEast);
|
||||
fmt.BorderStyles[cbEast].LineStyle := FixLineStyle(dw shr 4);
|
||||
Include(fmt.UsedFormattingFields, uffBorder);
|
||||
end;
|
||||
dw := xf.Border_Background_1 and MASK_XF_BORDER_TOP;
|
||||
dw := rec.Border_BkGr1 and MASK_XF_BORDER_TOP;
|
||||
if dw <> 0 then
|
||||
begin
|
||||
Include(lData.Borders, cbNorth);
|
||||
lData.BorderStyles[cbNorth].LineStyle := FixLineStyle(dw shr 8);
|
||||
Include(fmt.Border, cbNorth);
|
||||
fmt.BorderStyles[cbNorth].LineStyle := FixLineStyle(dw shr 8);
|
||||
Include(fmt.UsedFormattingFields, uffBorder);
|
||||
end;
|
||||
dw := xf.Border_Background_1 and MASK_XF_BORDER_BOTTOM;
|
||||
dw := rec.Border_BkGr1 and MASK_XF_BORDER_BOTTOM;
|
||||
if dw <> 0 then
|
||||
begin
|
||||
Include(lData.Borders, cbSouth);
|
||||
lData.BorderStyles[cbSouth].LineStyle := FixLineStyle(dw shr 12);
|
||||
Include(fmt.Border, cbSouth);
|
||||
fmt.BorderStyles[cbSouth].LineStyle := FixLineStyle(dw shr 12);
|
||||
Include(fmt.UsedFormattingFields, uffBorder);
|
||||
end;
|
||||
dw := xf.Border_Background_2 and MASK_XF_BORDER_DIAGONAL;
|
||||
dw := rec.Border_BkGr2 and MASK_XF_BORDER_DIAGONAL;
|
||||
if dw <> 0 then
|
||||
begin
|
||||
lData.BorderStyles[cbDiagUp].LineStyle := FixLineStyle(dw shr 21);
|
||||
lData.BorderStyles[cbDiagDown].LineStyle := lData.BorderStyles[cbDiagUp].LineStyle;
|
||||
if xf.Border_Background_1 and MASK_XF_BORDER_SHOW_DIAGONAL_UP <> 0 then
|
||||
Include(lData.Borders, cbDiagUp);
|
||||
if xf.Border_Background_1 and MASK_XF_BORDER_SHOW_DIAGONAL_DOWN <> 0 then
|
||||
Include(lData.Borders, cbDiagDown);
|
||||
fmt.BorderStyles[cbDiagUp].LineStyle := FixLineStyle(dw shr 21);
|
||||
fmt.BorderStyles[cbDiagDown].LineStyle := fmt.BorderStyles[cbDiagUp].LineStyle;
|
||||
if rec.Border_BkGr1 and MASK_XF_BORDER_SHOW_DIAGONAL_UP <> 0 then
|
||||
Include(fmt.Border, cbDiagUp);
|
||||
if rec.Border_BkGr1 and MASK_XF_BORDER_SHOW_DIAGONAL_DOWN <> 0 then
|
||||
Include(fmt.Border, cbDiagDown);
|
||||
Include(fmt.UsedFormattingFields, uffBorder);
|
||||
end;
|
||||
|
||||
// Border line colors
|
||||
lData.BorderStyles[cbWest].Color := (xf.Border_Background_1 and MASK_XF_BORDER_LEFT_COLOR) shr 16;
|
||||
lData.BorderStyles[cbEast].Color := (xf.Border_Background_1 and MASK_XF_BORDER_RIGHT_COLOR) shr 23;
|
||||
lData.BorderStyles[cbNorth].Color := (xf.Border_Background_2 and MASK_XF_BORDER_TOP_COLOR);
|
||||
lData.BorderStyles[cbSouth].Color := (xf.Border_Background_2 and MASK_XF_BORDER_BOTTOM_COLOR) shr 7;
|
||||
lData.BorderStyles[cbDiagUp].Color := (xf.Border_Background_2 and MASK_XF_BORDER_DIAGONAL_COLOR) shr 14;
|
||||
lData.BorderStyles[cbDiagDown].Color := lData.BorderStyles[cbDiagUp].Color;
|
||||
fmt.BorderStyles[cbWest].Color := (rec.Border_BkGr1 and MASK_XF_BORDER_LEFT_COLOR) shr 16;
|
||||
fmt.BorderStyles[cbEast].Color := (rec.Border_BkGr1 and MASK_XF_BORDER_RIGHT_COLOR) shr 23;
|
||||
fmt.BorderStyles[cbNorth].Color := (rec.Border_BkGr2 and MASK_XF_BORDER_TOP_COLOR);
|
||||
fmt.BorderStyles[cbSouth].Color := (rec.Border_BkGr2 and MASK_XF_BORDER_BOTTOM_COLOR) shr 7;
|
||||
fmt.BorderStyles[cbDiagUp].Color := (rec.Border_BkGr2 and MASK_XF_BORDER_DIAGONAL_COLOR) shr 14;
|
||||
fmt.BorderStyles[cbDiagDown].Color := fmt.BorderStyles[cbDiagUp].Color;
|
||||
|
||||
// Background fill pattern
|
||||
fill := (xf.Border_Background_2 and MASK_XF_BACKGROUND_PATTERN) shr 26;
|
||||
fill := (rec.Border_BkGr2 and MASK_XF_BACKGROUND_PATTERN) shr 26;
|
||||
|
||||
// Background color
|
||||
xf.Border_Background_3 := DWordLEToN(xf.Border_Background_3);
|
||||
if fill <> 0 then
|
||||
lData.BackgroundColor := xf.Border_Background_3 and $007F
|
||||
else
|
||||
lData.BackgroundColor := scTransparent; // this means "no fill"
|
||||
rec.BkGr3 := DWordLEToN(rec.BkGr3);
|
||||
if fill <> 0 then begin
|
||||
fmt.BackgroundColor := rec.BkGr3 and $007F;
|
||||
Include(fmt.UsedFormattingFields, uffBackgroundColor);
|
||||
end else
|
||||
fmt.BackgroundColor := scTransparent; // this means "no fill"
|
||||
|
||||
// Add the XF to the list
|
||||
FXFList.Add(lData);
|
||||
FCellFormatList.Add(fmt);
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFF8Reader.ReadFont(const AStream: TStream);
|
||||
@@ -2111,7 +2255,7 @@ begin
|
||||
FWorkbook.AddFont(font);
|
||||
end;
|
||||
|
||||
// Read the FORMAT record for formatting numerical data
|
||||
// Read the (number) FORMAT record for formatting numerical data
|
||||
procedure TsSpreadBIFF8Reader.ReadFormat(AStream: TStream);
|
||||
var
|
||||
fmtString: String;
|
||||
|
@@ -159,6 +159,10 @@ const
|
||||
MASK_XF_VERT_ALIGN_BOTTOM = $20;
|
||||
MASK_XF_VERT_ALIGN_JUSTIFIED = $30;
|
||||
|
||||
{ XF FILL PATTERNS }
|
||||
MASK_XF_FILL_PATT_EMPTY = $00;
|
||||
MASK_XF_FILL_PATT_SOLID = $01;
|
||||
|
||||
{ Cell Addresses constants, valid for BIFF2-BIFF5 }
|
||||
MASK_EXCEL_ROW = $3FFF;
|
||||
MASK_EXCEL_RELATIVE_COL = $4000;
|
||||
@@ -180,6 +184,9 @@ const
|
||||
ERR_OVERFLOW = $24; // #NUM!
|
||||
ERR_ARG_ERROR = $2A; // #N/A (not enough, or too many, arguments)
|
||||
|
||||
{ Index of last built-in XF format record }
|
||||
LAST_BUILTIN_XF = 15;
|
||||
|
||||
type
|
||||
TDateMode=(dm1900,dm1904); //DATEMODE values, 5.28
|
||||
|
||||
@@ -196,7 +203,7 @@ type
|
||||
// Converts an fps error value to the byte code needed in xls files
|
||||
function ConvertToExcelError(AValue: TsErrorValue): byte;
|
||||
|
||||
type
|
||||
type (*
|
||||
{ Contents of the XF record to be stored in the XFList of the reader }
|
||||
TXFListData = class
|
||||
public
|
||||
@@ -209,7 +216,7 @@ type
|
||||
Borders: TsCellBorders;
|
||||
BorderStyles: TsCellBorderStyles;
|
||||
BackgroundColor: TsColor;
|
||||
end;
|
||||
end; *)
|
||||
|
||||
{ TsBIFFNumFormatList }
|
||||
TsBIFFNumFormatList = class(TsCustomNumFormatList)
|
||||
@@ -227,21 +234,21 @@ type
|
||||
FCodepage: string; // in a format prepared for lconvencoding.ConvertEncoding
|
||||
FDateMode: TDateMode;
|
||||
FPaletteFound: Boolean;
|
||||
FXFList: TFPList; // of TXFListData
|
||||
// FXFList: TFPList; // of TXFListData
|
||||
FIncompleteCell: PCell;
|
||||
procedure ApplyCellFormatting(ARow, ACol: Cardinal; XFIndex: Word); overload;
|
||||
procedure ApplyCellFormatting(ACell: PCell; XFIndex: Word); virtual; overload;
|
||||
// procedure ApplyCellFormatting(ARow, ACol: Cardinal; XFIndex: Word); overload;
|
||||
procedure ApplyCellFormatting(ACell: PCell; XFIndex: Word); virtual; //overload;
|
||||
procedure CreateNumFormatList; override;
|
||||
// Extracts a number out of an RK value
|
||||
function DecodeRKValue(const ARK: DWORD): Double;
|
||||
// Returns the numberformat for a given XF record
|
||||
procedure ExtractNumberFormat(AXFIndex: WORD;
|
||||
out ANumberFormat: TsNumberFormat; //out ADecimals: Byte;
|
||||
//out ACurrencySymbol: String;
|
||||
out ANumberFormatStr: String); virtual;
|
||||
out ANumberFormat: TsNumberFormat; out ANumberFormatStr: String); virtual;
|
||||
{
|
||||
// Finds format record for XF record pointed to by cell
|
||||
// Will not return info for built-in formats
|
||||
function FindNumFormatDataForCell(const AXFIndex: Integer): TsNumFormatData;
|
||||
}
|
||||
// Tries to find if a number cell is actually a date/datetime/time cell and retrieves the value
|
||||
function IsDateTime(Number: Double; ANumberFormat: TsNumberFormat;
|
||||
ANumberFormatStr: String; out ADateTime: TDateTime): Boolean;
|
||||
@@ -303,7 +310,7 @@ type
|
||||
|
||||
public
|
||||
constructor Create(AWorkbook: TsWorkbook); override;
|
||||
destructor Destroy; override;
|
||||
// destructor Destroy; override;
|
||||
end;
|
||||
|
||||
{ TsSpreadBIFFWriter }
|
||||
@@ -313,9 +320,9 @@ type
|
||||
FDateMode: TDateMode;
|
||||
FLastRow: Cardinal;
|
||||
FLastCol: Cardinal;
|
||||
procedure AddDefaultFormats; override;
|
||||
// procedure AddDefaultFormats; override;
|
||||
procedure CreateNumFormatList; override;
|
||||
function FindXFIndex(ACell: PCell): Integer;
|
||||
function FindXFIndex(ACell: PCell): Integer; virtual;
|
||||
function FixColor(AColor: TsColor): TsColor; override;
|
||||
procedure GetLastRowCallback(ACell: PCell; AStream: TStream);
|
||||
function GetLastRowIndex(AWorksheet: TsWorksheet): Integer;
|
||||
@@ -343,14 +350,14 @@ type
|
||||
// Writes out ERROR cell record
|
||||
procedure WriteError(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
const AValue: TsErrorValue; ACell: PCell); override;
|
||||
// Writes out a FORMAT record
|
||||
procedure WriteFormat(AStream: TStream; AFormatData: TsNumFormatData;
|
||||
AListIndex: Integer); virtual;
|
||||
// Writes out all FORMAT records
|
||||
procedure WriteFormats(AStream: TStream);
|
||||
// Writes out a FORMULA record; formula is stored in cell already
|
||||
procedure WriteFormula(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
ACell: PCell); override;
|
||||
// Writes out a FORMAT record
|
||||
procedure WriteNumFormat(AStream: TStream; ANumFormatData: TsNumFormatData;
|
||||
AListIndex: Integer); virtual;
|
||||
// Writes out all FORMAT records
|
||||
procedure WriteNumFormats(AStream: TStream);
|
||||
// Writes out a floating point NUMBER record
|
||||
procedure WriteNumber(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
const AValue: Double; ACell: PCell); override;
|
||||
@@ -381,6 +388,7 @@ type
|
||||
procedure WriteRPNTokenArray(AStream: TStream; ACell: PCell;
|
||||
const AFormula: TsRPNFormula; UseRelAddr: Boolean; var RPNLength: Word);
|
||||
procedure WriteRPNTokenArraySize(AStream: TStream; ASize: Word); virtual;
|
||||
|
||||
// Writes out a SELECTION record
|
||||
procedure WriteSelection(AStream: TStream; ASheet: TsWorksheet; APane: Byte);
|
||||
procedure WriteSelections(AStream: TStream; ASheet: TsWorksheet);
|
||||
@@ -395,7 +403,13 @@ type
|
||||
// Writes out a WINDOW1 record
|
||||
procedure WriteWindow1(AStream: TStream); virtual;
|
||||
// Writes the index of the XF record used in the given cell
|
||||
procedure WriteXFIndex(AStream: TStream; ACell: PCell);
|
||||
//procedure WriteXFIndex(AStream: TStream; ACell: PCell);
|
||||
|
||||
// Writes an XF record
|
||||
procedure WriteXF(AStream: TStream; ACellFormat: PsCellFormat;
|
||||
XFType_Prot: Byte = 0); virtual;
|
||||
// Writes all xF records
|
||||
procedure WriteXFRecords(AStream: TStream);
|
||||
|
||||
public
|
||||
constructor Create(AWorkbook: TsWorkbook); override;
|
||||
@@ -562,47 +576,47 @@ begin
|
||||
fs := Workbook.FormatSettings;
|
||||
cs := Workbook.FormatSettings.CurrencyString;
|
||||
|
||||
AddFormat( 0, '', nfGeneral);
|
||||
AddFormat( 1, '0', nfFixed);
|
||||
AddFormat( 2, '0.00', nfFixed);
|
||||
AddFormat( 3, '#,##0', nfFixedTh);
|
||||
AddFormat( 4, '#,##0.00', nfFixedTh);
|
||||
AddFormat( 5, '"'+cs+'"#,##0;("'+cs+'"#,##0)', nfCurrency);
|
||||
AddFormat( 6, '"'+cs+'"#,##0;[Red]("'+cs+'"#,##0)', nfCurrencyRed);
|
||||
AddFormat( 7, '"'+cs+'"#,##0.00;("'+cs+'"#,##0.00)', nfCurrency);
|
||||
AddFormat( 8, '"'+cs+'"#,##0.00;[Red]("'+cs+'"#,##0.00)', nfCurrencyRed);
|
||||
AddFormat( 9, '0%', nfPercentage);
|
||||
AddFormat(10, '0.00%', nfPercentage);
|
||||
AddFormat(11, '0.00E+00', nfExp);
|
||||
AddFormat( 0, nfGeneral, '');
|
||||
AddFormat( 1, nfFixed, '0');
|
||||
AddFormat( 2, nfFixed, '0.00');
|
||||
AddFormat( 3, nfFixedTh, '#,##0');
|
||||
AddFormat( 4, nfFixedTh, '#,##0.00');
|
||||
AddFormat( 5, nfCurrency, '"'+cs+'"#,##0;("'+cs+'"#,##0)');
|
||||
AddFormat( 6, nfCurrencyRed, '"'+cs+'"#,##0;[Red]("'+cs+'"#,##0)');
|
||||
AddFormat( 7, nfCurrency, '"'+cs+'"#,##0.00;("'+cs+'"#,##0.00)');
|
||||
AddFormat( 8, nfCurrencyRed, '"'+cs+'"#,##0.00;[Red]("'+cs+'"#,##0.00)');
|
||||
AddFormat( 9, nfPercentage, '0%');
|
||||
AddFormat(10, nfPercentage, '0.00%');
|
||||
AddFormat(11, nfExp, '0.00E+00');
|
||||
// fraction formats 12 ('# ?/?') and 13 ('# ??/??') not supported
|
||||
AddFormat(14, fs.ShortDateFormat, nfShortDate); // 'M/D/YY'
|
||||
AddFormat(15, fs.LongDateFormat, nfLongDate); // 'D-MMM-YY'
|
||||
AddFormat(16, 'd/mmm', nfCustom); // 'D-MMM'
|
||||
AddFormat(17, 'mmm/yy', nfCustom); // 'MMM-YY'
|
||||
AddFormat(18, AddAMPM(fs.ShortTimeFormat, fs), nfShortTimeAM); // 'h:mm AM/PM'
|
||||
AddFormat(19, AddAMPM(fs.LongTimeFormat, fs), nfLongTimeAM); // 'h:mm:ss AM/PM'
|
||||
AddFormat(20, fs.ShortTimeFormat, nfShortTime); // 'h:mm'
|
||||
AddFormat(21, fs.LongTimeFormat, nfLongTime); // 'h:mm:ss'
|
||||
AddFormat(22, fs.ShortDateFormat + ' ' + fs.ShortTimeFormat, nfShortDateTime); // 'M/D/YY h:mm' (localized)
|
||||
AddFormat(14, nfShortDate, fs.ShortDateFormat); // 'M/D/YY'
|
||||
AddFormat(15, nfLongDate, fs.LongDateFormat); // 'D-MMM-YY'
|
||||
AddFormat(16, nfCustom, 'd/mmm'); // 'D-MMM'
|
||||
AddFormat(17, nfCustom, 'mmm/yy'); // 'MMM-YY'
|
||||
AddFormat(18, nfShortTimeAM, AddAMPM(fs.ShortTimeFormat, fs)); // 'h:mm AM/PM'
|
||||
AddFormat(19, nfLongTimeAM, AddAMPM(fs.LongTimeFormat, fs)); // 'h:mm:ss AM/PM'
|
||||
AddFormat(20, nfShortTime, fs.ShortTimeFormat); // 'h:mm'
|
||||
AddFormat(21, nfLongTime, fs.LongTimeFormat); // 'h:mm:ss'
|
||||
AddFormat(22, nfShortDateTime, fs.ShortDateFormat + ' ' + fs.ShortTimeFormat); // 'M/D/YY h:mm' (localized)
|
||||
// 23..36 not supported
|
||||
AddFormat(37, '_(#,##0_);(#,##0)', nfCurrency);
|
||||
AddFormat(38, '_(#,##0_);[Red](#,##0)', nfCurrencyRed);
|
||||
AddFormat(39, '_(#,##0.00_);(#,##0.00)', nfCurrency);
|
||||
AddFormat(40, '_(#,##0.00_);[Red](#,##0.00)', nfCurrencyRed);
|
||||
AddFormat(41, '_("'+cs+'"* #,##0_);_("'+cs+'"* (#,##0);_("'+cs+'"* "-"_);_(@_)', nfCustom);
|
||||
AddFormat(42, '_(* #,##0_);_(* (#,##0);_(* "-"_);_(@_)', nfCustom);
|
||||
AddFormat(43, '_("'+cs+'"* #,##0.00_);_("'+cs+'"* (#,##0.00);_("'+cs+'"* "-"??_);_(@_)', nfCustom);
|
||||
AddFormat(44, '_(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(@_)', nfCustom);
|
||||
AddFormat(45, 'nn:ss', nfCustom);
|
||||
AddFormat(46, '[h]:nn:ss', nfTimeInterval);
|
||||
AddFormat(47, 'nn:ss.z', nfCustom);
|
||||
AddFormat(48, '##0.0E+00', nfCustom);
|
||||
AddFormat(37, nfCurrency, '_(#,##0_);(#,##0)');
|
||||
AddFormat(38, nfCurrencyRed, '_(#,##0_);[Red](#,##0)');
|
||||
AddFormat(39, nfCurrency, '_(#,##0.00_);(#,##0.00)');
|
||||
AddFormat(40, nfCurrencyRed, '_(#,##0.00_);[Red](#,##0.00)');
|
||||
AddFormat(41, nfCustom, '_("'+cs+'"* #,##0_);_("'+cs+'"* (#,##0);_("'+cs+'"* "-"_);_(@_)');
|
||||
AddFormat(42, nfCustom, '_(* #,##0_);_(* (#,##0);_(* "-"_);_(@_)');
|
||||
AddFormat(43, nfCustom, '_("'+cs+'"* #,##0.00_);_("'+cs+'"* (#,##0.00);_("'+cs+'"* "-"??_);_(@_)');
|
||||
AddFormat(44, nfCustom, '_(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(@_)');
|
||||
AddFormat(45, nfCustom, 'nn:ss');
|
||||
AddFormat(46, nfTimeInterval, '[h]:nn:ss');
|
||||
AddFormat(47, nfCustom, 'nn:ss.z');
|
||||
AddFormat(48, nfCustom, '##0.0E+00');
|
||||
// 49 ("Text") not supported
|
||||
|
||||
// All indexes from 0 to 163 are reserved for built-in formats.
|
||||
// The first user-defined format starts at 164.
|
||||
FFirstFormatIndexInFile := 164;
|
||||
FNextFormatIndex := 164;
|
||||
FFirstNumFormatIndexInFile := 164;
|
||||
FNextNumFormatIndex := 164;
|
||||
end;
|
||||
|
||||
procedure TsBIFFNumFormatList.ConvertBeforeWriting(var AFormatString: String;
|
||||
@@ -628,7 +642,8 @@ end;
|
||||
constructor TsSpreadBIFFReader.Create(AWorkbook: TsWorkbook);
|
||||
begin
|
||||
inherited Create(AWorkbook);
|
||||
FXFList := TFPList.Create;
|
||||
FCellFormatList := TsCellFormatList.Create(true);
|
||||
// Allow duplicates! XF indexes get out of sync if not all format records are in list
|
||||
// Initial base date in case it won't be read from file
|
||||
FDateMode := dm1900;
|
||||
// Limitations of BIFF5 and BIFF8 file format
|
||||
@@ -637,6 +652,7 @@ begin
|
||||
FLimitations.MaxPaletteSize := 64;
|
||||
end;
|
||||
|
||||
{
|
||||
destructor TsSpreadBIFFReader.Destroy;
|
||||
var
|
||||
j: integer;
|
||||
@@ -645,7 +661,8 @@ begin
|
||||
FXFList.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
}
|
||||
(*
|
||||
{ Applies the XF formatting referred to by XFIndex to the specified cell }
|
||||
procedure TsSpreadBIFFReader.ApplyCellFormatting(ARow, ACol: Cardinal;
|
||||
XFIndex: Word);
|
||||
@@ -655,15 +672,23 @@ begin
|
||||
lCell := FWorksheet.GetCell(ARow, ACol);
|
||||
ApplyCellFormatting(lCell, XFIndex);
|
||||
end;
|
||||
|
||||
*)
|
||||
{ Applies the XF formatting referred to by XFIndex to the specified cell }
|
||||
procedure TsSpreadBIFFReader.ApplyCellFormatting(ACell: PCell; XFIndex: Word);
|
||||
var
|
||||
XFData: TXFListData;
|
||||
fmt: PsCellFormat;
|
||||
i: Integer;
|
||||
begin
|
||||
if Assigned(ACell) then begin
|
||||
XFData := TXFListData(FXFList.Items[XFIndex]);
|
||||
i := FCellFormatList.FindIndexOfID(XFIndex);
|
||||
if i > -1 then
|
||||
begin
|
||||
fmt := FCellFormatList.Items[i];
|
||||
ACell^.FormatIndex := FWorkbook.AddCellFormat(fmt^);
|
||||
end else
|
||||
ACell^.FormatIndex := 0;
|
||||
|
||||
(*
|
||||
// Font
|
||||
if XFData.FontIndex = 1 then
|
||||
Include(ACell^.UsedFormattingFields, uffBold)
|
||||
@@ -712,6 +737,7 @@ begin
|
||||
ACell^.BackgroundColor := XFData.BackgroundColor;
|
||||
end else
|
||||
Exclude(ACell^.UsedFormattingFields, uffBackgroundColor);
|
||||
*)
|
||||
end;
|
||||
end;
|
||||
|
||||
@@ -758,9 +784,24 @@ end;
|
||||
{ Extracts number format data from an XF record index by AXFIndex.
|
||||
Valid for BIFF5-BIFF8. Needs to be overridden for BIFF2 }
|
||||
procedure TsSpreadBIFFReader.ExtractNumberFormat(AXFIndex: WORD;
|
||||
out ANumberFormat: TsNumberFormat; //out ADecimals: Byte;
|
||||
//out ACurrencySymbol: String;
|
||||
out ANumberFormatStr: String);
|
||||
out ANumberFormat: TsNumberFormat; out ANumberFormatStr: String);
|
||||
var
|
||||
fmt: PsCellFormat;
|
||||
i: Integer;
|
||||
begin
|
||||
i := FCellFormatList.FindIndexOfID(AXFIndex);
|
||||
if i > -1 then
|
||||
begin
|
||||
fmt := FCellFormatList.Items[i];
|
||||
ANumberFormat := fmt^.NumberFormat;
|
||||
ANumberFormatStr := fmt^.NumberFormatStr;
|
||||
end else
|
||||
begin
|
||||
ANumberFormat := nfGeneral;
|
||||
ANumberFormatStr := '';
|
||||
end;
|
||||
end;
|
||||
{
|
||||
var
|
||||
lNumFormatData: TsNumFormatData;
|
||||
begin
|
||||
@@ -772,22 +813,24 @@ begin
|
||||
ANumberFormat := nfGeneral;
|
||||
ANumberFormatStr := '';
|
||||
end;
|
||||
end;
|
||||
|
||||
end; }
|
||||
(*
|
||||
{ Determines the format data (for numerical formatting) which belong to a given
|
||||
XF record. }
|
||||
function TsSpreadBIFFReader.FindNumFormatDataForCell(const AXFIndex: Integer
|
||||
): TsNumFormatData;
|
||||
var
|
||||
lXFData: TXFListData;
|
||||
fmt: TsCellFormat;
|
||||
i: Integer;
|
||||
begin
|
||||
Result := nil;
|
||||
fmt := FFormatList.FindByID(AXFIndex);
|
||||
i := NumFormatList.FindByIndex(
|
||||
lXFData := TXFListData(FXFList.Items[AXFIndex]);
|
||||
i := NumFormatList.FindByIndex(lXFData.FormatIndex);
|
||||
if i <> -1 then Result := NumFormatList[i];
|
||||
end;
|
||||
|
||||
*)
|
||||
{ Convert the number to a date/time and return that if it is }
|
||||
function TsSpreadBIFFReader.IsDateTime(Number: Double;
|
||||
ANumberFormat: TsNumberFormat; ANumberFormatStr: String;
|
||||
@@ -1010,7 +1053,7 @@ begin
|
||||
FWorksheet.DefaultRowHeight := h - ROW_HEIGHT_CORRECTION;
|
||||
end;
|
||||
|
||||
// Read the FORMAT record for formatting numerical data
|
||||
// Read the (number) FORMAT record for formatting numerical data
|
||||
procedure TsSpreadBIFFReader.ReadFormat(AStream: TStream);
|
||||
begin
|
||||
Unused(AStream);
|
||||
@@ -1774,7 +1817,7 @@ destructor TsSpreadBIFFWriter.Destroy;
|
||||
begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
(*
|
||||
{ These are default style formats which are added as XF fields regardless of
|
||||
being used in the document or not.
|
||||
Currently, only one additional default format is supported ("bold").
|
||||
@@ -1795,6 +1838,7 @@ begin
|
||||
NextXFIndex := 15 + Length(FFormattingStyles);
|
||||
// "15" is the index of the last pre-defined xf record
|
||||
end;
|
||||
*)
|
||||
|
||||
{ Creates the correct version of the number format list. It is for BIFF file
|
||||
formats.
|
||||
@@ -1807,6 +1851,10 @@ end;
|
||||
|
||||
{ Determines the index of the XF record, according to formatting of the given cell }
|
||||
function TsSpreadBIFFWriter.FindXFIndex(ACell: PCell): Integer;
|
||||
begin
|
||||
Result := LAST_BUILTIN_XF + ACell^.FormatIndex;
|
||||
end;
|
||||
{
|
||||
var
|
||||
idx: Integer;
|
||||
cell: TCell;
|
||||
@@ -1829,7 +1877,7 @@ begin
|
||||
else
|
||||
Result := FFormattingStyles[idx].Row;
|
||||
end;
|
||||
|
||||
}
|
||||
function TsSpreadBIFFWriter.FixColor(AColor: TsColor): TsColor;
|
||||
var
|
||||
rgb: TsColorValue;
|
||||
@@ -2061,30 +2109,31 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
{ Writes a BIFF format record defined in AFormatData. AListIndex the index of
|
||||
the formatdata in the format list (not the FormatIndex!).
|
||||
{ Writes a BIFF number format record defined in AFormatData.
|
||||
AListIndex the index of the numformatdata in the numformat list
|
||||
(not the FormatIndex!).
|
||||
Needs to be overridden by descendants. }
|
||||
procedure TsSpreadBIFFWriter.WriteFormat(AStream: TStream;
|
||||
AFormatData: TsNumFormatData; AListIndex: Integer);
|
||||
procedure TsSpreadBIFFWriter.WriteNumFormat(AStream: TStream;
|
||||
ANumFormatData: TsNumFormatData; AListIndex: Integer);
|
||||
begin
|
||||
Unused(AStream, AFormatData, AListIndex);
|
||||
Unused(AStream, ANumFormatData, AListIndex);
|
||||
// needs to be overridden
|
||||
end;
|
||||
|
||||
{ Writes all number formats to the stream. Saving starts at the item with the
|
||||
FirstFormatIndexInFile. }
|
||||
procedure TsSpreadBIFFWriter.WriteFormats(AStream: TStream);
|
||||
procedure TsSpreadBIFFWriter.WriteNumFormats(AStream: TStream);
|
||||
var
|
||||
i: Integer;
|
||||
item: TsNumFormatData;
|
||||
begin
|
||||
ListAllNumFormats;
|
||||
i := NumFormatList.FindByIndex(NumFormatList.FirstFormatIndexInFile);
|
||||
i := NumFormatList.FindByIndex(NumFormatList.FirstNumFormatIndexInFile);
|
||||
if i > -1 then
|
||||
while i < NumFormatList.Count do begin
|
||||
item := NumFormatList[i];
|
||||
if item <> nil then begin
|
||||
WriteFormat(AStream, item, i);
|
||||
WriteNumFormat(AStream, item, i);
|
||||
end;
|
||||
inc(i);
|
||||
end;
|
||||
@@ -2363,8 +2412,7 @@ begin
|
||||
AStream.WriteWord(WordToLE(ACol));
|
||||
|
||||
{ Index to XF record, according to formatting }
|
||||
//AStream.WriteWord(0);
|
||||
WriteXFIndex(AStream, ACell);
|
||||
AStream.WriteWord(FindXFIndex(ACell));
|
||||
|
||||
{ Encoded result of RPN formula }
|
||||
WriteRPNResult(AStream, ACell);
|
||||
@@ -2654,6 +2702,7 @@ var
|
||||
colindex: Cardinal;
|
||||
rowheight: Word;
|
||||
h: Single;
|
||||
fmt: PsCellFormat;
|
||||
begin
|
||||
if (ARowIndex >= FLimitations.MaxRowCount) or
|
||||
(AFirstColIndex >= FLimitations.MaxColCount) or
|
||||
@@ -2665,14 +2714,28 @@ begin
|
||||
spaceabove := false;
|
||||
spacebelow := false;
|
||||
colindex := AFirstColIndex;
|
||||
while colindex <= ALastColIndex do begin
|
||||
while colindex <= ALastColIndex do
|
||||
begin
|
||||
cell := ASheet.FindCell(ARowindex, colindex);
|
||||
if (cell <> nil) then
|
||||
begin
|
||||
fmt := Workbook.GetPointerToCellFormat(cell^.FormatIndex);
|
||||
if (uffBorder in fmt^.UsedFormattingFields) then
|
||||
begin
|
||||
if (cbNorth in fmt^.Border) and (fmt^.BorderStyles[cbNorth].LineStyle = lsThick)
|
||||
then spaceabove := true;
|
||||
if (cbSouth in fmt^.Border) and (fmt^.BorderStyles[cbSouth].LineStyle = lsThick)
|
||||
then spacebelow := true;
|
||||
end;
|
||||
end;
|
||||
{
|
||||
if (cell <> nil) and (uffBorder in cell^.UsedFormattingFields) then begin
|
||||
if (cbNorth in cell^.Border) and (cell^.BorderStyles[cbNorth].LineStyle = lsThick)
|
||||
then spaceabove := true;
|
||||
if (cbSouth in cell^.Border) and (cell^.BorderStyles[cbSouth].LineStyle = lsThick)
|
||||
then spacebelow := true;
|
||||
end;
|
||||
}
|
||||
if spaceabove and spacebelow then break;
|
||||
inc(colindex);
|
||||
end;
|
||||
@@ -3023,10 +3086,63 @@ begin
|
||||
AStream.WriteWord(WordToLE(600));
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFFWriter.WriteXF(AStream: TStream; ACellFormat: PsCellFormat;
|
||||
XFType_Prot: Byte = 0);
|
||||
begin
|
||||
Unused(AStream, ACellFormat, XFType_Prot);
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFFWriter.WriteXFRecords(AStream: TStream);
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
// XF0
|
||||
WriteXF(AStream, nil, MASK_XF_TYPE_PROT_STYLE_XF);
|
||||
// XF1
|
||||
WriteXF(AStream, nil, MASK_XF_TYPE_PROT_STYLE_XF);
|
||||
// XF2
|
||||
WriteXF(AStream, nil, MASK_XF_TYPE_PROT_STYLE_XF);
|
||||
// XF3
|
||||
WriteXF(AStream, nil, MASK_XF_TYPE_PROT_STYLE_XF);
|
||||
// XF4
|
||||
WriteXF(AStream, nil, MASK_XF_TYPE_PROT_STYLE_XF);
|
||||
// XF5
|
||||
WriteXF(AStream, nil, MASK_XF_TYPE_PROT_STYLE_XF);
|
||||
// XF6
|
||||
WriteXF(AStream, nil, MASK_XF_TYPE_PROT_STYLE_XF);
|
||||
// XF7
|
||||
WriteXF(AStream, nil, MASK_XF_TYPE_PROT_STYLE_XF);
|
||||
// XF8
|
||||
WriteXF(AStream, nil, MASK_XF_TYPE_PROT_STYLE_XF);
|
||||
// XF9
|
||||
WriteXF(AStream, nil, MASK_XF_TYPE_PROT_STYLE_XF);
|
||||
// XF10
|
||||
WriteXF(AStream, nil, MASK_XF_TYPE_PROT_STYLE_XF);
|
||||
// XF11
|
||||
WriteXF(AStream, nil, MASK_XF_TYPE_PROT_STYLE_XF);
|
||||
// XF12
|
||||
WriteXF(AStream, nil, MASK_XF_TYPE_PROT_STYLE_XF);
|
||||
// XF13
|
||||
WriteXF(AStream, nil, MASK_XF_TYPE_PROT_STYLE_XF);
|
||||
// XF14
|
||||
WriteXF(AStream, nil, MASK_XF_TYPE_PROT_STYLE_XF);
|
||||
// XF15 - Default, no formatting
|
||||
WriteXF(AStream, nil, 0);
|
||||
|
||||
// Add all further non-standard format records
|
||||
// The first style was already added --> begin loop with 1
|
||||
for i:=1 to Workbook.GetNumCellFormats - 1 do
|
||||
WriteXF(AStream, Workbook.GetPointerToCellFormat(i), 0);
|
||||
end;
|
||||
|
||||
(*
|
||||
{ Write the index of the XF record, according to formatting of the given cell
|
||||
Valid for BIFF5 and BIFF8.
|
||||
BIFF2 is handled differently. }
|
||||
procedure TsSpreadBIFFWriter.WriteXFIndex(AStream: TStream; ACell: PCell);
|
||||
begin
|
||||
AStream.WriteWord(AStream, LAST_BUILTIN_XF + ACell^.FormatIndex);
|
||||
{
|
||||
var
|
||||
lIndex: Integer;
|
||||
lXFIndex: Word;
|
||||
@@ -3051,7 +3167,8 @@ begin
|
||||
lXFIndex := FFormattingStyles[lIndex].Row;
|
||||
|
||||
AStream.WriteWord(WordToLE(lXFIndex));
|
||||
end;
|
||||
}
|
||||
end; *)
|
||||
|
||||
end.
|
||||
|
||||
|
@@ -58,7 +58,7 @@ const
|
||||
|
||||
{ Function Tokens }
|
||||
// _R: reference; _V: value; _A: array
|
||||
// Offset 0: token; offset 1: index to a built-in sheet function ( ➜ 3.111)
|
||||
// Offset 0: token; offset 1: index to a built-in sheet function ( ➜ 3.111) )
|
||||
INT_EXCEL_TOKEN_FUNC_R = $21;
|
||||
INT_EXCEL_TOKEN_FUNC_V = $41;
|
||||
INT_EXCEL_TOKEN_FUNC_A = $61;
|
||||
@@ -69,7 +69,7 @@ const
|
||||
INT_EXCEL_TOKEN_FUNCVAR_A = $62;
|
||||
|
||||
{ Special tokens }
|
||||
INT_EXCEL_TOKEN_TEXP = $01; // cell belongs to shared formula
|
||||
INT_EXCEL_TOKEN_TEXP = $01; // cell belongs to shared formula
|
||||
|
||||
{ Built-in/worksheet functions }
|
||||
INT_EXCEL_SHEET_FUNC_COUNT = 0;
|
||||
|
@@ -22,8 +22,9 @@ http://openxmldeveloper.org/default.aspx
|
||||
also:
|
||||
http://office.microsoft.com/en-us/excel-help/excel-specifications-and-limits-HP010073849.aspx#BMworksheetworkbook
|
||||
|
||||
AUTHORS: Felipe Monteiro de Carvalho
|
||||
AUTHORS: Felipe Monteiro de Carvalho, Reinier Olislagers, Werner Pamler
|
||||
}
|
||||
|
||||
unit xlsxooxml;
|
||||
|
||||
{$ifdef fpc}
|
||||
@@ -61,7 +62,6 @@ type
|
||||
FDateMode: TDateMode;
|
||||
FPointSeparatorSettings: TFormatSettings;
|
||||
FSharedStrings: TStringList;
|
||||
FXfList: TFPList;
|
||||
FFillList: TFPList;
|
||||
FBorderList: TFPList;
|
||||
FThemeColors: array of TsColorValue;
|
||||
@@ -105,16 +105,23 @@ type
|
||||
FDateMode: TDateMode;
|
||||
FPointSeparatorSettings: TFormatSettings;
|
||||
FSharedStringsCount: Integer;
|
||||
FFillList: array of PCell;
|
||||
FFillList: array of PsCellFormat;
|
||||
FBorderList: array of PsCellFormat;
|
||||
{
|
||||
FFillList: array of TsCell;
|
||||
FBorderList: array of PCell;
|
||||
}
|
||||
protected
|
||||
{ Helper routines }
|
||||
procedure AddDefaultFormats; override;
|
||||
// procedure AddDefaultFormats; override;
|
||||
procedure CreateNumFormatList; override;
|
||||
procedure CreateStreams;
|
||||
procedure DestroyStreams;
|
||||
{
|
||||
function FindBorderInList(ACell: PCell): Integer;
|
||||
function FindFillInList(ACell: PCell): Integer;
|
||||
function FindFillInList(ACell: PCell): Integer; }
|
||||
function FindBorderInList(AFormat: PsCellFormat): Integer;
|
||||
function FindFillInList(AFormat: PsCellFormat): Integer;
|
||||
function GetStyleIndex(ACell: PCell): Cardinal;
|
||||
procedure ListAllBorders;
|
||||
procedure ListAllFills;
|
||||
@@ -305,7 +312,7 @@ type
|
||||
Borders: TsCellBorders;
|
||||
BorderStyles: TsCellBorderStyles;
|
||||
end;
|
||||
|
||||
(*
|
||||
TXFListData = class
|
||||
NumFmtIndex: Integer;
|
||||
FontIndex: Integer;
|
||||
@@ -316,7 +323,7 @@ type
|
||||
WordWrap: Boolean;
|
||||
TextRotation: TsTextRotation;
|
||||
end;
|
||||
|
||||
*)
|
||||
|
||||
{ TsOOXMLNumFormatList }
|
||||
|
||||
@@ -332,47 +339,47 @@ begin
|
||||
fs := Workbook.FormatSettings;
|
||||
cs := AnsiToUTF8(Workbook.FormatSettings.CurrencyString);
|
||||
|
||||
AddFormat( 0, '', nfGeneral);
|
||||
AddFormat( 1, '0', nfFixed);
|
||||
AddFormat( 2, '0.00', nfFixed);
|
||||
AddFormat( 3, '#,##0', nfFixedTh);
|
||||
AddFormat( 4, '#,##0.00', nfFixedTh);
|
||||
AddFormat( 5, '"'+cs+'"#,##0_);("'+cs+'"#,##0)', nfCurrency);
|
||||
AddFormat( 6, '"'+cs+'"#,##0_);[Red]("'+cs+'"#,##0)', nfCurrencyRed);
|
||||
AddFormat( 7, '"'+cs+'"#,##0.00_);("'+cs+'"#,##0.00)', nfCurrency);
|
||||
AddFormat( 8, '"'+cs+'"#,##0.00_);[Red]("'+cs+'"#,##0.00)', nfCurrencyRed);
|
||||
AddFormat( 9, '0%', nfPercentage);
|
||||
AddFormat(10, '0.00%', nfPercentage);
|
||||
AddFormat(11, '0.00E+00', nfExp);
|
||||
AddFormat( 0, nfGeneral, '');
|
||||
AddFormat( 1, nfFixed, '0');
|
||||
AddFormat( 2, nfFixed, '0.00');
|
||||
AddFormat( 3, nfFixedTh, '#,##0');
|
||||
AddFormat( 4, nfFixedTh, '#,##0.00');
|
||||
AddFormat( 5, nfCurrency, '"'+cs+'"#,##0_);("'+cs+'"#,##0)');
|
||||
AddFormat( 6, nfCurrencyRed, '"'+cs+'"#,##0_);[Red]("'+cs+'"#,##0)');
|
||||
AddFormat( 7, nfCurrency, '"'+cs+'"#,##0.00_);("'+cs+'"#,##0.00)');
|
||||
AddFormat( 8, nfCurrencyRed, '"'+cs+'"#,##0.00_);[Red]("'+cs+'"#,##0.00)');
|
||||
AddFormat( 9, nfPercentage, '0%');
|
||||
AddFormat(10, nfPercentage, '0.00%');
|
||||
AddFormat(11, nfExp, '0.00E+00');
|
||||
// fraction formats 12 ('# ?/?') and 13 ('# ??/??') not supported
|
||||
AddFormat(14, fs.ShortDateFormat, nfShortDate); // 'M/D/YY'
|
||||
AddFormat(15, fs.LongDateFormat, nfLongDate); // 'D-MMM-YY'
|
||||
AddFormat(16, 'd/mmm', nfCustom); // 'D-MMM'
|
||||
AddFormat(17, 'mmm/yy', nfCustom); // 'MMM-YY'
|
||||
AddFormat(18, AddAMPM(fs.ShortTimeFormat, fs), nfShortTimeAM); // 'h:mm AM/PM'
|
||||
AddFormat(19, AddAMPM(fs.LongTimeFormat, fs), nfLongTimeAM); // 'h:mm:ss AM/PM'
|
||||
AddFormat(20, fs.ShortTimeFormat, nfShortTime); // 'h:mm'
|
||||
AddFormat(21, fs.LongTimeFormat, nfLongTime); // 'h:mm:ss'
|
||||
AddFormat(22, fs.ShortDateFormat + ' ' + fs.ShortTimeFormat, nfShortDateTime); // 'M/D/YY h:mm' (localized)
|
||||
AddFormat(14, nfShortDate, fs.ShortDateFormat); // 'M/D/YY'
|
||||
AddFormat(15, nfLongDate, fs.LongDateFormat); // 'D-MMM-YY'
|
||||
AddFormat(16, nfCustom, 'd/mmm'); // 'D-MMM'
|
||||
AddFormat(17, nfCustom, 'mmm/yy'); // 'MMM-YY'
|
||||
AddFormat(18, nfShortTimeAM, AddAMPM(fs.ShortTimeFormat, fs)); // 'h:mm AM/PM'
|
||||
AddFormat(19, nfLongTimeAM, AddAMPM(fs.LongTimeFormat, fs)); // 'h:mm:ss AM/PM'
|
||||
AddFormat(20, nfShortTime, fs.ShortTimeFormat); // 'h:mm'
|
||||
AddFormat(21, nfLongTime, fs.LongTimeFormat); // 'h:mm:ss'
|
||||
AddFormat(22, nfShortDateTime, fs.ShortDateFormat + ' ' + fs.ShortTimeFormat); // 'M/D/YY h:mm' (localized)
|
||||
// 23..36 not supported
|
||||
AddFormat(37, '_(#,##0_);(#,##0)', nfCurrency);
|
||||
AddFormat(38, '_(#,##0_);[Red](#,##0)', nfCurrencyRed);
|
||||
AddFormat(39, '_(#,##0.00_);(#,##0.00)', nfCurrency);
|
||||
AddFormat(40, '_(#,##0.00_);[Red](#,##0.00)', nfCurrencyRed);
|
||||
AddFormat(41, '_("'+cs+'"* #,##0_);_("'+cs+'"* (#,##0);_("'+cs+'"* "-"_);_(@_)', nfCustom);
|
||||
AddFormat(42, '_(* #,##0_);_(* (#,##0);_(* "-"_);_(@_)', nfCustom);
|
||||
AddFormat(43, '_("'+cs+'"* #,##0.00_);_("'+cs+'"* (#,##0.00);_("'+cs+'"* "-"??_);_(@_)', nfCustom);
|
||||
AddFormat(44, '_(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(@_)', nfCustom);
|
||||
AddFormat(45, 'nn:ss', nfCustom);
|
||||
AddFormat(46, '[h]:nn:ss', nfTimeInterval);
|
||||
AddFormat(47, 'nn:ss.z', nfCustom);
|
||||
AddFormat(48, '##0.0E+00', nfCustom);
|
||||
AddFormat(37, nfCurrency, '_(#,##0_);(#,##0)');
|
||||
AddFormat(38, nfCurrencyRed, '_(#,##0_);[Red](#,##0)');
|
||||
AddFormat(39, nfCurrency, '_(#,##0.00_);(#,##0.00)');
|
||||
AddFormat(40, nfCurrencyRed, '_(#,##0.00_);[Red](#,##0.00)');
|
||||
AddFormat(41, nfCustom, '_("'+cs+'"* #,##0_);_("'+cs+'"* (#,##0);_("'+cs+'"* "-"_);_(@_)');
|
||||
AddFormat(42, nfCustom, '_(* #,##0_);_(* (#,##0);_(* "-"_);_(@_)');
|
||||
AddFormat(43, nfCustom, '_("'+cs+'"* #,##0.00_);_("'+cs+'"* (#,##0.00);_("'+cs+'"* "-"??_);_(@_)');
|
||||
AddFormat(44, nfCustom, '_(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(@_)');
|
||||
AddFormat(45, nfCustom, 'nn:ss');
|
||||
AddFormat(46, nfTimeInterval, '[h]:nn:ss');
|
||||
AddFormat(47, nfCustom, 'nn:ss.z');
|
||||
AddFormat(48, nfCustom, '##0.0E+00');
|
||||
// 49 ("Text") not supported
|
||||
|
||||
// All indexes from 0 to 163 are reserved for built-in formats.
|
||||
// The first user-defined format starts at 164.
|
||||
FFirstFormatIndexInFile := 164;
|
||||
FNextFormatIndex := 164;
|
||||
FFirstNumFormatIndexInFile := 164;
|
||||
FNextNumFormatIndex := 164;
|
||||
end;
|
||||
|
||||
procedure TsOOXMLNumFormatList.ConvertBeforeWriting(var AFormatString: String;
|
||||
@@ -407,7 +414,8 @@ begin
|
||||
FSharedStrings := TStringList.Create;
|
||||
FFillList := TFPList.Create;
|
||||
FBorderList := TFPList.Create;
|
||||
FXfList := TFPList.Create;
|
||||
FCellFormatList := TsCellFormatList.Create(true);
|
||||
// Allow duplicates because xf indexes used in cell records cannot be found any more.
|
||||
|
||||
FPointSeparatorSettings := DefaultFormatSettings;
|
||||
FPointSeparatorSettings.DecimalSeparator := '.';
|
||||
@@ -417,9 +425,6 @@ destructor TsSpreadOOXMLReader.Destroy;
|
||||
var
|
||||
j: Integer;
|
||||
begin
|
||||
for j := FXfList.Count-1 downto 0 do TObject(FXfList[j]).Free;
|
||||
FXfList.Free;
|
||||
|
||||
for j := FFillList.Count-1 downto 0 do TObject(FFillList[j]).Free;
|
||||
FFillList.Free;
|
||||
|
||||
@@ -432,14 +437,24 @@ begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TsSpreadOOXMLReader.ApplyCellFormatting(ACell: PCell; XfIndex: Integer);
|
||||
procedure TsSpreadOOXMLReader.ApplyCellFormatting(ACell: PCell; XFIndex: Integer);
|
||||
var
|
||||
i: Integer;
|
||||
fmt: PsCellFormat;
|
||||
{
|
||||
xf: TXfListData;
|
||||
numFmtData: TsNumFormatData;
|
||||
fillData: TFillListData;
|
||||
borderData: TBorderListData;
|
||||
j: Integer;
|
||||
}
|
||||
begin
|
||||
if Assigned(ACell) then begin
|
||||
i := FCellFormatList.FindIndexOfID(XFIndex);
|
||||
fmt := FCellFormatList.Items[i];
|
||||
ACell^.FormatIndex := FWorkbook.AddCellFormat(fmt^);
|
||||
end;
|
||||
(*
|
||||
if Assigned(ACell) then begin
|
||||
xf := TXFListData(FXfList.Items[XfIndex]);
|
||||
|
||||
@@ -505,7 +520,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
*)
|
||||
end;
|
||||
|
||||
procedure TsSpreadOOXMLReader.CreateNumFormatList;
|
||||
@@ -626,6 +641,7 @@ var
|
||||
formulaStr: String;
|
||||
sstIndex: Integer;
|
||||
number: Double;
|
||||
fmt: TsCellFormat;
|
||||
begin
|
||||
if ANode = nil then
|
||||
exit;
|
||||
@@ -644,8 +660,11 @@ begin
|
||||
|
||||
// get style index
|
||||
s := GetAttrValue(ANode, 's');
|
||||
if s <> '' then
|
||||
if s <> '' then begin
|
||||
ApplyCellFormatting(cell, StrToInt(s));
|
||||
fmt := Workbook.GetCellFormat(cell^.FormatIndex);
|
||||
end else
|
||||
InitFormatRecord(fmt);
|
||||
|
||||
// get data
|
||||
datanode := ANode.FirstChild;
|
||||
@@ -699,10 +718,10 @@ begin
|
||||
if (s = '') or (s = 'n') then begin
|
||||
// Number or date/time, depending on format
|
||||
number := StrToFloat(dataStr, FPointSeparatorSettings);
|
||||
if IsDateTimeFormat(cell^.NumberFormatStr) then begin
|
||||
if cell^.NumberFormat <> nfTimeInterval then // no correction of time origin for "time interval" format
|
||||
if IsDateTimeFormat(fmt.NumberFormatStr) then begin
|
||||
if fmt.NumberFormat <> nfTimeInterval then // no correction of time origin for "time interval" format
|
||||
number := ConvertExcelDateTimeToDateTime(number, FDateMode);
|
||||
AWorksheet.WriteDateTime(cell, number, cell^.NumberFormatStr)
|
||||
AWorksheet.WriteDateTime(cell, number, fmt.NumberFormatStr)
|
||||
end
|
||||
else
|
||||
AWorksheet.WriteNumber(cell, number);
|
||||
@@ -751,79 +770,133 @@ var
|
||||
node: TDOMNode;
|
||||
childNode: TDOMNode;
|
||||
nodeName: String;
|
||||
xf: TXfListData;
|
||||
fmt: TsCellFormat;
|
||||
s1, s2: String;
|
||||
i, numFmtIndex, fillIndex, borderIndex: Integer;
|
||||
numFmtData: TsNumFormatData;
|
||||
fillData: TFillListData;
|
||||
borderData: TBorderListData;
|
||||
begin
|
||||
node := ANode.FirstChild;
|
||||
while Assigned(node) do begin
|
||||
while Assigned(node) do
|
||||
begin
|
||||
nodeName := node.NodeName;
|
||||
if nodeName = 'xf' then begin
|
||||
xf := TXfListData.Create;
|
||||
if nodeName = 'xf' then
|
||||
begin
|
||||
InitFormatRecord(fmt);
|
||||
fmt.ID := FCellFormatList.Count;
|
||||
fmt.Name := '';
|
||||
|
||||
// strange: sometimes the "apply*" are missing. Therefore, it may be better
|
||||
// to check against "<>0" instead of "=1"
|
||||
s1 := GetAttrValue(node, 'numFmtId');
|
||||
s2 := GetAttrValue(node, 'applyNumberFormat');
|
||||
if (s1 <> '') and (s2 <> '0') then xf.NumFmtIndex := StrToInt(s1);
|
||||
if (s1 <> '') and (s2 <> '0') then
|
||||
begin
|
||||
numFmtIndex := StrToInt(s1);
|
||||
i := NumFormatList.FindByIndex(numFmtIndex);
|
||||
if i > -1 then
|
||||
begin
|
||||
numFmtData := NumFormatList.Items[i];
|
||||
fmt.NumberFormat := numFmtData.NumFormat;
|
||||
fmt.NumberFormatStr := numFmtData.FormatString;
|
||||
if numFmtData.NumFormat <> nfGeneral then
|
||||
Include(fmt.UsedFormattingFields, uffNumberFormat);
|
||||
end;
|
||||
end;
|
||||
|
||||
s1 := GetAttrValue(node, 'fontId');
|
||||
s2 := GetAttrValue(node, 'applyFont');
|
||||
if (s1 <> '') and (s2 <> '0') then xf.FontIndex := StrToInt(s1);
|
||||
if (s1 <> '') and (s2 <> '0') then
|
||||
begin
|
||||
fmt.FontIndex := StrToInt(s1);
|
||||
if fmt.FontIndex = 1 then
|
||||
Include(fmt.UsedFormattingFields, uffBold)
|
||||
else if fmt.FontIndex > 1 then
|
||||
Include(fmt.UsedFormattingFields, uffFont);
|
||||
end;
|
||||
|
||||
s1 := GetAttrValue(node, 'fillId');
|
||||
s2 := GetAttrValue(node, 'applyFill');
|
||||
if (s1 <> '') and (s2 <> '0') then xf.FillIndex := StrToInt(s1);
|
||||
if (s1 <> '') and (s2 <> '0') then
|
||||
begin
|
||||
fillIndex := StrToInt(s1);
|
||||
fillData := FFillList[fillIndex];
|
||||
if (fillData <> nil) and (fillData.PatternType <> 'none') then begin
|
||||
Include(fmt.UsedFormattingFields, uffBackgroundColor);
|
||||
fmt.BackgroundColor := fillData.FgColor;
|
||||
end;
|
||||
end;
|
||||
|
||||
s1 := GetAttrValue(node, 'borderId');
|
||||
s2 := GetAttrValue(node, 'applyBorder');
|
||||
if (s1 <> '') and (s2 <> '0') then xf.BorderIndex := StrToInt(s1);
|
||||
if (s1 <> '') and (s2 <> '0') then
|
||||
begin
|
||||
borderIndex := StrToInt(s1);
|
||||
borderData := FBorderList[borderIndex];
|
||||
if (borderData <> nil) then
|
||||
begin
|
||||
fmt.BorderStyles := borderData.BorderStyles;
|
||||
fmt.Border := borderData.Borders;
|
||||
end;
|
||||
end;
|
||||
|
||||
s2 := GetAttrValue(node, 'applyAlignment');
|
||||
if (s2 <> '0') then begin
|
||||
if (s2 <> '0') and (s2 <> '') then begin
|
||||
childNode := node.FirstChild;
|
||||
while Assigned(childNode) do begin
|
||||
nodeName := childNode.NodeName;
|
||||
if nodeName = 'alignment' then begin
|
||||
s1 := GetAttrValue(childNode, 'horizontal');
|
||||
if s1 = 'left' then
|
||||
xf.HorAlignment := haLeft
|
||||
fmt.HorAlignment := haLeft
|
||||
else
|
||||
if s1 = 'center' then
|
||||
xf.HorAlignment := haCenter
|
||||
fmt.HorAlignment := haCenter
|
||||
else
|
||||
if s1 = 'right' then
|
||||
xf.HorAlignment := haRight;
|
||||
fmt.HorAlignment := haRight;
|
||||
|
||||
s1 := GetAttrValue(childNode, 'vertical');
|
||||
if s1 = 'top' then
|
||||
xf.VertAlignment := vaTop
|
||||
fmt.VertAlignment := vaTop
|
||||
else
|
||||
if s1 = 'center' then
|
||||
xf.VertAlignment := vaCenter
|
||||
fmt.VertAlignment := vaCenter
|
||||
else
|
||||
if s1 = 'bottom' then
|
||||
xf.VertAlignment := vaBottom;
|
||||
fmt.VertAlignment := vaBottom;
|
||||
|
||||
s1 := GetAttrValue(childNode, 'wrapText');
|
||||
if (s1 <> '0') then
|
||||
xf.WordWrap := true;
|
||||
Include(fmt.UsedFormattingFields, uffWordWrap);
|
||||
|
||||
s1 := GetAttrValue(childNode, 'textRotation');
|
||||
if s1 = '90' then
|
||||
xf.TextRotation := rt90DegreeCounterClockwiseRotation
|
||||
fmt.TextRotation := rt90DegreeCounterClockwiseRotation
|
||||
else
|
||||
if s1 = '180' then
|
||||
xf.TextRotation := rt90DegreeClockwiseRotation
|
||||
fmt.TextRotation := rt90DegreeClockwiseRotation
|
||||
else
|
||||
if s1 = '255' then
|
||||
xf.TextRotation := rtStacked
|
||||
fmt.TextRotation := rtStacked
|
||||
else
|
||||
xf.TextRotation := trHorizontal;
|
||||
fmt.TextRotation := trHorizontal;
|
||||
end;
|
||||
childNode := childNode.NextSibling;
|
||||
end;
|
||||
end;
|
||||
FXfList.Add(xf);
|
||||
if fmt.FontIndex > 0 then
|
||||
Include(fmt.UsedFormattingFields, uffFont);
|
||||
if fmt.Border <> [] then
|
||||
Include(fmt.UsedFormattingFields, uffBorder);
|
||||
if fmt.HorAlignment <> haDefault then
|
||||
Include(fmt.UsedFormattingFields, uffHorAlign);
|
||||
if fmt.VertAlignment <> vaDefault then
|
||||
Include(fmt.UsedFormattingFields, uffVertAlign);
|
||||
if fmt.TextRotation <> trHorizontal then
|
||||
Include(fmt.UsedFormattingFields, uffTextRotation);
|
||||
FCellFormatList.Add(fmt);
|
||||
end;
|
||||
node := node.NextSibling;
|
||||
end;
|
||||
@@ -1003,8 +1076,8 @@ begin
|
||||
fntStyles := fnt.Style;
|
||||
fntColor := fnt.Color;
|
||||
end else begin
|
||||
fntName := DEFAULTFONTNAME;
|
||||
fntSize := DEFAULTFONTSIZE;
|
||||
fntName := DEFAULT_FONTNAME;
|
||||
fntSize := DEFAULT_FONTSIZE;
|
||||
fntStyles := [];
|
||||
fntColor := scBlack;
|
||||
end;
|
||||
@@ -1245,14 +1318,19 @@ end;
|
||||
procedure TsSpreadOOXMLReader.ReadSheetList(ANode: TDOMNode; AList: TStrings);
|
||||
var
|
||||
node: TDOMNode;
|
||||
nodename: String;
|
||||
sheetName: String;
|
||||
//sheetId: String;
|
||||
begin
|
||||
node := ANode.FirstChild;
|
||||
while node <> nil do begin
|
||||
sheetName := GetAttrValue(node, 'name');
|
||||
//sheetId := GetAttrValue(node, 'sheetId');
|
||||
AList.Add(sheetName);
|
||||
nodename := node.NodeName;
|
||||
if nodename = 'sheet' then
|
||||
begin
|
||||
sheetName := GetAttrValue(node, 'name');
|
||||
//sheetId := GetAttrValue(node, 'sheetId');
|
||||
AList.Add(sheetName);
|
||||
end;
|
||||
node := node.NextSibling;
|
||||
end;
|
||||
end;
|
||||
@@ -1521,6 +1599,7 @@ end;
|
||||
- Bold styles for cells having UsedFormattingFileds = [uffBold]
|
||||
All other styles will be added by "ListAllFormattingStyles".
|
||||
}
|
||||
(*
|
||||
procedure TsSpreadOOXMLWriter.AddDefaultFormats();
|
||||
// We store the index of the XF record that will be assigned to this style in
|
||||
// the "row" of the style. Will be needed when writing the XF record.
|
||||
@@ -1541,7 +1620,9 @@ begin
|
||||
|
||||
NextXFIndex := 2;
|
||||
end;
|
||||
*)
|
||||
|
||||
(*
|
||||
{ Looks for the combination of border attributes of the given cell in the
|
||||
FBorderList and returns its index. }
|
||||
function TsSpreadOOXMLWriter.FindBorderInList(ACell: PCell): Integer;
|
||||
@@ -1566,7 +1647,32 @@ begin
|
||||
// Not found --> return -1
|
||||
Result := -1;
|
||||
end;
|
||||
*)
|
||||
{ Looks for the combination of border attributes of the given format record in
|
||||
the FBorderList and returns its index. }
|
||||
function TsSpreadOOXMLWriter.FindBorderInList(AFormat: PsCellFormat): Integer;
|
||||
var
|
||||
i: Integer;
|
||||
fmt: PsCellFormat;
|
||||
begin
|
||||
// No cell, or border-less --> index 0
|
||||
if (AFormat = nil) or not (uffBorder in AFormat.UsedFormattingFields) then begin
|
||||
Result := 0;
|
||||
exit;
|
||||
end;
|
||||
|
||||
for i:=0 to High(FBorderList) do begin
|
||||
fmt := FBorderList[i];
|
||||
if SameCellBorders(fmt, AFormat) then begin
|
||||
Result := i;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
// Not found --> return -1
|
||||
Result := -1;
|
||||
end;
|
||||
(*
|
||||
{ Looks for the combination of fill attributes of the given cell in the
|
||||
FFillList and returns its index. }
|
||||
function TsSpreadOOXMLWriter.FindFillInList(ACell: PCell): Integer;
|
||||
@@ -1593,11 +1699,46 @@ begin
|
||||
// Not found --> return -1
|
||||
Result := -1;
|
||||
end;
|
||||
*)
|
||||
|
||||
{ Looks for the combination of fill attributes of the given format record in the
|
||||
FFillList and returns its index. }
|
||||
function TsSpreadOOXMLWriter.FindFillInList(AFormat: PsCellFormat): Integer;
|
||||
var
|
||||
i: Integer;
|
||||
fmt: PsCellFormat;
|
||||
begin
|
||||
if (AFormat = nil) or not (uffBackgroundColor in AFormat^.UsedFormattingFields)
|
||||
then begin
|
||||
Result := 0;
|
||||
exit;
|
||||
end;
|
||||
|
||||
// Index 0 is "no fill" which already has been handled.
|
||||
// Index 1 is also pre-defined (gray 25%)
|
||||
for i:=2 to High(FFillList) do begin
|
||||
fmt := FFillList[i];
|
||||
if (fmt <> nil) and (uffBackgroundColor in fmt^.UsedFormattingFields) then
|
||||
if (AFormat^.BackgroundColor = fmt^.BackgroundColor) then
|
||||
begin
|
||||
Result := i;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
// Not found --> return -1
|
||||
Result := -1;
|
||||
end;
|
||||
|
||||
|
||||
{ Determines the formatting index which a given cell has in list of
|
||||
"FormattingStyles" which correspond to the section cellXfs of the styles.xml
|
||||
file. }
|
||||
function TsSpreadOOXMLWriter.GetStyleIndex(ACell: PCell): Cardinal;
|
||||
begin
|
||||
Result := ACell^.FormatIndex;
|
||||
end;
|
||||
{
|
||||
var
|
||||
idx: Integer;
|
||||
begin
|
||||
@@ -1613,14 +1754,26 @@ end;
|
||||
To be used for the styles.xml. }
|
||||
procedure TsSpreadOOXMLWriter.ListAllBorders;
|
||||
var
|
||||
styleCell: PCell;
|
||||
//styleCell: PCell;
|
||||
i, n : Integer;
|
||||
fmt: PsCellFormat;
|
||||
begin
|
||||
// first list entry is a no-border cell
|
||||
SetLength(FBorderList, 1);
|
||||
n := 1;
|
||||
SetLength(FBorderList, n);
|
||||
FBorderList[0] := nil;
|
||||
|
||||
n := 1;
|
||||
for i := 0 to FWorkbook.GetNumCellFormats - 1 do
|
||||
begin
|
||||
fmt := FWorkbook.GetPointerToCellFormat(i);
|
||||
if FindBorderInList(fmt) = -1 then
|
||||
begin
|
||||
SetLength(FBorderList, n+1);
|
||||
FBorderList[n] := fmt;
|
||||
inc(n);
|
||||
end;
|
||||
end;
|
||||
{
|
||||
for i := 0 to High(FFormattingStyles) do begin
|
||||
styleCell := @FFormattingStyles[i];
|
||||
if FindBorderInList(styleCell) = -1 then begin
|
||||
@@ -1628,7 +1781,7 @@ begin
|
||||
FBorderList[n] := styleCell;
|
||||
inc(n);
|
||||
end;
|
||||
end;
|
||||
end; }
|
||||
end;
|
||||
|
||||
{ Creates a list of all fill styles found in the workbook.
|
||||
@@ -1638,15 +1791,27 @@ end;
|
||||
To be used for styles.xml. }
|
||||
procedure TsSpreadOOXMLWriter.ListAllFills;
|
||||
var
|
||||
styleCell: PCell;
|
||||
//styleCell: PCell;
|
||||
i, n: Integer;
|
||||
fmt: PsCellFormat;
|
||||
begin
|
||||
// Add built-in fills first.
|
||||
SetLength(FFillList, 2);
|
||||
n := 2;
|
||||
SetLength(FFillList, n);
|
||||
FFillList[0] := nil; // built-in "no fill"
|
||||
FFillList[1] := nil; // built-in "gray125"
|
||||
|
||||
n := 2;
|
||||
for i := 0 to FWorkbook.GetNumCellFormats - 1 do
|
||||
begin
|
||||
fmt := FWorkbook.GetPointerToCellFormat(i);
|
||||
if FindFillInList(fmt) = -1 then
|
||||
begin
|
||||
SetLength(FFillList, n+1);
|
||||
FFillList[n] := fmt;
|
||||
inc(n);
|
||||
end;
|
||||
end;
|
||||
{
|
||||
for i := 0 to High(FFormattingStyles) do begin
|
||||
styleCell := @FFormattingStyles[i];
|
||||
if FindFillInList(styleCell) = -1 then begin
|
||||
@@ -1655,6 +1820,7 @@ begin
|
||||
inc(n);
|
||||
end;
|
||||
end;
|
||||
}
|
||||
end;
|
||||
|
||||
procedure TsSpreadOOXMLWriter.WriteBorderList(AStream: TStream);
|
||||
@@ -1662,8 +1828,10 @@ const
|
||||
LINESTYLE_NAME: Array[TsLineStyle] of String = (
|
||||
'thin', 'medium', 'dashed', 'dotted', 'thick', 'double', 'hair');
|
||||
|
||||
procedure WriteBorderStyle(AStream: TStream; ACell: PCell; ABorder: TsCellBorder;
|
||||
ABorderName: String);
|
||||
//procedure WriteBorderStyle(AStream: TStream; ACell: PCell; ABorder: TsCellBorder;
|
||||
// ABorderName: String);
|
||||
procedure WriteBorderStyle(AStream: TStream; AFormatRecord: PsCellFormat;
|
||||
ABorder: TsCellBorder; ABorderName: String);
|
||||
{ border names found in xlsx files for Excel selections:
|
||||
"thin", "hair", "dotted", "dashed", "dashDotDot", "dashDot", "mediumDashDotDot",
|
||||
"slantDashDot", "mediumDashDot", "mediumDashed", "medium", "thick", "double" }
|
||||
@@ -1672,11 +1840,15 @@ const
|
||||
colorName: String;
|
||||
rgb: TsColorValue;
|
||||
begin
|
||||
if (ABorder in ACell^.Border) then begin
|
||||
//if (ABorder in ACell^.Border) then begin
|
||||
if (ABorder in AFormatRecord^.Border) then begin
|
||||
// Line style
|
||||
styleName := LINESTYLE_NAME[ACell.BorderStyles[ABorder].LineStyle];
|
||||
styleName := LINESTYLE_NAME[AFormatRecord^.BorderStyles[ABorder].LineStyle];
|
||||
//styleName := LINESTYLE_NAME[ACell.BorderStyles[ABorder].LineStyle];
|
||||
|
||||
// Border color
|
||||
rgb := Workbook.GetPaletteColor(ACell^.BorderStyles[ABorder].Color);
|
||||
rgb := Workbook.GetPaletteColor(AFormatRecord^.BorderStyles[ABorder].Color);
|
||||
//rgb := Workbook.GetPaletteColor(ACell^.BorderStyles[ABorder].Color);
|
||||
colorName := ColorToHTMLColorStr(rgb, true);
|
||||
AppendToStream(AStream, Format(
|
||||
'<%s style="%s"><color rgb="%s" /></%s>',
|
||||
@@ -1689,25 +1861,33 @@ const
|
||||
|
||||
var
|
||||
i: Integer;
|
||||
styleCell: PCell;
|
||||
// styleCell: PCell;
|
||||
diag: String;
|
||||
begin
|
||||
AppendToStream(AStream, Format(
|
||||
'<borders count="%d">', [Length(FBorderList)]));
|
||||
|
||||
// index 0 -- build-in "no borders"
|
||||
// index 0 -- built-in "no borders"
|
||||
AppendToStream(AStream,
|
||||
'<border>',
|
||||
'<left /><right /><top /><bottom /><diagonal />',
|
||||
'</border>');
|
||||
|
||||
for i:=1 to High(FBorderList) do begin
|
||||
styleCell := FBorderList[i];
|
||||
//styleCell := FBorderList[i];
|
||||
diag := '';
|
||||
if (cbDiagUp in FBorderList[i].Border) then diag := diag + ' diagonalUp="1"';
|
||||
if (cbDiagDown in FBorderList[i].Border) then diag := diag + ' diagonalDown="1"';
|
||||
AppendToStream(AStream,
|
||||
'<border' + diag + '>');
|
||||
WriteBorderStyle(AStream, FBorderList[i], cbWest, 'left');
|
||||
WriteBorderStyle(AStream, FBorderList[i], cbEast, 'right');
|
||||
WriteBorderStyle(AStream, FBorderList[i], cbNorth, 'top');
|
||||
WriteBorderStyle(AStream, FBorderList[i], cbSouth, 'bottom');
|
||||
// OOXML uses the same border style for both diagonals. In agreement with
|
||||
// the biff implementation we select the style from the diagonal-up line.
|
||||
WriteBorderStyle(AStream, FBorderList[i], cbDiagUp, 'diagonal');
|
||||
{
|
||||
WriteBorderStyle(AStream, styleCell, cbWest, 'left');
|
||||
WriteBorderStyle(AStream, styleCell, cbEast, 'right');
|
||||
WriteBorderStyle(AStream, styleCell, cbNorth, 'top');
|
||||
@@ -1715,6 +1895,7 @@ begin
|
||||
// OOXML uses the same border style for both diagonals. In agreement with
|
||||
// the biff implementation we select the style from the diagonal-up line.
|
||||
WriteBorderStyle(AStream, styleCell, cbDiagUp, 'diagonal');
|
||||
}
|
||||
AppendToStream(AStream,
|
||||
'</border>');
|
||||
end;
|
||||
@@ -1750,7 +1931,7 @@ end;
|
||||
procedure TsSpreadOOXMLWriter.WriteFillList(AStream: TStream);
|
||||
var
|
||||
i: Integer;
|
||||
styleCell: PCell;
|
||||
//styleCell: PCell;
|
||||
rgb: TsColorValue;
|
||||
begin
|
||||
AppendToStream(AStream, Format(
|
||||
@@ -1770,8 +1951,9 @@ begin
|
||||
|
||||
// user-defined fills
|
||||
for i:=2 to High(FFillList) do begin
|
||||
styleCell := FFillList[i];
|
||||
rgb := Workbook.GetPaletteColor(styleCell^.BackgroundColor);
|
||||
//styleCell := FFillList[i];
|
||||
//rgb := Workbook.GetPaletteColor(styleCell^.BackgroundColor);
|
||||
rgb := Workbook.GetPaletteColor(FFillList[i]^.BackgroundColor);
|
||||
AppendToStream(AStream,
|
||||
'<fill>',
|
||||
'<patternFill patternType="solid">');
|
||||
@@ -1861,7 +2043,7 @@ var
|
||||
begin
|
||||
s := '';
|
||||
n := 0;
|
||||
i := NumFormatList.FindByIndex(NumFormatList.FirstFormatIndexInFile);
|
||||
i := NumFormatList.FindByIndex(NumFormatList.FirstNumFormatIndexInFile);
|
||||
if i > -1 then begin
|
||||
while i < NumFormatList.Count do begin
|
||||
item := NumFormatList[i];
|
||||
@@ -2083,27 +2265,36 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Writes the style list which the writer has collected in FFormattingStyles. }
|
||||
{ Writes the style list which the workbook has collected in its FormatList }
|
||||
procedure TsSpreadOOXMLWriter.WriteStyleList(AStream: TStream; ANodeName: String);
|
||||
var
|
||||
styleCell: TCell;
|
||||
// styleCell: TCell;
|
||||
s, sAlign: String;
|
||||
fontID: Integer;
|
||||
numFmtId: Integer;
|
||||
fillId: Integer;
|
||||
borderId: Integer;
|
||||
idx: Integer;
|
||||
fmt: PsCellFormat;
|
||||
i: Integer;
|
||||
begin
|
||||
AppendToStream(AStream, Format(
|
||||
'<%s count="%d">', [ANodeName, Length(FFormattingStyles)]));
|
||||
'<%s count="%d">', [ANodeName, FWorkbook.GetNumCellFormats]));
|
||||
// '<%s count="%d">', [ANodeName, Length(FFormattingStyles)]));
|
||||
|
||||
for styleCell in FFormattingStyles do begin
|
||||
// for styleCell in FFormattingStyles do begin
|
||||
for i:=0 to FWorkbook.GetNumCellFormats-1 do
|
||||
begin
|
||||
fmt := FWorkbook.GetPointerToCellFormat(i);
|
||||
s := '';
|
||||
sAlign := '';
|
||||
|
||||
{ Number format }
|
||||
if (uffNumberFormat in styleCell.UsedFormattingFields) then begin
|
||||
idx := NumFormatList.FindFormatOf(@styleCell);
|
||||
// if (uffNumberFormat in styleCell.UsedFormattingFields) then
|
||||
if (uffNumberFormat in fmt^.UsedFormattingFields) then
|
||||
begin
|
||||
// idx := NumFormatList.FindFormatOf(@styleCell);
|
||||
idx := NumFormatList.Find(fmt^.NumberFormat, fmt^.NumberFormatStr);
|
||||
if idx > -1 then begin
|
||||
numFmtID := NumFormatList[idx].Index;
|
||||
s := s + Format('numFmtId="%d" applyNumberFormat="1" ', [numFmtId]);
|
||||
@@ -2112,54 +2303,82 @@ begin
|
||||
|
||||
{ Font }
|
||||
fontId := 0;
|
||||
if (uffBold in fmt^.UsedFormattingFields) then
|
||||
fontID := 1;
|
||||
if (uffFont in fmt^.UsedFormattingFields) then
|
||||
fontID := fmt^.FontIndex;
|
||||
{
|
||||
if (uffBold in styleCell.UsedFormattingFields) then
|
||||
fontId := 1;
|
||||
if (uffFont in styleCell.UsedFormattingFields) then
|
||||
fontId := styleCell.FontIndex;
|
||||
}
|
||||
s := s + Format('fontId="%d" ', [fontId]);
|
||||
if fontID > 0 then s := s + 'applyFont="1" ';
|
||||
|
||||
if ANodeName = 'cellXfs' then s := s + 'xfId="0" ';
|
||||
|
||||
{ Text rotation }
|
||||
{
|
||||
if (uffTextRotation in styleCell.UsedFormattingFields) and (styleCell.TextRotation <> trHorizontal)
|
||||
then
|
||||
case styleCell.TextRotation of
|
||||
case styleCell.TextRotation of}
|
||||
if (uffTextRotation in fmt^.UsedFormattingFields) then
|
||||
case fmt^.TextRotation of
|
||||
trHorizontal : ;
|
||||
rt90DegreeClockwiseRotation : sAlign := sAlign + Format('textRotation="%d" ', [180]);
|
||||
rt90DegreeCounterClockwiseRotation: sAlign := sAlign + Format('textRotation="%d" ', [90]);
|
||||
rtStacked : sAlign := sAlign + Format('textRotation="%d" ', [255]);
|
||||
end;
|
||||
|
||||
{ Text alignment }
|
||||
{
|
||||
if (uffHorAlign in styleCell.UsedFormattingFields) and (styleCell.HorAlignment <> haDefault)
|
||||
then
|
||||
case styleCell.HorAlignment of
|
||||
case styleCell.HorAlignment of }
|
||||
if (uffHorAlign in fmt^.UsedFormattingFields) and (fmt^.HorAlignment <> haDefault)
|
||||
then
|
||||
case fmt.HorAlignment of
|
||||
haLeft : sAlign := sAlign + 'horizontal="left" ';
|
||||
haCenter: sAlign := sAlign + 'horizontal="center" ';
|
||||
haRight : sAlign := sAlign + 'horizontal="right" ';
|
||||
end;
|
||||
|
||||
{
|
||||
if (uffVertAlign in styleCell.UsedformattingFields) and (styleCell.VertAlignment <> vaDefault)
|
||||
then
|
||||
case styleCell.VertAlignment of
|
||||
}
|
||||
if (uffVertAlign in fmt^.UsedFormattingFields) and (fmt^.VertAlignment <> vaDefault)
|
||||
then
|
||||
case fmt.VertAlignment of
|
||||
vaTop : sAlign := sAlign + 'vertical="top" ';
|
||||
vaCenter: sAlign := sAlign + 'vertical="center" ';
|
||||
vaBottom: sAlign := sAlign + 'vertical="bottom" ';
|
||||
end;
|
||||
|
||||
if (uffWordWrap in styleCell.UsedFormattingFields) then
|
||||
//if (uffWordWrap in styleCell.UsedFormattingFields) then
|
||||
if (uffWordWrap in fmt^.UsedFormattingFields) then
|
||||
sAlign := sAlign + 'wrapText="1" ';
|
||||
|
||||
{ Fill }
|
||||
if (uffBackgroundColor in styleCell.UsedFormattingFields) then begin
|
||||
fillID := FindFillInList(@styleCell);
|
||||
{
|
||||
if (uffBackgroundColor in styleCell.UsedFormattingFields) then
|
||||
fillID := FindFillInList(@styleCell); }
|
||||
if (uffBackgroundColor in fmt.UsedFormattingFields) then
|
||||
begin
|
||||
fillID := FindFillInList(fmt);
|
||||
if fillID = -1 then fillID := 0;
|
||||
s := s + Format('fillId="%d" applyFill="1" ', [fillID]);
|
||||
end;
|
||||
|
||||
{ Border }
|
||||
if (uffBorder in styleCell.UsedFormattingFields) then begin
|
||||
borderID := FindBorderInList(@styleCell);
|
||||
{
|
||||
if (uffBorder in styleCell.UsedFormattingFields) then
|
||||
borderID := FindBorderInList(@styleCell); }
|
||||
if (uffBorder in fmt^.UsedFormattingFields) then
|
||||
begin
|
||||
borderID := FindBorderInList(fmt);
|
||||
if borderID = -1 then borderID := 0;
|
||||
s := s + Format('borderId="%d" applyBorder="1" ', [borderID]);
|
||||
end;
|
||||
@@ -2500,7 +2719,7 @@ var
|
||||
begin
|
||||
{ Analyze the workbook and collect all information needed }
|
||||
ListAllNumFormats;
|
||||
ListAllFormattingStyles;
|
||||
//ListAllFormattingStyles;
|
||||
ListAllFills;
|
||||
ListAllBorders;
|
||||
|
||||
@@ -2546,7 +2765,6 @@ var
|
||||
begin
|
||||
cellPosText := TsWorksheet.CellPosToText(ARow, ACol);
|
||||
lStyleIndex := GetStyleIndex(ACell);
|
||||
|
||||
AppendToStream(AStream, Format(
|
||||
'<c r="%s" s="%d">', [CellPosText, lStyleIndex]),
|
||||
'<v></v>',
|
||||
|
Reference in New Issue
Block a user