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 }
|
{@@ List of possible formatting fields }
|
||||||
|
|
||||||
TsUsedFormattingField = (uffTextRotation, uffBold, uffBorder{, uffBackgroundColor});
|
TsUsedFormattingField = (uffTextRotation, uffBold, uffBorder, uffBackgroundColor);
|
||||||
|
|
||||||
{@@ Describes which formatting fields are active }
|
{@@ Describes which formatting fields are active }
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ type
|
|||||||
|
|
||||||
{.@@ Colors in FPSpreadsheet as given by a list of possible default values }
|
{.@@ Colors in FPSpreadsheet as given by a list of possible default values }
|
||||||
|
|
||||||
//TsColor = ();
|
TsColor = (scLtGrey);
|
||||||
|
|
||||||
{@@ Cell structure for TsWorksheet
|
{@@ Cell structure for TsWorksheet
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ type
|
|||||||
UsedFormattingFields: TsUsedFormattingFields;
|
UsedFormattingFields: TsUsedFormattingFields;
|
||||||
TextRotation: TsTextRotation;
|
TextRotation: TsTextRotation;
|
||||||
Border: TsCellBorders;
|
Border: TsCellBorders;
|
||||||
//BackgroundColor: TsColor;
|
BackgroundColor: TsColor;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
PCell = ^TCell;
|
PCell = ^TCell;
|
||||||
@ -232,6 +232,8 @@ type
|
|||||||
|
|
||||||
TsSpreadWriterClass = class of TsCustomSpreadWriter;
|
TsSpreadWriterClass = class of TsCustomSpreadWriter;
|
||||||
|
|
||||||
|
TCellsCallback = procedure (ACell: PCell; AStream: TStream) of object;
|
||||||
|
|
||||||
{ TsCustomSpreadWriter }
|
{ TsCustomSpreadWriter }
|
||||||
|
|
||||||
TsCustomSpreadWriter = class
|
TsCustomSpreadWriter = class
|
||||||
@ -239,8 +241,9 @@ type
|
|||||||
{ Helper routines }
|
{ Helper routines }
|
||||||
function ExpandFormula(AFormula: TsFormula): TsExpandedFormula;
|
function ExpandFormula(AFormula: TsFormula): TsExpandedFormula;
|
||||||
{ General writing methods }
|
{ General writing methods }
|
||||||
procedure WriteCellCallback(data, arg: pointer);
|
procedure WriteCellCallback(ACell: PCell; AStream: TStream);
|
||||||
procedure WriteCellsToStream(AStream: TStream; ACells: TAVLTree);
|
procedure WriteCellsToStream(AStream: TStream; ACells: TAVLTree);
|
||||||
|
procedure IterateThroughCells(AStream: TStream; ACells: TAVLTree; ACallback: TCellsCallback);
|
||||||
procedure WriteToFile(const AFileName: string; AData: TsWorkbook;
|
procedure WriteToFile(const AFileName: string; AData: TsWorkbook;
|
||||||
const AOverwriteExisting: Boolean = False); virtual;
|
const AOverwriteExisting: Boolean = False); virtual;
|
||||||
procedure WriteToStream(AStream: TStream; AData: TsWorkbook); virtual;
|
procedure WriteToStream(AStream: TStream; AData: TsWorkbook); virtual;
|
||||||
@ -1000,14 +1003,8 @@ end;
|
|||||||
|
|
||||||
@see TsCustomSpreadWriter.WriteCellsToStream
|
@see TsCustomSpreadWriter.WriteCellsToStream
|
||||||
}
|
}
|
||||||
procedure TsCustomSpreadWriter.WriteCellCallback(data, arg: pointer);
|
procedure TsCustomSpreadWriter.WriteCellCallback(ACell: PCell; AStream: TStream);
|
||||||
var
|
|
||||||
ACell: PCell;
|
|
||||||
AStream: TStream;
|
|
||||||
begin
|
begin
|
||||||
ACell := PCell(data);
|
|
||||||
AStream := TStream(arg);
|
|
||||||
|
|
||||||
case ACell.ContentType of
|
case ACell.ContentType of
|
||||||
cctNumber: WriteNumber(AStream, ACell^.Row, ACell^.Col, ACell^.NumberValue, ACell);
|
cctNumber: WriteNumber(AStream, ACell^.Row, ACell^.Col, ACell^.NumberValue, ACell);
|
||||||
cctUTF8String: WriteLabel(AStream, ACell^.Row, ACell^.Col, ACell^.UTF8StringValue, ACell);
|
cctUTF8String: WriteLabel(AStream, ACell^.Row, ACell^.Col, ACell^.UTF8StringValue, ACell);
|
||||||
@ -1025,13 +1022,18 @@ end;
|
|||||||
@param ACells List of cells to be writeen
|
@param ACells List of cells to be writeen
|
||||||
}
|
}
|
||||||
procedure TsCustomSpreadWriter.WriteCellsToStream(AStream: TStream; ACells: TAVLTree);
|
procedure TsCustomSpreadWriter.WriteCellsToStream(AStream: TStream; ACells: TAVLTree);
|
||||||
|
begin
|
||||||
|
IterateThroughCells(AStream, ACells, WriteCellCallback);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TsCustomSpreadWriter.IterateThroughCells(AStream: TStream; ACells: TAVLTree; ACallback: TCellsCallback);
|
||||||
var
|
var
|
||||||
AVLNode: TAVLTreeNode;
|
AVLNode: TAVLTreeNode;
|
||||||
begin
|
begin
|
||||||
AVLNode := ACells.FindLowest;
|
AVLNode := ACells.FindLowest;
|
||||||
While Assigned(AVLNode) do
|
While Assigned(AVLNode) do
|
||||||
begin
|
begin
|
||||||
WriteCellCallback(AVLNode.Data, Pointer(AStream));
|
ACallback(PCell(AVLNode.Data), AStream);
|
||||||
AVLNode := ACells.FindSuccessor(AVLNode);
|
AVLNode := ACells.FindSuccessor(AVLNode);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
@ -58,6 +58,7 @@ type
|
|||||||
TsSpreadBIFF2Writer = class(TsCustomSpreadWriter)
|
TsSpreadBIFF2Writer = class(TsCustomSpreadWriter)
|
||||||
private
|
private
|
||||||
function FEKindToExcelID(AElement: TFEKind; var AParamsNum, AFuncNum: Byte): Byte;
|
function FEKindToExcelID(AElement: TFEKind; var AParamsNum, AFuncNum: Byte): Byte;
|
||||||
|
procedure WriteCellFormatting(AStream: TStream; ACell: PCell);
|
||||||
public
|
public
|
||||||
{ General writing methods }
|
{ General writing methods }
|
||||||
procedure WriteToStream(AStream: TStream; AData: TsWorkbook); override;
|
procedure WriteToStream(AStream: TStream; AData: TsWorkbook); override;
|
||||||
@ -120,6 +121,40 @@ begin
|
|||||||
end;
|
end;
|
||||||
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
|
Writes an Excel 2 file to a stream
|
||||||
|
|
||||||
@ -298,9 +333,7 @@ begin
|
|||||||
AStream.WriteWord(WordToLE(ACol));
|
AStream.WriteWord(WordToLE(ACol));
|
||||||
|
|
||||||
{ BIFF2 Attributes }
|
{ BIFF2 Attributes }
|
||||||
AStream.WriteByte($0);
|
WriteCellFormatting(AStream, ACell);
|
||||||
AStream.WriteByte($0);
|
|
||||||
AStream.WriteByte($0);
|
|
||||||
|
|
||||||
{ String with 8-bit size }
|
{ String with 8-bit size }
|
||||||
AStream.WriteByte(L);
|
AStream.WriteByte(L);
|
||||||
|
@ -102,6 +102,12 @@ type
|
|||||||
{ TsSpreadBIFF8Writer }
|
{ TsSpreadBIFF8Writer }
|
||||||
|
|
||||||
TsSpreadBIFF8Writer = class(TsCustomSpreadWriter)
|
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
|
public
|
||||||
// constructor Create;
|
// constructor Create;
|
||||||
// destructor Destroy; override;
|
// destructor Destroy; override;
|
||||||
@ -243,6 +249,69 @@ const
|
|||||||
|
|
||||||
{ TsSpreadBIFF8Writer }
|
{ 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 ()
|
* TsSpreadBIFF8Writer.WriteToFile ()
|
||||||
*
|
*
|
||||||
@ -391,6 +460,9 @@ begin
|
|||||||
WriteXF(AStream, 0, 0, XF_ROTATION_HORIZONTAL, [cbWest, cbEast, cbSouth]);
|
WriteXF(AStream, 0, 0, XF_ROTATION_HORIZONTAL, [cbWest, cbEast, cbSouth]);
|
||||||
// XF33 - Border
|
// XF33 - Border
|
||||||
WriteXF(AStream, 0, 0, XF_ROTATION_HORIZONTAL, [cbNorth, cbWest, cbEast, cbSouth]);
|
WriteXF(AStream, 0, 0, XF_ROTATION_HORIZONTAL, [cbNorth, cbWest, cbEast, cbSouth]);
|
||||||
|
// Add further all non-standard formatting styles
|
||||||
|
// ListAllFormattingStyles(AData);
|
||||||
|
// WriteXFFieldsForFormattingStyles();
|
||||||
|
|
||||||
WriteStyle(AStream);
|
WriteStyle(AStream);
|
||||||
|
|
||||||
@ -770,40 +842,7 @@ begin
|
|||||||
AStream.WriteWord(WordToLE(ACol));
|
AStream.WriteWord(WordToLE(ACol));
|
||||||
|
|
||||||
{ Index to XF record, according to formatting }
|
{ Index to XF record, according to formatting }
|
||||||
if ACell^.UsedFormattingFields = [uffTextRotation] then
|
WriteXFIndex(AStream, ACell);
|
||||||
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));
|
|
||||||
|
|
||||||
{ Byte String with 16-bit size }
|
{ Byte String with 16-bit size }
|
||||||
AStream.WriteWord(WordToLE(L));
|
AStream.WriteWord(WordToLE(L));
|
||||||
|
Reference in New Issue
Block a user