diff --git a/components/fpspreadsheet/fpsfunc.pas b/components/fpspreadsheet/fpsfunc.pas
index cb8d0112b..f3e3cbf0b 100644
--- a/components/fpspreadsheet/fpsfunc.pas
+++ b/components/fpspreadsheet/fpsfunc.pas
@@ -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
diff --git a/components/fpspreadsheet/fpspreadsheet.pas b/components/fpspreadsheet/fpspreadsheet.pas
index 327f3af4e..b37145a38 100755
--- a/components/fpspreadsheet/fpspreadsheet.pas
+++ b/components/fpspreadsheet/fpspreadsheet.pas
@@ -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
diff --git a/components/fpspreadsheet/tests/spreadtestgui.lpi b/components/fpspreadsheet/tests/spreadtestgui.lpi
index e4dc9f4dd..15be00ba3 100644
--- a/components/fpspreadsheet/tests/spreadtestgui.lpi
+++ b/components/fpspreadsheet/tests/spreadtestgui.lpi
@@ -52,7 +52,6 @@
-
@@ -66,16 +65,15 @@
-
-
+
diff --git a/components/fpspreadsheet/xlsbiff2.pas b/components/fpspreadsheet/xlsbiff2.pas
index aa51f57b8..725e0b7f0 100755
--- a/components/fpspreadsheet/xlsbiff2.pas
+++ b/components/fpspreadsheet/xlsbiff2.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
diff --git a/components/fpspreadsheet/xlsbiff5.pas b/components/fpspreadsheet/xlsbiff5.pas
index 9ff85c300..ba1ee6d07 100755
--- a/components/fpspreadsheet/xlsbiff5.pas
+++ b/components/fpspreadsheet/xlsbiff5.pas
@@ -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;
{*******************************************************************
diff --git a/components/fpspreadsheet/xlsbiff8.pas b/components/fpspreadsheet/xlsbiff8.pas
index 2a31c3f03..0a80dcfdc 100755
--- a/components/fpspreadsheet/xlsbiff8.pas
+++ b/components/fpspreadsheet/xlsbiff8.pas
@@ -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;
{*******************************************************************
diff --git a/components/fpspreadsheet/xlsxooxml.pas b/components/fpspreadsheet/xlsxooxml.pas
index 4694ca6ae..f28c8efa3 100755
--- a/components/fpspreadsheet/xlsxooxml.pas
+++ b/components/fpspreadsheet/xlsxooxml.pas
@@ -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 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
'');
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(
+ '' +
+ '%s' +
+ '', [
+ CellPosText, lStyleIndex,
+ PrepareFormula(AFormula)
+ ]));
+end;
{*******************************************************************
* TsSpreadOOXMLWriter.WriteLabel ()