You've already forked lazarus-ccr
fpspreadsheet: Add workbook option boIgnoreFormulas for writing unsupported formulas (See forum https://forum.lazarus.freepascal.org/index.php/topic,40146.0.html).
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@6209 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -0,0 +1,64 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<CONFIG>
|
||||||
|
<ProjectOptions>
|
||||||
|
<Version Value="11"/>
|
||||||
|
<PathDelim Value="\"/>
|
||||||
|
<General>
|
||||||
|
<Flags>
|
||||||
|
<MainUnitHasCreateFormStatements Value="False"/>
|
||||||
|
<MainUnitHasTitleStatement Value="False"/>
|
||||||
|
<MainUnitHasScaledStatement Value="False"/>
|
||||||
|
</Flags>
|
||||||
|
<SessionStorage Value="InProjectDir"/>
|
||||||
|
<MainUnit Value="0"/>
|
||||||
|
<Title Value="demo_ignore_formula"/>
|
||||||
|
<UseAppBundle Value="False"/>
|
||||||
|
<ResourceType Value="res"/>
|
||||||
|
</General>
|
||||||
|
<BuildModes Count="1">
|
||||||
|
<Item1 Name="Default" Default="True"/>
|
||||||
|
</BuildModes>
|
||||||
|
<PublishOptions>
|
||||||
|
<Version Value="2"/>
|
||||||
|
</PublishOptions>
|
||||||
|
<RunParams>
|
||||||
|
<FormatVersion Value="2"/>
|
||||||
|
<Modes Count="0"/>
|
||||||
|
</RunParams>
|
||||||
|
<RequiredPackages Count="1">
|
||||||
|
<Item1>
|
||||||
|
<PackageName Value="laz_fpspreadsheet"/>
|
||||||
|
</Item1>
|
||||||
|
</RequiredPackages>
|
||||||
|
<Units Count="1">
|
||||||
|
<Unit0>
|
||||||
|
<Filename Value="demo_ignore_formula.lpr"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
</Unit0>
|
||||||
|
</Units>
|
||||||
|
</ProjectOptions>
|
||||||
|
<CompilerOptions>
|
||||||
|
<Version Value="11"/>
|
||||||
|
<PathDelim Value="\"/>
|
||||||
|
<Target>
|
||||||
|
<Filename Value="demo_ignore_formula"/>
|
||||||
|
</Target>
|
||||||
|
<SearchPaths>
|
||||||
|
<IncludeFiles Value="$(ProjOutDir)"/>
|
||||||
|
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
|
||||||
|
</SearchPaths>
|
||||||
|
</CompilerOptions>
|
||||||
|
<Debugging>
|
||||||
|
<Exceptions Count="3">
|
||||||
|
<Item1>
|
||||||
|
<Name Value="EAbort"/>
|
||||||
|
</Item1>
|
||||||
|
<Item2>
|
||||||
|
<Name Value="ECodetoolError"/>
|
||||||
|
</Item2>
|
||||||
|
<Item3>
|
||||||
|
<Name Value="EFOpenError"/>
|
||||||
|
</Item3>
|
||||||
|
</Exceptions>
|
||||||
|
</Debugging>
|
||||||
|
</CONFIG>
|
114
components/fpspreadsheet/examples/other/demo_ignore_formula.lpr
Normal file
114
components/fpspreadsheet/examples/other/demo_ignore_formula.lpr
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
{ This example uses the "ignoreFormula" workbook option to create an ods
|
||||||
|
file with an external reference.
|
||||||
|
|
||||||
|
NOTE: The external reference is not calculated. This will happen when
|
||||||
|
LibreOffice Calc loads the file. When the file is closed in LOCalc
|
||||||
|
confirmation must be given to save the file because it has been changed
|
||||||
|
by LOCalc.
|
||||||
|
|
||||||
|
This method does not work with Excel because it writes an additonal
|
||||||
|
folder and xml files for external links. }
|
||||||
|
|
||||||
|
program demo_ignore_formula;
|
||||||
|
|
||||||
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
{$DEFINE ODS}
|
||||||
|
{.$DEFINE XLSX} // <---- NOT WORKING
|
||||||
|
|
||||||
|
uses
|
||||||
|
SysUtils, FileUtil,
|
||||||
|
fpsTypes, fpsUtils, fpSpreadsheet, fpsOpenDocument, xlsxOOXML;
|
||||||
|
|
||||||
|
const
|
||||||
|
{$IFDEF ODS}
|
||||||
|
FILE_FORMAT = sfOpenDocument;
|
||||||
|
MASTER_FILE = 'master.ods';
|
||||||
|
EXTERNAL_FILE = 'external.ods';
|
||||||
|
{$ENDIF}
|
||||||
|
{$IFDEF XLSX}
|
||||||
|
FILE_FORMAT = sfOOXML;
|
||||||
|
MASTER_FILE = 'master.xlsx';
|
||||||
|
EXTERNAL_FILE = 'external.xlsx';
|
||||||
|
{$ENDIF}
|
||||||
|
EXTERNAL_SHEET = 'Sheet';
|
||||||
|
CELL1 = 'A1';
|
||||||
|
CELL2 = 'B1';
|
||||||
|
|
||||||
|
|
||||||
|
var
|
||||||
|
book: TsWorkbook;
|
||||||
|
sheet: TsWorksheet;
|
||||||
|
cell: PCell;
|
||||||
|
|
||||||
|
// example for an external ods reference:
|
||||||
|
// ='file:///D:/fpspreadsheet/examples/other/external.ods'#$Sheet.A1
|
||||||
|
function ODS_ExtRef(AFilename, ASheetName, ACellAddr: String): String;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
Result := ExpandFileName(AFileName);
|
||||||
|
for i:=1 to Length(Result) do
|
||||||
|
if Result[i] = '\' then Result[i] := '/';
|
||||||
|
Result := Format('''file:///%s''#$%s.%s', [
|
||||||
|
Result, ASheetName, ACellAddr
|
||||||
|
]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// example for an external xlsx reference:
|
||||||
|
// =[external.xlsx]Sheet!$A$1
|
||||||
|
function XLSX_ExtRef(AFilename, ASheetName, ACellAddr: String): String;
|
||||||
|
var
|
||||||
|
r, c: Cardinal;
|
||||||
|
flags: TsRelFlags;
|
||||||
|
begin
|
||||||
|
ParseCellString(ACellAddr, r, c, flags);
|
||||||
|
Result := Format('[%s]%s!%s', [
|
||||||
|
ExtractFileName(AFileName), ASheetName, GetCellString(r, c, [])
|
||||||
|
]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function ExtRef(AFileName, ASheetName, ACellAddr: String): String;
|
||||||
|
begin
|
||||||
|
{$IFDEF ODS}
|
||||||
|
Result := ODS_ExtRef(AFileName, ASheetName, ACellAddr);
|
||||||
|
{$ENDIF}
|
||||||
|
{$IFDEF XLSX}
|
||||||
|
Result := XLSX_ExtRef(AFilename, ASheetName, ACellAddr);
|
||||||
|
{$ENDIF}
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
// Write external file
|
||||||
|
book := TsWorkbook.Create;
|
||||||
|
try
|
||||||
|
sheet := book.AddWorksheet(EXTERNAL_SHEET);
|
||||||
|
|
||||||
|
cell := sheet.GetCell(CELL1);
|
||||||
|
sheet.WriteNumber(cell, 1000.0);
|
||||||
|
|
||||||
|
cell := sheet.GetCell(CELL2);
|
||||||
|
sheet.WriteText(cell, 'Hallo');
|
||||||
|
|
||||||
|
book.WriteToFile(EXTERNAL_FILE, FILE_FORMAT, true);
|
||||||
|
finally
|
||||||
|
book.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Write ods and xlsx master files
|
||||||
|
book := TsWorkbook.Create;
|
||||||
|
try
|
||||||
|
// Instruct fpspreadsheet to leave the formula alone.
|
||||||
|
book.Options := book.Options + [boIgnoreFormulas];
|
||||||
|
sheet := book.AddWorksheet('Sheet');
|
||||||
|
|
||||||
|
// Write external references
|
||||||
|
sheet.WriteFormula(0, 0, ExtRef(EXTERNAL_FILE, EXTERNAL_SHEET, CELL1));
|
||||||
|
sheet.WriteFormula(1, 0, ExtRef(EXTERNAL_FILE, EXTERNAL_SHEET, CELL2));
|
||||||
|
book.WriteToFile(MASTER_FILE, FILE_FORMAT, true);
|
||||||
|
|
||||||
|
finally
|
||||||
|
book.Free;
|
||||||
|
end;
|
||||||
|
end.
|
||||||
|
|
@ -7446,8 +7446,10 @@ var
|
|||||||
comment: String;
|
comment: String;
|
||||||
r1,c1,r2,c2: Cardinal;
|
r1,c1,r2,c2: Cardinal;
|
||||||
fmt: TsCellFormat;
|
fmt: TsCellFormat;
|
||||||
|
ignoreFormulas: Boolean;
|
||||||
begin
|
begin
|
||||||
Unused(ARow, ACol);
|
Unused(ARow, ACol);
|
||||||
|
ignoreFormulas := (boIgnoreFormulas in FWorkbook.Options);
|
||||||
|
|
||||||
// Style
|
// Style
|
||||||
fmt := FWorkbook.GetCellFormat(ACell^.FormatIndex);
|
fmt := FWorkbook.GetCellFormat(ACell^.FormatIndex);
|
||||||
@ -7473,6 +7475,12 @@ begin
|
|||||||
if FWorksheet.HasHyperlink(ACell) then
|
if FWorksheet.HasHyperlink(ACell) then
|
||||||
FWorkbook.AddErrorMsg(rsODSHyperlinksOfTextCellsOnly, [GetCellString(ARow, ACol)]);
|
FWorkbook.AddErrorMsg(rsODSHyperlinksOfTextCellsOnly, [GetCellString(ARow, ACol)]);
|
||||||
|
|
||||||
|
if ignoreFormulas then begin
|
||||||
|
formula := ACell^.FormulaValue;
|
||||||
|
if (formula <> '') and (formula[1] = '=') then Delete(formula, 1, 1);
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
valueStr := '';
|
||||||
// Convert string formula to the format needed by ods: semicolon list separators!
|
// Convert string formula to the format needed by ods: semicolon list separators!
|
||||||
parser := TsSpreadsheetParser.Create(FWorksheet);
|
parser := TsSpreadsheetParser.Create(FWorksheet);
|
||||||
try
|
try
|
||||||
@ -7483,7 +7491,6 @@ begin
|
|||||||
parser.Free;
|
parser.Free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
valueStr := '';
|
|
||||||
case ACell^.ContentType of
|
case ACell^.ContentType of
|
||||||
cctNumber:
|
cctNumber:
|
||||||
begin
|
begin
|
||||||
@ -7527,13 +7534,14 @@ begin
|
|||||||
value := ' office:value=""';
|
value := ' office:value=""';
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
{ Fix special xml characters }
|
{ Fix special xml characters }
|
||||||
formula := UTF8TextToXMLText(formula);
|
formula := UTF8TextToXMLText(formula);
|
||||||
|
|
||||||
{ We are writing a very rudimentary formula here without result and result
|
{ We are writing a very rudimentary formula here without result and result
|
||||||
data type. Seems to work... }
|
data type. Seems to work... }
|
||||||
if FWorksheet.GetCalcState(ACell) = csCalculated then
|
if not ignoreFormulas or (FWorksheet.GetCalcState(ACell) = csCalculated) then
|
||||||
AppendToStream(AStream, Format(
|
AppendToStream(AStream, Format(
|
||||||
'<table:table-cell table:formula="=%s" office:value-type="%s"%s%s%s>' +
|
'<table:table-cell table:formula="=%s" office:value-type="%s"%s%s%s>' +
|
||||||
comment +
|
comment +
|
||||||
|
@ -675,10 +675,12 @@ type
|
|||||||
@param boWriteZoomfactor Instructs the writer to write the current zoom
|
@param boWriteZoomfactor Instructs the writer to write the current zoom
|
||||||
factors of the worksheets to file.
|
factors of the worksheets to file.
|
||||||
@param boAbortReadOnFormulaError Aborts reading if a formula error is
|
@param boAbortReadOnFormulaError Aborts reading if a formula error is
|
||||||
encountered }
|
encountered
|
||||||
|
@param boIgnoreFormulas Formulas are not checked and not calculated.
|
||||||
|
Cannot be used for biff formats. }
|
||||||
TsWorkbookOption = (boVirtualMode, boBufStream, boFileStream,
|
TsWorkbookOption = (boVirtualMode, boBufStream, boFileStream,
|
||||||
boAutoCalc, boCalcBeforeSaving, boReadFormulas, boWriteZoomFactor,
|
boAutoCalc, boCalcBeforeSaving, boReadFormulas, boWriteZoomFactor,
|
||||||
boAbortReadOnFormulaError);
|
boAbortReadOnFormulaError, boIgnoreFormulas);
|
||||||
|
|
||||||
{@@ Set of option flags for the workbook }
|
{@@ Set of option flags for the workbook }
|
||||||
TsWorkbookOptions = set of TsWorkbookOption;
|
TsWorkbookOptions = set of TsWorkbookOption;
|
||||||
@ -1273,6 +1275,9 @@ var
|
|||||||
cell: PCell;
|
cell: PCell;
|
||||||
formula: String;
|
formula: String;
|
||||||
begin
|
begin
|
||||||
|
if (boIgnoreFormulas in Workbook.Options) then
|
||||||
|
exit;
|
||||||
|
|
||||||
formula := ACell^.FormulaValue;
|
formula := ACell^.FormulaValue;
|
||||||
ACell^.Flags := ACell^.Flags + [cfCalculating] - [cfCalculated];
|
ACell^.Flags := ACell^.Flags + [cfCalculating] - [cfCalculated];
|
||||||
|
|
||||||
@ -1345,6 +1350,9 @@ procedure TsWorksheet.CalcFormulas;
|
|||||||
var
|
var
|
||||||
cell: PCell;
|
cell: PCell;
|
||||||
begin
|
begin
|
||||||
|
if (boIgnoreFormulas in Workbook.Options) then
|
||||||
|
exit;
|
||||||
|
|
||||||
// prevent infinite loop due to triggering of formula calculation whenever
|
// prevent infinite loop due to triggering of formula calculation whenever
|
||||||
// a cell changes during execution of CalcFormulas.
|
// a cell changes during execution of CalcFormulas.
|
||||||
inc(FWorkbook.FCalculationLock);
|
inc(FWorkbook.FCalculationLock);
|
||||||
@ -5669,6 +5677,8 @@ begin
|
|||||||
if ACell = nil then
|
if ACell = nil then
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
|
if not (boIgnoreFormulas in Workbook.Options) then
|
||||||
|
begin
|
||||||
// Remove '='; is not stored internally
|
// Remove '='; is not stored internally
|
||||||
if (AFormula <> '') and (AFormula[1] = '=') then
|
if (AFormula <> '') and (AFormula[1] = '=') then
|
||||||
AFormula := Copy(AFormula, 2, Length(AFormula));
|
AFormula := Copy(AFormula, 2, Length(AFormula));
|
||||||
@ -5683,6 +5693,7 @@ begin
|
|||||||
parser.Free;
|
parser.Free;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
// Store formula in cell
|
// Store formula in cell
|
||||||
if AFormula <> '' then
|
if AFormula <> '' then
|
||||||
|
Reference in New Issue
Block a user