You've already forked lazarus-ccr
FPSpreadsheet: Starts implementing biff2 formatting and also flexible support for biff formats, but all parts are unfinished
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@1644 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -88,7 +88,7 @@ type
|
||||
|
||||
{@@ List of possible formatting fields }
|
||||
|
||||
TsUsedFormattingField = (uffTextRotation, uffBold, uffBorder{, uffBackgroundColor});
|
||||
TsUsedFormattingField = (uffTextRotation, uffBold, uffBorder, uffBackgroundColor);
|
||||
|
||||
{@@ Describes which formatting fields are active }
|
||||
|
||||
@ -109,7 +109,7 @@ type
|
||||
|
||||
{.@@ Colors in FPSpreadsheet as given by a list of possible default values }
|
||||
|
||||
//TsColor = ();
|
||||
TsColor = (scLtGrey);
|
||||
|
||||
{@@ Cell structure for TsWorksheet
|
||||
|
||||
@ -133,7 +133,7 @@ type
|
||||
UsedFormattingFields: TsUsedFormattingFields;
|
||||
TextRotation: TsTextRotation;
|
||||
Border: TsCellBorders;
|
||||
//BackgroundColor: TsColor;
|
||||
BackgroundColor: TsColor;
|
||||
end;
|
||||
|
||||
PCell = ^TCell;
|
||||
@ -232,6 +232,8 @@ type
|
||||
|
||||
TsSpreadWriterClass = class of TsCustomSpreadWriter;
|
||||
|
||||
TCellsCallback = procedure (ACell: PCell; AStream: TStream) of object;
|
||||
|
||||
{ TsCustomSpreadWriter }
|
||||
|
||||
TsCustomSpreadWriter = class
|
||||
@ -239,8 +241,9 @@ type
|
||||
{ Helper routines }
|
||||
function ExpandFormula(AFormula: TsFormula): TsExpandedFormula;
|
||||
{ General writing methods }
|
||||
procedure WriteCellCallback(data, arg: pointer);
|
||||
procedure WriteCellCallback(ACell: PCell; AStream: TStream);
|
||||
procedure WriteCellsToStream(AStream: TStream; ACells: TAVLTree);
|
||||
procedure IterateThroughCells(AStream: TStream; ACells: TAVLTree; ACallback: TCellsCallback);
|
||||
procedure WriteToFile(const AFileName: string; AData: TsWorkbook;
|
||||
const AOverwriteExisting: Boolean = False); virtual;
|
||||
procedure WriteToStream(AStream: TStream; AData: TsWorkbook); virtual;
|
||||
@ -1000,14 +1003,8 @@ end;
|
||||
|
||||
@see TsCustomSpreadWriter.WriteCellsToStream
|
||||
}
|
||||
procedure TsCustomSpreadWriter.WriteCellCallback(data, arg: pointer);
|
||||
var
|
||||
ACell: PCell;
|
||||
AStream: TStream;
|
||||
procedure TsCustomSpreadWriter.WriteCellCallback(ACell: PCell; AStream: TStream);
|
||||
begin
|
||||
ACell := PCell(data);
|
||||
AStream := TStream(arg);
|
||||
|
||||
case ACell.ContentType of
|
||||
cctNumber: WriteNumber(AStream, ACell^.Row, ACell^.Col, ACell^.NumberValue, ACell);
|
||||
cctUTF8String: WriteLabel(AStream, ACell^.Row, ACell^.Col, ACell^.UTF8StringValue, ACell);
|
||||
@ -1025,13 +1022,18 @@ end;
|
||||
@param ACells List of cells to be writeen
|
||||
}
|
||||
procedure TsCustomSpreadWriter.WriteCellsToStream(AStream: TStream; ACells: TAVLTree);
|
||||
begin
|
||||
IterateThroughCells(AStream, ACells, WriteCellCallback);
|
||||
end;
|
||||
|
||||
procedure TsCustomSpreadWriter.IterateThroughCells(AStream: TStream; ACells: TAVLTree; ACallback: TCellsCallback);
|
||||
var
|
||||
AVLNode: TAVLTreeNode;
|
||||
begin
|
||||
AVLNode := ACells.FindLowest;
|
||||
While Assigned(AVLNode) do
|
||||
begin
|
||||
WriteCellCallback(AVLNode.Data, Pointer(AStream));
|
||||
ACallback(PCell(AVLNode.Data), AStream);
|
||||
AVLNode := ACells.FindSuccessor(AVLNode);
|
||||
end;
|
||||
end;
|
||||
|
@ -58,6 +58,7 @@ type
|
||||
TsSpreadBIFF2Writer = class(TsCustomSpreadWriter)
|
||||
private
|
||||
function FEKindToExcelID(AElement: TFEKind; var AParamsNum, AFuncNum: Byte): Byte;
|
||||
procedure WriteCellFormatting(AStream: TStream; ACell: PCell);
|
||||
public
|
||||
{ General writing methods }
|
||||
procedure WriteToStream(AStream: TStream; AData: TsWorkbook); override;
|
||||
@ -120,6 +121,40 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFF2Writer.WriteCellFormatting(AStream: TStream; ACell: PCell);
|
||||
var
|
||||
BorderByte: Byte = 0;
|
||||
begin
|
||||
if ACell^.UsedFormattingFields = [] then
|
||||
begin
|
||||
AStream.WriteByte($0);
|
||||
AStream.WriteByte($0);
|
||||
AStream.WriteByte($0);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
AStream.WriteByte($0);
|
||||
AStream.WriteByte($0);
|
||||
|
||||
// The Border and Background
|
||||
|
||||
BorderByte := 0;
|
||||
|
||||
if uffBorder in ACell^.UsedFormattingFields then
|
||||
begin
|
||||
if cbNorth in ACell^.Border then BorderByte := BorderByte or $20;
|
||||
if cbWest in ACell^.Border then BorderByte := BorderByte or $08;
|
||||
if cbEast in ACell^.Border then BorderByte := BorderByte or $10;
|
||||
if cbSouth in ACell^.Border then BorderByte := BorderByte or $40;
|
||||
end;
|
||||
|
||||
// BIFF2 does not support a background color, just a "shaded" option
|
||||
if uffBackgroundColor in ACell^.UsedFormattingFields then
|
||||
BorderByte := BorderByte or $80;
|
||||
|
||||
AStream.WriteByte(BorderByte);
|
||||
end;
|
||||
|
||||
{
|
||||
Writes an Excel 2 file to a stream
|
||||
|
||||
@ -298,9 +333,7 @@ begin
|
||||
AStream.WriteWord(WordToLE(ACol));
|
||||
|
||||
{ BIFF2 Attributes }
|
||||
AStream.WriteByte($0);
|
||||
AStream.WriteByte($0);
|
||||
AStream.WriteByte($0);
|
||||
WriteCellFormatting(AStream, ACell);
|
||||
|
||||
{ String with 8-bit size }
|
||||
AStream.WriteByte(L);
|
||||
|
@ -102,6 +102,12 @@ type
|
||||
{ TsSpreadBIFF8Writer }
|
||||
|
||||
TsSpreadBIFF8Writer = class(TsCustomSpreadWriter)
|
||||
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();
|
||||
public
|
||||
// constructor Create;
|
||||
// destructor Destroy; override;
|
||||
@ -243,6 +249,69 @@ const
|
||||
|
||||
{ TsSpreadBIFF8Writer }
|
||||
|
||||
{@@ Index to XF record, according to formatting }
|
||||
procedure TsSpreadBIFF8Writer.WriteXFIndex(AStream: TStream; ACell: PCell);
|
||||
begin
|
||||
if ACell^.UsedFormattingFields = [uffTextRotation] then
|
||||
begin
|
||||
case ACell^.TextRotation of
|
||||
rt90DegreeCounterClockwiseRotation: AStream.WriteWord(WordToLE(16));
|
||||
rt90DegreeClockwiseRotation: AStream.WriteWord(WordToLE(17));
|
||||
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);
|
||||
end;
|
||||
|
||||
// Unfinished ...
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFF8Writer.WriteXFFieldsForFormattingStyles();
|
||||
begin
|
||||
// Unfinished ...
|
||||
end;
|
||||
|
||||
{*******************************************************************
|
||||
* TsSpreadBIFF8Writer.WriteToFile ()
|
||||
*
|
||||
@ -391,6 +460,9 @@ begin
|
||||
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();
|
||||
|
||||
WriteStyle(AStream);
|
||||
|
||||
@ -770,40 +842,7 @@ begin
|
||||
AStream.WriteWord(WordToLE(ACol));
|
||||
|
||||
{ Index to XF record, according to formatting }
|
||||
if ACell^.UsedFormattingFields = [uffTextRotation] then
|
||||
begin
|
||||
case ACell^.TextRotation of
|
||||
rt90DegreeCounterClockwiseRotation: AStream.WriteWord(WordToLE(16));
|
||||
rt90DegreeClockwiseRotation: AStream.WriteWord(WordToLE(17));
|
||||
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));
|
||||
WriteXFIndex(AStream, ACell);
|
||||
|
||||
{ Byte String with 16-bit size }
|
||||
AStream.WriteWord(WordToLE(L));
|
||||
|
Reference in New Issue
Block a user