You've already forked lazarus-ccr
fpspreadsheet: Redo storage of formulas: formulas now are stored in a separate tree independent of the cells tree. The field FormulaValue of TCell record was removed. All unit tests passed. Demos updated (issues of speedtest due to SST in BIFF8 found - not related).
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@6446 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<CONFIG>
|
<CONFIG>
|
||||||
<ProjectOptions>
|
<ProjectOptions>
|
||||||
<Version Value="10"/>
|
<Version Value="11"/>
|
||||||
<PathDelim Value="\"/>
|
<PathDelim Value="\"/>
|
||||||
<General>
|
<General>
|
||||||
<SessionStorage Value="InProjectDir"/>
|
<SessionStorage Value="InProjectDir"/>
|
||||||
@ -21,9 +21,10 @@
|
|||||||
<DestinationDirectory Value="c:\temp\fpsspeedtest"/>
|
<DestinationDirectory Value="c:\temp\fpsspeedtest"/>
|
||||||
</PublishOptions>
|
</PublishOptions>
|
||||||
<RunParams>
|
<RunParams>
|
||||||
<local>
|
<FormatVersion Value="2"/>
|
||||||
<FormatVersion Value="1"/>
|
<Modes Count="1">
|
||||||
</local>
|
<Mode0 Name="default"/>
|
||||||
|
</Modes>
|
||||||
</RunParams>
|
</RunParams>
|
||||||
<RequiredPackages Count="2">
|
<RequiredPackages Count="2">
|
||||||
<Item1>
|
<Item1>
|
||||||
|
@ -51,7 +51,7 @@ begin
|
|||||||
parser := TsSpreadsheetParser.Create(worksheet);
|
parser := TsSpreadsheetParser.Create(worksheet);
|
||||||
try
|
try
|
||||||
try
|
try
|
||||||
parser.Expression := cell^.FormulaValue;
|
parser.Expression := worksheet.ReadFormula(cell);
|
||||||
res := parser.Evaluate;
|
res := parser.Evaluate;
|
||||||
|
|
||||||
WriteLn('A2: ', parser.Expression);
|
WriteLn('A2: ', parser.Expression);
|
||||||
|
@ -7,7 +7,7 @@ uses
|
|||||||
cthreads,
|
cthreads,
|
||||||
{$ENDIF}{$ENDIF}
|
{$ENDIF}{$ENDIF}
|
||||||
SysUtils, Classes, TypInfo,
|
SysUtils, Classes, TypInfo,
|
||||||
fpsTypes, fpSpreadsheet, fpsSearch, fpsUtils, laz_fpspreadsheet;
|
fpsTypes, fpSpreadsheet, fpsSearch, fpsUtils;
|
||||||
|
|
||||||
var
|
var
|
||||||
workbook: TsWorkbook;
|
workbook: TsWorkbook;
|
||||||
|
@ -55,7 +55,7 @@
|
|||||||
<SearchPaths>
|
<SearchPaths>
|
||||||
<IncludeFiles Value="..\..\source"/>
|
<IncludeFiles Value="..\..\source"/>
|
||||||
<OtherUnitFiles Value="..\..\source\common"/>
|
<OtherUnitFiles Value="..\..\source\common"/>
|
||||||
<UnitOutputDirectory Value="..\..\lib\$(TargetCPU)-$(TargetOS)"/>
|
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
|
||||||
</SearchPaths>
|
</SearchPaths>
|
||||||
<Parsing>
|
<Parsing>
|
||||||
<SyntaxOptions>
|
<SyntaxOptions>
|
||||||
|
@ -50,7 +50,7 @@ begin
|
|||||||
UTF8ToConsole(MyWorkSheet.ReadAsText(CurCell^.Row, CurCell^.Col))
|
UTF8ToConsole(MyWorkSheet.ReadAsText(CurCell^.Row, CurCell^.Col))
|
||||||
);
|
);
|
||||||
if HasFormula(CurCell) then
|
if HasFormula(CurCell) then
|
||||||
Write(' (Formula ', CurCell^.FormulaValue, ')');
|
Write(' (Formula ', MyWorksheet.ReadFormula(CurCell), ')');
|
||||||
WriteLn;
|
WriteLn;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ begin
|
|||||||
' Col: ', CurCell^.Col, ' Value: ',
|
' Col: ', CurCell^.Col, ' Value: ',
|
||||||
UTF8ToConsole(MyWorkSheet.ReadAsText(CurCell^.Row, CurCell^.Col)));
|
UTF8ToConsole(MyWorkSheet.ReadAsText(CurCell^.Row, CurCell^.Col)));
|
||||||
if HasFormula(CurCell) then
|
if HasFormula(CurCell) then
|
||||||
Write(' - Formula: ', CurCell^.FormulaValue);
|
Write(' - Formula: ', MyWorksheet.ReadFormula(CurCell));
|
||||||
WriteLn;
|
WriteLn;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<CONFIG>
|
<CONFIG>
|
||||||
<ProjectOptions>
|
<ProjectOptions>
|
||||||
<Version Value="10"/>
|
<Version Value="11"/>
|
||||||
<PathDelim Value="\"/>
|
<PathDelim Value="\"/>
|
||||||
<General>
|
<General>
|
||||||
<Flags>
|
<Flags>
|
||||||
@ -23,9 +23,16 @@
|
|||||||
</PublishOptions>
|
</PublishOptions>
|
||||||
<RunParams>
|
<RunParams>
|
||||||
<local>
|
<local>
|
||||||
<FormatVersion Value="1"/>
|
|
||||||
<LaunchingApplication PathPlusParams="\usr\X11R6\bin\xterm -T 'Lazarus Run Output' -e $(LazarusDir)\tools\runwait.sh $(TargetCmdLine)"/>
|
<LaunchingApplication PathPlusParams="\usr\X11R6\bin\xterm -T 'Lazarus Run Output' -e $(LazarusDir)\tools\runwait.sh $(TargetCmdLine)"/>
|
||||||
</local>
|
</local>
|
||||||
|
<FormatVersion Value="2"/>
|
||||||
|
<Modes Count="1">
|
||||||
|
<Mode0 Name="default">
|
||||||
|
<local>
|
||||||
|
<LaunchingApplication PathPlusParams="\usr\X11R6\bin\xterm -T 'Lazarus Run Output' -e $(LazarusDir)\tools\runwait.sh $(TargetCmdLine)"/>
|
||||||
|
</local>
|
||||||
|
</Mode0>
|
||||||
|
</Modes>
|
||||||
</RunParams>
|
</RunParams>
|
||||||
<RequiredPackages Count="1">
|
<RequiredPackages Count="1">
|
||||||
<Item1>
|
<Item1>
|
||||||
|
@ -20,7 +20,7 @@ var
|
|||||||
|
|
||||||
const
|
const
|
||||||
// url = 'http://unicode.e-workers.de/entities.php';
|
// url = 'http://unicode.e-workers.de/entities.php';
|
||||||
url = 'http://www.freepascal.org/docs.var';
|
url = 'https://www.freepascal.org/docs.var';
|
||||||
|
|
||||||
begin
|
begin
|
||||||
stream := TMemoryStream.Create;
|
stream := TMemoryStream.Create;
|
||||||
|
@ -53,7 +53,7 @@ begin
|
|||||||
UTF8ToConsole(MyWorkSheet.ReadAsText(CurCell^.Row, CurCell^.Col))
|
UTF8ToConsole(MyWorkSheet.ReadAsText(CurCell^.Row, CurCell^.Col))
|
||||||
);
|
);
|
||||||
if HasFormula(CurCell) then
|
if HasFormula(CurCell) then
|
||||||
WriteLn(' Formula: ', CurCell^.FormulaValue)
|
WriteLn(' Formula: ', MyWorksheet.ReadFormula(Curcell))
|
||||||
else
|
else
|
||||||
WriteLn;
|
WriteLn;
|
||||||
end;
|
end;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<CONFIG>
|
<CONFIG>
|
||||||
<ProjectOptions>
|
<ProjectOptions>
|
||||||
<Version Value="10"/>
|
<Version Value="11"/>
|
||||||
<PathDelim Value="\"/>
|
<PathDelim Value="\"/>
|
||||||
<General>
|
<General>
|
||||||
<SessionStorage Value="InProjectDir"/>
|
<SessionStorage Value="InProjectDir"/>
|
||||||
@ -44,9 +44,10 @@
|
|||||||
<Version Value="2"/>
|
<Version Value="2"/>
|
||||||
</PublishOptions>
|
</PublishOptions>
|
||||||
<RunParams>
|
<RunParams>
|
||||||
<local>
|
<FormatVersion Value="2"/>
|
||||||
<FormatVersion Value="1"/>
|
<Modes Count="1">
|
||||||
</local>
|
<Mode0 Name="default"/>
|
||||||
|
</Modes>
|
||||||
</RunParams>
|
</RunParams>
|
||||||
<RequiredPackages Count="3">
|
<RequiredPackages Count="3">
|
||||||
<Item1>
|
<Item1>
|
||||||
|
@ -7,8 +7,7 @@ uses
|
|||||||
cthreads,
|
cthreads,
|
||||||
{$ENDIF}{$ENDIF}
|
{$ENDIF}{$ENDIF}
|
||||||
Interfaces, // this includes the LCL widgetset
|
Interfaces, // this includes the LCL widgetset
|
||||||
Forms, mainform, tachartlazaruspkg
|
Forms, mainform;
|
||||||
{ you can add units after this };
|
|
||||||
|
|
||||||
{$R *.res}
|
{$R *.res}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ object Form1: TForm1
|
|||||||
ClientHeight = 634
|
ClientHeight = 634
|
||||||
ClientWidth = 877
|
ClientWidth = 877
|
||||||
OnCreate = FormCreate
|
OnCreate = FormCreate
|
||||||
LCLVersion = '1.7'
|
LCLVersion = '1.9.0.0'
|
||||||
object Panel1: TPanel
|
object Panel1: TPanel
|
||||||
Left = 0
|
Left = 0
|
||||||
Height = 40
|
Height = 40
|
||||||
@ -77,7 +77,6 @@ object Form1: TForm1
|
|||||||
WorkbookSource = sWorkbookSource1
|
WorkbookSource = sWorkbookSource1
|
||||||
Align = alClient
|
Align = alClient
|
||||||
AutoAdvance = aaDown
|
AutoAdvance = aaDown
|
||||||
ColCount = 27
|
|
||||||
DefaultColWidth = 64
|
DefaultColWidth = 64
|
||||||
DefaultRowHeight = 22
|
DefaultRowHeight = 22
|
||||||
Font.Color = clBlack
|
Font.Color = clBlack
|
||||||
@ -85,7 +84,6 @@ object Form1: TForm1
|
|||||||
Font.Name = 'Calibri'
|
Font.Name = 'Calibri'
|
||||||
Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goEditing, goThumbTracking]
|
Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goEditing, goThumbTracking]
|
||||||
ParentFont = False
|
ParentFont = False
|
||||||
RowCount = 101
|
|
||||||
TabOrder = 1
|
TabOrder = 1
|
||||||
TitleFont.Color = clBlack
|
TitleFont.Color = clBlack
|
||||||
TitleFont.Height = -15
|
TitleFont.Height = -15
|
||||||
@ -110,12 +108,16 @@ object Form1: TForm1
|
|||||||
Width = 470
|
Width = 470
|
||||||
AxisList = <
|
AxisList = <
|
||||||
item
|
item
|
||||||
|
Marks.LabelBrush.Style = bsClear
|
||||||
Minors = <>
|
Minors = <>
|
||||||
Title.LabelFont.Orientation = 900
|
Title.LabelFont.Orientation = 900
|
||||||
|
Title.LabelBrush.Style = bsClear
|
||||||
end
|
end
|
||||||
item
|
item
|
||||||
Alignment = calBottom
|
Alignment = calBottom
|
||||||
|
Marks.LabelBrush.Style = bsClear
|
||||||
Minors = <>
|
Minors = <>
|
||||||
|
Title.LabelBrush.Style = bsClear
|
||||||
end>
|
end>
|
||||||
BackColor = clWhite
|
BackColor = clWhite
|
||||||
Foot.Brush.Color = clBtnFace
|
Foot.Brush.Color = clBtnFace
|
||||||
@ -141,12 +143,16 @@ object Form1: TForm1
|
|||||||
Width = 470
|
Width = 470
|
||||||
AxisList = <
|
AxisList = <
|
||||||
item
|
item
|
||||||
|
Marks.LabelBrush.Style = bsClear
|
||||||
Minors = <>
|
Minors = <>
|
||||||
Title.LabelFont.Orientation = 900
|
Title.LabelFont.Orientation = 900
|
||||||
|
Title.LabelBrush.Style = bsClear
|
||||||
end
|
end
|
||||||
item
|
item
|
||||||
Alignment = calBottom
|
Alignment = calBottom
|
||||||
|
Marks.LabelBrush.Style = bsClear
|
||||||
Minors = <>
|
Minors = <>
|
||||||
|
Title.LabelBrush.Style = bsClear
|
||||||
end>
|
end>
|
||||||
BackColor = clWhite
|
BackColor = clWhite
|
||||||
Depth = 10
|
Depth = 10
|
||||||
@ -179,13 +185,17 @@ object Form1: TForm1
|
|||||||
AxisList = <
|
AxisList = <
|
||||||
item
|
item
|
||||||
Visible = False
|
Visible = False
|
||||||
|
Marks.LabelBrush.Style = bsClear
|
||||||
Minors = <>
|
Minors = <>
|
||||||
Title.LabelFont.Orientation = 900
|
Title.LabelFont.Orientation = 900
|
||||||
|
Title.LabelBrush.Style = bsClear
|
||||||
end
|
end
|
||||||
item
|
item
|
||||||
Visible = False
|
Visible = False
|
||||||
Alignment = calBottom
|
Alignment = calBottom
|
||||||
|
Marks.LabelBrush.Style = bsClear
|
||||||
Minors = <>
|
Minors = <>
|
||||||
|
Title.LabelBrush.Style = bsClear
|
||||||
end>
|
end>
|
||||||
Foot.Brush.Color = clBtnFace
|
Foot.Brush.Color = clBtnFace
|
||||||
Foot.Font.Color = clBlue
|
Foot.Font.Color = clBlue
|
||||||
@ -210,7 +220,7 @@ object Form1: TForm1
|
|||||||
end
|
end
|
||||||
object sWorkbookSource1: TsWorkbookSource
|
object sWorkbookSource1: TsWorkbookSource
|
||||||
AutoDetectFormat = False
|
AutoDetectFormat = False
|
||||||
FileFormat = sfOOXML
|
FileFormat = sfUser
|
||||||
Options = []
|
Options = []
|
||||||
left = 184
|
left = 184
|
||||||
top = 320
|
top = 320
|
||||||
|
@ -7,7 +7,7 @@ interface
|
|||||||
uses
|
uses
|
||||||
Classes, SysUtils, FileUtil, TAGraph, TASeries, Forms, Controls,
|
Classes, SysUtils, FileUtil, TAGraph, TASeries, Forms, Controls,
|
||||||
Graphics, Dialogs, ExtCtrls, StdCtrls,
|
Graphics, Dialogs, ExtCtrls, StdCtrls,
|
||||||
fpstypes, fpspreadsheetctrls, fpspreadsheetgrid, fpspreadsheetchart;
|
fpstypes, fpspreadsheetctrls, fpspreadsheetgrid, fpspreadsheetchart, fpsallformats;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<CONFIG>
|
<CONFIG>
|
||||||
<ProjectOptions>
|
<ProjectOptions>
|
||||||
<Version Value="10"/>
|
<Version Value="11"/>
|
||||||
<General>
|
<General>
|
||||||
<SessionStorage Value="InProjectDir"/>
|
<SessionStorage Value="InProjectDir"/>
|
||||||
<MainUnit Value="0"/>
|
<MainUnit Value="0"/>
|
||||||
@ -24,9 +24,16 @@
|
|||||||
</PublishOptions>
|
</PublishOptions>
|
||||||
<RunParams>
|
<RunParams>
|
||||||
<local>
|
<local>
|
||||||
<FormatVersion Value="1"/>
|
|
||||||
<LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
|
<LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
|
||||||
</local>
|
</local>
|
||||||
|
<FormatVersion Value="2"/>
|
||||||
|
<Modes Count="1">
|
||||||
|
<Mode0 Name="default">
|
||||||
|
<local>
|
||||||
|
<LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
|
||||||
|
</local>
|
||||||
|
</Mode0>
|
||||||
|
</Modes>
|
||||||
</RunParams>
|
</RunParams>
|
||||||
<RequiredPackages Count="4">
|
<RequiredPackages Count="4">
|
||||||
<Item1>
|
<Item1>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<CONFIG>
|
<CONFIG>
|
||||||
<ProjectOptions>
|
<ProjectOptions>
|
||||||
<Version Value="10"/>
|
<Version Value="11"/>
|
||||||
<PathDelim Value="\"/>
|
<PathDelim Value="\"/>
|
||||||
<General>
|
<General>
|
||||||
<SessionStorage Value="InProjectDir"/>
|
<SessionStorage Value="InProjectDir"/>
|
||||||
@ -21,9 +21,10 @@
|
|||||||
<Version Value="2"/>
|
<Version Value="2"/>
|
||||||
</PublishOptions>
|
</PublishOptions>
|
||||||
<RunParams>
|
<RunParams>
|
||||||
<local>
|
<FormatVersion Value="2"/>
|
||||||
<FormatVersion Value="1"/>
|
<Modes Count="1">
|
||||||
</local>
|
<Mode0 Name="default"/>
|
||||||
|
</Modes>
|
||||||
</RunParams>
|
</RunParams>
|
||||||
<RequiredPackages Count="1">
|
<RequiredPackages Count="1">
|
||||||
<Item1>
|
<Item1>
|
||||||
@ -51,7 +52,7 @@
|
|||||||
<Filename Value="demo_ctrls"/>
|
<Filename Value="demo_ctrls"/>
|
||||||
</Target>
|
</Target>
|
||||||
<SearchPaths>
|
<SearchPaths>
|
||||||
<IncludeFiles Value="$(ProjOutDir)"/>
|
<IncludeFiles Value="$(ProjOutDir);..\..\..\source"/>
|
||||||
<OtherUnitFiles Value="..\..\..\source\common;..\..\..\source\visual"/>
|
<OtherUnitFiles Value="..\..\..\source\common;..\..\..\source\visual"/>
|
||||||
<UnitOutputDirectory Value="..\..\lib\$(TargetCPU)-$(TargetOS)"/>
|
<UnitOutputDirectory Value="..\..\lib\$(TargetCPU)-$(TargetOS)"/>
|
||||||
</SearchPaths>
|
</SearchPaths>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<CONFIG>
|
<CONFIG>
|
||||||
<ProjectOptions>
|
<ProjectOptions>
|
||||||
<Version Value="10"/>
|
<Version Value="11"/>
|
||||||
<PathDelim Value="\"/>
|
<PathDelim Value="\"/>
|
||||||
<General>
|
<General>
|
||||||
<SessionStorage Value="InProjectDir"/>
|
<SessionStorage Value="InProjectDir"/>
|
||||||
@ -83,9 +83,10 @@
|
|||||||
<ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
|
<ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
|
||||||
</PublishOptions>
|
</PublishOptions>
|
||||||
<RunParams>
|
<RunParams>
|
||||||
<local>
|
<FormatVersion Value="2"/>
|
||||||
<FormatVersion Value="1"/>
|
<Modes Count="1">
|
||||||
</local>
|
<Mode0 Name="default"/>
|
||||||
|
</Modes>
|
||||||
</RunParams>
|
</RunParams>
|
||||||
<RequiredPackages Count="3">
|
<RequiredPackages Count="3">
|
||||||
<Item1>
|
<Item1>
|
||||||
@ -124,7 +125,7 @@
|
|||||||
<Filename Value="wikitablemaker"/>
|
<Filename Value="wikitablemaker"/>
|
||||||
</Target>
|
</Target>
|
||||||
<SearchPaths>
|
<SearchPaths>
|
||||||
<IncludeFiles Value="$(ProjOutDir)"/>
|
<IncludeFiles Value="$(ProjOutDir);..\..\..\source"/>
|
||||||
<OtherUnitFiles Value="..\..\..\source\common;..\..\..\source\visual"/>
|
<OtherUnitFiles Value="..\..\..\source\common;..\..\..\source\visual"/>
|
||||||
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
|
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
|
||||||
</SearchPaths>
|
</SearchPaths>
|
||||||
|
@ -7,7 +7,7 @@ object MainForm: TMainForm
|
|||||||
ClientHeight = 476
|
ClientHeight = 476
|
||||||
ClientWidth = 678
|
ClientWidth = 678
|
||||||
OnCreate = FormCreate
|
OnCreate = FormCreate
|
||||||
LCLVersion = '1.7'
|
LCLVersion = '1.9.0.0'
|
||||||
object Grid: TsWorksheetGrid
|
object Grid: TsWorksheetGrid
|
||||||
Left = 5
|
Left = 5
|
||||||
Height = 386
|
Height = 386
|
||||||
@ -20,12 +20,10 @@ object MainForm: TMainForm
|
|||||||
WorkbookSource = Grid.internal
|
WorkbookSource = Grid.internal
|
||||||
Anchors = [akTop, akLeft, akRight, akBottom]
|
Anchors = [akTop, akLeft, akRight, akBottom]
|
||||||
AutoAdvance = aaDown
|
AutoAdvance = aaDown
|
||||||
ColCount = 27
|
|
||||||
DefaultColWidth = 64
|
DefaultColWidth = 64
|
||||||
DefaultRowHeight = 22
|
DefaultRowHeight = 22
|
||||||
MouseWheelOption = mwGrid
|
MouseWheelOption = mwGrid
|
||||||
Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goRowSizing, goColSizing, goEditing, goThumbTracking, goSmoothScroll]
|
Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goRowSizing, goColSizing, goEditing, goThumbTracking, goSmoothScroll]
|
||||||
RowCount = 101
|
|
||||||
TabOrder = 0
|
TabOrder = 0
|
||||||
OnMouseWheel = GridMouseWheel
|
OnMouseWheel = GridMouseWheel
|
||||||
end
|
end
|
||||||
|
@ -7,7 +7,7 @@ interface
|
|||||||
uses
|
uses
|
||||||
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
|
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
|
||||||
Spin, Buttons, Types,
|
Spin, Buttons, Types,
|
||||||
fpstypes, fpspreadsheet, fpspreadsheetgrid;
|
fpstypes, fpspreadsheet, fpspreadsheetgrid, {%H-}fpsAllFormats;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<CONFIG>
|
<CONFIG>
|
||||||
<ProjectOptions>
|
<ProjectOptions>
|
||||||
<Version Value="10"/>
|
<Version Value="11"/>
|
||||||
<PathDelim Value="\"/>
|
<PathDelim Value="\"/>
|
||||||
<General>
|
<General>
|
||||||
<SessionStorage Value="InProjectDir"/>
|
<SessionStorage Value="InProjectDir"/>
|
||||||
@ -18,9 +18,10 @@
|
|||||||
<Version Value="2"/>
|
<Version Value="2"/>
|
||||||
</PublishOptions>
|
</PublishOptions>
|
||||||
<RunParams>
|
<RunParams>
|
||||||
<local>
|
<FormatVersion Value="2"/>
|
||||||
<FormatVersion Value="1"/>
|
<Modes Count="1">
|
||||||
</local>
|
<Mode0 Name="default"/>
|
||||||
|
</Modes>
|
||||||
</RunParams>
|
</RunParams>
|
||||||
<RequiredPackages Count="2">
|
<RequiredPackages Count="2">
|
||||||
<Item1>
|
<Item1>
|
||||||
|
@ -6,7 +6,7 @@ interface
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, avglvltree,
|
Classes, SysUtils, avglvltree,
|
||||||
fpstypes;
|
fpstypes, fpsExprParser;
|
||||||
|
|
||||||
type
|
type
|
||||||
{ forward declarations }
|
{ forward declarations }
|
||||||
@ -61,7 +61,8 @@ type
|
|||||||
function GetFirst: PsRowCol;
|
function GetFirst: PsRowCol;
|
||||||
function GetLast: PsRowCol;
|
function GetLast: PsRowCol;
|
||||||
procedure InsertRowOrCol(AIndex: Cardinal; IsRow: Boolean);
|
procedure InsertRowOrCol(AIndex: Cardinal; IsRow: Boolean);
|
||||||
procedure MoveAlongRow(ARow, AFromCol, AToCol: Cardinal);
|
procedure MoveAlongCol(ARow, ACol, AToRow: Cardinal);
|
||||||
|
procedure MoveAlongRow(ARow, ACol, AToCol: Cardinal);
|
||||||
procedure Remove(ARow, ACol: Cardinal); overload;
|
procedure Remove(ARow, ACol: Cardinal); overload;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -174,6 +175,32 @@ type
|
|||||||
function GetEnumerator: TsCellRangeEnumerator;
|
function GetEnumerator: TsCellRangeEnumerator;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TsFormulas }
|
||||||
|
TsFormulaEnumerator = class(TsRowColEnumerator)
|
||||||
|
protected
|
||||||
|
function GetCurrent: PsFormula;
|
||||||
|
public
|
||||||
|
function GetEnumerator: TsFormulaEnumerator; inline;
|
||||||
|
property Current: PsFormula read GetCurrent;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TsFormulas = class(TsRowColAVLTree)
|
||||||
|
protected
|
||||||
|
procedure DisposeData(var AData: Pointer); override;
|
||||||
|
function NewData: Pointer; override;
|
||||||
|
public
|
||||||
|
function AddFormula(ARow, ACol: Cardinal; AFormula: String = '';
|
||||||
|
AParsedFormula: TsExpressionParser = nil): PsFormula;
|
||||||
|
procedure DeleteFormula(ACell: PCell); overload;
|
||||||
|
procedure DeleteFormula(ARow, ACol: Cardinal); overload;
|
||||||
|
procedure DeleteRowOrCol(AIndex: Cardinal; IsRow: Boolean);
|
||||||
|
function FindFormula(ACell: PCell): PsFormula; overload;
|
||||||
|
function FindFormula(ARow, ACol: Cardinal): PsFormula; overload;
|
||||||
|
procedure InsertRowOrCol(AIndex: Cardinal; IsRow: Boolean);
|
||||||
|
// enumerators
|
||||||
|
function GetEnumerator: TsFormulaEnumerator;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TsCellFormatList }
|
{ TsCellFormatList }
|
||||||
TsCellFormatList = class(TFPList)
|
TsCellFormatList = class(TFPList)
|
||||||
private
|
private
|
||||||
@ -223,6 +250,146 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{ Call-back function for formulas when rows/cols are inserted/deleted }
|
||||||
|
|
||||||
|
function FixDeletedCol(AExprNode: TsExprNode; AData: Pointer): Boolean;
|
||||||
|
var
|
||||||
|
colIndex: Cardinal;
|
||||||
|
rng: TsCellRange;
|
||||||
|
begin
|
||||||
|
Result := false;
|
||||||
|
colIndex := PtrInt(AData);
|
||||||
|
if AExprNode is TsCellExprNode then
|
||||||
|
begin
|
||||||
|
if not TsCellExprNode(AExprNode).Has3dLink then
|
||||||
|
if TsCellExprNode(AExprNode).Col > colIndex then begin
|
||||||
|
TsCellExprNode(AExprNode).Col := TsCellexprNode(AExprNode).Col - 1;
|
||||||
|
Result := true;
|
||||||
|
end else
|
||||||
|
if TsCellExprNode(AExprNode).Col = colIndex then begin
|
||||||
|
TsCellExprNode(AExprNode).Error := errIllegalRef;
|
||||||
|
Result := true;
|
||||||
|
end;
|
||||||
|
end else
|
||||||
|
if AExprNode is TsCellRangeExprNode then
|
||||||
|
begin
|
||||||
|
if not TsCellRangeExprNode(AExprNode).Has3dLink then begin
|
||||||
|
rng := TsCellRangeExprNode(AExprNode).Range;
|
||||||
|
if (rng.Col1 = colIndex) and (rng.Col2 = colIndex) then begin
|
||||||
|
TsCellRangeExprNode(AExprNode).Error := errIllegalRef;
|
||||||
|
Result := true;
|
||||||
|
end else begin
|
||||||
|
if rng.Col1 > colIndex then begin
|
||||||
|
dec(rng.Col1);
|
||||||
|
Result := true;
|
||||||
|
end;
|
||||||
|
if rng.Col2 >= colIndex then begin
|
||||||
|
dec(rng.Col2);
|
||||||
|
Result := true;
|
||||||
|
end;
|
||||||
|
TsCellRangeExprNode(AExprNode).Range := rng;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FixDeletedRow(AExprNode: TsExprNode; AData: Pointer): Boolean;
|
||||||
|
var
|
||||||
|
rowIndex: Cardinal;
|
||||||
|
rng: TsCellRange;
|
||||||
|
begin
|
||||||
|
Result := false;
|
||||||
|
rowIndex := PtrInt(AData);
|
||||||
|
if AExprNode is TsCellExprNode then
|
||||||
|
begin
|
||||||
|
if not TsCellExprNode(AExprNode).Has3dLink then
|
||||||
|
if TsCellExprNode(AExprNode).Row > rowIndex then begin
|
||||||
|
TsCellExprNode(AExprNode).Row := TsCellExprNode(AExprNode).Row - 1;
|
||||||
|
Result := true;
|
||||||
|
end else
|
||||||
|
if TsCellExprNode(AExprNode).Row = rowIndex then begin
|
||||||
|
TsCelLExprNode(AExprNode).Error := errIllegalRef;
|
||||||
|
Result := true;
|
||||||
|
end;
|
||||||
|
end else
|
||||||
|
if AExprNode is TsCellRangeExprNode then
|
||||||
|
begin
|
||||||
|
if not TsCellRangeExprNode(AExprNode).Has3dLink then begin
|
||||||
|
rng := TsCellRangeExprNode(AExprNode).Range;
|
||||||
|
if (rng.Row1 = rowIndex) and (rng.Row2 = rowIndex) then begin
|
||||||
|
TsCellRangeExprNode(AExprNode).Error := errIllegalRef;
|
||||||
|
Result := true;
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
if rng.Row1 > rowIndex then begin
|
||||||
|
dec(rng.Row1);
|
||||||
|
Result := true;
|
||||||
|
end;
|
||||||
|
if rng.Row2 >= rowIndex then begin
|
||||||
|
dec(rng.Row2);
|
||||||
|
Result := true;
|
||||||
|
end;
|
||||||
|
TsCellRangeExprNode(AExprNode).Range := rng;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FixInsertedCol(AExprNode: TsExprNode; AData: Pointer): Boolean;
|
||||||
|
var
|
||||||
|
colIndex: Cardinal;
|
||||||
|
rng: TsCellRange;
|
||||||
|
begin
|
||||||
|
Result := false;
|
||||||
|
colIndex := PtrInt(AData);
|
||||||
|
if AExprNode is TsCellExprNode then
|
||||||
|
begin
|
||||||
|
if not TsCellExprNode(AExprNode).Has3dLink then
|
||||||
|
if TsCellExprNode(AExprNode).Col >= colIndex then begin
|
||||||
|
TsCellExprNode(AExprNode).Col := TsCellexprNode(AExprNode).Col + 1;
|
||||||
|
Result := true;
|
||||||
|
end;
|
||||||
|
end else
|
||||||
|
if AExprNode is TsCellRangeExprNode then
|
||||||
|
begin
|
||||||
|
if not TsCellRangeExprNode(AExprNode).Has3dLink then begin
|
||||||
|
rng := TsCellRangeExprNode(AExprNode).Range;
|
||||||
|
if rng.Col1 >= colIndex then inc(rng.Col1);
|
||||||
|
if rng.Col2 >= colIndex then inc(rng.Col2);
|
||||||
|
TsCellRangeExprNode(AExprNode).Range := rng;
|
||||||
|
Result := true;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FixInsertedRow(AExprNode: TsExprNode; AData: Pointer): Boolean;
|
||||||
|
var
|
||||||
|
rowIndex: Cardinal;
|
||||||
|
rng: TsCellRange;
|
||||||
|
begin
|
||||||
|
Result := false;
|
||||||
|
rowIndex := PtrInt(AData);
|
||||||
|
if AExprNode is TsCellExprNode then
|
||||||
|
begin
|
||||||
|
if not TsCellexprNode(AExprNode).Has3dLink then
|
||||||
|
if TsCellExprNode(AExprNode).Row >= rowIndex then begin
|
||||||
|
TsCellExprNode(AExprNode).Row := TsCellExprNode(AExprNode).Row + 1;
|
||||||
|
Result := true;
|
||||||
|
end;
|
||||||
|
end else
|
||||||
|
if AExprNode is TsCellRangeExprNode then
|
||||||
|
begin
|
||||||
|
if not TsCellRangeExprNode(AExprNode).Has3dLink then begin
|
||||||
|
rng := TsCellRangeExprNode(AExprNode).Range;
|
||||||
|
if rng.Row1 >= rowIndex then inc(rng.Row1);
|
||||||
|
if rng.Row2 >= rowIndex then inc(rng.Row2);
|
||||||
|
TsCellRangeExprNode(AExprNode).Range := rng;
|
||||||
|
Result := true;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
{==============================================================================}
|
{==============================================================================}
|
||||||
{ TsRowColEnumerator }
|
{ TsRowColEnumerator }
|
||||||
{ A specialized enumerator for TsRowColAVLTree using the pointers to the data }
|
{ A specialized enumerator for TsRowColAVLTree using the pointers to the data }
|
||||||
@ -608,20 +775,64 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
This method moves the cell in the specified column (ACol) and at row AFromRow
|
||||||
|
along the row before the row with index AToRow.
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
procedure TsRowColAVLTree.MoveAlongCol(ARow, ACol, AToRow: Cardinal);
|
||||||
|
var
|
||||||
|
r: Cardinal;
|
||||||
|
node: TAvgLvlTreeNode;
|
||||||
|
item: PsRowCol;
|
||||||
|
begin
|
||||||
|
if ARow = AToRow then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
if ARow < AToRow then
|
||||||
|
begin
|
||||||
|
node := FindLowest;
|
||||||
|
while Assigned(node) do
|
||||||
|
begin
|
||||||
|
item := PsRowCol(node.Data);
|
||||||
|
if item^.Col = ACol then break;
|
||||||
|
node := FindSuccessor(node);
|
||||||
|
end;
|
||||||
|
r := ARow;
|
||||||
|
while r < AToRow do begin
|
||||||
|
Exchange(r, ACol, r+1, ACol);
|
||||||
|
inc(r);
|
||||||
|
end;
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
node:= FindHighest;
|
||||||
|
while Assigned(node) do
|
||||||
|
begin
|
||||||
|
item := PsRowCol(node.Data);
|
||||||
|
if item^.Col = ACol then break;
|
||||||
|
node := FindPrecessor(node);
|
||||||
|
end;
|
||||||
|
r := ARow;
|
||||||
|
while r > AToRow do begin
|
||||||
|
Exchange(r, ACol, r-1, ACol);
|
||||||
|
dec(r);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
This method moves the cell in the specified row (ARow) and at column AFromCol
|
This method moves the cell in the specified row (ARow) and at column AFromCol
|
||||||
along the row before the column with index AToCol.
|
along the row before the column with index AToCol.
|
||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
procedure TsRowColAVLTree.MoveAlongRow(ARow, AFromCol, AToCol: Cardinal);
|
procedure TsRowColAVLTree.MoveAlongRow(ARow, ACol, AToCol: Cardinal);
|
||||||
var
|
var
|
||||||
c: Cardinal;
|
c: Cardinal;
|
||||||
node: TAvgLvlTreeNode;
|
node: TAvgLvlTreeNode;
|
||||||
item: PsRowCol;
|
item: PsRowCol;
|
||||||
begin
|
begin
|
||||||
if AFromCol = AToCol then
|
if ACol = AToCol then
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
if AFromCol < AToCol then
|
if ACol < AToCol then
|
||||||
begin
|
begin
|
||||||
node := FindLowest;
|
node := FindLowest;
|
||||||
while Assigned(node) do
|
while Assigned(node) do
|
||||||
@ -631,7 +842,7 @@ begin
|
|||||||
if item^.Row = ARow then break;
|
if item^.Row = ARow then break;
|
||||||
node := FindSuccessor(node);
|
node := FindSuccessor(node);
|
||||||
end;
|
end;
|
||||||
c := AFromCol;
|
c := ACol;
|
||||||
while c < AToCol do begin
|
while c < AToCol do begin
|
||||||
Exchange(ARow, c, ARow, c+1);
|
Exchange(ARow, c, ARow, c+1);
|
||||||
inc(c);
|
inc(c);
|
||||||
@ -646,7 +857,7 @@ begin
|
|||||||
if item^.Row = ARow then break;
|
if item^.Row = ARow then break;
|
||||||
node := FindPrecessor(node);
|
node := FindPrecessor(node);
|
||||||
end;
|
end;
|
||||||
c := AFromCol;
|
c := ACol;
|
||||||
while c > AToCol do begin
|
while c > AToCol do begin
|
||||||
Exchange(ARow, c, ARow, c-1);
|
Exchange(ARow, c, ARow, c-1);
|
||||||
dec(c);
|
dec(c);
|
||||||
@ -926,16 +1137,16 @@ end;
|
|||||||
{ TsHyperlinkEnumerator: enumerator for the TsHyperlinks AVLTree }
|
{ TsHyperlinkEnumerator: enumerator for the TsHyperlinks AVLTree }
|
||||||
{==============================================================================}
|
{==============================================================================}
|
||||||
|
|
||||||
function TsHyperlinkEnumerator.GetEnumerator: TsHyperlinkEnumerator;
|
|
||||||
begin
|
|
||||||
Result := self;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TsHyperlinkEnumerator.GetCurrent: PsHyperlink;
|
function TsHyperlinkEnumerator.GetCurrent: PsHyperlink;
|
||||||
begin
|
begin
|
||||||
Result := PsHyperlink(inherited GetCurrent);
|
Result := PsHyperlink(inherited GetCurrent);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TsHyperlinkEnumerator.GetEnumerator: TsHyperlinkEnumerator;
|
||||||
|
begin
|
||||||
|
Result := self;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
{==============================================================================}
|
{==============================================================================}
|
||||||
{ TsHyperlinks: an AVLTree to store hyperlink records for cells }
|
{ TsHyperlinks: an AVLTree to store hyperlink records for cells }
|
||||||
@ -1186,6 +1397,151 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{==============================================================================}
|
||||||
|
{ TsFormulaEnumerator }
|
||||||
|
{==============================================================================}
|
||||||
|
function TsFormulaEnumerator.GetCurrent: PsFormula;
|
||||||
|
begin
|
||||||
|
Result := PsFormula(inherited GetCurrent);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TsFormulaEnumerator.GetEnumerator: TsFormulaEnumerator;
|
||||||
|
begin
|
||||||
|
Result := self;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{==============================================================================}
|
||||||
|
{ TsFormulas }
|
||||||
|
{==============================================================================}
|
||||||
|
function TsFormulas.AddFormula(ARow, ACol: Cardinal; AFormula: String = '';
|
||||||
|
AParsedFormula: TsExpressionParser = nil): PsFormula;
|
||||||
|
begin
|
||||||
|
Result := PsFormula(FindByRowCol(ARow, ACol));
|
||||||
|
if Result = nil then
|
||||||
|
Result := PsFormula(Add(ARow, ACol));
|
||||||
|
Result^.Text := AFormula; // unparsed formula
|
||||||
|
Result^.Parser := AParsedFormula; // if nil, will be parsed on next calculation
|
||||||
|
Result^.CalcState := csNotCalculated;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TsFormulas.DeleteFormula(ACell: PCell);
|
||||||
|
begin
|
||||||
|
if ACell <> nil then
|
||||||
|
Delete(ACell^.Row, ACell^.Col);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TsFormulas.DeleteFormula(ARow, ACol: Cardinal);
|
||||||
|
begin
|
||||||
|
Delete(ARow, ACol); // will release memory automatically
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TsFormulas.DeleteRowOrCol(AIndex: Cardinal; IsRow: Boolean);
|
||||||
|
var
|
||||||
|
node, nextnode: TAvgLvlTreeNode;
|
||||||
|
formula: PsFormula;
|
||||||
|
changed: Boolean;
|
||||||
|
begin
|
||||||
|
node := FindLowest;
|
||||||
|
while Assigned(node) do
|
||||||
|
begin
|
||||||
|
changed := false;
|
||||||
|
nextnode := FindSuccessor(node);
|
||||||
|
formula := PsFormula(node.Data);
|
||||||
|
if IsRow then
|
||||||
|
begin
|
||||||
|
// Remove and destroy the formula record if it is in the deleted row
|
||||||
|
if formula^.Row = AIndex then
|
||||||
|
Delete(node)
|
||||||
|
else
|
||||||
|
if formula^.Row > AIndex then
|
||||||
|
dec(formula^.Row);
|
||||||
|
// Update all RowCol records at row indexes above the deleted row
|
||||||
|
changed := formula^.Parser.IterateNodes(@FixDeletedRow, Pointer(PtrInt(AIndex)));
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
// Remove and destroy the formula record if it is in the deleted column
|
||||||
|
if formula^.Col = AIndex then
|
||||||
|
Delete(node)
|
||||||
|
else begin
|
||||||
|
if formula^.Col > AIndex then
|
||||||
|
dec(formula^.Col);
|
||||||
|
// Update all RowCol records at column indexes above the deleted column
|
||||||
|
changed := formula^.Parser.IterateNodes(@FixDeletedCol, Pointer(PtrInt(AIndex)));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
// Recreate the formula if required.
|
||||||
|
if changed then
|
||||||
|
formula^.Text := formula^.Parser.Expression;
|
||||||
|
node := nextnode;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TsFormulas.DisposeData(var AData: Pointer);
|
||||||
|
begin
|
||||||
|
if AData <> nil then begin
|
||||||
|
PsFormula(AData)^.Text := '';
|
||||||
|
PsFormula(AData)^.Parser.Free;
|
||||||
|
Dispose(PsFormula(AData));
|
||||||
|
end;
|
||||||
|
AData := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TsFormulas.FindFormula(ACell: PCell): PsFormula;
|
||||||
|
begin
|
||||||
|
if ACell <> nil then
|
||||||
|
Result := PsFormula(FindbyRowCol(ACell^.Row, ACell^.Col))
|
||||||
|
else
|
||||||
|
Result := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TsFormulas.FindFormula(ARow, ACol: Cardinal): PsFormula;
|
||||||
|
begin
|
||||||
|
Result := PsFormula(FindByRowCol(ARow, ACol));
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Formula enumerators (use in "for ... in" syntax)
|
||||||
|
function TsFormulas.GetEnumerator: TsFormulaEnumerator;
|
||||||
|
begin
|
||||||
|
Result := TsFormulaEnumerator.Create(self, 0, 0, $7FFFFFFF, $7FFFFFFF, false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TsFormulas.InsertRowOrCol(AIndex: Cardinal; IsRow: Boolean);
|
||||||
|
var
|
||||||
|
node: TAvgLvlTreeNode;
|
||||||
|
formula: PsFormula;
|
||||||
|
changed: Boolean;
|
||||||
|
begin
|
||||||
|
node := FindLowest;
|
||||||
|
while Assigned(node) do begin
|
||||||
|
formula := PsFormula(node.Data);
|
||||||
|
if IsRow then
|
||||||
|
begin
|
||||||
|
if formula^.Row >= AIndex then inc(formula^.Row);
|
||||||
|
changed := formula^.Parser.IterateNodes(@FixInsertedRow, Pointer(PtrInt(AIndex)));
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
if formula^.Col >= AIndex then inc(formula^.Col);
|
||||||
|
changed := formula^.Parser.IterateNodes(@FixInsertedCol, Pointer(PtrInt(AIndex)));
|
||||||
|
end;
|
||||||
|
if changed then
|
||||||
|
formula^.Text := formula^.Parser.Expression;
|
||||||
|
node := FindSuccessor(node);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TsFormulas.NewData: Pointer;
|
||||||
|
var
|
||||||
|
f: PsFormula;
|
||||||
|
begin
|
||||||
|
New(f);
|
||||||
|
f^.Text := '';
|
||||||
|
f^.Parser := nil;
|
||||||
|
f^.CalcState := csNotCalculated;
|
||||||
|
Result := f;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
{==============================================================================}
|
{==============================================================================}
|
||||||
{ TsCellFormatList }
|
{ TsCellFormatList }
|
||||||
{==============================================================================}
|
{==============================================================================}
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
// Keep spaces in formula
|
// Keep spaces in formula
|
||||||
|
|
||||||
{$mode objfpc}
|
{$mode objfpc}
|
||||||
{$h+}
|
{$H+}
|
||||||
unit fpsExprParser;
|
unit fpsExprParser;
|
||||||
|
|
||||||
interface
|
interface
|
||||||
@ -78,8 +78,10 @@ const
|
|||||||
];
|
];
|
||||||
|
|
||||||
type
|
type
|
||||||
|
// Forward declarations
|
||||||
TsExpressionParser = class;
|
TsExpressionParser = class;
|
||||||
TsBuiltInExpressionManager = class;
|
TsBuiltInExpressionManager = class;
|
||||||
|
TsExprNode = class;
|
||||||
|
|
||||||
TsResultType = (rtEmpty, rtBoolean, rtInteger, rtFloat, rtDateTime, rtString,
|
TsResultType = (rtEmpty, rtBoolean, rtInteger, rtFloat, rtDateTime, rtString,
|
||||||
rtCell, rtCellRange, rtHyperlink, rtError, rtMissingArg, rtAny);
|
rtCell, rtCellRange, rtHyperlink, rtError, rtMissingArg, rtAny);
|
||||||
@ -104,6 +106,10 @@ type
|
|||||||
PsExpressionResult = ^TsExpressionResult;
|
PsExpressionResult = ^TsExpressionResult;
|
||||||
TsExprParameterArray = array of TsExpressionResult;
|
TsExprParameterArray = array of TsExpressionResult;
|
||||||
|
|
||||||
|
{ Function executed when iterating through all nodes (Parser.IterateNodes).
|
||||||
|
The function returns true if the text formula has to be rebuilt. }
|
||||||
|
TsExprNodeFunc = function(ANode: TsExprNode; AData: Pointer): Boolean;
|
||||||
|
|
||||||
{ TsExprNode }
|
{ TsExprNode }
|
||||||
TsExprNode = class(TObject)
|
TsExprNode = class(TObject)
|
||||||
private
|
private
|
||||||
@ -116,6 +122,7 @@ type
|
|||||||
function AsString: string; virtual; abstract;
|
function AsString: string; virtual; abstract;
|
||||||
procedure Check; virtual; //abstract;
|
procedure Check; virtual; //abstract;
|
||||||
function Has3DLink: Boolean; virtual;
|
function Has3DLink: Boolean; virtual;
|
||||||
|
function IterateNodes(AFunc: TsExprNodeFunc; AData: Pointer): Boolean; virtual;
|
||||||
function NodeType: TsResultType; virtual; abstract;
|
function NodeType: TsResultType; virtual; abstract;
|
||||||
function NodeValue: TsExpressionResult;
|
function NodeValue: TsExpressionResult;
|
||||||
property Parser: TsExpressionParser read FParser;
|
property Parser: TsExpressionParser read FParser;
|
||||||
@ -134,6 +141,7 @@ type
|
|||||||
constructor Create(AParser: TsExpressionParser; ALeft, ARight: TsExprNode);
|
constructor Create(AParser: TsExpressionParser; ALeft, ARight: TsExprNode);
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
function Has3DLink: Boolean; override;
|
function Has3DLink: Boolean; override;
|
||||||
|
function IterateNodes(AFunc: TsExprNodeFunc; AData: Pointer): boolean; override;
|
||||||
property Left: TsExprNode read FLeft;
|
property Left: TsExprNode read FLeft;
|
||||||
property Right: TsExprNode read FRight;
|
property Right: TsExprNode read FRight;
|
||||||
end;
|
end;
|
||||||
@ -555,6 +563,7 @@ type
|
|||||||
function AsString: String; override;
|
function AsString: String; override;
|
||||||
procedure Check; override;
|
procedure Check; override;
|
||||||
function Has3DLink: Boolean; override;
|
function Has3DLink: Boolean; override;
|
||||||
|
function IterateNodes(AFunc: TsExprNodeFunc; AData: Pointer): Boolean; override;
|
||||||
property ArgumentNodes: TsExprArgumentArray read FArgumentNodes;
|
property ArgumentNodes: TsExprArgumentArray read FArgumentNodes;
|
||||||
property ArgumentParams: TsExprParameterArray read FArgumentParams;
|
property ArgumentParams: TsExprParameterArray read FArgumentParams;
|
||||||
end;
|
end;
|
||||||
@ -592,12 +601,11 @@ type
|
|||||||
FCell: PCell;
|
FCell: PCell;
|
||||||
FSheetName: String;
|
FSheetName: String;
|
||||||
FIsRef: Boolean;
|
FIsRef: Boolean;
|
||||||
|
FError: TsErrorValue;
|
||||||
protected
|
protected
|
||||||
function GetCol: Cardinal;
|
function GetCol: Cardinal;
|
||||||
function GetRow: Cardinal;
|
function GetRow: Cardinal;
|
||||||
function GetSheet: TsBasicWorksheet;
|
function GetSheet: TsBasicWorksheet;
|
||||||
function GetSheetIndex: Integer;
|
|
||||||
function GetSheetName: String;
|
|
||||||
function GetWorkbook: TsBasicWorkbook;
|
function GetWorkbook: TsBasicWorkbook;
|
||||||
procedure GetNodeValue(out AResult: TsExpressionResult); override;
|
procedure GetNodeValue(out AResult: TsExpressionResult); override;
|
||||||
public
|
public
|
||||||
@ -606,8 +614,14 @@ type
|
|||||||
function AsRPNItem(ANext: PRPNItem): PRPNItem; override;
|
function AsRPNItem(ANext: PRPNItem): PRPNItem; override;
|
||||||
function AsString: string; override;
|
function AsString: string; override;
|
||||||
procedure Check; override;
|
procedure Check; override;
|
||||||
|
function GetSheetIndex: Integer;
|
||||||
|
function GetSheetName: String;
|
||||||
function Has3DLink: Boolean; override;
|
function Has3DLink: Boolean; override;
|
||||||
|
function IterateNodes(AFunc: TsExprNodeFunc; AData: Pointer): Boolean; override;
|
||||||
function NodeType: TsResultType; override;
|
function NodeType: TsResultType; override;
|
||||||
|
property Col: Cardinal read FCol write FCol; // Be careful when modifying Col and Row
|
||||||
|
property Row: Cardinal read FRow write FRow;
|
||||||
|
property Error: TsErrorValue read FError write FError;
|
||||||
property Worksheet: TsBasicWorksheet read FWorksheet;
|
property Worksheet: TsBasicWorksheet read FWorksheet;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -622,10 +636,13 @@ type
|
|||||||
FSheetIndex: array[TsCellRangeIndex] of Integer;
|
FSheetIndex: array[TsCellRangeIndex] of Integer;
|
||||||
FFlags: TsRelFlags;
|
FFlags: TsRelFlags;
|
||||||
F3dRange: Boolean;
|
F3dRange: Boolean;
|
||||||
|
FError: TsErrorValue;
|
||||||
|
function GetRange: TsCellRange;
|
||||||
|
procedure SetRange(const ARange: TsCellRange);
|
||||||
protected
|
protected
|
||||||
function GetCol(AIndex: TsCellRangeIndex): Cardinal;
|
function GetCol(AIndex: TsCellRangeIndex): Cardinal;
|
||||||
function GetRow(AIndex: TsCellRangeIndex): Cardinal;
|
function GetRow(AIndex: TsCellRangeIndex): Cardinal;
|
||||||
procedure GetNodeValue(out Result: TsExpressionResult); override;
|
procedure GetNodeValue(out AResult: TsExpressionResult); override;
|
||||||
function GetWorkbook: TsBasicWorkbook;
|
function GetWorkbook: TsBasicWorkbook;
|
||||||
public
|
public
|
||||||
constructor Create(AParser: TsExpressionParser; AWorksheet: TsBasicWorksheet;
|
constructor Create(AParser: TsExpressionParser; AWorksheet: TsBasicWorksheet;
|
||||||
@ -633,8 +650,12 @@ type
|
|||||||
function AsRPNItem(ANext: PRPNItem): PRPNItem; override;
|
function AsRPNItem(ANext: PRPNItem): PRPNItem; override;
|
||||||
function AsString: String; override;
|
function AsString: String; override;
|
||||||
procedure Check; override;
|
procedure Check; override;
|
||||||
|
function GetSheetIndex(AIndex: TsCellRangeIndex): Integer;
|
||||||
function Has3DLink: Boolean; override;
|
function Has3DLink: Boolean; override;
|
||||||
|
function IterateNodes(AFunc: TsExprNodeFunc; AData: Pointer): Boolean; override;
|
||||||
function NodeType: TsResultType; override;
|
function NodeType: TsResultType; override;
|
||||||
|
property Error: TsErrorValue read FError write FError;
|
||||||
|
property Range: TsCellRange read GetRange write SetRange; // Be careful!
|
||||||
property Workbook: TsBasicWorkbook read GetWorkbook;
|
property Workbook: TsBasicWorkbook read GetWorkbook;
|
||||||
property Worksheet: TsBasicWorksheet read FWorksheet;
|
property Worksheet: TsBasicWorksheet read FWorksheet;
|
||||||
end;
|
end;
|
||||||
@ -744,8 +765,8 @@ type
|
|||||||
function TokenType: TsTokenType;
|
function TokenType: TsTokenType;
|
||||||
procedure CreateHashList;
|
procedure CreateHashList;
|
||||||
property Scanner: TsExpressionScanner read FScanner;
|
property Scanner: TsExpressionScanner read FScanner;
|
||||||
property ExprNode: TsExprNode read FExprNode;
|
|
||||||
property Dirty: Boolean read FDirty;
|
property Dirty: Boolean read FDirty;
|
||||||
|
property ExprNode: TsExprNode read FExprNode;
|
||||||
|
|
||||||
public
|
public
|
||||||
constructor Create(AWorksheet: TsBasicWorksheet); virtual;
|
constructor Create(AWorksheet: TsBasicWorksheet); virtual;
|
||||||
@ -756,6 +777,7 @@ type
|
|||||||
function Evaluate: TsExpressionResult;
|
function Evaluate: TsExpressionResult;
|
||||||
procedure EvaluateExpression(out AResult: TsExpressionResult);
|
procedure EvaluateExpression(out AResult: TsExpressionResult);
|
||||||
function Has3DLinks: Boolean;
|
function Has3DLinks: Boolean;
|
||||||
|
function IterateNodes(AFunc: TsExprNodeFunc; AData: Pointer): boolean;
|
||||||
procedure PrepareCopyMode(ASourceCell, ADestCell: PCell);
|
procedure PrepareCopyMode(ASourceCell, ADestCell: PCell);
|
||||||
function ResultType: TsResultType;
|
function ResultType: TsResultType;
|
||||||
|
|
||||||
@ -820,6 +842,16 @@ type
|
|||||||
property Identifiers[AIndex: Integer]: TsBuiltInExprIdentifierDef read GetI;
|
property Identifiers[AIndex: Integer]: TsBuiltInExprIdentifierDef read GetI;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TsFormula }
|
||||||
|
TsFormula = record
|
||||||
|
Row, Col: Cardinal;
|
||||||
|
Text: String;
|
||||||
|
Parser: TsExpressionParser;
|
||||||
|
CalcState: TsCalcState;
|
||||||
|
end;
|
||||||
|
PsFormula = ^TsFormula;
|
||||||
|
|
||||||
|
{ Exception classes }
|
||||||
EExprParser = class(Exception);
|
EExprParser = class(Exception);
|
||||||
ECalcEngine = class(Exception);
|
ECalcEngine = class(Exception);
|
||||||
|
|
||||||
@ -1494,8 +1526,10 @@ end;
|
|||||||
|
|
||||||
procedure TsExpressionParser.EvaluateExpression(out AResult: TsExpressionResult);
|
procedure TsExpressionParser.EvaluateExpression(out AResult: TsExpressionResult);
|
||||||
begin
|
begin
|
||||||
|
{ // Not needed. May be missing after copying formulas
|
||||||
if (FExpression = '') then
|
if (FExpression = '') then
|
||||||
ParserError(rsExpressionEmpty);
|
ParserError(rsExpressionEmpty);
|
||||||
|
}
|
||||||
if not Assigned(FExprNode) then
|
if not Assigned(FExprNode) then
|
||||||
ParserError(rsErrorInExpression);
|
ParserError(rsErrorInExpression);
|
||||||
FExprNode.GetNodeValue(AResult);
|
FExprNode.GetNodeValue(AResult);
|
||||||
@ -1941,6 +1975,12 @@ begin
|
|||||||
Result := FExprNode.Has3DLink;
|
Result := FExprNode.Has3DLink;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TsExpressionParser.IterateNodes(AFunc: TsExprNodeFunc;
|
||||||
|
AData: Pointer): Boolean;
|
||||||
|
begin
|
||||||
|
Result := FExprNode.IterateNodes(AFunc, AData);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TsExpressionParser.SetDialect(const AValue: TsFormulaDialect);
|
procedure TsExpressionParser.SetDialect(const AValue: TsFormulaDialect);
|
||||||
begin
|
begin
|
||||||
if FDialect = AValue then exit;
|
if FDialect = AValue then exit;
|
||||||
@ -2723,6 +2763,12 @@ begin
|
|||||||
Result := false;
|
Result := false;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TsExprNode.IterateNodes(AFunc: TsExprNodeFunc; AData: Pointer): Boolean;
|
||||||
|
begin
|
||||||
|
Unused(AFunc, AData);
|
||||||
|
// to be overridden by descendant classes
|
||||||
|
end;
|
||||||
|
|
||||||
function TsExprNode.NodeValue: TsExpressionResult;
|
function TsExprNode.NodeValue: TsExpressionResult;
|
||||||
begin
|
begin
|
||||||
GetNodeValue(Result);
|
GetNodeValue(Result);
|
||||||
@ -2773,6 +2819,12 @@ begin
|
|||||||
Result := FLeft.Has3DLink or FRight.Has3DLink;
|
Result := FLeft.Has3DLink or FRight.Has3DLink;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TsBinaryOperationExprNode.IterateNodes(AFunc: TsExprNodeFunc;
|
||||||
|
AData: Pointer): Boolean;
|
||||||
|
begin
|
||||||
|
Result := FLeft.IterateNodes(AFunc, AData) or FRight.IterateNodes(AFunc, AData);
|
||||||
|
end;
|
||||||
|
|
||||||
function TsBinaryOperationExprNode.HasError(out AResult: TsExpressionResult): Boolean;
|
function TsBinaryOperationExprNode.HasError(out AResult: TsExpressionResult): Boolean;
|
||||||
begin
|
begin
|
||||||
Result := Left.HasError(AResult) or Right.HasError(AResult);
|
Result := Left.HasError(AResult) or Right.HasError(AResult);
|
||||||
@ -3724,6 +3776,16 @@ begin
|
|||||||
Result := false;
|
Result := false;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TsFunctionExprNode.IterateNodes(AFunc: TsExprNodeFunc;
|
||||||
|
AData: Pointer): Boolean;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
Result := false;
|
||||||
|
for i:=0 to High(FArgumentParams) do
|
||||||
|
Result := Result or FArgumentNodes[i].IterateNodes(AFunc, AData);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
{ TsFunctionCallBackExprNode }
|
{ TsFunctionCallBackExprNode }
|
||||||
|
|
||||||
@ -3773,12 +3835,16 @@ begin
|
|||||||
FRow := ARow;
|
FRow := ARow;
|
||||||
FCol := ACol;
|
FCol := ACol;
|
||||||
FFlags := AFlags;
|
FFlags := AFlags;
|
||||||
|
FError := errOK;
|
||||||
FCell := (GetSheet as TsWorksheet).FindCell(FRow, FCol);
|
FCell := (GetSheet as TsWorksheet).FindCell(FRow, FCol);
|
||||||
if Has3DLink then FParser.FContains3DRef := true;
|
if Has3DLink then FParser.FContains3DRef := true;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsCellExprNode.AsRPNItem(ANext: PRPNItem): PRPNItem;
|
function TsCellExprNode.AsRPNItem(ANext: PRPNItem): PRPNItem;
|
||||||
begin
|
begin
|
||||||
|
if FError <> errOK then
|
||||||
|
Result := RPNErr(FError, ANext)
|
||||||
|
else
|
||||||
if FIsRef then
|
if FIsRef then
|
||||||
begin
|
begin
|
||||||
if Has3dLink then
|
if Has3dLink then
|
||||||
@ -3798,6 +3864,11 @@ function TsCellExprNode.AsString: string;
|
|||||||
var
|
var
|
||||||
r, c: Cardinal;
|
r, c: Cardinal;
|
||||||
begin
|
begin
|
||||||
|
if FError <> errOK then begin
|
||||||
|
Result := GetErrorValueStr(FError);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
r := Getrow;
|
r := Getrow;
|
||||||
c := GetCol;
|
c := GetCol;
|
||||||
if Has3dLink then
|
if Has3dLink then
|
||||||
@ -3843,6 +3914,46 @@ begin
|
|||||||
Result := FCol - FParser.FSourceCell^.Col + FParser.FDestCell^.Col;
|
Result := FCol - FParser.FSourceCell^.Col + FParser.FDestCell^.Col;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TsCellExprNode.GetNodeValue(out AResult: TsExpressionResult);
|
||||||
|
var
|
||||||
|
cell: PCell;
|
||||||
|
formula: PsFormula;
|
||||||
|
sheet: TsWorksheet;
|
||||||
|
begin
|
||||||
|
if FError <> errOK then begin
|
||||||
|
AResult.ResultType := rtError;
|
||||||
|
AResult.ResError := FError;
|
||||||
|
{
|
||||||
|
AResult.ResRow := GetRow;
|
||||||
|
AResult.ResCol := GetCol;
|
||||||
|
AResult.Worksheet := GetSheet;
|
||||||
|
}
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if Parser.CopyMode then
|
||||||
|
cell := (FWorksheet as TsWorksheet).FindCell(GetRow, GetCol)
|
||||||
|
else
|
||||||
|
cell := FCell;
|
||||||
|
|
||||||
|
if (cell <> nil) and HasFormula(cell) then begin
|
||||||
|
sheet := TsWorksheet(cell^.Worksheet);
|
||||||
|
formula := sheet.Formulas.FindFormula(cell^.Row, cell^.Col);
|
||||||
|
case formula^.CalcState of
|
||||||
|
csNotCalculated:
|
||||||
|
sheet.CalcFormula(formula);
|
||||||
|
csCalculating:
|
||||||
|
raise ECalcEngine.CreateFmt(rsCircularReference, [GetCellString(cell^.Row, cell^.Col)]);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
AResult.ResultType := rtCell;
|
||||||
|
AResult.ResRow := GetRow;
|
||||||
|
AResult.ResCol := GetCol;
|
||||||
|
AResult.Worksheet := GetSheet;
|
||||||
|
end;
|
||||||
|
|
||||||
|
(*
|
||||||
procedure TsCellExprNode.GetNodeValue(out AResult: TsExpressionResult);
|
procedure TsCellExprNode.GetNodeValue(out AResult: TsExpressionResult);
|
||||||
var
|
var
|
||||||
cell: PCell;
|
cell: PCell;
|
||||||
@ -3865,6 +3976,7 @@ begin
|
|||||||
AResult.ResCol := GetCol;
|
AResult.ResCol := GetCol;
|
||||||
AResult.Worksheet := GetSheet;
|
AResult.Worksheet := GetSheet;
|
||||||
end;
|
end;
|
||||||
|
*)
|
||||||
|
|
||||||
{ See: GetCol }
|
{ See: GetCol }
|
||||||
function TsCellExprNode.GetRow: Cardinal;
|
function TsCellExprNode.GetRow: Cardinal;
|
||||||
@ -3878,8 +3990,10 @@ function TsCellExprNode.GetSheet: TsBasicWorksheet;
|
|||||||
begin
|
begin
|
||||||
if FSheetName = '' then
|
if FSheetName = '' then
|
||||||
Result := FWorksheet
|
Result := FWorksheet
|
||||||
else
|
else begin
|
||||||
Result := (GetWorkbook as TsWorkbook).GetWorksheetByName(FSheetName);
|
Result := (GetWorkbook as TsWorkbook).GetWorksheetByName(FSheetName);
|
||||||
|
if Result = nil then FError := errIllegalREF;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsCellExprNode.GetSheetIndex: Integer;
|
function TsCellExprNode.GetSheetIndex: Integer;
|
||||||
@ -3916,6 +4030,12 @@ begin
|
|||||||
Result := rtCell;
|
Result := rtCell;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TsCellExprNode.IterateNodes(AFunc: TsExprNodeFunc;
|
||||||
|
AData: Pointer): Boolean;
|
||||||
|
begin
|
||||||
|
Result := AFunc(self, AData);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{ TsCellRangeExprNode }
|
{ TsCellRangeExprNode }
|
||||||
@ -3932,15 +4052,25 @@ begin
|
|||||||
FParser := AParser;
|
FParser := AParser;
|
||||||
FWorksheet := AWorksheet;
|
FWorksheet := AWorksheet;
|
||||||
FFlags := [];
|
FFlags := [];
|
||||||
|
FError := errOK;
|
||||||
book := TsWorkbook(GetWorkbook);
|
book := TsWorkbook(GetWorkbook);
|
||||||
|
|
||||||
F3dRange := ((ASheet1 <> '') and (ASheet2 <> '') { and (ASheet1 <> ASheet2)}) or
|
F3dRange := ((ASheet1 <> '') and (ASheet2 <> '') { and (ASheet1 <> ASheet2)}) or
|
||||||
((ASheet1 <> '') and (ASheet2 = ''));
|
((ASheet1 <> '') and (ASheet2 = ''));
|
||||||
|
|
||||||
FSheetIndex[1] := book.GetWorksheetIndex(ASheet1);
|
FSheetIndex[1] := book.GetWorksheetIndex(ASheet1);
|
||||||
if ASheet2 <> '' then
|
{
|
||||||
FSheetIndex[2] := book.GetWorksheetIndex(ASheet2)
|
if FSheetIndex[1] = -1 then
|
||||||
|
FError := errIllegalREF
|
||||||
else
|
else
|
||||||
|
}
|
||||||
|
if ASheet2 <> '' then begin
|
||||||
|
FSheetIndex[2] := book.GetWorksheetIndex(ASheet2);
|
||||||
|
{
|
||||||
|
if FSheetIndex[2] = -1 then
|
||||||
|
FError := errIllegalREF;
|
||||||
|
}
|
||||||
|
end else
|
||||||
FSheetIndex[2] := FSheetIndex[1];
|
FSheetIndex[2] := FSheetIndex[1];
|
||||||
EnsureOrder(FSheetIndex[1], FSheetIndex[2]);
|
EnsureOrder(FSheetIndex[1], FSheetIndex[2]);
|
||||||
|
|
||||||
@ -3982,6 +4112,9 @@ end;
|
|||||||
|
|
||||||
function TsCellRangeExprNode.AsRPNItem(ANext: PRPNItem): PRPNItem;
|
function TsCellRangeExprNode.AsRPNItem(ANext: PRPNItem): PRPNItem;
|
||||||
begin
|
begin
|
||||||
|
if FError <> errOK then
|
||||||
|
Result := RPNErr(FError, ANext)
|
||||||
|
else
|
||||||
if F3dRange then
|
if F3dRange then
|
||||||
Result := RPNCellRange3D(
|
Result := RPNCellRange3D(
|
||||||
FSheetIndex[1], GetRow(1), Integer(GetCol(1)),
|
FSheetIndex[1], GetRow(1), Integer(GetCol(1)),
|
||||||
@ -4001,6 +4134,11 @@ var
|
|||||||
r1, c1, r2, c2: Cardinal;
|
r1, c1, r2, c2: Cardinal;
|
||||||
s1, s2: String;
|
s1, s2: String;
|
||||||
begin
|
begin
|
||||||
|
if FError <> errOK then begin
|
||||||
|
Result := GetErrorValueStr(FError);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
if FSheetIndex[1] = -1 then
|
if FSheetIndex[1] = -1 then
|
||||||
s1 := FWorksheet.Name
|
s1 := FWorksheet.Name
|
||||||
else
|
else
|
||||||
@ -4058,7 +4196,7 @@ begin
|
|||||||
Result := FCol[AIndex] - FParser.FSourceCell^.Col + FParser.FDestCell^.Col;
|
Result := FCol[AIndex] - FParser.FSourceCell^.Col + FParser.FDestCell^.Col;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TsCellRangeExprNode.GetNodeValue(out Result: TsExpressionResult);
|
procedure TsCellRangeExprNode.GetNodeValue(out AResult: TsExpressionResult);
|
||||||
var
|
var
|
||||||
r, c, s: Array[TsCellRangeIndex] of Integer;
|
r, c, s: Array[TsCellRangeIndex] of Integer;
|
||||||
rr, cc, ss: Integer;
|
rr, cc, ss: Integer;
|
||||||
@ -4066,7 +4204,14 @@ var
|
|||||||
cell: PCell;
|
cell: PCell;
|
||||||
book: TsWorkbook;
|
book: TsWorkbook;
|
||||||
sheet: TsWorksheet;
|
sheet: TsWorksheet;
|
||||||
|
formula: PsFormula;
|
||||||
begin
|
begin
|
||||||
|
if FError <> errOK then begin
|
||||||
|
AResult.ResultType := rtError;
|
||||||
|
AResult.ResError := FError;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
for i in TsCellRangeIndex do
|
for i in TsCellRangeIndex do
|
||||||
begin
|
begin
|
||||||
r[i] := GetRow(i);
|
r[i] := GetRow(i);
|
||||||
@ -4081,29 +4226,35 @@ begin
|
|||||||
|
|
||||||
for ss := s[1] to s[2] do begin
|
for ss := s[1] to s[2] do begin
|
||||||
sheet := (Workbook as TsWorkbook).GetWorksheetByIndex(ss);
|
sheet := (Workbook as TsWorkbook).GetWorksheetByIndex(ss);
|
||||||
for rr := r[1] to r[2] do
|
for formula in sheet.Formulas do
|
||||||
for cc := c[1] to c[2] do
|
if (formula^.Row >= r[1]) and (formula^.Row <= r[2]) and
|
||||||
begin
|
(formula^.Col >= c[1]) and (formula^.Col <= c[2])
|
||||||
cell := sheet.FindCell(rr, cc);
|
then
|
||||||
if HasFormula(cell) then
|
case formula^.CalcState of
|
||||||
case sheet.GetCalcState(cell) of
|
|
||||||
csNotCalculated:
|
csNotCalculated:
|
||||||
sheet.CalcFormula(cell);
|
sheet.CalcFormula(formula);
|
||||||
csCalculating:
|
csCalculating:
|
||||||
raise ECalcEngine.Create(rsCircularReference);
|
raise ECalcEngine.Create(rsCircularReference);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
AResult.ResultType := rtCellRange;
|
||||||
|
AResult.ResCellRange.Row1 := r[1];
|
||||||
|
AResult.ResCellRange.Col1 := c[1];
|
||||||
|
AResult.ResCellRange.Row2 := r[2];
|
||||||
|
AResult.ResCellRange.Col2 := c[2];
|
||||||
|
AResult.ResCellRange.Sheet1 := s[1];
|
||||||
|
AResult.ResCellRange.Sheet2 := s[2];
|
||||||
|
AResult.Worksheet := FWorksheet;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Result.ResultType := rtCellRange;
|
// Be careful when modifying GetRange - it may break everything
|
||||||
Result.ResCellRange.Row1 := r[1];
|
function TsCellRangeExprNode.GetRange: TsCellRange;
|
||||||
Result.ResCellRange.Col1 := c[1];
|
begin
|
||||||
Result.ResCellRange.Row2 := r[2];
|
Result.Row1 := FRow[1];
|
||||||
Result.ResCellRange.Col2 := c[2];
|
Result.Col1 := FCol[1];
|
||||||
Result.ResCellRange.Sheet1 := s[1];
|
Result.Row2 := FRow[2];
|
||||||
Result.ResCellRange.Sheet2 := s[2];
|
Result.Col2 := FCol[2];
|
||||||
Result.Worksheet := FWorksheet;
|
|
||||||
// Result.Worksheet2 := FWorksheet2;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsCellRangeExprNode.GetRow(AIndex: TsCellRangeIndex): Cardinal;
|
function TsCellRangeExprNode.GetRow(AIndex: TsCellRangeIndex): Cardinal;
|
||||||
@ -4115,19 +4266,41 @@ end;
|
|||||||
|
|
||||||
function TsCellRangeExprNode.GetWorkbook: TsBasicWorkbook;
|
function TsCellRangeExprNode.GetWorkbook: TsBasicWorkbook;
|
||||||
begin
|
begin
|
||||||
|
if FWorksheet = nil then
|
||||||
|
Result := nil
|
||||||
|
else
|
||||||
Result := (FWorksheet as TsWorksheet).Workbook;
|
Result := (FWorksheet as TsWorksheet).Workbook;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TsCellRangeExprNode.GetSheetIndex(AIndex: TsCellRangeIndex): Integer;
|
||||||
|
begin
|
||||||
|
Result := FSheetIndex[AIndex];
|
||||||
|
end;
|
||||||
|
|
||||||
function TsCellRangeExprNode.Has3DLink: Boolean;
|
function TsCellRangeExprNode.Has3DLink: Boolean;
|
||||||
begin
|
begin
|
||||||
Result := F3dRange;
|
Result := F3dRange;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TsCellRangeExprNode.IterateNodes(AFunc: TsExprNodeFunc;
|
||||||
|
AData: Pointer): Boolean;
|
||||||
|
begin
|
||||||
|
Result := AFunc(self, AData);
|
||||||
|
end;
|
||||||
|
|
||||||
function TsCellRangeExprNode.NodeType: TsResultType;
|
function TsCellRangeExprNode.NodeType: TsResultType;
|
||||||
begin
|
begin
|
||||||
Result := rtCellRange;
|
Result := rtCellRange;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TsCellRangeExprNode.SetRange(const ARange: TsCellRange);
|
||||||
|
begin
|
||||||
|
FRow[1] := ARange.Row1;
|
||||||
|
FCol[1] := ARange.Col1;
|
||||||
|
FRow[2] := ARange.Row2;
|
||||||
|
FCol[2] := ARange.Col2;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
{------------------------------------------------------------------------------}
|
{------------------------------------------------------------------------------}
|
||||||
{ Conversion of arguments to simple data types }
|
{ Conversion of arguments to simple data types }
|
||||||
|
@ -112,7 +112,7 @@ type
|
|||||||
function FindNumFormatByName(ANumFmtName: String): Integer;
|
function FindNumFormatByName(ANumFmtName: String): Integer;
|
||||||
function FindRowStyleByName(AStyleName: String): Integer;
|
function FindRowStyleByName(AStyleName: String): Integer;
|
||||||
function FindTableStyleByName(AStyleName: String): Integer;
|
function FindTableStyleByName(AStyleName: String): Integer;
|
||||||
procedure FixFormulas;
|
// procedure FixFormulas;
|
||||||
procedure ReadCell(ANode: TDOMNode; ARow, ACol: Integer;
|
procedure ReadCell(ANode: TDOMNode; ARow, ACol: Integer;
|
||||||
AFormatIndex: Integer; out AColsRepeated: Integer);
|
AFormatIndex: Integer; out AColsRepeated: Integer);
|
||||||
procedure ReadColumns(ATableNode: TDOMNode);
|
procedure ReadColumns(ATableNode: TDOMNode);
|
||||||
@ -134,6 +134,7 @@ type
|
|||||||
procedure ReadRowStyle(AStyleNode: TDOMNode);
|
procedure ReadRowStyle(AStyleNode: TDOMNode);
|
||||||
procedure ReadShapes(ATableNode: TDOMNode);
|
procedure ReadShapes(ATableNode: TDOMNode);
|
||||||
procedure ReadSheetProtection(ANode: TDOMNode; ASheet: TsBasicWorksheet);
|
procedure ReadSheetProtection(ANode: TDOMNode; ASheet: TsBasicWorksheet);
|
||||||
|
procedure ReadSheets(ANode: TDOMNode);
|
||||||
procedure ReadTableStyle(AStyleNode: TDOMNode);
|
procedure ReadTableStyle(AStyleNode: TDOMNode);
|
||||||
|
|
||||||
protected
|
protected
|
||||||
@ -1435,7 +1436,7 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
Result := -1;
|
Result := -1;
|
||||||
end;
|
end;
|
||||||
|
(*
|
||||||
procedure TsSpreadOpenDocReader.FixFormulas;
|
procedure TsSpreadOpenDocReader.FixFormulas;
|
||||||
|
|
||||||
procedure FixCell(ACell: PCell);
|
procedure FixCell(ACell: PCell);
|
||||||
@ -1480,7 +1481,7 @@ begin
|
|||||||
for cell in sheet.Cells do
|
for cell in sheet.Cells do
|
||||||
if HasFormula(cell) then FixCell(cell);
|
if HasFormula(cell) then FixCell(cell);
|
||||||
end;
|
end;
|
||||||
end;
|
end; *)
|
||||||
|
|
||||||
procedure TsSpreadOpenDocReader.ReadAutomaticStyles(AStylesNode: TDOMNode);
|
procedure TsSpreadOpenDocReader.ReadAutomaticStyles(AStylesNode: TDOMNode);
|
||||||
var
|
var
|
||||||
@ -2387,7 +2388,8 @@ procedure TsSpreadOpenDocReader.ReadFormula(ARow, ACol: Cardinal;
|
|||||||
AStyleIndex: Integer; ACellNode: TDOMNode);
|
AStyleIndex: Integer; ACellNode: TDOMNode);
|
||||||
var
|
var
|
||||||
cell: PCell;
|
cell: PCell;
|
||||||
formula: String;
|
formula: PsFormula;
|
||||||
|
formulaStr: String;
|
||||||
// stylename: String;
|
// stylename: String;
|
||||||
floatValue: Double;
|
floatValue: Double;
|
||||||
boolValue: Boolean;
|
boolValue: Boolean;
|
||||||
@ -2418,31 +2420,38 @@ begin
|
|||||||
}
|
}
|
||||||
fmt := TsWorkbook(Workbook).GetPointerToCellFormat(cell^.FormatIndex);
|
fmt := TsWorkbook(Workbook).GetPointerToCellFormat(cell^.FormatIndex);
|
||||||
|
|
||||||
formula := '';
|
formulaStr := '';
|
||||||
if (boReadFormulas in FWorkbook.Options) then
|
if (boReadFormulas in FWorkbook.Options) then
|
||||||
begin
|
begin
|
||||||
// Read formula, trim it, ...
|
// Read formula, trim it, ...
|
||||||
formula := GetAttrValue(ACellNode, 'table:formula');
|
formulaStr := GetAttrValue(ACellNode, 'table:formula');
|
||||||
if formula <> '' then
|
if formulaStr <> '' then
|
||||||
begin
|
begin
|
||||||
// Formulas written by Spread begin with 'of:=', by Excel with 'msof:='.
|
// Formulas written by Spread begin with 'of:=', by Excel with 'msof:='.
|
||||||
// Remove that. And both use different list separators.
|
// Remove that. And both use different list separators.
|
||||||
p := pos('=', formula);
|
p := pos('=', formulaStr);
|
||||||
ns := Copy(formula, 1, p-2);
|
ns := Copy(formulaStr, 1, p-2);
|
||||||
case ns of
|
case ns of
|
||||||
'of' : FPointSeparatorSettings.ListSeparator := ';';
|
'of' : FPointSeparatorSettings.ListSeparator := ';';
|
||||||
'msoxl': FPointSeparatorSettings.ListSeparator := ',';
|
'msoxl': FPointSeparatorSettings.ListSeparator := ',';
|
||||||
end;
|
end;
|
||||||
Delete(formula, 1, p);
|
Delete(formulaStr, 1, p);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// ... and store in cell's FormulaValue field.
|
// ... and store in cell's FormulaValue field.
|
||||||
|
formula := TsWorksheet(FWorksheet).Formulas.AddFormula(ARow, ACol);
|
||||||
|
formula^.Parser := TsSpreadsheetParser.Create(FWorksheet);
|
||||||
|
formula^.Parser.Dialect := fdOpenDocument; // Parse in ODS dialect
|
||||||
|
formula^.Parser.Expression := formulaStr;
|
||||||
|
formula^.Parser.Dialect := fdExcelA1; // Convert formula to Excel A1 dialect
|
||||||
|
formula^.Text := formula^.Parser.Expression;
|
||||||
|
{
|
||||||
cell^.FormulaValue := formula;
|
cell^.FormulaValue := formula;
|
||||||
// Note: This formula is still in OpenDocument dialect. Conversion to
|
// Note: This formula is still in OpenDocument dialect. Conversion to
|
||||||
// ExcelA1 dialect (used by fps) is postponed until all sheets have beeon
|
// ExcelA1 dialect (used by fps) is postponed until all sheets have beeon
|
||||||
// read (--> FixFormulas) because of possible references to other sheets
|
// read (--> FixFormulas) because of possible references to other sheets
|
||||||
// which might not have been loaded yet at this moment.
|
// which might not have been loaded yet at this moment.
|
||||||
|
}
|
||||||
{$IFDEF FPSpreadDebug}
|
{$IFDEF FPSpreadDebug}
|
||||||
DebugLn(' Formula found: ' + formula);
|
DebugLn(' Formula found: ' + formula);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
@ -2587,6 +2596,7 @@ begin
|
|||||||
if not Assigned(SpreadSheetNode) then
|
if not Assigned(SpreadSheetNode) then
|
||||||
raise EFPSpreadsheet.Create('[TsSpreadOpenDocReader.ReadFromStream] Node "office:spreadsheet" not found.');
|
raise EFPSpreadsheet.Create('[TsSpreadOpenDocReader.ReadFromStream] Node "office:spreadsheet" not found.');
|
||||||
|
|
||||||
|
ReadSheets(SpreadsheetNode);
|
||||||
ReadDocumentProtection(SpreadsheetNode);
|
ReadDocumentProtection(SpreadsheetNode);
|
||||||
ReadDateMode(SpreadSheetNode);
|
ReadDateMode(SpreadSheetNode);
|
||||||
|
|
||||||
@ -2613,7 +2623,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
sheetName := GetAttrValue(TableNode, 'table:name');
|
sheetName := GetAttrValue(TableNode, 'table:name');
|
||||||
FWorkSheet := TsWorkbook(FWorkbook).AddWorksheet(sheetName, true);
|
FWorksheet := TsWorkbook(FWorkbook).GetWorksheetByName(sheetName);
|
||||||
|
// FWorkSheet := TsWorkbook(FWorkbook).AddWorksheet(sheetName, true);
|
||||||
tablestyleName := GetAttrValue(TableNode, 'table:style-name');
|
tablestyleName := GetAttrValue(TableNode, 'table:style-name');
|
||||||
// Read protection
|
// Read protection
|
||||||
ReadSheetProtection(TableNode, FWorksheet);
|
ReadSheetProtection(TableNode, FWorksheet);
|
||||||
@ -2660,7 +2671,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
// Convert formulas from OpenDocument to ExcelA1 dialect
|
// Convert formulas from OpenDocument to ExcelA1 dialect
|
||||||
FixFormulas;
|
// FixFormulas;
|
||||||
|
|
||||||
// Active sheet
|
// Active sheet
|
||||||
if FActiveSheet <> '' then
|
if FActiveSheet <> '' then
|
||||||
@ -4085,6 +4096,24 @@ begin
|
|||||||
(ASheet as TsWorksheet).Protect(false);
|
(ASheet as TsWorksheet).Protect(false);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TsSpreadOpenDocReader.ReadSheets(ANode: TDOMNode);
|
||||||
|
var
|
||||||
|
nodename: String;
|
||||||
|
sheetName: String;
|
||||||
|
begin
|
||||||
|
ANode := ANode.FirstChild;
|
||||||
|
while ANode <> nil do begin
|
||||||
|
nodeName := ANode.NodeName;
|
||||||
|
if nodeName = 'table:table' then begin
|
||||||
|
sheetName := GetAttrValue(ANode, 'table:name');
|
||||||
|
if sheetName <> '' then
|
||||||
|
// Create worksheet immediately because it may be needed for 3d formulas
|
||||||
|
(FWorkbook as TsWorkbook).AddWorksheet(sheetname, true);
|
||||||
|
end;
|
||||||
|
ANode := ANode.NextSibling;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TsSpreadOpenDocReader.ReadStyles(AStylesNode: TDOMNode);
|
procedure TsSpreadOpenDocReader.ReadStyles(AStylesNode: TDOMNode);
|
||||||
var
|
var
|
||||||
styleNode: TDOMNode;
|
styleNode: TDOMNode;
|
||||||
@ -7564,8 +7593,9 @@ procedure TsSpreadOpenDocWriter.WriteFormula(AStream: TStream; const ARow,
|
|||||||
ACol: Cardinal; ACell: PCell);
|
ACol: Cardinal; ACell: PCell);
|
||||||
var
|
var
|
||||||
lStyle: String = '';
|
lStyle: String = '';
|
||||||
|
formula: PsFormula;
|
||||||
|
formulaStr: String;
|
||||||
parser: TsExpressionParser;
|
parser: TsExpressionParser;
|
||||||
formula: String;
|
|
||||||
valuetype: String;
|
valuetype: String;
|
||||||
value: string;
|
value: string;
|
||||||
valueStr: String;
|
valueStr: String;
|
||||||
@ -7577,6 +7607,7 @@ var
|
|||||||
fmt: TsCellFormat;
|
fmt: TsCellFormat;
|
||||||
ignoreFormulas: Boolean;
|
ignoreFormulas: Boolean;
|
||||||
sheet: TsWorksheet;
|
sheet: TsWorksheet;
|
||||||
|
oldDialect: TsFormulaDialect;
|
||||||
begin
|
begin
|
||||||
Unused(ARow, ACol);
|
Unused(ARow, ACol);
|
||||||
ignoreFormulas := (boIgnoreFormulas in FWorkbook.Options);
|
ignoreFormulas := (boIgnoreFormulas in FWorkbook.Options);
|
||||||
@ -7608,16 +7639,32 @@ begin
|
|||||||
FWorkbook.AddErrorMsg(rsODSHyperlinksOfTextCellsOnly, [GetCellString(ARow, ACol)]);
|
FWorkbook.AddErrorMsg(rsODSHyperlinksOfTextCellsOnly, [GetCellString(ARow, ACol)]);
|
||||||
|
|
||||||
// Formula string
|
// Formula string
|
||||||
|
formula := sheet.Formulas.FindFormula(ACell);
|
||||||
|
|
||||||
if ignoreFormulas then begin
|
if ignoreFormulas then begin
|
||||||
formula := ACell^.FormulaValue;
|
formulaStr := formula^.Text;
|
||||||
if (formula <> '') then begin
|
if (formulaStr <> '') then begin
|
||||||
if not ((pos('of:=', formula) = 1) or (pos('=', formula) = 1)) then
|
if not ((pos('of:=', formulaStr) = 1) or (pos('=', formulaStr) = 1)) then
|
||||||
formula := 'of:=' + formula;
|
formulaStr := 'of:=' + formulaStr;
|
||||||
end;
|
end;
|
||||||
end else
|
end else
|
||||||
begin
|
begin
|
||||||
valueStr := '';
|
valueStr := '';
|
||||||
// Convert string formula to the format needed by ods: semicolon list separators!
|
if formula^.Parser = nil then begin
|
||||||
|
formula^.Parser := TsSpreadsheetParser.Create(FWorksheet);
|
||||||
|
formula^.Parser.Expression := formula^.Text;
|
||||||
|
end;
|
||||||
|
// Convert string formula to the format needed by ods
|
||||||
|
oldDialect := formula^.Parser.Dialect;
|
||||||
|
try
|
||||||
|
formula^.Parser.Dialect := fdOpenDocument;
|
||||||
|
formulaStr := formula^.Parser.Expression; // Formula converted to ODS dialect
|
||||||
|
if (formulaStr <> '') and (formulastr[1] <> '=') then
|
||||||
|
formulaStr := '=' + formulaStr;
|
||||||
|
finally
|
||||||
|
formula^.Parser.Dialect := oldDialect;
|
||||||
|
end;
|
||||||
|
{
|
||||||
parser := TsSpreadsheetParser.Create(FWorksheet);
|
parser := TsSpreadsheetParser.Create(FWorksheet);
|
||||||
try
|
try
|
||||||
parser.Expression := ACell^.FormulaValue; // Formula still in Excel dialect
|
parser.Expression := ACell^.FormulaValue; // Formula still in Excel dialect
|
||||||
@ -7628,7 +7675,7 @@ begin
|
|||||||
finally
|
finally
|
||||||
parser.Free;
|
parser.Free;
|
||||||
end;
|
end;
|
||||||
|
}
|
||||||
case ACell^.ContentType of
|
case ACell^.ContentType of
|
||||||
cctNumber:
|
cctNumber:
|
||||||
begin
|
begin
|
||||||
@ -7675,23 +7722,24 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
{ Fix special xml characters }
|
{ Fix special xml characters }
|
||||||
formula := UTF8TextToXMLText(formula);
|
formulaStr := UTF8TextToXMLText(formulaStr);
|
||||||
|
|
||||||
{ 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 not ignoreFormulas or (sheet.GetCalcState(ACell) = csCalculated) then
|
// if not ignoreFormulas or (sheet.GetCalcState(ACell) = csCalculated) then
|
||||||
|
if not ignoreFormulas or (formula^.CalcState = csCalculated) then // LOOKS STRANGE - IS THIS CORRECT?
|
||||||
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 +
|
||||||
valueStr +
|
valueStr +
|
||||||
'</table:table-cell>', [
|
'</table:table-cell>', [
|
||||||
formula, valuetype, value, lStyle, spannedStr
|
formulaStr, valuetype, value, lStyle, spannedStr
|
||||||
]))
|
]))
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
AppendToStream(AStream, Format(
|
AppendToStream(AStream, Format(
|
||||||
'<table:table-cell table:formula="%s"%s%s', [
|
'<table:table-cell table:formula="%s"%s%s', [
|
||||||
formula, lStyle, spannedStr]));
|
formulaStr, lStyle, spannedStr]));
|
||||||
if comment <> '' then
|
if comment <> '' then
|
||||||
AppendToStream(AStream, '>' + comment + '</table:table-cell>')
|
AppendToStream(AStream, '>' + comment + '</table:table-cell>')
|
||||||
else
|
else
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -205,6 +205,9 @@ const
|
|||||||
SHEETSEPARATOR = '!';
|
SHEETSEPARATOR = '!';
|
||||||
|
|
||||||
type
|
type
|
||||||
|
TsFormulaFlag = (ffCalculating, ffCalculated);
|
||||||
|
TsFormulaFlags = set of TsFormulaFlag;
|
||||||
|
|
||||||
{@@ Elements of an expanded formula.
|
{@@ Elements of an expanded formula.
|
||||||
Note: If ElementKind is fekCellOffset, "Row" and "Col" have to be cast to signed integers! }
|
Note: If ElementKind is fekCellOffset, "Row" and "Col" have to be cast to signed integers! }
|
||||||
TsFormulaElement = record
|
TsFormulaElement = record
|
||||||
@ -589,8 +592,8 @@ type
|
|||||||
TsCalcState = (csNotCalculated, csCalculating, csCalculated);
|
TsCalcState = (csNotCalculated, csCalculating, csCalculated);
|
||||||
|
|
||||||
{@@ Cell flag }
|
{@@ Cell flag }
|
||||||
TsCellFlag = (cfCalculating, cfCalculated, cfHasComment, cfHyperlink, cfMerged,
|
TsCellFlag = ({cfCalculating, cfCalculated, }cfHasComment, cfHyperlink, cfMerged,
|
||||||
cf3dFormula);
|
cfHasFormula, cf3dFormula);
|
||||||
|
|
||||||
{@@ Set of cell flags }
|
{@@ Set of cell flags }
|
||||||
TsCellFlags = set of TsCellFlag;
|
TsCellFlags = set of TsCellFlag;
|
||||||
@ -744,7 +747,7 @@ type
|
|||||||
{ Cell content }
|
{ Cell content }
|
||||||
UTF8StringValue: String; // Strings cannot be part of a variant record
|
UTF8StringValue: String; // Strings cannot be part of a variant record
|
||||||
RichTextParams: TsRichTextParams; // Formatting of individual text ranges
|
RichTextParams: TsRichTextParams; // Formatting of individual text ranges
|
||||||
FormulaValue: String; // Formula for calculation of cell content
|
// FormulaValue: String; // Formula for calculation of cell content
|
||||||
case ContentType: TCellContentType of // variant part must be at the end
|
case ContentType: TCellContentType of // variant part must be at the end
|
||||||
cctEmpty : (); // has no data at all
|
cctEmpty : (); // has no data at all
|
||||||
cctFormula : (); // FormulaValue is outside the variant record
|
cctFormula : (); // FormulaValue is outside the variant record
|
||||||
|
@ -202,8 +202,9 @@ procedure InitImageRecord(out AValue: TsImage; ARow, ACol: Cardinal;
|
|||||||
AOffsetX, AOffsetY, AScaleX, AScaleY: Double);
|
AOffsetX, AOffsetY, AScaleX, AScaleY: Double);
|
||||||
procedure InitHeaderFooterImageRecord(out AImage: TsHeaderFooterImage);
|
procedure InitHeaderFooterImageRecord(out AImage: TsHeaderFooterImage);
|
||||||
|
|
||||||
procedure CopyCellValue(AFromCell, AToCell: PCell);
|
//procedure CopyCellValue(AFromCell, AToCell: PCell);
|
||||||
function HasFormula(ACell: PCell): Boolean;
|
function HasFormula(ACell: PCell): Boolean;
|
||||||
|
function Has3dFormula(ACell: PCell): Boolean;
|
||||||
function SameCellBorders(AFormat1, AFormat2: PsCellFormat): Boolean;
|
function SameCellBorders(AFormat1, AFormat2: PsCellFormat): Boolean;
|
||||||
function SameFont(AFont1, AFont2: TsFont): Boolean; overload;
|
function SameFont(AFont1, AFont2: TsFont): Boolean; overload;
|
||||||
function SameFont(AFont: TsFont; AFontName: String; AFontSize: Single;
|
function SameFont(AFont: TsFont; AFontName: String; AFontSize: Single;
|
||||||
@ -2334,7 +2335,6 @@ end;
|
|||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
procedure InitCell(out ACell: TCell);
|
procedure InitCell(out ACell: TCell);
|
||||||
begin
|
begin
|
||||||
ACell.FormulaValue := '';
|
|
||||||
ACell.UTF8StringValue := '';
|
ACell.UTF8StringValue := '';
|
||||||
FillChar(ACell, SizeOf(ACell), 0);
|
FillChar(ACell, SizeOf(ACell), 0);
|
||||||
end;
|
end;
|
||||||
@ -2418,7 +2418,7 @@ begin
|
|||||||
Index := -1;
|
Index := -1;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
(*
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Copies the value of a cell to another one. Does not copy the formula, erases
|
Copies the value of a cell to another one. Does not copy the formula, erases
|
||||||
the formula of the destination cell if there is one!
|
the formula of the destination cell if there is one!
|
||||||
@ -2428,18 +2428,20 @@ end;
|
|||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
procedure CopyCellValue(AFromCell, AToCell: PCell);
|
procedure CopyCellValue(AFromCell, AToCell: PCell);
|
||||||
begin
|
begin
|
||||||
Assert(AFromCell <> nil);
|
|
||||||
Assert(AToCell <> nil);
|
Assert(AToCell <> nil);
|
||||||
|
|
||||||
|
if AFromCell <> nil then begin
|
||||||
AToCell^.ContentType := AFromCell^.ContentType;
|
AToCell^.ContentType := AFromCell^.ContentType;
|
||||||
AToCell^.NumberValue := AFromCell^.NumberValue;
|
AToCell^.NumberValue := AFromCell^.NumberValue;
|
||||||
AToCell^.DateTimeValue := AFromCell^.DateTimeValue;
|
AToCell^.DateTimeValue := AFromCell^.DateTimeValue;
|
||||||
AToCell^.BoolValue := AFromCell^.BoolValue;
|
AToCell^.BoolValue := AFromCell^.BoolValue;
|
||||||
AToCell^.ErrorValue := AFromCell^.ErrorValue;
|
AToCell^.ErrorValue := AFromCell^.ErrorValue;
|
||||||
AToCell^.UTF8StringValue := AFromCell^.UTF8StringValue;
|
AToCell^.UTF8StringValue := AFromCell^.UTF8StringValue;
|
||||||
AToCell^.FormulaValue := ''; // This is confirmed with Excel
|
// Note: As confirmed with Excel, the formula is not to be copied here.
|
||||||
|
// Note: The calling routine must erase the formula if the destination cell has one.
|
||||||
end;
|
end;
|
||||||
|
end;
|
||||||
|
*)
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Returns TRUE if the cell contains a formula.
|
Returns TRUE if the cell contains a formula.
|
||||||
|
|
||||||
@ -2447,7 +2449,15 @@ end;
|
|||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
function HasFormula(ACell: PCell): Boolean;
|
function HasFormula(ACell: PCell): Boolean;
|
||||||
begin
|
begin
|
||||||
Result := Assigned(ACell) and (Length(ACell^.FormulaValue) > 0);
|
Result := Assigned(ACell) and (cfHasFormula in ACell^.Flags);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Returns TRUE if the cell has a 3D formula (i.e. reference to another sheet)
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
function Has3dFormula(ACell: PCell): Boolean;
|
||||||
|
begin
|
||||||
|
Result := HasFormula(ACell) and (cf3dFormula in ACell^.Flags);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
@ -2554,6 +2554,29 @@ begin
|
|||||||
AStream.WriteWord(0);
|
AStream.WriteWord(0);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function DoCollectSheetsWith3dRefs(ANode: TsExprNode; AData: Pointer): Boolean;
|
||||||
|
var
|
||||||
|
sheetlist: TsBIFF8ExternSheetList;
|
||||||
|
sheetIdx, sheetIdx1, sheetIdx2: Integer;
|
||||||
|
workbook: TsWorkbook;
|
||||||
|
begin
|
||||||
|
sheetlist := TsBIFF8ExternSheetList(AData);
|
||||||
|
if (ANode is TsCellExprNode) and TsCellExprNode(ANode).Has3DLink then
|
||||||
|
begin
|
||||||
|
sheetIdx := TsCellExprNode(ANode).GetSheetIndex;
|
||||||
|
sheetList.AddSheets('', nil, sheetIdx, sheetIdx);
|
||||||
|
end else
|
||||||
|
if (ANode is TsCellRangeExprNode) and TsCellRangeExprNode(ANode).Has3DLink then
|
||||||
|
begin
|
||||||
|
workbook := TsCellRangeExprNode(ANode).Workbook as TsWorkbook;
|
||||||
|
sheetIdx1 := TsCellRangeExprNode(ANode).GetSheetIndex(1);
|
||||||
|
sheetIdx2 := TsCellRangeExprNode(ANode).GetSheetIndex(2);
|
||||||
|
for sheetIdx := sheetIdx1 to sheetIdx2 do
|
||||||
|
sheetList.AddSheets('', nil, sheetIdx1, sheetIdx2);
|
||||||
|
end;
|
||||||
|
Result := false;
|
||||||
|
end;
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Collects the data for out-of-sheet links found in the specified worksheet
|
Collects the data for out-of-sheet links found in the specified worksheet
|
||||||
(or all worksheets if the parameter is omitted).
|
(or all worksheets if the parameter is omitted).
|
||||||
@ -2561,6 +2584,14 @@ end;
|
|||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
procedure TsSpreadBIFF8Writer.CollectExternData;
|
procedure TsSpreadBIFF8Writer.CollectExternData;
|
||||||
|
|
||||||
|
procedure DoCollectForSheet(ASheet: TsWorksheet);
|
||||||
|
var
|
||||||
|
formula: PsFormula;
|
||||||
|
begin
|
||||||
|
for formula in ASheet.Formulas do
|
||||||
|
formula^.Parser.IterateNodes(@DoCollectSheetsWith3dRefs, FBiff8ExternSheets);
|
||||||
|
end;
|
||||||
|
{
|
||||||
procedure DoCollectForSheet(ASheet: TsWorksheet);
|
procedure DoCollectForSheet(ASheet: TsWorksheet);
|
||||||
var
|
var
|
||||||
cell: PCell;
|
cell: PCell;
|
||||||
@ -2593,7 +2624,7 @@ procedure TsSpreadBIFF8Writer.CollectExternData;
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
}
|
||||||
var
|
var
|
||||||
book: TsWorkbook;
|
book: TsWorkbook;
|
||||||
sheet: TsWorksheet;
|
sheet: TsWorksheet;
|
||||||
|
@ -2872,13 +2872,35 @@ var
|
|||||||
n: Word;
|
n: Word;
|
||||||
rpnFormula: TsRPNformula;
|
rpnFormula: TsRPNformula;
|
||||||
strFormula: String;
|
strFormula: String;
|
||||||
|
formula: PsFormula;
|
||||||
begin
|
begin
|
||||||
n := ReadRPNTokenArraySize(AStream);
|
n := ReadRPNTokenArraySize(AStream);
|
||||||
|
if n = 0 then
|
||||||
|
exit(false);
|
||||||
|
|
||||||
Result := ReadRPNTokenArray(AStream, n, rpnFormula, ACell, ASharedFormulaBase);
|
Result := ReadRPNTokenArray(AStream, n, rpnFormula, ACell, ASharedFormulaBase);
|
||||||
if Result then begin
|
if Result then begin
|
||||||
|
formula := TsWorksheet(FWorksheet).Formulas.FindFormula(ACell);
|
||||||
|
if formula = nil then begin
|
||||||
|
formula := TsWorksheet(FWorksheet).Formulas.AddFormula(ACell^.Row, ACell^.Col);
|
||||||
|
formula^.Parser := TsSpreadsheetParser.Create(FWorksheet);
|
||||||
|
end;
|
||||||
|
formula^.Parser.RPNFormula := rpnFormula;
|
||||||
|
formula^.Text := formula^.Parser.Expression;
|
||||||
|
if formula^.Parser.Has3dLinks then
|
||||||
|
ACell^.Flags := ACell^.Flags + [cfHasFormula, cf3dFormula]
|
||||||
|
else
|
||||||
|
ACell^.Flags := ACell^.Flags + [cfHasFormula];
|
||||||
|
{
|
||||||
strFormula := tsWorksheet(FWorksheet).ConvertRPNFormulaToStringFormula(rpnFormula);
|
strFormula := tsWorksheet(FWorksheet).ConvertRPNFormulaToStringFormula(rpnFormula);
|
||||||
if strFormula <> '' then
|
if strFormula <> '' then begin
|
||||||
ACell^.FormulaValue := strFormula;
|
formula := TsWorksheet(FWorksheet).Formulas.AddFormula(ACell^.Row, ACell^.Col, strFormula);
|
||||||
|
if formula^.Parsed.Has3dLinks then
|
||||||
|
ACell^.Flags := ACell^.Flags + [cfHasFormula, cf3dFormula]
|
||||||
|
else
|
||||||
|
ACell^.Flags := ACell^.Flags + [cfHasFormula];
|
||||||
|
end;
|
||||||
|
}
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -3441,6 +3463,27 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function DoCollectSheetsWith3dRefs(ANode: TsExprNode; AData: Pointer): Boolean;
|
||||||
|
var
|
||||||
|
sheetlist: TsBIFFExternSheetList;
|
||||||
|
sheetIdx, sheetIdx1, sheetIdx2: Integer;
|
||||||
|
workbook: TsWorkbook;
|
||||||
|
begin
|
||||||
|
sheetlist := TsBIFFExternSheetList(AData);
|
||||||
|
if (ANode is TsCellExprNode) and TsCellExprNode(ANode).Has3DLink then
|
||||||
|
sheetList.AddSheet(TsCellExprNode(ANode).GetSheetName, ebkInternal)
|
||||||
|
else
|
||||||
|
if (ANode is TsCellRangeExprNode) and TsCellRangeExprNode(ANode).Has3DLink then
|
||||||
|
begin
|
||||||
|
workbook := TsCellRangeExprNode(ANode).Workbook as TsWorkbook;
|
||||||
|
sheetIdx1 := TsCellRangeExprNode(ANode).GetSheetIndex(1);
|
||||||
|
sheetIdx2 := TsCellRangeExprNode(ANode).GetSheetIndex(2);
|
||||||
|
for sheetIdx := sheetIdx1 to sheetIdx2 do
|
||||||
|
sheetList.AddSheet(workbook.GetWorksheetByIndex(sheetIdx).Name, ebkInternal);
|
||||||
|
end;
|
||||||
|
Result := false; // No need to rebuild the text formula
|
||||||
|
end;
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Collects the data for out-of-sheet links found in the specified worksheet
|
Collects the data for out-of-sheet links found in the specified worksheet
|
||||||
(or all worksheets if the parameter is omitted).
|
(or all worksheets if the parameter is omitted).
|
||||||
@ -3450,6 +3493,13 @@ end;
|
|||||||
function TsSpreadBIFFWriter.CollectExternData(AWorksheet: TsBasicWorksheet = nil): Integer;
|
function TsSpreadBIFFWriter.CollectExternData(AWorksheet: TsBasicWorksheet = nil): Integer;
|
||||||
|
|
||||||
procedure DoCollectForSheet(ASheet: TsWorksheet; ASheetList: TsBIFFExternSheetList);
|
procedure DoCollectForSheet(ASheet: TsWorksheet; ASheetList: TsBIFFExternSheetList);
|
||||||
|
var
|
||||||
|
formula: PsFormula;
|
||||||
|
begin
|
||||||
|
for formula in ASheet.Formulas do
|
||||||
|
formula^.Parser.IterateNodes(@DoCollectSheetsWith3dRefs, ASheetList);
|
||||||
|
end;
|
||||||
|
{
|
||||||
var
|
var
|
||||||
cell: PCell;
|
cell: PCell;
|
||||||
workbook: TsWorkbook;
|
workbook: TsWorkbook;
|
||||||
@ -3496,6 +3546,7 @@ function TsSpreadBIFFWriter.CollectExternData(AWorksheet: TsBasicWorksheet = nil
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
}
|
||||||
|
|
||||||
var
|
var
|
||||||
sheet: TsWorksheet;
|
sheet: TsWorksheet;
|
||||||
|
@ -641,6 +641,7 @@ var
|
|||||||
datanode, tnode: TDOMNode;
|
datanode, tnode: TDOMNode;
|
||||||
dataStr: String;
|
dataStr: String;
|
||||||
formulaStr: String;
|
formulaStr: String;
|
||||||
|
formula: PsFormula;
|
||||||
nodeName: String;
|
nodeName: String;
|
||||||
sstIndex: Integer;
|
sstIndex: Integer;
|
||||||
number: Double;
|
number: Double;
|
||||||
@ -731,8 +732,11 @@ begin
|
|||||||
sharedformulabase := TSharedFormulaData(FSharedFormulaBaseList[StrToInt(s)]);
|
sharedformulabase := TSharedFormulaData(FSharedFormulaBaseList[StrToInt(s)]);
|
||||||
// ... and copy shared formula to destination cell
|
// ... and copy shared formula to destination cell
|
||||||
InitCell(FWorksheet, sharedformulabase.Row, sharedformulabase.Col, lCell);
|
InitCell(FWorksheet, sharedformulabase.Row, sharedformulabase.Col, lCell);
|
||||||
lCell.Formulavalue := sharedformulabase.Formula;
|
formula := sharedFormulaBase.Worksheet.Formulas.AddFormula(
|
||||||
lCell.Worksheet := sharedformulabase.Worksheet;
|
sharedFormulabase.Row, sharedFormulaBase.Col, sharedformulabase.Formula
|
||||||
|
);
|
||||||
|
// lCell.Formulavalue := sharedformulabase.Formula;
|
||||||
|
// lCell.Worksheet := sharedformulabase.Worksheet;
|
||||||
sheet.CopyFormula(@lCell, cell);
|
sheet.CopyFormula(@lCell, cell);
|
||||||
cell^.ContentType := cctFormula;
|
cell^.ContentType := cctFormula;
|
||||||
end;
|
end;
|
||||||
@ -740,8 +744,8 @@ begin
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
// "Normal" formula
|
// "Normal" formula
|
||||||
cell^.FormulaValue := formulaStr;
|
sheet.WriteFormula(cell, formulaStr);
|
||||||
// AWorksheet.WriteFormula(cell, formulaStr);
|
// cell^.FormulaValue := formulaStr;
|
||||||
except
|
except
|
||||||
on E:EExprParser do begin
|
on E:EExprParser do begin
|
||||||
FWorkbook.AddErrorMsg(E.Message);
|
FWorkbook.AddErrorMsg(E.Message);
|
||||||
@ -759,11 +763,8 @@ begin
|
|||||||
// get data type
|
// get data type
|
||||||
s := GetAttrValue(ANode, 't'); // "t" = data type
|
s := GetAttrValue(ANode, 't'); // "t" = data type
|
||||||
if (s = '') and (dataStr = '') then
|
if (s = '') and (dataStr = '') then
|
||||||
begin
|
sheet.WriteBlank(cell, true) // true --> do not erase the formula!!!
|
||||||
formulaStr := cell^.FormulaValue;
|
else
|
||||||
sheet.WriteBlank(cell); // this erases the formula!!!
|
|
||||||
cell^.FormulaValue := formulaStr;
|
|
||||||
end else
|
|
||||||
if (s = '') or (s = 'n') then begin
|
if (s = '') or (s = 'n') then begin
|
||||||
// Number or date/time, depending on format
|
// Number or date/time, depending on format
|
||||||
number := StrToFloat(dataStr, FPointSeparatorSettings);
|
number := StrToFloat(dataStr, FPointSeparatorSettings);
|
||||||
@ -795,9 +796,9 @@ begin
|
|||||||
end else
|
end else
|
||||||
if (s = 'str') or (s = 'inlineStr') then begin
|
if (s = 'str') or (s = 'inlineStr') then begin
|
||||||
// literal string
|
// literal string
|
||||||
formulaStr := cell^.FormulaValue;
|
// formulaStr := cell^.FormulaValue;
|
||||||
sheet.WriteText(cell, datastr);
|
sheet.WriteText(cell, datastr);
|
||||||
cell^.FormulaValue := formulaStr;
|
// cell^.FormulaValue := formulaStr;
|
||||||
end else
|
end else
|
||||||
if s = 'b' then
|
if s = 'b' then
|
||||||
// boolean
|
// boolean
|
||||||
@ -2068,6 +2069,8 @@ begin
|
|||||||
sheetData.ID := GetAttrvalue(node, 'sheetID');
|
sheetData.ID := GetAttrvalue(node, 'sheetID');
|
||||||
sheetData.Hidden := GetAttrValue(node, 'state') = 'hidden';
|
sheetData.Hidden := GetAttrValue(node, 'state') = 'hidden';
|
||||||
FSheetList.Add(sheetData);
|
FSheetList.Add(sheetData);
|
||||||
|
// Create worksheet - needed because of 3d references
|
||||||
|
(FWorkbook as TsWorkbook).AddWorksheet(sheetData.Name, true);
|
||||||
end;
|
end;
|
||||||
node := node.NextSibling;
|
node := node.NextSibling;
|
||||||
end;
|
end;
|
||||||
@ -2520,8 +2523,12 @@ begin
|
|||||||
|
|
||||||
// read worksheets
|
// read worksheets
|
||||||
for i:=0 to FSheetList.Count-1 do begin
|
for i:=0 to FSheetList.Count-1 do begin
|
||||||
|
{
|
||||||
// Create worksheet
|
// Create worksheet
|
||||||
FWorksheet := (FWorkbook as TsWorkbook).AddWorksheet(TSheetData(FSheetList[i]).Name, true);
|
FWorksheet := (FWorkbook as TsWorkbook).AddWorksheet(TSheetData(FSheetList[i]).Name, true);
|
||||||
|
}
|
||||||
|
// Worksheets are already created...
|
||||||
|
FWorksheet := (FWorkbook as TsWorkbook).GetWorksheetByName(TSheetData(FSheetList[i]).Name);
|
||||||
if TSheetData(FSheetList[i]).Hidden then
|
if TSheetData(FSheetList[i]).Hidden then
|
||||||
FWorksheet.Options := FWorksheet.Options + [soHidden];
|
FWorksheet.Options := FWorksheet.Options + [soHidden];
|
||||||
|
|
||||||
@ -5219,10 +5226,15 @@ var
|
|||||||
cellPosText: String;
|
cellPosText: String;
|
||||||
lStyleIndex: Integer;
|
lStyleIndex: Integer;
|
||||||
t, v: String;
|
t, v: String;
|
||||||
|
formula: PsFormula;
|
||||||
|
formulaStr: String;
|
||||||
begin
|
begin
|
||||||
cellPosText := TsWorksheet.CellPosToText(ARow, ACol);
|
cellPosText := TsWorksheet.CellPosToText(ARow, ACol);
|
||||||
lStyleIndex := GetStyleIndex(ACell);
|
lStyleIndex := GetStyleIndex(ACell);
|
||||||
|
|
||||||
|
formula := TsWorksheet(FWorksheet).Formulas.FindFormula(ARow, ACol);
|
||||||
|
formulaStr := PrepareFormula(formula^.Text);
|
||||||
|
|
||||||
case ACell^.ContentType of
|
case ACell^.ContentType of
|
||||||
cctFormula:
|
cctFormula:
|
||||||
begin
|
begin
|
||||||
@ -5265,7 +5277,7 @@ begin
|
|||||||
'%s' +
|
'%s' +
|
||||||
'</c>', [
|
'</c>', [
|
||||||
CellPosText, lStyleIndex, t,
|
CellPosText, lStyleIndex, t,
|
||||||
PrepareFormula(ACell^.FormulaValue),
|
formulaStr,
|
||||||
v
|
v
|
||||||
]));
|
]));
|
||||||
end;
|
end;
|
||||||
|
@ -162,12 +162,12 @@ type
|
|||||||
published
|
published
|
||||||
{@@ Automatically detects the fileformat when loading the spreadsheet file
|
{@@ Automatically detects the fileformat when loading the spreadsheet file
|
||||||
specified by FileName }
|
specified by FileName }
|
||||||
property AutoDetectFormat: Boolean read FAutoDetectFormat write FAutoDetectFormat;
|
property AutoDetectFormat: Boolean read FAutoDetectFormat write FAutoDetectFormat default true;
|
||||||
{@@ File format of the next spreadsheet file to be loaded by means of the
|
{@@ File format of the next spreadsheet file to be loaded by means of the
|
||||||
Filename property. Not used when AutoDetectFormat is TRUE.
|
Filename property. Not used when AutoDetectFormat is TRUE.
|
||||||
Note that if FileFormat is sfUser then the format ID must be specified at
|
Note that if FileFormat is sfUser then the format ID must be specified at
|
||||||
runtime. }
|
runtime. }
|
||||||
property FileFormat: TsSpreadsheetFormat read GetFileFormat write SetFileFormat;
|
property FileFormat: TsSpreadsheetFormat read GetFileFormat write SetFileFormat default sfOOXML;
|
||||||
{@@ Name of the loaded spreadsheet file which is loaded by assigning a file name
|
{@@ Name of the loaded spreadsheet file which is loaded by assigning a file name
|
||||||
to this property. Format detection is determined by the properties
|
to this property. Format detection is determined by the properties
|
||||||
AutoDetectFormat and FileFormat. Using this property loads the file at
|
AutoDetectFormat and FileFormat. Using this property loads the file at
|
||||||
@ -752,7 +752,8 @@ constructor TsWorkbookSource.Create(AOwner: TComponent);
|
|||||||
begin
|
begin
|
||||||
inherited Create(AOwner);
|
inherited Create(AOwner);
|
||||||
FListeners := TFPList.Create;
|
FListeners := TFPList.Create;
|
||||||
FFileFormatID := ord(sfExcel8);
|
FFileFormatID := ord(sfOOXML);
|
||||||
|
FAutoDetectFormat := True;
|
||||||
CreateNewWorkbook;
|
CreateNewWorkbook;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -6587,7 +6587,8 @@ begin
|
|||||||
// If the cell already exists and contains a formula then the formula must be
|
// If the cell already exists and contains a formula then the formula must be
|
||||||
// removed. The formula would dominate over the data value.
|
// removed. The formula would dominate over the data value.
|
||||||
cell := Worksheet.FindCell(r, c);
|
cell := Worksheet.FindCell(r, c);
|
||||||
if HasFormula(cell) then cell^.FormulaValue := '';
|
if HasFormula(cell) then
|
||||||
|
Worksheet.UseformulaInCell(cell, nil); //cell^.FormulaValue := '';
|
||||||
|
|
||||||
if VarIsNull(AValue) then
|
if VarIsNull(AValue) then
|
||||||
Worksheet.WriteBlank(r, c)
|
Worksheet.WriteBlank(r, c)
|
||||||
|
@ -161,13 +161,14 @@ var
|
|||||||
i, row, col: Integer;
|
i, row, col: Integer;
|
||||||
cell: PCell;
|
cell: PCell;
|
||||||
expectedFormula: String;
|
expectedFormula: String;
|
||||||
|
expectedStr, actualStr: String;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
TempFile := GetTempFileName;
|
TempFile := GetTempFileName;
|
||||||
|
|
||||||
MyWorkbook := TsWorkbook.Create;
|
MyWorkbook := TsWorkbook.Create;
|
||||||
try
|
try
|
||||||
// MyWorkbook.Options := MyWorkbook.Options + [boCalcBeforeSaving]; //boAutoCalc];
|
MyWorkbook.Options := MyWorkbook.Options + [boCalcBeforeSaving]; //boAutoCalc];
|
||||||
|
|
||||||
MyWorkSheet:= MyWorkBook.AddWorksheet(CopyTestSheet);
|
MyWorkSheet:= MyWorkBook.AddWorksheet(CopyTestSheet);
|
||||||
|
|
||||||
@ -212,6 +213,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
cell := Myworksheet.FindCell(row, 0);
|
cell := Myworksheet.FindCell(row, 0);
|
||||||
case ATestKind of
|
case ATestKind of
|
||||||
|
// 0: ; // don't copy, just write the original file for debugging
|
||||||
1: MyWorksheet.CopyValue(cell, row, 2);
|
1: MyWorksheet.CopyValue(cell, row, 2);
|
||||||
2: MyWorksheet.CopyValue(cell, row, 1);
|
2: MyWorksheet.CopyValue(cell, row, 1);
|
||||||
3: MyWorksheet.CopyFormat(cell, row, 2);
|
3: MyWorksheet.CopyFormat(cell, row, 2);
|
||||||
@ -233,6 +235,7 @@ begin
|
|||||||
// Read spreadsheet file...
|
// Read spreadsheet file...
|
||||||
MyWorkbook.ReadFromFile(TempFile, AFormat);
|
MyWorkbook.ReadFromFile(TempFile, AFormat);
|
||||||
MyWorksheet := MyWorkbook.GetFirstWorksheet;
|
MyWorksheet := MyWorkbook.GetFirstWorksheet;
|
||||||
|
MyWorksheet.CalcFormulas;
|
||||||
|
|
||||||
if odd(ATestKind) then col := 2 else col := 1;
|
if odd(ATestKind) then col := 2 else col := 1;
|
||||||
|
|
||||||
@ -335,9 +338,12 @@ begin
|
|||||||
)
|
)
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
expectedStr := SetToString(PTypeInfo(TypeInfo(TsUsedFormattingFields)),
|
||||||
|
integer(Sourcecells[i+col-2].UsedformattingFields), true);
|
||||||
|
actualStr := SetToString(PTypeInfo(TypeInfo(TsUsedFormattingFields)),
|
||||||
|
integer(MyWorksheet.ReadUsedFormatting(cell)), true);
|
||||||
CheckEquals(
|
CheckEquals(
|
||||||
true,
|
expectedStr, actualStr,
|
||||||
SourceCells[i+(col-2)].UsedFormattingFields = MyWorksheet.ReadUsedFormatting(cell),
|
|
||||||
'Used formatting fields mismatch, cell ' + CellNotation(myWorksheet, row, col)
|
'Used formatting fields mismatch, cell ' + CellNotation(myWorksheet, row, col)
|
||||||
);
|
);
|
||||||
if (uffBackground in SourceCells[i+(col-2)].UsedFormattingFields) then
|
if (uffBackground in SourceCells[i+(col-2)].UsedFormattingFields) then
|
||||||
@ -390,7 +396,8 @@ begin
|
|||||||
else
|
else
|
||||||
CheckEquals(
|
CheckEquals(
|
||||||
SourceCells[i+col-2].FormulaValue,
|
SourceCells[i+col-2].FormulaValue,
|
||||||
cell^.Formulavalue,
|
MyWorksheet.ReadFormula(cell),
|
||||||
|
// cell^.Formulavalue,
|
||||||
'Formula mismatch, cell ' + CellNotation(MyWorksheet, row, col)
|
'Formula mismatch, cell ' + CellNotation(MyWorksheet, row, col)
|
||||||
);
|
);
|
||||||
5:
|
5:
|
||||||
@ -403,7 +410,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
CheckEquals(
|
CheckEquals(
|
||||||
expectedFormula,
|
expectedFormula,
|
||||||
cell^.FormulaValue,
|
MyWorksheet.ReadFormula(cell),
|
||||||
|
// cell^.FormulaValue,
|
||||||
'Formula mismatch, cell ' + Cellnotation(Myworksheet, row, col)
|
'Formula mismatch, cell ' + Cellnotation(Myworksheet, row, col)
|
||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
@ -421,7 +429,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
CheckEquals(
|
CheckEquals(
|
||||||
expectedFormula,
|
expectedFormula,
|
||||||
cell^.FormulaValue,
|
MyWorksheet.ReadFormula(cell),
|
||||||
|
// cell^.FormulaValue,
|
||||||
'Formula mismatch, cell ' + Cellnotation(Myworksheet, row, col)
|
'Formula mismatch, cell ' + Cellnotation(Myworksheet, row, col)
|
||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
|
@ -763,7 +763,7 @@ begin
|
|||||||
cctEmpty : actual := EmptyResult;
|
cctEmpty : actual := EmptyResult;
|
||||||
else fail('ContentType not supported');
|
else fail('ContentType not supported');
|
||||||
end;
|
end;
|
||||||
actualformula := cell^.FormulaValue;
|
actualformula := sheet1.Formulas.FindFormula(cell)^.Text; //cell^.FormulaValue;
|
||||||
|
|
||||||
expected := SollValues[row];
|
expected := SollValues[row];
|
||||||
// Cell does not store integers!
|
// Cell does not store integers!
|
||||||
|
@ -565,7 +565,7 @@ begin
|
|||||||
'67890123';
|
'67890123';
|
||||||
DeleteCol := 2;
|
DeleteCol := 2;
|
||||||
Formula := 'C3';
|
Formula := 'C3';
|
||||||
SollFormula := '#REF!'; // col index unchanged due to deletion after cell
|
SollFormula := '#REF!'; // cell needec by formula does not exist any more
|
||||||
SollLayout := '1245678|'+
|
SollLayout := '1245678|'+
|
||||||
'2356789|'+
|
'2356789|'+
|
||||||
'346E890|'+ // "E" = error
|
'346E890|'+ // "E" = error
|
||||||
@ -617,7 +617,7 @@ begin
|
|||||||
Layout := '12345678|'+
|
Layout := '12345678|'+
|
||||||
'23456789|'+
|
'23456789|'+
|
||||||
'3456F890|'+ // "F" = Formula in row 2, col 4
|
'3456F890|'+ // "F" = Formula in row 2, col 4
|
||||||
'45678901|'+
|
'45678901|'+ // delete this row
|
||||||
'56789012|'+
|
'56789012|'+
|
||||||
'67890123';
|
'67890123';
|
||||||
DeleteRow := 3;
|
DeleteRow := 3;
|
||||||
@ -1010,6 +1010,7 @@ begin
|
|||||||
if InsDelTestData[ATestIndex].DeleteRow >= 0 then
|
if InsDelTestData[ATestIndex].DeleteRow >= 0 then
|
||||||
MyWorksheet.DeleteRow(InsDelTestData[ATestIndex].DeleteRow);
|
MyWorksheet.DeleteRow(InsDelTestData[ATestIndex].DeleteRow);
|
||||||
|
|
||||||
|
MyWorkbook.CalcFormulas;
|
||||||
MyWorkBook.WriteToFile(TempFile, AFormat, true);
|
MyWorkBook.WriteToFile(TempFile, AFormat, true);
|
||||||
finally
|
finally
|
||||||
MyWorkbook.Free;
|
MyWorkbook.Free;
|
||||||
|
@ -140,8 +140,8 @@ begin
|
|||||||
cell := worksheet.WriteFormula(TESTCELL_ROW, TESTCELL_COL, AFormula);
|
cell := worksheet.WriteFormula(TESTCELL_ROW, TESTCELL_COL, AFormula);
|
||||||
|
|
||||||
// Read formula before saving
|
// Read formula before saving
|
||||||
actualFormula := cell^.Formulavalue;
|
actualFormula := worksheet.ReadFormula(cell);
|
||||||
CheckEquals(AFormula, actualFormula, 'Unsaved formula text mismatch');
|
CheckEquals(AExpectedFormula, actualFormula, 'Unsaved formula text mismatch');
|
||||||
|
|
||||||
// Read calculated value before saving
|
// Read calculated value before saving
|
||||||
actualvalue := worksheet.ReadAsNumber(TESTCELL_ROW, TESTCELL_COL);
|
actualvalue := worksheet.ReadAsNumber(TESTCELL_ROW, TESTCELL_COL);
|
||||||
@ -165,7 +165,8 @@ begin
|
|||||||
CheckEquals(AExpected, actualValue, 'Saved calculated value mismatch');
|
CheckEquals(AExpected, actualValue, 'Saved calculated value mismatch');
|
||||||
|
|
||||||
cell := worksheet.FindCell(TESTCELL_ROW, TESTCELL_COL);
|
cell := worksheet.FindCell(TESTCELL_ROW, TESTCELL_COL);
|
||||||
actualformula := cell^.FormulaValue;
|
actualformula := worksheet.Formulas.FindFormula(cell)^.Text;
|
||||||
|
// actualformula := cell^.FormulaValue;
|
||||||
// When writing ranges are reconstructed in correct order.
|
// When writing ranges are reconstructed in correct order.
|
||||||
CheckEquals(AExpectedFormula, actualformula, 'Saved formula text mismatch.');
|
CheckEquals(AExpectedFormula, actualformula, 'Saved formula text mismatch.');
|
||||||
finally
|
finally
|
||||||
@ -302,15 +303,16 @@ end;
|
|||||||
|
|
||||||
{ --- }
|
{ --- }
|
||||||
|
|
||||||
|
{ Range formulas in which the parts are not ordered. They will be put into the
|
||||||
|
correct order when then formula is written to the worksheet. --> the
|
||||||
|
expected range must be in correct order. }
|
||||||
procedure TSpreadSingleFormulaTests.SumMultiSheetRange_FlippedSheetsAndCells_OOXML;
|
procedure TSpreadSingleFormulaTests.SumMultiSheetRange_FlippedSheetsAndCells_OOXML;
|
||||||
begin
|
begin
|
||||||
// In OOXML the range is written literally.
|
TestFloatFormula('SUM(Sheet3:Sheet2!C5:C3)', 55.0, ftkCellRangeSheetRange, sfOOXML, 'SUM(Sheet2:Sheet3!C3:C5)');
|
||||||
TestFloatFormula('SUM(Sheet3:Sheet2!C5:C3)', 55.0, ftkCellRangeSheetRange, sfOOXML);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TSpreadSingleFormulaTests.SumMultiSheetRange_FlippedSheetsAndCells_ODS;
|
procedure TSpreadSingleFormulaTests.SumMultiSheetRange_FlippedSheetsAndCells_ODS;
|
||||||
begin
|
begin
|
||||||
// ODS requires conversion of the formula which results in reordering of ranges.
|
|
||||||
TestFloatFormula('SUM(Sheet3:Sheet2!C5:C3)', 55.0, ftkCellRangeSheetRange, sfOpenDocument, 'SUM(Sheet2:Sheet3!C3:C5)');
|
TestFloatFormula('SUM(Sheet3:Sheet2!C5:C3)', 55.0, ftkCellRangeSheetRange, sfOpenDocument, 'SUM(Sheet2:Sheet3!C3:C5)');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -322,14 +324,12 @@ end;
|
|||||||
|
|
||||||
procedure TSpreadSingleFormulaTests.SumMultiSheetRange_FlippedCells_OOXML;
|
procedure TSpreadSingleFormulaTests.SumMultiSheetRange_FlippedCells_OOXML;
|
||||||
begin
|
begin
|
||||||
// In OOXML the range is written literally.
|
TestFloatFormula('SUM(Sheet2:Sheet3!C5:C3)', 55.0, ftkCellRangeSheetRange, sfOOXML, 'SUM(Sheet2:Sheet3!C3:C5)');
|
||||||
TestFloatFormula('SUM(Sheet2:Sheet3!C5:C3)', 55.0, ftkCellRangeSheetRange, sfOOXML);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TSpreadSingleFormulaTests.SumMultiSheetRange_FlippedSheets_OOXML;
|
procedure TSpreadSingleFormulaTests.SumMultiSheetRange_FlippedSheets_OOXML;
|
||||||
begin
|
begin
|
||||||
// In OOXML the range is written literally.
|
TestFloatFormula('SUM(Sheet3:Sheet2!C3:C5)', 55.0, ftkCellRangeSheetRange, sfOOXML, 'SUM(Sheet2:Sheet3!C3:C5)');
|
||||||
TestFloatFormula('SUM(Sheet3:Sheet2!C3:C5)', 55.0, ftkCellRangeSheetRange, sfOOXML);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
@ -1026,6 +1026,9 @@
|
|||||||
else
|
else
|
||||||
Myworksheet.WriteFormula(Row, 1, formula);
|
Myworksheet.WriteFormula(Row, 1, formula);
|
||||||
SetLength(sollValues, Row+1);
|
SetLength(sollValues, Row+1);
|
||||||
|
if AFormat = sfExcel2 then
|
||||||
|
sollValues[Row] := ErrorResult(errFormulaNotSupported)
|
||||||
|
else
|
||||||
sollValues[Row] := FloatResult(arccosh(number));
|
sollValues[Row] := FloatResult(arccosh(number));
|
||||||
MyWorksheet.WriteNumber(Row, 2, sollValues[Row].ResFloat);
|
MyWorksheet.WriteNumber(Row, 2, sollValues[Row].ResFloat);
|
||||||
|
|
||||||
@ -1043,6 +1046,9 @@
|
|||||||
SetLength(sollValues, Row+1);
|
SetLength(sollValues, Row+1);
|
||||||
if AFormat = sfOpenDocument then
|
if AFormat = sfOpenDocument then
|
||||||
sollValues[Row] := FloatResult(0)
|
sollValues[Row] := FloatResult(0)
|
||||||
|
else
|
||||||
|
if AFormat = sfExcel2 then
|
||||||
|
sollValues[Row] := ErrorResult(errFormulaNotSupported)
|
||||||
else
|
else
|
||||||
sollValues[Row] := ErrorResult(errOverFlow);
|
sollValues[Row] := ErrorResult(errOverFlow);
|
||||||
|
|
||||||
@ -1090,6 +1096,9 @@
|
|||||||
else
|
else
|
||||||
MyWorksheet.WriteFormula(Row, 1, formula);
|
MyWorksheet.WriteFormula(Row, 1, formula);
|
||||||
SetLength(sollValues, Row+1);
|
SetLength(sollValues, Row+1);
|
||||||
|
if AFormat = sfExcel2 then
|
||||||
|
sollValues[Row] := ErrorResult(errFormulaNotSupported)
|
||||||
|
else
|
||||||
sollValues[Row] := FloatResult(arcsinh(number));
|
sollValues[Row] := FloatResult(arcsinh(number));
|
||||||
MyWorksheet.WriteNumber(Row, 2, sollValues[Row].ResFloat);
|
MyWorksheet.WriteNumber(Row, 2, sollValues[Row].ResFloat);
|
||||||
|
|
||||||
@ -1120,6 +1129,9 @@
|
|||||||
else
|
else
|
||||||
MyWorksheet.WriteFormula(Row, 1, formula);
|
MyWorksheet.WriteFormula(Row, 1, formula);
|
||||||
SetLength(sollValues, Row+1);
|
SetLength(sollValues, Row+1);
|
||||||
|
if AFormat = sfExcel2 then
|
||||||
|
sollValues[Row] := ErrorResult(errFormulaNotSupported)
|
||||||
|
else
|
||||||
sollValues[Row] := FloatResult(arctanh(number));
|
sollValues[Row] := FloatResult(arctanh(number));
|
||||||
MyWorksheet.WriteNumber(Row, 2, sollValues[Row].ResFloat);
|
MyWorksheet.WriteNumber(Row, 2, sollValues[Row].ResFloat);
|
||||||
|
|
||||||
@ -1137,6 +1149,9 @@
|
|||||||
SetLength(sollValues, Row+1);
|
SetLength(sollValues, Row+1);
|
||||||
if AFormat = sfOpenDocument then
|
if AFormat = sfOpenDocument then
|
||||||
sollValues[Row] := FloatResult(0)
|
sollValues[Row] := FloatResult(0)
|
||||||
|
else
|
||||||
|
if AFormat = sfExcel2 then
|
||||||
|
sollValues[Row] := ErrorResult(errFormulaNotSupported)
|
||||||
else
|
else
|
||||||
sollValues[Row] := ErrorResult(errOverFlow);
|
sollValues[Row] := ErrorResult(errOverFlow);
|
||||||
|
|
||||||
@ -1185,8 +1200,12 @@
|
|||||||
else
|
else
|
||||||
MyWorksheet.WriteFormula(Row, 1, formula);
|
MyWorksheet.WriteFormula(Row, 1, formula);
|
||||||
SetLength(sollValues, Row+1);
|
SetLength(sollValues, Row+1);
|
||||||
|
if AFormat = sfExcel2 then
|
||||||
|
sollValues[Row] := ErrorResult(errFormulaNotSupported)
|
||||||
|
else begin
|
||||||
sollValues[Row] := FloatResult(cosh(number));
|
sollValues[Row] := FloatResult(cosh(number));
|
||||||
MyWorksheet.WriteNumber(Row, 2, sollValues[Row].ResFloat);
|
MyWorksheet.WriteNumber(Row, 2, sollValues[Row].ResFloat);
|
||||||
|
end;
|
||||||
|
|
||||||
// DEGREES
|
// DEGREES
|
||||||
if AFormat <> sfExcel2 then
|
if AFormat <> sfExcel2 then
|
||||||
@ -1678,6 +1697,9 @@
|
|||||||
MyWorksheet.WriteFormula(Row, 1, formula);
|
MyWorksheet.WriteFormula(Row, 1, formula);
|
||||||
MyWorksheet.WriteNumber(Row, 2, sinh(number));
|
MyWorksheet.WriteNumber(Row, 2, sinh(number));
|
||||||
SetLength(sollValues, Row+1);
|
SetLength(sollValues, Row+1);
|
||||||
|
if AFormat = sfExcel2 then
|
||||||
|
sollValues[Row] := ErrorResult(errFormulaNotSupported)
|
||||||
|
else
|
||||||
sollValues[Row] := FloatResult(sinh(number));
|
sollValues[Row] := FloatResult(sinh(number));
|
||||||
|
|
||||||
// SINH of cell value
|
// SINH of cell value
|
||||||
@ -1692,6 +1714,9 @@
|
|||||||
MyWorksheet.WriteFormula(Row, 1, formula);
|
MyWorksheet.WriteFormula(Row, 1, formula);
|
||||||
MyWorksheet.WriteNumber(Row, 2, sinh(cellB1));
|
MyWorksheet.WriteNumber(Row, 2, sinh(cellB1));
|
||||||
SetLength(sollValues, Row+1);
|
SetLength(sollValues, Row+1);
|
||||||
|
if AFormat = sfExcel2 then
|
||||||
|
sollValues[Row] := ErrorResult(errFormulaNotSupported)
|
||||||
|
else
|
||||||
sollValues[Row] := FloatResult(sinh(cellB1));
|
sollValues[Row] := FloatResult(sinh(cellB1));
|
||||||
|
|
||||||
// SQRT - valid result
|
// SQRT - valid result
|
||||||
@ -1785,6 +1810,9 @@
|
|||||||
MyWorksheet.WriteFormula(Row, 1, formula);
|
MyWorksheet.WriteFormula(Row, 1, formula);
|
||||||
MyWorksheet.WriteNumber(Row, 2, tanh(number));
|
MyWorksheet.WriteNumber(Row, 2, tanh(number));
|
||||||
SetLength(sollValues, Row+1);
|
SetLength(sollValues, Row+1);
|
||||||
|
if AFormat = sfExcel2 then
|
||||||
|
sollValues[Row] := ErrorResult(errFormulaNotSupported)
|
||||||
|
else
|
||||||
sollValues[Row] := FloatResult(tanh(number));
|
sollValues[Row] := FloatResult(tanh(number));
|
||||||
|
|
||||||
// TANH of cell value
|
// TANH of cell value
|
||||||
@ -1799,8 +1827,12 @@
|
|||||||
MyWorksheet.WriteFormula(Row, 1, formula);
|
MyWorksheet.WriteFormula(Row, 1, formula);
|
||||||
MyWorksheet.WriteNumber(Row, 2, tanh(cellB1));
|
MyWorksheet.WriteNumber(Row, 2, tanh(cellB1));
|
||||||
SetLength(sollValues, Row+1);
|
SetLength(sollValues, Row+1);
|
||||||
|
if AFormat = sfExcel2 then
|
||||||
|
sollValues[Row] := ErrorResult(errFormulaNotSupported)
|
||||||
|
else
|
||||||
sollValues[Row] := FloatResult(tanh(cellB1));
|
sollValues[Row] := FloatResult(tanh(cellB1));
|
||||||
|
|
||||||
|
|
||||||
{------------------------------------------------------------------------------}
|
{------------------------------------------------------------------------------}
|
||||||
{ Date/time functions }
|
{ Date/time functions }
|
||||||
{------------------------------------------------------------------------------}
|
{------------------------------------------------------------------------------}
|
||||||
@ -2087,6 +2119,9 @@
|
|||||||
Myworksheet.WriteDateTimeFormat(Row, 1, nfShortDate);
|
Myworksheet.WriteDateTimeFormat(Row, 1, nfShortDate);
|
||||||
Myworksheet.WriteDateTime(Row, 2, Date(), nfShortDate);
|
Myworksheet.WriteDateTime(Row, 2, Date(), nfShortDate);
|
||||||
SetLength(sollValues, Row+1);
|
SetLength(sollValues, Row+1);
|
||||||
|
if AFormat = sfExcel2 then
|
||||||
|
sollValues[Row] := ErrorResult(errFormulaNotSupported)
|
||||||
|
else
|
||||||
sollValues[Row] := DateTimeResult(Date());
|
sollValues[Row] := DateTimeResult(Date());
|
||||||
|
|
||||||
// WEEKDAY / argument number
|
// WEEKDAY / argument number
|
||||||
|
Reference in New Issue
Block a user