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;
|
||||
r1,c1,r2,c2: Cardinal;
|
||||
fmt: TsCellFormat;
|
||||
ignoreFormulas: Boolean;
|
||||
begin
|
||||
Unused(ARow, ACol);
|
||||
ignoreFormulas := (boIgnoreFormulas in FWorkbook.Options);
|
||||
|
||||
// Style
|
||||
fmt := FWorkbook.GetCellFormat(ACell^.FormatIndex);
|
||||
@ -7473,6 +7475,12 @@ begin
|
||||
if FWorksheet.HasHyperlink(ACell) then
|
||||
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!
|
||||
parser := TsSpreadsheetParser.Create(FWorksheet);
|
||||
try
|
||||
@ -7483,7 +7491,6 @@ begin
|
||||
parser.Free;
|
||||
end;
|
||||
|
||||
valueStr := '';
|
||||
case ACell^.ContentType of
|
||||
cctNumber:
|
||||
begin
|
||||
@ -7527,13 +7534,14 @@ begin
|
||||
value := ' office:value=""';
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Fix special xml characters }
|
||||
formula := UTF8TextToXMLText(formula);
|
||||
|
||||
{ We are writing a very rudimentary formula here without result and result
|
||||
data type. Seems to work... }
|
||||
if FWorksheet.GetCalcState(ACell) = csCalculated then
|
||||
if not ignoreFormulas or (FWorksheet.GetCalcState(ACell) = csCalculated) then
|
||||
AppendToStream(AStream, Format(
|
||||
'<table:table-cell table:formula="=%s" office:value-type="%s"%s%s%s>' +
|
||||
comment +
|
||||
|
@ -675,10 +675,12 @@ type
|
||||
@param boWriteZoomfactor Instructs the writer to write the current zoom
|
||||
factors of the worksheets to file.
|
||||
@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,
|
||||
boAutoCalc, boCalcBeforeSaving, boReadFormulas, boWriteZoomFactor,
|
||||
boAbortReadOnFormulaError);
|
||||
boAbortReadOnFormulaError, boIgnoreFormulas);
|
||||
|
||||
{@@ Set of option flags for the workbook }
|
||||
TsWorkbookOptions = set of TsWorkbookOption;
|
||||
@ -1273,6 +1275,9 @@ var
|
||||
cell: PCell;
|
||||
formula: String;
|
||||
begin
|
||||
if (boIgnoreFormulas in Workbook.Options) then
|
||||
exit;
|
||||
|
||||
formula := ACell^.FormulaValue;
|
||||
ACell^.Flags := ACell^.Flags + [cfCalculating] - [cfCalculated];
|
||||
|
||||
@ -1345,6 +1350,9 @@ procedure TsWorksheet.CalcFormulas;
|
||||
var
|
||||
cell: PCell;
|
||||
begin
|
||||
if (boIgnoreFormulas in Workbook.Options) then
|
||||
exit;
|
||||
|
||||
// prevent infinite loop due to triggering of formula calculation whenever
|
||||
// a cell changes during execution of CalcFormulas.
|
||||
inc(FWorkbook.FCalculationLock);
|
||||
@ -5669,6 +5677,8 @@ begin
|
||||
if ACell = nil then
|
||||
exit;
|
||||
|
||||
if not (boIgnoreFormulas in Workbook.Options) then
|
||||
begin
|
||||
// Remove '='; is not stored internally
|
||||
if (AFormula <> '') and (AFormula[1] = '=') then
|
||||
AFormula := Copy(AFormula, 2, Length(AFormula));
|
||||
@ -5683,6 +5693,7 @@ begin
|
||||
parser.Free;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
// Store formula in cell
|
||||
if AFormula <> '' then
|
||||
|
Reference in New Issue
Block a user