You've already forked lazarus-ccr
FPSpreadsheet: Finishes implementing a generic font style manager for biff formats. Finishes integrating it with biff8
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@1646 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -94,7 +94,21 @@ type
|
||||
|
||||
TsUsedFormattingFields = set of TsUsedFormattingField;
|
||||
|
||||
{@@ Text rotation formatting }
|
||||
{@@ Text rotation formatting. The text is rotated relative to the standard
|
||||
orientation, which is from left to right horizontal: --->
|
||||
ABC
|
||||
|
||||
So 90 degrees clockwise means that the text will be:
|
||||
| A
|
||||
| B
|
||||
\|/ C
|
||||
|
||||
And 90 degree counter clockwise will be:
|
||||
|
||||
/|\ C
|
||||
| B
|
||||
| A
|
||||
}
|
||||
|
||||
TsTextRotation = (trHorizontal, rt90DegreeClockwiseRotation,
|
||||
rt90DegreeCounterClockwiseRotation);
|
||||
|
@ -4,16 +4,21 @@
|
||||
<PathDelim Value="\"/>
|
||||
<Name Value="laz_fpspreadsheet"/>
|
||||
<CompilerOptions>
|
||||
<Version Value="8"/>
|
||||
<Version Value="10"/>
|
||||
<PathDelim Value="\"/>
|
||||
<SearchPaths>
|
||||
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
|
||||
</SearchPaths>
|
||||
<Parsing>
|
||||
<SyntaxOptions>
|
||||
<UseAnsiStrings Value="False"/>
|
||||
</SyntaxOptions>
|
||||
</Parsing>
|
||||
<Other>
|
||||
<CompilerPath Value="$(CompPath)"/>
|
||||
</Other>
|
||||
</CompilerOptions>
|
||||
<Files Count="19">
|
||||
<Files Count="20">
|
||||
<Item1>
|
||||
<Filename Value="fpolestorage.pas"/>
|
||||
<UnitName Value="fpolestorage"/>
|
||||
@ -90,6 +95,10 @@
|
||||
<Filename Value="fpsconvencoding.pas"/>
|
||||
<UnitName Value="fpsconvencoding"/>
|
||||
</Item19>
|
||||
<Item20>
|
||||
<Filename Value="xlsbiffcommon.pas"/>
|
||||
<UnitName Value="xlsbiffcommon"/>
|
||||
</Item20>
|
||||
</Files>
|
||||
<Type Value="RunAndDesignTime"/>
|
||||
<RequiredPkgs Count="1">
|
||||
|
@ -1,4 +1,4 @@
|
||||
{ This file was automatically created by Lazarus. do not edit!
|
||||
{ This file was automatically created by Lazarus. Do not edit!
|
||||
This source is only used to compile and install the package.
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ uses
|
||||
xlsbiff5, xlsbiff8, xlsxooxml, fpsutils, fpszipper, uvirtuallayer_types,
|
||||
uvirtuallayer, uvirtuallayer_ole, uvirtuallayer_ole_helpers,
|
||||
uvirtuallayer_ole_types, uvirtuallayer_stream, fpolebasic, xlscommon,
|
||||
fpsconvencoding, LazarusPackageIntf;
|
||||
fpsconvencoding, xlsbiffcommon, LazarusPackageIntf;
|
||||
|
||||
implementation
|
||||
|
||||
|
@ -53,7 +53,7 @@ interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, fpcanvas,
|
||||
fpspreadsheet,
|
||||
fpspreadsheet, xlsbiffcommon,
|
||||
{$ifdef USE_NEW_OLE}
|
||||
fpolebasic,
|
||||
{$else}
|
||||
@ -65,7 +65,7 @@ type
|
||||
|
||||
{ TsSpreadBIFF8Reader }
|
||||
|
||||
TsSpreadBIFF8Reader = class(TsCustomSpreadReader)
|
||||
TsSpreadBIFF8Reader = class(TsSpreadBIFFReader)
|
||||
private
|
||||
RecordSize: Word;
|
||||
PendingRecordSize: SizeInt;
|
||||
@ -101,13 +101,12 @@ type
|
||||
|
||||
{ TsSpreadBIFF8Writer }
|
||||
|
||||
TsSpreadBIFF8Writer = class(TsCustomSpreadWriter)
|
||||
TsSpreadBIFF8Writer = class(TsSpreadBIFFWriter)
|
||||
private
|
||||
FFormattingStyles: array of TCell; // An array with cells which are models for the used styles
|
||||
procedure WriteXFIndex(AStream: TStream; ACell: PCell);
|
||||
procedure ListAllFormattingStylesCallback(ACell: PCell; AStream: TStream);
|
||||
procedure ListAllFormattingStyles(AData: TsWorkbook);
|
||||
procedure WriteXFFieldsForFormattingStyles();
|
||||
procedure WriteXFFieldsForFormattingStyles(AStream: TStream);
|
||||
protected
|
||||
procedure AddDefaultFormats(); override;
|
||||
public
|
||||
// constructor Create;
|
||||
// destructor Destroy; override;
|
||||
@ -249,9 +248,19 @@ const
|
||||
|
||||
{ TsSpreadBIFF8Writer }
|
||||
|
||||
{@@ Index to XF record, according to formatting }
|
||||
{ Index to XF record, according to formatting }
|
||||
procedure TsSpreadBIFF8Writer.WriteXFIndex(AStream: TStream; ACell: PCell);
|
||||
var
|
||||
lIndex: Integer;
|
||||
lXFIndex: Word;
|
||||
begin
|
||||
// First try the fast methods for default formats
|
||||
if ACell^.UsedFormattingFields = [] then
|
||||
begin
|
||||
AStream.WriteWord(WordToLE(15));
|
||||
Exit;
|
||||
end;
|
||||
|
||||
if ACell^.UsedFormattingFields = [uffTextRotation] then
|
||||
begin
|
||||
case ACell^.TextRotation of
|
||||
@ -260,56 +269,93 @@ begin
|
||||
else
|
||||
AStream.WriteWord(WordToLE(15));
|
||||
end;
|
||||
end
|
||||
else if ACell^.UsedFormattingFields = [uffBold] then
|
||||
begin
|
||||
AStream.WriteWord(WordToLE(18));
|
||||
end
|
||||
else if ACell^.UsedFormattingFields = [uffBorder] then
|
||||
begin
|
||||
if ACell^.Border = [] then AStream.WriteWord(WordToLE(15))
|
||||
else if ACell^.Border = [cbNorth] then AStream.WriteWord(WordToLE(19))
|
||||
else if ACell^.Border = [cbWest] then AStream.WriteWord(WordToLE(20))
|
||||
else if ACell^.Border = [cbEast] then AStream.WriteWord(WordToLE(21))
|
||||
else if ACell^.Border = [cbSouth] then AStream.WriteWord(WordToLE(22))
|
||||
else if ACell^.Border = [cbNorth, cbWest] then AStream.WriteWord(WordToLE(23))
|
||||
else if ACell^.Border = [cbNorth, cbEast] then AStream.WriteWord(WordToLE(24))
|
||||
else if ACell^.Border = [cbNorth, cbSouth] then AStream.WriteWord(WordToLE(25))
|
||||
else if ACell^.Border = [cbWest, cbEast] then AStream.WriteWord(WordToLE(26))
|
||||
else if ACell^.Border = [cbWest, cbSouth] then AStream.WriteWord(WordToLE(27))
|
||||
else if ACell^.Border = [cbEast, cbSouth] then AStream.WriteWord(WordToLE(28))
|
||||
else if ACell^.Border = [cbNorth, cbWest, cbEast] then AStream.WriteWord(WordToLE(29))
|
||||
else if ACell^.Border = [cbNorth, cbWest, cbSouth] then AStream.WriteWord(WordToLE(30))
|
||||
else if ACell^.Border = [cbNorth, cbEast, cbSouth] then AStream.WriteWord(WordToLE(31))
|
||||
else if ACell^.Border = [cbWest, cbEast, cbSouth] then AStream.WriteWord(WordToLE(32))
|
||||
else if ACell^.Border = [cbNorth, cbWest, cbEast, cbSouth] then AStream.WriteWord(WordToLE(33));
|
||||
end
|
||||
else
|
||||
AStream.WriteWord(WordToLE(15));
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFF8Writer.ListAllFormattingStylesCallback(ACell: PCell; AStream: TStream);
|
||||
begin
|
||||
if ACell^.UsedFormattingFields = [] then Exit;
|
||||
|
||||
// Unfinished ...
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFF8Writer.ListAllFormattingStyles(AData: TsWorkbook);
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
for i := 0 to AData.GetWorksheetCount - 1 do
|
||||
begin
|
||||
IterateThroughCells(nil, AData.GetWorksheetByIndex(i).Cells, ListAllFormattingStylesCallback);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
// Unfinished ...
|
||||
if ACell^.UsedFormattingFields = [uffBold] then
|
||||
begin
|
||||
AStream.WriteWord(WordToLE(18));
|
||||
Exit;
|
||||
end;
|
||||
|
||||
// If not, then we need to search in the list of dynamic formats
|
||||
|
||||
lIndex := FindFormattingInList(ACell);
|
||||
// Carefully check the index
|
||||
if (lIndex < 0) or (lIndex > Length(FFormattingStyles)) then
|
||||
raise Exception.Create('[TsSpreadBIFF8Writer.WriteXFIndex] Invalid Index, this should not happen!');
|
||||
|
||||
lXFIndex := FFormattingStyles[lIndex].Row;
|
||||
|
||||
AStream.WriteWord(WordToLE(lXFIndex));
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFF8Writer.WriteXFFieldsForFormattingStyles();
|
||||
procedure TsSpreadBIFF8Writer.WriteXFFieldsForFormattingStyles(AStream: TStream);
|
||||
var
|
||||
i: Integer;
|
||||
lFontIndex: Word;
|
||||
lTextRotation: Byte;
|
||||
lBorders: TsCellBorders;
|
||||
begin
|
||||
// Unfinished ...
|
||||
// The first 4 styles were already added
|
||||
for i := 4 to Length(FFormattingStyles) - 1 do
|
||||
begin
|
||||
// Default styles
|
||||
lFontIndex := 0;
|
||||
lTextRotation := XF_ROTATION_HORIZONTAL;
|
||||
lBorders := [];
|
||||
|
||||
// Now apply the modifications
|
||||
if uffBorder in FFormattingStyles[i].UsedFormattingFields then
|
||||
lBorders := FFormattingStyles[i].Border;
|
||||
|
||||
if uffTextRotation in FFormattingStyles[i].UsedFormattingFields then
|
||||
begin
|
||||
case FFormattingStyles[i].TextRotation of
|
||||
trHorizontal: lTextRotation := XF_ROTATION_HORIZONTAL;
|
||||
rt90DegreeClockwiseRotation: lTextRotation := XF_ROTATION_90_DEGREE_CLOCKWISE;
|
||||
rt90DegreeCounterClockwiseRotation: lTextRotation := XF_ROTATION_90_DEGREE_COUNTERCLOCKWISE;
|
||||
end;
|
||||
end;
|
||||
|
||||
if uffBold in FFormattingStyles[i].UsedFormattingFields then
|
||||
lFontIndex := 1;
|
||||
|
||||
// if uffBackgroundColor in FFormattingStyles[i].UsedFormattingFields then
|
||||
// lFontIndex := 1;
|
||||
|
||||
// And finally write the style
|
||||
WriteXF(AStream, lFontIndex, 0, lTextRotation, lBorders);
|
||||
end;
|
||||
end;
|
||||
|
||||
{@@
|
||||
These are default formats which are added as XF fields regardless of being used
|
||||
in the document or not.
|
||||
}
|
||||
procedure TsSpreadBIFF8Writer.AddDefaultFormats();
|
||||
begin
|
||||
NextXFIndex := 19;
|
||||
|
||||
SetLength(FFormattingStyles, 4);
|
||||
|
||||
// XF15 - Default, no formatting
|
||||
FFormattingStyles[0].UsedFormattingFields := [];
|
||||
FFormattingStyles[0].Row := 15;
|
||||
|
||||
// XF16 - Rotated
|
||||
FFormattingStyles[1].UsedFormattingFields := [uffTextRotation];
|
||||
FFormattingStyles[1].Row := 16;
|
||||
FFormattingStyles[1].TextRotation := rt90DegreeCounterClockwiseRotation;
|
||||
|
||||
// XF17 - Rotated
|
||||
FFormattingStyles[2].UsedFormattingFields := [uffTextRotation];
|
||||
FFormattingStyles[2].Row := 17;
|
||||
FFormattingStyles[2].TextRotation := rt90DegreeClockwiseRotation;
|
||||
|
||||
// XF18 - Bold
|
||||
FFormattingStyles[3].UsedFormattingFields := [uffBold];
|
||||
FFormattingStyles[3].Row := 18;
|
||||
end;
|
||||
|
||||
{*******************************************************************
|
||||
@ -430,39 +476,9 @@ begin
|
||||
WriteXF(AStream, 0, 0, XF_ROTATION_90_DEGREE_CLOCKWISE, []);
|
||||
// XF18 - Bold
|
||||
WriteXF(AStream, 1, 0, XF_ROTATION_HORIZONTAL, []);
|
||||
// XF19 - Border
|
||||
WriteXF(AStream, 0, 0, XF_ROTATION_HORIZONTAL, [cbNorth]);
|
||||
// XF20 - Border
|
||||
WriteXF(AStream, 0, 0, XF_ROTATION_HORIZONTAL, [cbWest]);
|
||||
// XF21 - Border
|
||||
WriteXF(AStream, 0, 0, XF_ROTATION_HORIZONTAL, [cbEast]);
|
||||
// XF22 - Border
|
||||
WriteXF(AStream, 0, 0, XF_ROTATION_HORIZONTAL, [cbSouth]);
|
||||
// XF23 - Border
|
||||
WriteXF(AStream, 0, 0, XF_ROTATION_HORIZONTAL, [cbNorth, cbWest]);
|
||||
// XF24 - Border
|
||||
WriteXF(AStream, 0, 0, XF_ROTATION_HORIZONTAL, [cbNorth, cbEast]);
|
||||
// XF25 - Border
|
||||
WriteXF(AStream, 0, 0, XF_ROTATION_HORIZONTAL, [cbNorth, cbSouth]);
|
||||
// XF26 - Border
|
||||
WriteXF(AStream, 0, 0, XF_ROTATION_HORIZONTAL, [cbWest, cbEast]);
|
||||
// XF27 - Border
|
||||
WriteXF(AStream, 0, 0, XF_ROTATION_HORIZONTAL, [cbWest, cbSouth]);
|
||||
// XF28 - Border
|
||||
WriteXF(AStream, 0, 0, XF_ROTATION_HORIZONTAL, [cbEast, cbSouth]);
|
||||
// XF29 - Border
|
||||
WriteXF(AStream, 0, 0, XF_ROTATION_HORIZONTAL, [cbNorth, cbWest, cbEast]);
|
||||
// XF30 - Border
|
||||
WriteXF(AStream, 0, 0, XF_ROTATION_HORIZONTAL, [cbNorth, cbWest, cbSouth]);
|
||||
// XF31 - Border
|
||||
WriteXF(AStream, 0, 0, XF_ROTATION_HORIZONTAL, [cbNorth, cbEast, cbSouth]);
|
||||
// XF32 - Border
|
||||
WriteXF(AStream, 0, 0, XF_ROTATION_HORIZONTAL, [cbWest, cbEast, cbSouth]);
|
||||
// XF33 - Border
|
||||
WriteXF(AStream, 0, 0, XF_ROTATION_HORIZONTAL, [cbNorth, cbWest, cbEast, cbSouth]);
|
||||
// Add further all non-standard formatting styles
|
||||
// ListAllFormattingStyles(AData);
|
||||
// WriteXFFieldsForFormattingStyles();
|
||||
ListAllFormattingStyles(AData);
|
||||
WriteXFFieldsForFormattingStyles(AStream);
|
||||
|
||||
WriteStyle(AStream);
|
||||
|
||||
|
106
components/fpspreadsheet/xlsbiffcommon.pas
Normal file
106
components/fpspreadsheet/xlsbiffcommon.pas
Normal file
@ -0,0 +1,106 @@
|
||||
unit xlsbiffcommon;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils,
|
||||
fpspreadsheet,
|
||||
fpsutils;
|
||||
|
||||
type
|
||||
|
||||
{ TsSpreadBIFFReader }
|
||||
|
||||
TsSpreadBIFFReader = class(TsCustomSpreadReader)
|
||||
protected
|
||||
end;
|
||||
|
||||
{ TsSpreadBIFFWriter }
|
||||
|
||||
TsSpreadBIFFWriter = class(TsCustomSpreadWriter)
|
||||
protected
|
||||
{
|
||||
An array with cells which are models for the used styles
|
||||
In this array the Row property holds the Index to the corresponding XF field
|
||||
}
|
||||
FFormattingStyles: array of TCell;
|
||||
NextXFIndex: Integer; // Indicates which should be the next XF Index when filling the styles list
|
||||
function FindFormattingInList(AFormat: PCell): Integer;
|
||||
procedure AddDefaultFormats(); virtual;
|
||||
procedure ListAllFormattingStylesCallback(ACell: PCell; AStream: TStream);
|
||||
procedure ListAllFormattingStyles(AData: TsWorkbook);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
{
|
||||
Checks if the style of a cell is in the list FFormattingStyles and returns the index
|
||||
or -1 if it isn't
|
||||
}
|
||||
function TsSpreadBIFFWriter.FindFormattingInList(AFormat: PCell): Integer;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
Result := -1;
|
||||
|
||||
for i := 0 to Length(FFormattingStyles) - 1 do
|
||||
begin
|
||||
if (FFormattingStyles[i].UsedFormattingFields <> AFormat^.UsedFormattingFields) then Continue;
|
||||
|
||||
if uffTextRotation in AFormat^.UsedFormattingFields then
|
||||
if (FFormattingStyles[i].TextRotation <> AFormat^.TextRotation) then Continue;
|
||||
|
||||
if uffBorder in AFormat^.UsedFormattingFields then
|
||||
if (FFormattingStyles[i].Border <> AFormat^.Border) then Continue;
|
||||
|
||||
if uffBackgroundColor in AFormat^.UsedFormattingFields then
|
||||
if (FFormattingStyles[i].BackgroundColor <> AFormat^.BackgroundColor) then Continue;
|
||||
|
||||
// If we arrived here it means that the styles match
|
||||
Exit(i);
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Each descendent should define it's own default formats, if any.
|
||||
Always add the normal, unformatted style first to speed up. }
|
||||
procedure TsSpreadBIFFWriter.AddDefaultFormats();
|
||||
begin
|
||||
SetLength(FFormattingStyles, 0);
|
||||
NextXFIndex := 0;
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFFWriter.ListAllFormattingStylesCallback(ACell: PCell; AStream: TStream);
|
||||
var
|
||||
Len: Integer;
|
||||
begin
|
||||
if ACell^.UsedFormattingFields = [] then Exit;
|
||||
|
||||
if FindFormattingInList(ACell) <> -1 then Exit;
|
||||
|
||||
Len := Length(FFormattingStyles);
|
||||
SetLength(FFormattingStyles, Len+1);
|
||||
FFormattingStyles[Len] := ACell^;
|
||||
FFormattingStyles[Len].Row := NextXFIndex;
|
||||
Inc(NextXFIndex);
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFFWriter.ListAllFormattingStyles(AData: TsWorkbook);
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
SetLength(FFormattingStyles, 0);
|
||||
|
||||
AddDefaultFormats();
|
||||
|
||||
for i := 0 to AData.GetWorksheetCount - 1 do
|
||||
begin
|
||||
IterateThroughCells(nil, AData.GetWorksheetByIndex(i).Cells, ListAllFormattingStylesCallback);
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
Reference in New Issue
Block a user