You've already forked lazarus-ccr
fpspreadsheet: Write OOXML string formulas. Write biff2 dimension record.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3456 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -1372,7 +1372,6 @@ function fpsDATEDIF(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
= YD - The difference between the days (years and dates are ignored). }
|
||||
var
|
||||
interval: String;
|
||||
data: TsArgStringArray;
|
||||
start_date, end_date: TDate;
|
||||
res1, res2, res3: TsArgument;
|
||||
begin
|
||||
@ -1599,7 +1598,6 @@ function fpsCOUNTBLANK(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
arg: TsArgument;
|
||||
r, c, n: Cardinal;
|
||||
cell: PCell;
|
||||
begin
|
||||
arg := Args.Pop;
|
||||
case arg.ArgumentType of
|
||||
|
@ -584,6 +584,8 @@ type
|
||||
|
||||
function WriteFormula(ARow, ACol: Cardinal; AFormula: TsFormula): PCell; overload;
|
||||
procedure WriteFormula(ACell: PCell; AFormula: TsFormula); overload;
|
||||
function WriteFormula(ARow, ACol: Cardinal; AFormula: String): PCell; overload;
|
||||
procedure WriteFormula(ACell: PCell; AFormula: String); overload;
|
||||
|
||||
procedure WriteNumber(ARow, ACol: Cardinal; ANumber: double); overload;
|
||||
procedure WriteNumber(ACell: PCell; ANumber: Double); overload;
|
||||
@ -1700,7 +1702,6 @@ end;
|
||||
procedure TsWorksheet.CalcRPNFormula(ACell: PCell);
|
||||
var
|
||||
i: Integer;
|
||||
formula: TsRPNFormula;
|
||||
args: TsArgumentStack;
|
||||
func: TsFormulaFunc;
|
||||
val: TsArgument;
|
||||
@ -2342,7 +2343,6 @@ function TsWorksheet.ReadAsUTF8Text(ACell: PCell): ansistring;
|
||||
ANumberFormat: TsNumberFormat; ANumberFormatStr: string): ansistring;
|
||||
var
|
||||
fs: TFormatSettings;
|
||||
left, right: String;
|
||||
begin
|
||||
fs := FWorkbook.FormatSettings;
|
||||
if IsNan(Value) then
|
||||
@ -3456,6 +3456,35 @@ begin
|
||||
ChangedCell(ACell^.Row, ACell^.Col);
|
||||
end;
|
||||
|
||||
{@@
|
||||
Writes a formula to a given cell
|
||||
|
||||
@param ARow The row of the cell
|
||||
@param ACol The column of the cell
|
||||
@param AFormula The formula string to be written
|
||||
@return Pointer to the cell
|
||||
}
|
||||
function TsWorksheet.WriteFormula(ARow, ACol: Cardinal; AFormula: string): PCell;
|
||||
begin
|
||||
Result := GetCell(ARow, ACol);
|
||||
WriteFormula(Result, AFormula);
|
||||
end;
|
||||
|
||||
{@@
|
||||
Writes a formula to a given cell
|
||||
|
||||
@param ACell Pointer to the cell
|
||||
@param AFormula Formula string to be written
|
||||
}
|
||||
procedure TsWorksheet.WriteFormula(ACell: PCell; AFormula: String);
|
||||
begin
|
||||
if ACell = nil then
|
||||
exit;
|
||||
ACell^.ContentType := cctFormula;
|
||||
ACell^.FormulaValue.FormulaStr := AFormula;
|
||||
ChangedCell(ACell^.Row, ACell^.Col);
|
||||
end;
|
||||
|
||||
{@@
|
||||
Adds a number format to the formatting of a cell
|
||||
|
||||
|
@ -52,7 +52,6 @@
|
||||
<Unit2>
|
||||
<Filename Value="stringtests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="stringtests"/>
|
||||
</Unit2>
|
||||
<Unit3>
|
||||
<Filename Value="numberstests.pas"/>
|
||||
@ -66,16 +65,15 @@
|
||||
<Unit5>
|
||||
<Filename Value="testsutility.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="testsutility"/>
|
||||
</Unit5>
|
||||
<Unit6>
|
||||
<Filename Value="internaltests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="internaltests"/>
|
||||
</Unit6>
|
||||
<Unit7>
|
||||
<Filename Value="formattests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="formattests"/>
|
||||
</Unit7>
|
||||
<Unit8>
|
||||
<Filename Value="colortests.pas"/>
|
||||
|
@ -93,6 +93,7 @@ type
|
||||
procedure WriteCellFormatting(AStream: TStream; ACell: PCell; XFIndex: Word);
|
||||
procedure WriteColWidth(AStream: TStream; ACol: PCol);
|
||||
procedure WriteColWidths(AStream: TStream);
|
||||
procedure WriteDimensions(AStream: TStream; AWorksheet: TsWorksheet);
|
||||
procedure WriteEOF(AStream: TStream);
|
||||
procedure WriteFont(AStream: TStream; AFontIndex: Integer);
|
||||
procedure WriteFonts(AStream: TStream);
|
||||
@ -148,6 +149,7 @@ uses
|
||||
|
||||
const
|
||||
{ Excel record IDs }
|
||||
INT_EXCEL_ID_DIMENSIONS = $0000;
|
||||
INT_EXCEL_ID_BLANK = $0001;
|
||||
INT_EXCEL_ID_INTEGER = $0002;
|
||||
INT_EXCEL_ID_NUMBER = $0003;
|
||||
@ -169,6 +171,15 @@ const
|
||||
INT_EXCEL_MACRO_SHEET = $0040;
|
||||
|
||||
type
|
||||
TBIFF2DimensionsRecord = packed record
|
||||
RecordID: Word;
|
||||
RecordSize: Word;
|
||||
FirstRow: Word;
|
||||
LastRowPlus1: Word;
|
||||
FirstCol: Word;
|
||||
LastColPlus1: Word;
|
||||
end;
|
||||
|
||||
TBIFF2LabelRecord = packed record
|
||||
RecordID: Word;
|
||||
RecordSize: Word;
|
||||
@ -1112,6 +1123,30 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
{
|
||||
Writes an Excel 2 DIMENSIONS record
|
||||
}
|
||||
procedure TsSpreadBIFF2Writer.WriteDimensions(AStream: TStream; AWorksheet: TsWorksheet);
|
||||
var
|
||||
firstRow, lastRow, firstCol, lastCol: Cardinal;
|
||||
rec: TBIFF2DimensionsRecord;
|
||||
begin
|
||||
{ Determine sheet size }
|
||||
GetSheetDimensions(AWorksheet, firstRow, lastRow, firstCol, lastCol);
|
||||
|
||||
{ Populate BIFF record }
|
||||
rec.RecordID := WordToLE(INT_EXCEL_ID_DIMENSIONS);
|
||||
rec.RecordSize := WordToLE(8);
|
||||
rec.FirstRow := WordToLE(firstRow);
|
||||
rec.LastRowPlus1 := WordToLE(Min(lastRow+1, $FFFF)); // avoid WORD overflow
|
||||
rec.FirstCol := WordToLE(firstCol);
|
||||
rec.LastColPlus1 := WordToLE(lastCol+1);
|
||||
|
||||
{ Write BIFF record to stream }
|
||||
AStream.WriteBuffer(rec, SizeOf(rec));
|
||||
end;
|
||||
|
||||
|
||||
{
|
||||
Writes an Excel 2 IXFE record
|
||||
This record contains the "real" XF index if it is > 62.
|
||||
@ -1143,6 +1178,7 @@ begin
|
||||
WriteFormats(AStream);
|
||||
WriteXFRecords(AStream);
|
||||
WriteColWidths(AStream);
|
||||
WriteDimensions(AStream, sheet);
|
||||
WriteRows(AStream, sheet);
|
||||
|
||||
if (boVirtualMode in Workbook.Options) then
|
||||
|
@ -219,7 +219,7 @@ var
|
||||
implementation
|
||||
|
||||
uses
|
||||
fpsStreams;
|
||||
Math, fpsStreams;
|
||||
|
||||
const
|
||||
{ Excel record IDs }
|
||||
@ -563,7 +563,6 @@ procedure TsSpreadBIFF5Writer.WriteDimensions(AStream: TStream; AWorksheet: TsWo
|
||||
var
|
||||
rec: TBIFF5DimensionsRecord;
|
||||
firstCol, lastCol, firstRow, lastRow: Cardinal;
|
||||
lLastRow, lLastCol: Word;
|
||||
begin
|
||||
{ Determine sheet size }
|
||||
GetSheetDimensions(AWorksheet, firstRow, lastRow, firstCol, lastCol);
|
||||
@ -572,37 +571,13 @@ begin
|
||||
rec.RecordID := WordToLE(INT_EXCEL_ID_DIMENSIONS);
|
||||
rec.RecordSize := WordToLE(10);
|
||||
rec.FirstRow := WordToLE(firstRow);
|
||||
rec.LastRowPlus1 := WordToLE(lastRow+1);
|
||||
rec.LastRowPlus1 := WordToLE(Min(lastRow+1, $FFFF)); // avoid word overflow
|
||||
rec.FirstCol := WordToLe(firstCol);
|
||||
rec.LastColPlus1 := WordToLE(lastCol+1);
|
||||
rec.NotUsed := 0;
|
||||
|
||||
{ Write BIFF record }
|
||||
AStream.WriteBuffer(rec, SizeOf(rec));
|
||||
|
||||
(*
|
||||
|
||||
{ BIFF Record header }
|
||||
AStream.WriteWord(WordToLE(INT_EXCEL_ID_DIMENSIONS));
|
||||
AStream.WriteWord(WordToLE(10));
|
||||
|
||||
{ Index to first used row }
|
||||
AStream.WriteWord(0);
|
||||
|
||||
{ Index to last used row, increased by 1 }
|
||||
lLastRow := Word(GetLastRowIndex(AWorksheet)+1);
|
||||
AStream.WriteWord(WordToLE(lLastRow)); // Old dummy value: 33
|
||||
|
||||
{ Index to first used column }
|
||||
AStream.WriteWord(0);
|
||||
|
||||
{ Index to last used column, increased by 1 }
|
||||
lLastCol := Word(GetLastColIndex(AWorksheet)+1);
|
||||
AStream.WriteWord(WordToLE(lLastCol)); // Old dummy value: 10
|
||||
|
||||
{ Not used }
|
||||
AStream.WriteWord(0);
|
||||
*)
|
||||
end;
|
||||
|
||||
{*******************************************************************
|
||||
|
@ -606,30 +606,6 @@ begin
|
||||
|
||||
{ Write BIFF record to stream }
|
||||
AStream.WriteBuffer(rec, SizeOf(rec));
|
||||
|
||||
(*
|
||||
{ BIFF Record header }
|
||||
AStream.WriteWord(WordToLE(INT_EXCEL_ID_DIMENSIONS));
|
||||
AStream.WriteWord(WordToLE(14));
|
||||
|
||||
{ Determine sheet size }
|
||||
GetSheetDimensions(AWorksheet, firstRow, lastRow, firstCol, lastCol);
|
||||
|
||||
{ Index to first used row }
|
||||
AStream.WriteDWord(DWordToLE(firstRow));
|
||||
|
||||
{ Index to last used row, increased by 1 }
|
||||
AStream.WriteDWord(DWordToLE(lastRow+1));
|
||||
|
||||
{ Index to first used column }
|
||||
AStream.WriteWord(WordToLE(firstCol));
|
||||
|
||||
{ Index to last used column, increased by 1 }
|
||||
AStream.WriteWord(WordToLE(lastCol+1));
|
||||
|
||||
{ Not used }
|
||||
AStream.WriteWord(WordToLE(0));
|
||||
*)
|
||||
end;
|
||||
|
||||
{*******************************************************************
|
||||
|
@ -114,6 +114,7 @@ type
|
||||
function GetStyleIndex(ACell: PCell): Cardinal;
|
||||
procedure ListAllBorders;
|
||||
procedure ListAllFills;
|
||||
function PrepareFormula(const AFormula: TsFormula): String;
|
||||
procedure ResetStreams;
|
||||
procedure WriteBorderList(AStream: TStream);
|
||||
procedure WriteCols(AStream: TStream; AWorksheet: TsWorksheet);
|
||||
@ -143,10 +144,16 @@ type
|
||||
protected
|
||||
{ Record writing methods }
|
||||
//todo: add WriteDate
|
||||
procedure WriteBlank(AStream: TStream; const ARow, ACol: Cardinal; ACell: PCell); 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 WriteDateTime(AStream: TStream; const ARow, ACol: Cardinal; const AValue: TDateTime; ACell: PCell); override;
|
||||
procedure WriteBlank(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
ACell: PCell); override;
|
||||
procedure WriteFormula(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
const AFormula: TsFormula; ACell: PCell); 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 WriteDateTime(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
const AValue: TDateTime; ACell: PCell); override;
|
||||
|
||||
public
|
||||
constructor Create(AWorkbook: TsWorkbook); override;
|
||||
@ -1907,15 +1914,6 @@ begin
|
||||
end else
|
||||
begin
|
||||
// The cells need to be written in order, row by row, cell by cell
|
||||
(*
|
||||
c1 := AWorksheet.GetFirstColIndex;
|
||||
c2 := AWorksheet.GetLastColIndex;
|
||||
if (c1 = $FFFFFFFF) and (c2 = 0) then c1 := 0; // avoid arithmetic overflow in case of empty worksheet
|
||||
r1 := AWorksheet.GetFirstRowIndex;
|
||||
r2 := AWorksheet.GetlastRowIndex;
|
||||
if (r1 = $FFFFFFFF) and (r2 = 0) then r1 := 0; // avoid arithmetic overflow in case of empty worksheet
|
||||
// for r := 0 to AWorksheet.GetLastRowIndex do begin
|
||||
*)
|
||||
for r := r1 to r2 do begin
|
||||
// If the row has a custom height add this value to the <row> specification
|
||||
row := AWorksheet.FindRow(r);
|
||||
@ -2364,6 +2362,13 @@ begin
|
||||
SetLength(FSSheets, 0);
|
||||
end;
|
||||
|
||||
{ Prepares a string formula for writing }
|
||||
function TsSpreadOOXMLWriter.PrepareFormula(const AFormula: TsFormula): String;
|
||||
begin
|
||||
Result := AFormula.FormulaStr;
|
||||
if (Result <> '') and (Result[1] = '=') then Delete(Result, 1, 1);
|
||||
end;
|
||||
|
||||
{ Is called before zipping the individual file parts. Rewinds the streams. }
|
||||
procedure TsSpreadOOXMLWriter.ResetStreams;
|
||||
var
|
||||
@ -2486,6 +2491,24 @@ begin
|
||||
'</c>');
|
||||
end;
|
||||
|
||||
{ Writes a string formula to the given cell. }
|
||||
procedure TsSpreadOOXMLWriter.WriteFormula(AStream: TStream;
|
||||
const ARow, ACol: Cardinal; const AFormula: TsFormula; ACell: PCell);
|
||||
var
|
||||
cellPosText: String;
|
||||
lStyleIndex: Integer;
|
||||
begin
|
||||
cellPosText := TsWorksheet.CellPosToText(ARow, ACol);
|
||||
lStyleIndex := GetStyleIndex(ACell);
|
||||
|
||||
AppendToStream(AStream, Format(
|
||||
'<c r="%s" s="%d">' +
|
||||
'<f>%s</f>' +
|
||||
'</c>', [
|
||||
CellPosText, lStyleIndex,
|
||||
PrepareFormula(AFormula)
|
||||
]));
|
||||
end;
|
||||
|
||||
{*******************************************************************
|
||||
* TsSpreadOOXMLWriter.WriteLabel ()
|
||||
|
Reference in New Issue
Block a user