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:
sekelsenmat
2011-05-26 09:25:56 +00:00
parent a4b7594f31
commit 4570c4785a
5 changed files with 235 additions and 90 deletions

View File

@ -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);

View File

@ -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">

View File

@ -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

View File

@ -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);

View 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.