You've already forked lazarus-ccr
fpspreadsheet: Major reconstruction of numberformat parser to facilitate creation of xml formats for ods. Some minor regressions in unit tests and fpsgrid demo to be fixed. Removed elements "Decimals" and "CurrencySymbol" from TCell (this information is taken from the format string now). Removed the built-in format nfFmtDateTime (makes life easier, use nfCustom instead).
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3156 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -64,9 +64,6 @@
|
|||||||
</Debugging>
|
</Debugging>
|
||||||
</Linking>
|
</Linking>
|
||||||
<Other>
|
<Other>
|
||||||
<CompilerMessages>
|
|
||||||
<UseMsgFile Value="True"/>
|
|
||||||
</CompilerMessages>
|
|
||||||
<CompilerPath Value="$(CompPath)"/>
|
<CompilerPath Value="$(CompPath)"/>
|
||||||
</Other>
|
</Other>
|
||||||
</CompilerOptions>
|
</CompilerOptions>
|
||||||
|
@ -53,9 +53,9 @@ begin
|
|||||||
{ non-frozen panes not working, at the moment. Requires SELECTION records?
|
{ non-frozen panes not working, at the moment. Requires SELECTION records?
|
||||||
MyWorksheet.LeftPaneWidth := 20*72*2; // 72 pt = inch --> 2 inches = 5 cm
|
MyWorksheet.LeftPaneWidth := 20*72*2; // 72 pt = inch --> 2 inches = 5 cm
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write some cells
|
// Write some cells
|
||||||
MyWorksheet.WriteNumber(0, 0, 1.0, nfFixed, 3);// A1
|
MyWorksheet.WriteNumber(0, 0, 0.0, nfSci, 1);
|
||||||
|
(*
|
||||||
MyWorksheet.WriteNumber(0, 1, 2.0);// B1
|
MyWorksheet.WriteNumber(0, 1, 2.0);// B1
|
||||||
MyWorksheet.WriteNumber(0, 2, 3.0);// C1
|
MyWorksheet.WriteNumber(0, 2, 3.0);// C1
|
||||||
MyWorksheet.WriteNumber(0, 3, 4.0);// D1
|
MyWorksheet.WriteNumber(0, 3, 4.0);// D1
|
||||||
@ -131,7 +131,7 @@ begin
|
|||||||
MyWorksheet.WriteUTF8Text(8, 3, 'Colors...');
|
MyWorksheet.WriteUTF8Text(8, 3, 'Colors...');
|
||||||
MyWorksheet.WriteFont(8, 3, 'Courier New', 12, [fssUnderline], scBlue);
|
MyWorksheet.WriteFont(8, 3, 'Courier New', 12, [fssUnderline], scBlue);
|
||||||
MyWorksheet.WriteBackgroundColor(8, 3, scYellow);
|
MyWorksheet.WriteBackgroundColor(8, 3, scYellow);
|
||||||
|
{}
|
||||||
{
|
{
|
||||||
// Uncomment this to test large XLS files
|
// Uncomment this to test large XLS files
|
||||||
for i := 50 to 1000 do
|
for i := 50 to 1000 do
|
||||||
@ -174,6 +174,9 @@ begin
|
|||||||
MyWorksheet.WriteUTF8Text(r, 0, 'Writing current date/time:');
|
MyWorksheet.WriteUTF8Text(r, 0, 'Writing current date/time:');
|
||||||
inc(r, 2);
|
inc(r, 2);
|
||||||
// Write current date/time to cells B11:B16
|
// Write current date/time to cells B11:B16
|
||||||
|
MyWorksheet.WriteUTF8Text(r, 0, '(default format)');
|
||||||
|
MyWorksheet.WriteDateTime(r, 1, now);
|
||||||
|
inc(r);
|
||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfShortDate');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfShortDate');
|
||||||
MyWorksheet.WriteDateTime(r, 1, now, nfShortDate);
|
MyWorksheet.WriteDateTime(r, 1, now, nfShortDate);
|
||||||
inc(r);
|
inc(r);
|
||||||
@ -189,11 +192,11 @@ begin
|
|||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfShortDateTime');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfShortDateTime');
|
||||||
MyWorksheet.WriteDateTime(r, 1, now, nfShortDateTime);
|
MyWorksheet.WriteDateTime(r, 1, now, nfShortDateTime);
|
||||||
inc(r);
|
inc(r);
|
||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfFmtDateTime, DM');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfCustom, ''dd/mmm''');
|
||||||
MyWorksheet.WriteDateTime(r, 1, now, nfFmtDateTime, 'DM');
|
MyWorksheet.WriteDateTime(r, 1, now, nfCustom, 'dd/mmm');
|
||||||
inc(r);
|
inc(r);
|
||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfFmtDateTime, MY');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfCustom, ''MMM/YY''');
|
||||||
MyWorksheet.WriteDateTime(r, 1, now, nfFmtDateTime, 'MY');
|
MyWorksheet.WriteDateTime(r, 1, now, nfCustom, 'mmm/yy');
|
||||||
inc(r);
|
inc(r);
|
||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfShortTimeAM');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfShortTimeAM');
|
||||||
MyWorksheet.WriteDateTime(r, 1, now, nfShortTimeAM);
|
MyWorksheet.WriteDateTime(r, 1, now, nfShortTimeAM);
|
||||||
@ -201,14 +204,14 @@ begin
|
|||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfLongTimeAM');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfLongTimeAM');
|
||||||
MyWorksheet.WriteDateTime(r, 1, now, nfLongTimeAM);
|
MyWorksheet.WriteDateTime(r, 1, now, nfLongTimeAM);
|
||||||
inc(r);
|
inc(r);
|
||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfFmtDateTime, MS');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfCustom, ''mm:ss''');
|
||||||
MyWorksheet.WriteDateTime(r, 1, now, nfFmtDateTime, 'MS');
|
MyWorksheet.WriteDateTime(r, 1, now, nfCustom, 'mm:ss');
|
||||||
inc(r);
|
inc(r);
|
||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfFmtDateTime, MSZ');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfCustom, ''mm:ss.z''');
|
||||||
MyWorksheet.WriteDateTime(r, 1, now, nfFmtDateTime, 'MSZ');
|
MyWorksheet.WriteDateTime(r, 1, now, nfCustom, 'mm:ss.z');
|
||||||
inc(r);
|
inc(r);
|
||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfFmtDateTime, mm:ss.zzz');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfCustom, ''mm:ss.zzz''');
|
||||||
MyWorksheet.WriteDateTime(r, 1, now, nfFmtDateTime, 'mm:ss.zzz');
|
MyWorksheet.WriteDateTime(r, 1, now, nfCustom, 'mm:ss.zzz');
|
||||||
|
|
||||||
// Write formatted numbers
|
// Write formatted numbers
|
||||||
s := '31415.9265359';
|
s := '31415.9265359';
|
||||||
@ -301,26 +304,28 @@ begin
|
|||||||
MyWorksheet.WriteNumber(r, 3, 1.0/number, nfExp, 3);
|
MyWorksheet.WriteNumber(r, 3, 1.0/number, nfExp, 3);
|
||||||
MyWorksheet.WriteNumber(r, 4, -1.0/number, nfExp, 3);
|
MyWorksheet.WriteNumber(r, 4, -1.0/number, nfExp, 3);
|
||||||
inc(r,2);
|
inc(r,2);
|
||||||
|
|
||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfCurrency, 0 decs');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfCurrency, 0 decs');
|
||||||
MyWorksheet.WriteNumber(r, 1, number, nfCurrency, 0, 'USD');
|
MyWorksheet.WriteCurrency(r, 1, number, nfCurrency, 0, 'USD');
|
||||||
MyWorksheet.WriteNumber(r, 2, -number, nfCurrency, 0, 'USD');
|
MyWorksheet.WriteCurrency(r, 2, -number, nfCurrency, 0, 'USD');
|
||||||
MyWorksheet.WriteNumber(r, 3, 0.0, nfCurrency, 0, 'USD');
|
MyWorksheet.WriteCurrency(r, 3, 0.0, nfCurrency, 0, 'USD');
|
||||||
inc(r);
|
inc(r);
|
||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfCurrencyRed, 0 decs');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfCurrencyRed, 0 decs');
|
||||||
MyWorksheet.WriteNumber(r, 1, number, nfCurrencyRed, 0, 'USD');
|
MyWorksheet.WriteCurrency(r, 1, number, nfCurrencyRed, 0, 'USD');
|
||||||
MyWorksheet.WriteNumber(r, 2, -number, nfCurrencyRed, 0, 'USD');
|
MyWorksheet.WriteCurrency(r, 2, -number, nfCurrencyRed, 0, 'USD');
|
||||||
MyWorksheet.WriteNumber(r, 3, 0.0, nfCurrencyRed, 0, 'USD');
|
MyWorksheet.WriteCurrency(r, 3, 0.0, nfCurrencyRed, 0, 'USD');
|
||||||
inc(r);
|
inc(r);
|
||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfAccounting, 0 decs');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfAccounting, 0 decs');
|
||||||
MyWorksheet.WriteNumber(r, 1, number, nfAccounting, 0, 'USD');
|
MyWorksheet.WriteCurrency(r, 1, number, nfAccounting, 0, 'USD');
|
||||||
MyWorksheet.WriteNumber(r, 2, -number, nfAccounting, 0, 'USD');
|
MyWorksheet.WriteCurrency(r, 2, -number, nfAccounting, 0, 'USD');
|
||||||
MyWorksheet.WriteNumber(r, 3, 0.0, nfAccounting, 0, 'USD');
|
MyWorksheet.WriteCurrency(r, 3, 0.0, nfAccounting, 0, 'USD');
|
||||||
inc(r);
|
inc(r);
|
||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfAccountingRed, 0 decs');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfAccountingRed, 0 decs');
|
||||||
MyWorksheet.WriteNumber(r, 1, -number, nfAccountingRed, 0, 'USD');
|
MyWorksheet.WriteCurrency(r, 1, -number, nfAccountingRed, 0, 'USD');
|
||||||
MyWorksheet.WriteNumber(r, 2, number, nfAccountingRed, 0, 'USD');
|
MyWorksheet.WriteCurrency(r, 2, number, nfAccountingRed, 0, 'USD');
|
||||||
MyWorksheet.WriteNumber(r, 3, 0.0, nfAccountingRed, 0, 'USD');
|
MyWorksheet.WriteCurrency(r, 3, 0.0, nfAccountingRed, 0, 'USD');
|
||||||
|
|
||||||
|
{
|
||||||
inc(r,2);
|
inc(r,2);
|
||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfCustom, "EUR "#,##0_);("EUR "#,##0)');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfCustom, "EUR "#,##0_);("EUR "#,##0)');
|
||||||
MyWorksheet.WriteNumber(r, 1, number);
|
MyWorksheet.WriteNumber(r, 1, number);
|
||||||
@ -333,7 +338,7 @@ begin
|
|||||||
MyWorksheet.WriteNumberFormat(r, 1, nfCustom, '"$"#,##0.0_);[Red]("$"#,##0.0)');
|
MyWorksheet.WriteNumberFormat(r, 1, nfCustom, '"$"#,##0.0_);[Red]("$"#,##0.0)');
|
||||||
MyWorksheet.WriteNumber(r, 2, -number);
|
MyWorksheet.WriteNumber(r, 2, -number);
|
||||||
MyWorksheet.WriteNumberFormat(r, 2, nfCustom, '"$"#,##0.0_);[Red]("$"#,##0.0)');
|
MyWorksheet.WriteNumberFormat(r, 2, nfCustom, '"$"#,##0.0_);[Red]("$"#,##0.0)');
|
||||||
|
}
|
||||||
inc(r, 2);
|
inc(r, 2);
|
||||||
number := 1.333333333;
|
number := 1.333333333;
|
||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfPercentage, 0 decs');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfPercentage, 0 decs');
|
||||||
@ -348,29 +353,44 @@ begin
|
|||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfPercentage, 3 decs');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfPercentage, 3 decs');
|
||||||
MyWorksheet.WriteNumber(r, 1, number, nfPercentage, 3);
|
MyWorksheet.WriteNumber(r, 1, number, nfPercentage, 3);
|
||||||
inc(r);
|
inc(r);
|
||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfTimeInterval, hh:mm:ss');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfTimeInterval Default=[h]:mm:ss');
|
||||||
MyWorksheet.WriteDateTime(r, 1, number, nfTimeInterval);
|
MyWorksheet.WriteDateTime(r, 1, number, nfTimeInterval);
|
||||||
inc(r);
|
inc(r);
|
||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfTimeInterval, h:m:s');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfTimeInterval, h:m:s');
|
||||||
MyWorksheet.WriteDateTime(r, 1, number, nfTimeInterval, 'h:m:s');
|
MyWorksheet.WriteDateTime(r, 1, number, nfTimeInterval, 'h:m:s');
|
||||||
inc(r);
|
inc(r);
|
||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfTimeInterval, h:n:s');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfTimeInterval, [h]:m:s');
|
||||||
MyWorksheet.WriteDateTime(r, 1, number, nfTimeInterval, 'h:n:s');
|
MyWorksheet.WriteDateTime(r, 1, number, nfTimeInterval, '[h]:m:s');
|
||||||
inc(r);
|
inc(r);
|
||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfTimeInterval, hh:mm');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfTimeInterval, [h]:n:s');
|
||||||
MyWorksheet.WriteDateTime(r, 1, number, nfTimeInterval, 'hh:mm');
|
MyWorksheet.WriteDateTime(r, 1, number, nfTimeInterval, '[h]:n:s');
|
||||||
inc(r);
|
inc(r);
|
||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfTimeInterval, hh:nn');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfTimeInterval, [hh]:mm');
|
||||||
MyWorksheet.WriteDateTime(r, 1, number, nfTimeInterval, 'hh:nn');
|
MyWorksheet.WriteDateTime(r, 1, number, nfTimeInterval, '[hh]:mm');
|
||||||
inc(r);
|
inc(r);
|
||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfTimeInterval, h:m');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfTimeInterval, [hh]:nn');
|
||||||
MyWorksheet.WriteDateTime(r, 1, number, nfTimeInterval, 'h:m');
|
MyWorksheet.WriteDateTime(r, 1, number, nfTimeInterval, '[hh]:nn');
|
||||||
inc(r);
|
inc(r);
|
||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfTimeInterval, h:n');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfTimeInterval [h]:m');
|
||||||
MyWorksheet.WriteDateTime(r, 1, number, nfTimeInterval, 'h:n');
|
MyWorksheet.WriteDateTime(r, 1, number, nfTimeInterval, '[h]:m');
|
||||||
inc(r);
|
inc(r);
|
||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfTimeInterval, h');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfTimeInterval, [h]:n');
|
||||||
MyWorksheet.WriteDateTime(r, 1, number, nfTimeInterval, 'h');
|
MyWorksheet.WriteDateTime(r, 1, number, nfTimeInterval, '[h]:n');
|
||||||
|
inc(r);
|
||||||
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfTimeInterval, [h]');
|
||||||
|
MyWorksheet.WriteDateTime(r, 1, number, nfTimeInterval, '[h]');
|
||||||
|
inc(r);
|
||||||
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfTimeInterval, [m]:s');
|
||||||
|
MyWorksheet.WriteDateTime(r, 1, number, nfTimeInterval, '[m]:s');
|
||||||
|
inc(r);
|
||||||
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfTimeInterval, m:s');
|
||||||
|
MyWorksheet.WriteDateTime(r, 1, number, nfTimeInterval, 'm:s');
|
||||||
|
inc(r);
|
||||||
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfTimeInterval, [mm]:ss');
|
||||||
|
MyWorksheet.WriteDateTime(r, 1, number, nfTimeInterval, '[mm]:ss');
|
||||||
|
inc(r);
|
||||||
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfTimeInterval, [ss]');
|
||||||
|
MyWorksheet.WriteDateTime(r, 1, number, nfTimeInterval, '[ss]');
|
||||||
|
|
||||||
// Set width of columns 0, 1 and 5
|
// Set width of columns 0, 1 and 5
|
||||||
MyWorksheet.WriteColWidth(0, 30);
|
MyWorksheet.WriteColWidth(0, 30);
|
||||||
@ -395,7 +415,7 @@ begin
|
|||||||
MyWorksheet.WriteUTF8Text(0, 3, Str_Fourth);
|
MyWorksheet.WriteUTF8Text(0, 3, Str_Fourth);
|
||||||
MyWorksheet.WriteTextRotation(0, 0, rt90DegreeClockwiseRotation);
|
MyWorksheet.WriteTextRotation(0, 0, rt90DegreeClockwiseRotation);
|
||||||
MyWorksheet.WriteUsedFormatting(0, 1, [uffBold]);
|
MyWorksheet.WriteUsedFormatting(0, 1, [uffBold]);
|
||||||
|
*)
|
||||||
// Save the spreadsheet to a file
|
// Save the spreadsheet to a file
|
||||||
MyWorkbook.WriteToFile(MyDir + 'test.xls', sfExcel8, true);
|
MyWorkbook.WriteToFile(MyDir + 'test.xls', sfExcel8, true);
|
||||||
MyWorkbook.Free;
|
MyWorkbook.Free;
|
||||||
|
@ -4,7 +4,7 @@ object Form1: TForm1
|
|||||||
Top = 248
|
Top = 248
|
||||||
Width = 884
|
Width = 884
|
||||||
Caption = 'fpsGrid'
|
Caption = 'fpsGrid'
|
||||||
ClientHeight = 624
|
ClientHeight = 629
|
||||||
ClientWidth = 884
|
ClientWidth = 884
|
||||||
Menu = MainMenu
|
Menu = MainMenu
|
||||||
OnActivate = FormActivate
|
OnActivate = FormActivate
|
||||||
@ -14,7 +14,7 @@ object Form1: TForm1
|
|||||||
object Panel1: TPanel
|
object Panel1: TPanel
|
||||||
Left = 0
|
Left = 0
|
||||||
Height = 85
|
Height = 85
|
||||||
Top = 539
|
Top = 544
|
||||||
Width = 884
|
Width = 884
|
||||||
Align = alBottom
|
Align = alBottom
|
||||||
BevelOuter = bvNone
|
BevelOuter = bvNone
|
||||||
@ -23,9 +23,9 @@ object Form1: TForm1
|
|||||||
TabOrder = 0
|
TabOrder = 0
|
||||||
object CbShowHeaders: TCheckBox
|
object CbShowHeaders: TCheckBox
|
||||||
Left = 8
|
Left = 8
|
||||||
Height = 24
|
Height = 19
|
||||||
Top = 8
|
Top = 8
|
||||||
Width = 116
|
Width = 93
|
||||||
Caption = 'Show headers'
|
Caption = 'Show headers'
|
||||||
Checked = True
|
Checked = True
|
||||||
OnClick = CbShowHeadersClick
|
OnClick = CbShowHeadersClick
|
||||||
@ -34,9 +34,9 @@ object Form1: TForm1
|
|||||||
end
|
end
|
||||||
object CbShowGridLines: TCheckBox
|
object CbShowGridLines: TCheckBox
|
||||||
Left = 8
|
Left = 8
|
||||||
Height = 24
|
Height = 19
|
||||||
Top = 32
|
Top = 32
|
||||||
Width = 125
|
Width = 100
|
||||||
Caption = 'Show grid lines'
|
Caption = 'Show grid lines'
|
||||||
Checked = True
|
Checked = True
|
||||||
OnClick = CbShowGridLinesClick
|
OnClick = CbShowGridLinesClick
|
||||||
@ -45,7 +45,7 @@ object Form1: TForm1
|
|||||||
end
|
end
|
||||||
object EdFrozenCols: TSpinEdit
|
object EdFrozenCols: TSpinEdit
|
||||||
Left = 389
|
Left = 389
|
||||||
Height = 28
|
Height = 23
|
||||||
Top = 8
|
Top = 8
|
||||||
Width = 52
|
Width = 52
|
||||||
OnChange = EdFrozenColsChange
|
OnChange = EdFrozenColsChange
|
||||||
@ -53,7 +53,7 @@ object Form1: TForm1
|
|||||||
end
|
end
|
||||||
object EdFrozenRows: TSpinEdit
|
object EdFrozenRows: TSpinEdit
|
||||||
Left = 389
|
Left = 389
|
||||||
Height = 28
|
Height = 23
|
||||||
Top = 39
|
Top = 39
|
||||||
Width = 52
|
Width = 52
|
||||||
OnChange = EdFrozenRowsChange
|
OnChange = EdFrozenRowsChange
|
||||||
@ -61,37 +61,37 @@ object Form1: TForm1
|
|||||||
end
|
end
|
||||||
object Label1: TLabel
|
object Label1: TLabel
|
||||||
Left = 304
|
Left = 304
|
||||||
Height = 20
|
Height = 15
|
||||||
Top = 13
|
Top = 13
|
||||||
Width = 77
|
Width = 62
|
||||||
Caption = 'Frozen cols:'
|
Caption = 'Frozen cols:'
|
||||||
FocusControl = EdFrozenCols
|
FocusControl = EdFrozenCols
|
||||||
ParentColor = False
|
ParentColor = False
|
||||||
end
|
end
|
||||||
object Label2: TLabel
|
object Label2: TLabel
|
||||||
Left = 304
|
Left = 304
|
||||||
Height = 20
|
Height = 15
|
||||||
Top = 40
|
Top = 40
|
||||||
Width = 82
|
Width = 66
|
||||||
Caption = 'Frozen rows:'
|
Caption = 'Frozen rows:'
|
||||||
FocusControl = EdFrozenRows
|
FocusControl = EdFrozenRows
|
||||||
ParentColor = False
|
ParentColor = False
|
||||||
end
|
end
|
||||||
object CbReadFormulas: TCheckBox
|
object CbReadFormulas: TCheckBox
|
||||||
Left = 8
|
Left = 8
|
||||||
Height = 24
|
Height = 19
|
||||||
Top = 56
|
Top = 56
|
||||||
Width = 120
|
Width = 96
|
||||||
Caption = 'Read formulas'
|
Caption = 'Read formulas'
|
||||||
OnChange = CbReadFormulasChange
|
OnChange = CbReadFormulasChange
|
||||||
TabOrder = 4
|
TabOrder = 4
|
||||||
end
|
end
|
||||||
object CbHeaderStyle: TComboBox
|
object CbHeaderStyle: TComboBox
|
||||||
Left = 152
|
Left = 152
|
||||||
Height = 28
|
Height = 23
|
||||||
Top = 8
|
Top = 8
|
||||||
Width = 116
|
Width = 116
|
||||||
ItemHeight = 20
|
ItemHeight = 15
|
||||||
ItemIndex = 2
|
ItemIndex = 2
|
||||||
Items.Strings = (
|
Items.Strings = (
|
||||||
'Lazarus'
|
'Lazarus'
|
||||||
@ -106,7 +106,7 @@ object Form1: TForm1
|
|||||||
end
|
end
|
||||||
object PageControl1: TPageControl
|
object PageControl1: TPageControl
|
||||||
Left = 0
|
Left = 0
|
||||||
Height = 460
|
Height = 465
|
||||||
Top = 79
|
Top = 79
|
||||||
Width = 884
|
Width = 884
|
||||||
ActivePage = TabSheet1
|
ActivePage = TabSheet1
|
||||||
@ -116,11 +116,11 @@ object Form1: TForm1
|
|||||||
OnChange = PageControl1Change
|
OnChange = PageControl1Change
|
||||||
object TabSheet1: TTabSheet
|
object TabSheet1: TTabSheet
|
||||||
Caption = 'Sheet1'
|
Caption = 'Sheet1'
|
||||||
ClientHeight = 427
|
ClientHeight = 437
|
||||||
ClientWidth = 876
|
ClientWidth = 876
|
||||||
object WorksheetGrid: TsWorksheetGrid
|
object WorksheetGrid: TsWorksheetGrid
|
||||||
Left = 0
|
Left = 0
|
||||||
Height = 427
|
Height = 437
|
||||||
Top = 0
|
Top = 0
|
||||||
Width = 876
|
Width = 876
|
||||||
FrozenCols = 0
|
FrozenCols = 0
|
||||||
@ -136,7 +136,7 @@ object Form1: TForm1
|
|||||||
TitleStyle = tsNative
|
TitleStyle = tsNative
|
||||||
OnSelection = WorksheetGridSelection
|
OnSelection = WorksheetGridSelection
|
||||||
ColWidths = (
|
ColWidths = (
|
||||||
56
|
42
|
||||||
64
|
64
|
||||||
64
|
64
|
||||||
64
|
64
|
||||||
@ -244,19 +244,19 @@ object Form1: TForm1
|
|||||||
end
|
end
|
||||||
object FontComboBox: TComboBox
|
object FontComboBox: TComboBox
|
||||||
Left = 52
|
Left = 52
|
||||||
Height = 28
|
Height = 23
|
||||||
Top = 2
|
Top = 2
|
||||||
Width = 127
|
Width = 127
|
||||||
ItemHeight = 20
|
ItemHeight = 15
|
||||||
OnSelect = FontComboBoxSelect
|
OnSelect = FontComboBoxSelect
|
||||||
TabOrder = 0
|
TabOrder = 0
|
||||||
end
|
end
|
||||||
object FontSizeComboBox: TComboBox
|
object FontSizeComboBox: TComboBox
|
||||||
Left = 179
|
Left = 179
|
||||||
Height = 28
|
Height = 23
|
||||||
Top = 2
|
Top = 2
|
||||||
Width = 48
|
Width = 48
|
||||||
ItemHeight = 20
|
ItemHeight = 15
|
||||||
Items.Strings = (
|
Items.Strings = (
|
||||||
'8'
|
'8'
|
||||||
'9'
|
'9'
|
||||||
@ -2455,70 +2455,70 @@ object Form1: TForm1
|
|||||||
OnExecute = AcNumFormatExecute
|
OnExecute = AcNumFormatExecute
|
||||||
end
|
end
|
||||||
object AcNFFmtDateTimeDM: TAction
|
object AcNFFmtDateTimeDM: TAction
|
||||||
Tag = 1111
|
Tag = 1181
|
||||||
Category = 'Format'
|
Category = 'Format'
|
||||||
AutoCheck = True
|
AutoCheck = True
|
||||||
Caption = 'Day + month'
|
Caption = 'Day + month'
|
||||||
OnExecute = AcNumFormatExecute
|
OnExecute = AcNumFormatExecute
|
||||||
end
|
end
|
||||||
object AcNFFmtDateTimeMY: TAction
|
object AcNFFmtDateTimeMY: TAction
|
||||||
Tag = 1112
|
Tag = 1182
|
||||||
Category = 'Format'
|
Category = 'Format'
|
||||||
AutoCheck = True
|
AutoCheck = True
|
||||||
Caption = 'Month + year'
|
Caption = 'Month + year'
|
||||||
OnExecute = AcNumFormatExecute
|
OnExecute = AcNumFormatExecute
|
||||||
end
|
end
|
||||||
object AcNFLongDate: TAction
|
object AcNFLongDate: TAction
|
||||||
Tag = 1130
|
Tag = 1120
|
||||||
Category = 'Format'
|
Category = 'Format'
|
||||||
AutoCheck = True
|
AutoCheck = True
|
||||||
Caption = 'Long date'
|
Caption = 'Long date'
|
||||||
OnExecute = AcNumFormatExecute
|
OnExecute = AcNumFormatExecute
|
||||||
end
|
end
|
||||||
object AcNFShortTime: TAction
|
object AcNFShortTime: TAction
|
||||||
Tag = 1140
|
Tag = 1130
|
||||||
Category = 'Format'
|
Category = 'Format'
|
||||||
AutoCheck = True
|
AutoCheck = True
|
||||||
Caption = 'Short time'
|
Caption = 'Short time'
|
||||||
OnExecute = AcNumFormatExecute
|
OnExecute = AcNumFormatExecute
|
||||||
end
|
end
|
||||||
object AcNFLongTime: TAction
|
object AcNFLongTime: TAction
|
||||||
Tag = 1150
|
Tag = 1140
|
||||||
Category = 'Format'
|
Category = 'Format'
|
||||||
AutoCheck = True
|
AutoCheck = True
|
||||||
Caption = 'Long time'
|
Caption = 'Long time'
|
||||||
OnExecute = AcNumFormatExecute
|
OnExecute = AcNumFormatExecute
|
||||||
end
|
end
|
||||||
object AcNFShortTimeAM: TAction
|
object AcNFShortTimeAM: TAction
|
||||||
Tag = 1160
|
Tag = 1150
|
||||||
Category = 'Format'
|
Category = 'Format'
|
||||||
AutoCheck = True
|
AutoCheck = True
|
||||||
Caption = 'Short time AM/PM'
|
Caption = 'Short time AM/PM'
|
||||||
OnExecute = AcNumFormatExecute
|
OnExecute = AcNumFormatExecute
|
||||||
end
|
end
|
||||||
object AcNFLongTimeAM: TAction
|
object AcNFLongTimeAM: TAction
|
||||||
Tag = 1170
|
Tag = 1160
|
||||||
Category = 'Format'
|
Category = 'Format'
|
||||||
AutoCheck = True
|
AutoCheck = True
|
||||||
Caption = 'Long time AM/PM'
|
Caption = 'Long time AM/PM'
|
||||||
OnExecute = AcNumFormatExecute
|
OnExecute = AcNumFormatExecute
|
||||||
end
|
end
|
||||||
object AcNFFmtDateTimeMS: TAction
|
object AcNFFmtDateTimeMS: TAction
|
||||||
Tag = 1113
|
Tag = 1183
|
||||||
Category = 'Format'
|
Category = 'Format'
|
||||||
AutoCheck = True
|
AutoCheck = True
|
||||||
Caption = 'Minutes + seconds'
|
Caption = 'Minutes + seconds'
|
||||||
OnExecute = AcNumFormatExecute
|
OnExecute = AcNumFormatExecute
|
||||||
end
|
end
|
||||||
object AcNFFmtDateTimeMSZ: TAction
|
object AcNFFmtDateTimeMSZ: TAction
|
||||||
Tag = 1114
|
Tag = 1184
|
||||||
Category = 'Format'
|
Category = 'Format'
|
||||||
AutoCheck = True
|
AutoCheck = True
|
||||||
Caption = 'Minutes + seconds + milliseconds'
|
Caption = 'Minutes + seconds + milliseconds'
|
||||||
OnExecute = AcNumFormatExecute
|
OnExecute = AcNumFormatExecute
|
||||||
end
|
end
|
||||||
object AcNFTimeInterval: TAction
|
object AcNFTimeInterval: TAction
|
||||||
Tag = 1180
|
Tag = 1170
|
||||||
Category = 'Format'
|
Category = 'Format'
|
||||||
AutoCheck = True
|
AutoCheck = True
|
||||||
Caption = 'Time interval'
|
Caption = 'Time interval'
|
||||||
|
@ -271,7 +271,7 @@ var
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
fpcanvas, fpsutils;
|
fpcanvas, fpsutils, fpsnumformatparser;
|
||||||
|
|
||||||
const
|
const
|
||||||
HORALIGN_TAG = 100;
|
HORALIGN_TAG = 100;
|
||||||
@ -455,17 +455,25 @@ procedure TForm1.AcIncDecDecimalsExecute(Sender: TObject);
|
|||||||
var
|
var
|
||||||
cell: PCell;
|
cell: PCell;
|
||||||
decs: Byte;
|
decs: Byte;
|
||||||
|
parser: TsNumFormatParser;
|
||||||
begin
|
begin
|
||||||
with WorksheetGrid do begin
|
with WorksheetGrid do begin
|
||||||
if Workbook = nil then
|
if Workbook = nil then
|
||||||
exit;
|
exit;
|
||||||
cell := Worksheet.FindCell(GetWorksheetRow(Row), GetWorksheetCol(Col));
|
cell := Worksheet.FindCell(GetWorksheetRow(Row), GetWorksheetCol(Col));
|
||||||
if (cell <> nil) then begin
|
if (cell <> nil) then begin
|
||||||
decs := cell^.Decimals;
|
parser := TsNumFormatParser.Create(Workbook, cell^.NumberFormatStr);
|
||||||
|
try
|
||||||
|
decs := parser.Decimals;
|
||||||
if (Sender = AcIncDecimals) then
|
if (Sender = AcIncDecimals) then
|
||||||
Worksheet.WriteDecimals(cell, decs+1);
|
Parser.Decimals := decs+1;
|
||||||
if (Sender = AcDecDecimals) and (decs > 0) then
|
if (Sender = AcDecDecimals) and (decs > 0) then
|
||||||
Worksheet.WriteDecimals(cell, decs-1);
|
Parser.Decimals := decs-1;
|
||||||
|
cell^.NumberFormatStr := parser.FormatString[nfdDefault];
|
||||||
|
finally
|
||||||
|
parser.Free;
|
||||||
|
end;
|
||||||
|
Invalidate;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -477,23 +485,20 @@ end;
|
|||||||
|
|
||||||
procedure TForm1.AcNumFormatExecute(Sender: TObject);
|
procedure TForm1.AcNumFormatExecute(Sender: TObject);
|
||||||
const
|
const
|
||||||
DATETIME_FMT: array[0..4] of string = ('', 'dm', 'my', 'ms', 'msz');
|
DATETIME_CUSTOM: array[0..4] of string = ('', 'dm', 'my', 'ms', 'msz');
|
||||||
var
|
var
|
||||||
nf: TsNumberFormat;
|
nf: TsNumberFormat;
|
||||||
c, r: Cardinal;
|
c, r: Cardinal;
|
||||||
cell: PCell;
|
cell: PCell;
|
||||||
fmt: String;
|
fmt: String;
|
||||||
begin
|
begin
|
||||||
if WorksheetGrid.Worksheet = nil then
|
|
||||||
exit;
|
|
||||||
|
|
||||||
if TAction(Sender).Checked then
|
if TAction(Sender).Checked then
|
||||||
nf := TsNumberFormat((TAction(Sender).Tag - NUMFMT_TAG) div 10)
|
nf := TsNumberFormat((TAction(Sender).Tag - NUMFMT_TAG) div 10)
|
||||||
else
|
else
|
||||||
nf := nfGeneral;
|
nf := nfGeneral;
|
||||||
|
|
||||||
if nf = nfFmtDateTime then
|
if nf = nfCustom then
|
||||||
fmt := DATETIME_FMT[TAction(Sender).Tag mod 10]
|
fmt := DATETIME_CUSTOM[TAction(Sender).Tag mod 10]
|
||||||
else
|
else
|
||||||
fmt := '';
|
fmt := '';
|
||||||
|
|
||||||
@ -508,17 +513,22 @@ begin
|
|||||||
Worksheet.WriteDateTime(cell, cell^.DateTimeValue, nf, fmt)
|
Worksheet.WriteDateTime(cell, cell^.DateTimeValue, nf, fmt)
|
||||||
else
|
else
|
||||||
Worksheet.WriteDateTime(cell, cell^.NumberValue, nf, fmt);
|
Worksheet.WriteDateTime(cell, cell^.NumberValue, nf, fmt);
|
||||||
|
end else
|
||||||
|
if IsCurrencyFormat(nf) then begin
|
||||||
|
if IsDateTimeFormat(cell^.NumberFormat) then
|
||||||
|
Worksheet.WriteCurrency(cell, cell^.DateTimeValue, nf, fmt)
|
||||||
|
else
|
||||||
|
Worksheet.WriteCurrency(cell, cell^.Numbervalue, nf, fmt);
|
||||||
end else begin
|
end else begin
|
||||||
if IsDateTimeFormat(cell^.NumberFormat) then
|
if IsDateTimeFormat(cell^.NumberFormat) then
|
||||||
Worksheet.WriteNumber(cell, cell^.DateTimeValue, nf, cell^.Decimals, cell^.CurrencySymbol)
|
Worksheet.WriteNumber(cell, cell^.DateTimeValue, nf, fmt)
|
||||||
else
|
else
|
||||||
Worksheet.WriteNumber(cell, cell^.NumberValue, nf, cell^.Decimals, cell^.CurrencySymbol);
|
Worksheet.WriteNumber(cell, cell^.NumberValue, nf, fmt)
|
||||||
end;
|
end;
|
||||||
else
|
else
|
||||||
Worksheet.WriteNumberformat(cell, nf, fmt);
|
Worksheet.WriteNumberformat(cell, nf, fmt);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
UpdateNumFormatActions;
|
UpdateNumFormatActions;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -872,14 +882,12 @@ begin
|
|||||||
t := ac.Tag;
|
t := ac.Tag;
|
||||||
if (ac.Tag >= NUMFMT_TAG) and (ac.Tag < NUMFMT_TAG + 200) then begin
|
if (ac.Tag >= NUMFMT_TAG) and (ac.Tag < NUMFMT_TAG + 200) then begin
|
||||||
found := ((ac.Tag - NUMFMT_TAG) div 10 = ord(nf));
|
found := ((ac.Tag - NUMFMT_TAG) div 10 = ord(nf));
|
||||||
if (nf = nfFmtDateTime) then
|
if nf = nfCustom then
|
||||||
case (ac.Tag - NUMFMT_TAG) mod 10 of
|
case (ac.Tag - NUMFMT_TAG) mod 10 of
|
||||||
1: found := pos('d/m', cell^.NumberFormatStr) > 0;
|
1: found := cell^.NumberFormatStr = 'dd/mmm';
|
||||||
2: found := pos('m/y', cell^.NumberFormatStr) > 0;
|
2: found := cell^.NumberFormatStr = 'mmm/yy';
|
||||||
3: found := (pos('n:s', cell^.NumberFormatStr) > 0)
|
3: found := cell^.NumberFormatStr = 'nn:ss';
|
||||||
and (pos ('.z', cell^.NumberFormatStr) = 0);
|
4: found := cell^.NumberFormatStr = 'nn:ss.z';
|
||||||
4: found := (pos('n:s', cell^.NumberFormatStr) > 0)
|
|
||||||
and (pos ('.z', cell^.NumberFormatStr) > 0);
|
|
||||||
end;
|
end;
|
||||||
ac.Checked := found;
|
ac.Checked := found;
|
||||||
end;
|
end;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -452,8 +452,6 @@ begin
|
|||||||
Include(ACell^.UsedFormattingFields, uffNumberFormat);
|
Include(ACell^.UsedFormattingFields, uffNumberFormat);
|
||||||
ACell^.NumberFormat := numFmtData.NumFormat;
|
ACell^.NumberFormat := numFmtData.NumFormat;
|
||||||
ACell^.NumberFormatStr := numFmtData.FormatString;
|
ACell^.NumberFormatStr := numFmtData.FormatString;
|
||||||
ACell^.Decimals := numFmtData.Decimals;
|
|
||||||
ACell^.CurrencySymbol := numFmtData.CurrencySymbol;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -1074,7 +1072,7 @@ procedure TsSpreadOpenDocReader.ReadNumFormats(AStylesNode: TDOMNode);
|
|||||||
if negfmt <> '' then AFormatStr := AFormatStr + ';' + negfmt;
|
if negfmt <> '' then AFormatStr := AFormatStr + ';' + negfmt;
|
||||||
if zerofmt <> '' then AFormatStr := AFormatStr + ';' + zerofmt;
|
if zerofmt <> '' then AFormatStr := AFormatStr + ';' + zerofmt;
|
||||||
|
|
||||||
if ANumFormat <> nfFmtDateTime then
|
// if ANumFormat <> nfFmtDateTime then
|
||||||
ANumFormat := nfCustom;
|
ANumFormat := nfCustom;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1141,7 +1139,7 @@ procedure TsSpreadOpenDocReader.ReadNumFormats(AStylesNode: TDOMNode);
|
|||||||
else if ANumFormatNode.NodeName = 'number:currency-style' then
|
else if ANumFormatNode.NodeName = 'number:currency-style' then
|
||||||
nf := nfCurrency;
|
nf := nfCurrency;
|
||||||
|
|
||||||
NumFormatList.AddFormat(ANumFormatName, fmt, nf, decs, cs);
|
NumFormatList.AddFormat(ANumFormatName, fmt, nf);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure ReadDateTimeStyle(ANumFormatNode: TDOMNode; ANumFormatName: String);
|
procedure ReadDateTimeStyle(ANumFormatNode: TDOMNode; ANumFormatName: String);
|
||||||
@ -1233,7 +1231,8 @@ procedure TsSpreadOpenDocReader.ReadNumFormats(AStylesNode: TDOMNode);
|
|||||||
node := node.NextSibling;
|
node := node.NextSibling;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
nf := IfThen(isInterval, nfTimeInterval, nfFmtDateTime);
|
// nf := IfThen(isInterval, nfTimeInterval, nfFmtDateTime);
|
||||||
|
nf := IfThen(isInterval, nfTimeInterval, nfCustom);
|
||||||
node := ANumFormatNode.FindNode('style:map');
|
node := ANumFormatNode.FindNode('style:map');
|
||||||
if node <> nil then
|
if node <> nil then
|
||||||
ReadStyleMap(node, nf, fmt);
|
ReadStyleMap(node, nf, fmt);
|
||||||
@ -1271,9 +1270,11 @@ procedure TsSpreadOpenDocReader.ReadNumFormats(AStylesNode: TDOMNode);
|
|||||||
node := ANumFormatNode.FindNode('style:map');
|
node := ANumFormatNode.FindNode('style:map');
|
||||||
if node <> nil then
|
if node <> nil then
|
||||||
ReadStyleMap(node, nf, fmt);
|
ReadStyleMap(node, nf, fmt);
|
||||||
|
{
|
||||||
if IsDateTimeFormat(fmt) then
|
if IsDateTimeFormat(fmt) then
|
||||||
nf := nfFmtDateTime
|
nf := nfFmtDateTime
|
||||||
else
|
else
|
||||||
|
}
|
||||||
nf := nfCustom;
|
nf := nfCustom;
|
||||||
|
|
||||||
NumFormatList.AddFormat(ANumFormatName, fmt, nf);
|
NumFormatList.AddFormat(ANumFormatName, fmt, nf);
|
||||||
|
@ -174,11 +174,46 @@ type
|
|||||||
// currency
|
// currency
|
||||||
nfCurrency, nfCurrencyRed, nfAccounting, nfAccountingRed,
|
nfCurrency, nfCurrencyRed, nfAccounting, nfAccountingRed,
|
||||||
// dates and times
|
// dates and times
|
||||||
nfShortDateTime, nfFmtDateTime, nfShortDate, nfLongDate, nfShortTime, nfLongTime,
|
nfShortDateTime, {nfFmtDateTime, }nfShortDate, nfLongDate, nfShortTime, nfLongTime,
|
||||||
nfShortTimeAM, nfLongTimeAM, nfTimeInterval,
|
nfShortTimeAM, nfLongTimeAM, nfTimeInterval,
|
||||||
// other (format string goes directly into the file)
|
// other (format string goes directly into the file)
|
||||||
nfCustom);
|
nfCustom);
|
||||||
|
|
||||||
|
const
|
||||||
|
{ @@ Codes for curreny format according to FormatSettings.CurrencyFormat:
|
||||||
|
"C" = currency symbol, "V" = currency value, "S" = space character
|
||||||
|
For the negative value formats, we use also:
|
||||||
|
"B" = bracket, "M" = Minus
|
||||||
|
The order of these characters represents the order of these items.
|
||||||
|
Example: 1000 dollars --> "$1000" for pCV, or "1000 $" for pVsC
|
||||||
|
-1000 dollars --> "($1000)" for nbCVb, or "-$ 1000" for nMCSV
|
||||||
|
Assignment taken from "sysstr.inc" }
|
||||||
|
|
||||||
|
pcfDefault = -1; // use value from Worksheet.FormatSettings.CurrencyFormat
|
||||||
|
pcfCV = 0; // $1000
|
||||||
|
pcfVC = 1; // 1000$
|
||||||
|
pcfCSV = 2; // $ 1000
|
||||||
|
pcfVSC = 3; // 1000 $
|
||||||
|
|
||||||
|
ncfDefault = -1; // use value from Worksheet.FormatSettings.NegCurrFormat
|
||||||
|
ncfBCVB = 0; // ($1000)
|
||||||
|
ncfMCV = 1; // -$1000
|
||||||
|
ncfCMV = 2; // $-1000
|
||||||
|
ncfCVM = 3; // $1000-
|
||||||
|
ncfBVCB = 4; // (1000$)
|
||||||
|
ccfMVC = 5; // -1000$
|
||||||
|
ncfVMC = 6; // 1000-$
|
||||||
|
ncfVCM = 7; // 1000$-
|
||||||
|
ncfMVSC = 8; // -1000 $
|
||||||
|
ncfMCSV = 9; // -$ 1000
|
||||||
|
ncfVSCM = 10; // 1000 $-
|
||||||
|
ncfCSVM = 11; // $ 1000-
|
||||||
|
ncfCSMV = 12; // $ -1000
|
||||||
|
ncfVMSC = 13; // 1000- $
|
||||||
|
ncfBCSVB = 14; // ($ 1000)
|
||||||
|
ncfBVSCB = 15; // (1000 $)
|
||||||
|
|
||||||
|
type
|
||||||
{@@ Text rotation formatting. The text is rotated relative to the standard
|
{@@ Text rotation formatting. The text is rotated relative to the standard
|
||||||
orientation, which is from left to right horizontal:
|
orientation, which is from left to right horizontal:
|
||||||
--->
|
--->
|
||||||
@ -328,8 +363,6 @@ type
|
|||||||
BackgroundColor: TsColor;
|
BackgroundColor: TsColor;
|
||||||
NumberFormat: TsNumberFormat;
|
NumberFormat: TsNumberFormat;
|
||||||
NumberFormatStr: String;
|
NumberFormatStr: String;
|
||||||
Decimals: Byte;
|
|
||||||
CurrencySymbol: String;
|
|
||||||
RGBBackgroundColor: TFPColor; // only valid if BackgroundColor=scRGBCOLOR
|
RGBBackgroundColor: TFPColor; // only valid if BackgroundColor=scRGBCOLOR
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -396,22 +429,9 @@ type
|
|||||||
|
|
||||||
{ Utils }
|
{ Utils }
|
||||||
class function CellPosToText(ARow, ACol: Cardinal): string;
|
class function CellPosToText(ARow, ACol: Cardinal): string;
|
||||||
|
procedure RemoveAllCells;
|
||||||
|
|
||||||
{ Data manipulation methods - For Cells }
|
{ Reading of values }
|
||||||
procedure CopyCell(AFromRow, AFromCol, AToRow, AToCol: Cardinal; AFromWorksheet: TsWorksheet);
|
|
||||||
procedure CopyFormat(AFormat: PCell; AToRow, AToCol: Cardinal); overload;
|
|
||||||
procedure CopyFormat(AFromCell, AToCell: PCell); overload;
|
|
||||||
function FindCell(ARow, ACol: Cardinal): PCell;
|
|
||||||
function GetCell(ARow, ACol: Cardinal): PCell;
|
|
||||||
function GetCellCount: Cardinal;
|
|
||||||
function GetFirstCell(): PCell;
|
|
||||||
function GetNextCell(): PCell;
|
|
||||||
function GetFirstCellOfRow(ARow: Cardinal): PCell;
|
|
||||||
function GetLastCellOfRow(ARow: Cardinal): PCell;
|
|
||||||
function GetLastColIndex: Cardinal;
|
|
||||||
function GetLastColNumber: Cardinal; deprecated 'Use GetLastColIndex';
|
|
||||||
function GetLastRowIndex: Cardinal;
|
|
||||||
function GetLastRowNumber: Cardinal; deprecated 'Use GetLastRowIndex';
|
|
||||||
function ReadAsUTF8Text(ARow, ACol: Cardinal): ansistring; overload;
|
function ReadAsUTF8Text(ARow, ACol: Cardinal): ansistring; overload;
|
||||||
function ReadAsUTF8Text(ACell: PCell): ansistring; overload;
|
function ReadAsUTF8Text(ACell: PCell): ansistring; overload;
|
||||||
function ReadAsNumber(ARow, ACol: Cardinal): Double;
|
function ReadAsNumber(ARow, ACol: Cardinal): Double;
|
||||||
@ -421,25 +441,46 @@ type
|
|||||||
function ReadUsedFormatting(ARow, ACol: Cardinal): TsUsedFormattingFields;
|
function ReadUsedFormatting(ARow, ACol: Cardinal): TsUsedFormattingFields;
|
||||||
function ReadBackgroundColor(ARow, ACol: Cardinal): TsColor;
|
function ReadBackgroundColor(ARow, ACol: Cardinal): TsColor;
|
||||||
|
|
||||||
procedure RemoveAllCells;
|
|
||||||
|
|
||||||
{ Writing of values }
|
{ Writing of values }
|
||||||
procedure WriteBlank(ARow, ACol: Cardinal);
|
procedure WriteBlank(ARow, ACol: Cardinal);
|
||||||
procedure WriteBoolValue(ARow, ACol: Cardinal; AValue: Boolean);
|
procedure WriteBoolValue(ARow, ACol: Cardinal; AValue: Boolean);
|
||||||
|
|
||||||
|
procedure WriteCurrency(ARow, ACol: Cardinal; AValue: Double;
|
||||||
|
AFormat: TsNumberFormat = nfCurrency; ADecimals: Integer = 2;
|
||||||
|
ACurrencySymbol: String = '?'; APosCurrFormat: Integer = -1;
|
||||||
|
ANegCurrFormat: Integer = -1); overload;
|
||||||
|
procedure WriteCurrency(ACell: PCell; AValue: Double;
|
||||||
|
AFormat: TsNumberFormat = nfCurrency; ADecimals: Integer = -1;
|
||||||
|
ACurrencySymbol: String = '?'; APosCurrFormat: Integer = -1;
|
||||||
|
ANegCurrFormat: Integer = -1); overload;
|
||||||
|
procedure WriteCurrency(ARow, ACol: Cardinal; AValue: Double;
|
||||||
|
AFormat: TsNumberFormat; AFormatString: String); overload;
|
||||||
|
procedure WriteCurrency(ACell: PCell; AValue: Double;
|
||||||
|
AFormat: TsNumberFormat; AFormatString: String); overload;
|
||||||
|
|
||||||
procedure WriteDateTime(ARow, ACol: Cardinal; AValue: TDateTime;
|
procedure WriteDateTime(ARow, ACol: Cardinal; AValue: TDateTime;
|
||||||
AFormat: TsNumberFormat = nfGeneral; AFormatStr: String = ''); overload;
|
AFormat: TsNumberFormat = nfShortDateTime; AFormatStr: String = ''); overload;
|
||||||
procedure WriteDateTime(ACell: PCell; AValue: TDateTime;
|
procedure WriteDateTime(ACell: PCell; AValue: TDateTime;
|
||||||
AFormat: TsNumberFormat = nfGeneral; AFormatStr: String = ''); overload;
|
AFormat: TsNumberFormat = nfShortDateTime; AFormatStr: String = ''); overload;
|
||||||
|
procedure WriteDateTime(ARow, ACol: Cardinal; AValue: TDateTime;
|
||||||
|
AFormatStr: String); overload;
|
||||||
|
procedure WriteDateTime(ACell: PCell; AValue: TDateTime;
|
||||||
|
AFormatStr: String); overload;
|
||||||
|
|
||||||
procedure WriteErrorValue(ARow, ACol: Cardinal; AValue: TsErrorValue); overload;
|
procedure WriteErrorValue(ARow, ACol: Cardinal; AValue: TsErrorValue); overload;
|
||||||
procedure WriteErrorValue(ACell: PCell; AValue: TsErrorValue); overload;
|
procedure WriteErrorValue(ACell: PCell; AValue: TsErrorValue); overload;
|
||||||
procedure WriteFormula(ARow, ACol: Cardinal; AFormula: TsFormula);
|
procedure WriteFormula(ARow, ACol: Cardinal; AFormula: TsFormula);
|
||||||
|
|
||||||
procedure WriteNumber(ARow, ACol: Cardinal; ANumber: double;
|
procedure WriteNumber(ARow, ACol: Cardinal; ANumber: double;
|
||||||
AFormat: TsNumberFormat = nfGeneral; ADecimals: Byte = 2;
|
AFormat: TsNumberFormat = nfGeneral; ADecimals: Byte = 2;
|
||||||
ACurrencySymbol: String = ''); overload;
|
ACurrencySymbol: String = ''); overload;
|
||||||
procedure WriteNumber(ACell: PCell; ANumber: Double; AFormat: TsNumberFormat = nfGeneral;
|
procedure WriteNumber(ACell: PCell; ANumber: Double; AFormat: TsNumberFormat = nfGeneral;
|
||||||
ADecimals: Byte = 2; ACurrencySymbol: String = ''); overload;
|
ADecimals: Byte = 2; ACurrencySymbol: String = ''); overload;
|
||||||
procedure WriteNumber(ARow, ACol: Cardinal; ANumber: double;
|
procedure WriteNumber(ARow, ACol: Cardinal; ANumber: double;
|
||||||
AFormatString: String); overload;
|
AFormat: TsNumberFormat; AFormatString: String); overload;
|
||||||
|
procedure WriteNumber(ACell: PCell; ANumber: Double;
|
||||||
|
AFormat: TsNumberFormat; AFormatString: String); overload;
|
||||||
|
|
||||||
procedure WriteRPNFormula(ARow, ACol: Cardinal; AFormula: TsRPNFormula);
|
procedure WriteRPNFormula(ARow, ACol: Cardinal; AFormula: TsRPNFormula);
|
||||||
procedure WriteUTF8Text(ARow, ACol: Cardinal; AText: ansistring); overload;
|
procedure WriteUTF8Text(ARow, ACol: Cardinal; AText: ansistring); overload;
|
||||||
procedure WriteUTF8Text(ACell: PCell; AText: ansistring); overload;
|
procedure WriteUTF8Text(ACell: PCell; AText: ansistring); overload;
|
||||||
@ -483,6 +524,22 @@ type
|
|||||||
|
|
||||||
procedure WriteWordwrap(ARow, ACol: Cardinal; AValue: boolean);
|
procedure WriteWordwrap(ARow, ACol: Cardinal; AValue: boolean);
|
||||||
|
|
||||||
|
{ Data manipulation methods - For Cells }
|
||||||
|
procedure CopyCell(AFromRow, AFromCol, AToRow, AToCol: Cardinal; AFromWorksheet: TsWorksheet);
|
||||||
|
procedure CopyFormat(AFormat: PCell; AToRow, AToCol: Cardinal); overload;
|
||||||
|
procedure CopyFormat(AFromCell, AToCell: PCell); overload;
|
||||||
|
function FindCell(ARow, ACol: Cardinal): PCell;
|
||||||
|
function GetCell(ARow, ACol: Cardinal): PCell;
|
||||||
|
function GetCellCount: Cardinal;
|
||||||
|
function GetFirstCell(): PCell;
|
||||||
|
function GetNextCell(): PCell;
|
||||||
|
function GetFirstCellOfRow(ARow: Cardinal): PCell;
|
||||||
|
function GetLastCellOfRow(ARow: Cardinal): PCell;
|
||||||
|
function GetLastColIndex: Cardinal;
|
||||||
|
function GetLastColNumber: Cardinal; deprecated 'Use GetLastColIndex';
|
||||||
|
function GetLastRowIndex: Cardinal;
|
||||||
|
function GetLastRowNumber: Cardinal; deprecated 'Use GetLastRowIndex';
|
||||||
|
|
||||||
{ Data manipulation methods - For Rows and Cols }
|
{ Data manipulation methods - For Rows and Cols }
|
||||||
function FindRow(ARow: Cardinal): PRow;
|
function FindRow(ARow: Cardinal): PRow;
|
||||||
function FindCol(ACol: Cardinal): PCol;
|
function FindCol(ACol: Cardinal): PCol;
|
||||||
@ -506,7 +563,7 @@ type
|
|||||||
property Rows: TIndexedAVLTree read FRows;
|
property Rows: TIndexedAVLTree read FRows;
|
||||||
property Workbook: TsWorkbook read FWorkbook;
|
property Workbook: TsWorkbook read FWorkbook;
|
||||||
|
|
||||||
// These are properties to interface to fpspreadsheetgrid.
|
// These are properties to interface to TsWorksheetGrid
|
||||||
property Options: TsSheetOptions read FOptions write FOptions;
|
property Options: TsSheetOptions read FOptions write FOptions;
|
||||||
property LeftPaneWidth: Integer read FLeftPaneWidth write FLeftPaneWidth;
|
property LeftPaneWidth: Integer read FLeftPaneWidth write FLeftPaneWidth;
|
||||||
property TopPaneHeight: Integer read FTopPaneHeight write FTopPaneHeight;
|
property TopPaneHeight: Integer read FTopPaneHeight write FTopPaneHeight;
|
||||||
@ -608,8 +665,6 @@ type
|
|||||||
Index: Integer;
|
Index: Integer;
|
||||||
Name: String;
|
Name: String;
|
||||||
NumFormat: TsNumberFormat;
|
NumFormat: TsNumberFormat;
|
||||||
Decimals: Byte;
|
|
||||||
CurrencySymbol: String;
|
|
||||||
FormatString: string;
|
FormatString: string;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -630,27 +685,21 @@ type
|
|||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
function AddFormat(AFormatCell: PCell): Integer; overload;
|
function AddFormat(AFormatCell: PCell): Integer; overload;
|
||||||
function AddFormat(AFormatIndex: Integer; AFormatName, AFormatString: String;
|
function AddFormat(AFormatIndex: Integer; AFormatName, AFormatString: String;
|
||||||
ANumFormat: TsNumberFormat; ADecimals: Byte = 0;
|
ANumFormat: TsNumberFormat): Integer; overload;
|
||||||
ACurrencySymbol: String = ''): Integer; overload;
|
|
||||||
function AddFormat(AFormatIndex: Integer; AFormatString: String;
|
function AddFormat(AFormatIndex: Integer; AFormatString: String;
|
||||||
ANumFormat: TsNumberFormat; ADecimals: Byte = 0;
|
ANumFormat: TsNumberFormat): Integer; overload;
|
||||||
ACurrencySymbol: String = ''): Integer; overload;
|
|
||||||
function AddFormat(AFormatName, AFormatString: String;
|
function AddFormat(AFormatName, AFormatString: String;
|
||||||
ANumFormat: TsNumberFormat; ADecimals: Byte = 0;
|
ANumFormat: TsNumberFormat): Integer; overload;
|
||||||
ACurrencySymbol: String = ''): Integer; overload;
|
function AddFormat(AFormatString: String; ANumFormat: TsNumberFormat): Integer; overload;
|
||||||
function AddFormat(AFormatString: String; ANumFormat: TsNumberFormat;
|
|
||||||
ADecimals: Byte = 0; ACurrencySymbol: String = ''): Integer; overload;
|
|
||||||
procedure AnalyzeAndAdd(AFormatIndex: Integer; AFormatString: String);
|
procedure AnalyzeAndAdd(AFormatIndex: Integer; AFormatString: String);
|
||||||
procedure Clear;
|
procedure Clear;
|
||||||
procedure ConvertAfterReading(AFormatIndex: Integer; var AFormatString: String;
|
procedure ConvertAfterReading(AFormatIndex: Integer; var AFormatString: String;
|
||||||
var ANumFormat: TsNumberFormat; var ADecimals: Byte;
|
var ANumFormat: TsNumberFormat); virtual;
|
||||||
var ACurrencySymbol: String); virtual;
|
|
||||||
procedure ConvertBeforeWriting(var AFormatString: String;
|
procedure ConvertBeforeWriting(var AFormatString: String;
|
||||||
var ANumFormat: TsNumberFormat; var ADecimals: Byte;
|
var ANumFormat: TsNumberFormat; var ADecimals: Byte;
|
||||||
var ACurrencySymbol: String); virtual;
|
var ACurrencySymbol: String); virtual;
|
||||||
procedure Delete(AIndex: Integer);
|
procedure Delete(AIndex: Integer);
|
||||||
function Find(ANumFormat: TsNumberFormat; AFormatString: String;
|
function Find(ANumFormat: TsNumberFormat; AFormatString: String): Integer; overload;
|
||||||
ADecimals: Byte; ACurrencySymbol: String): Integer; overload;
|
|
||||||
function Find(AFormatString: String): Integer; overload;
|
function Find(AFormatString: String): Integer; overload;
|
||||||
function FindByIndex(AFormatIndex: Integer): Integer;
|
function FindByIndex(AFormatIndex: Integer): Integer;
|
||||||
function FindByName(AFormatName: String): Integer;
|
function FindByName(AFormatName: String): Integer;
|
||||||
@ -829,6 +878,7 @@ resourcestring
|
|||||||
lpUnknownSpreadsheetFormat = 'unknown format';
|
lpUnknownSpreadsheetFormat = 'unknown format';
|
||||||
lpInvalidFontIndex = 'Invalid font index';
|
lpInvalidFontIndex = 'Invalid font index';
|
||||||
lpInvalidNumberFormat = 'Trying to use an incompatible number format.';
|
lpInvalidNumberFormat = 'Trying to use an incompatible number format.';
|
||||||
|
lpInvalidDateTimeFormat = 'Trying to use an incompatible date/time format.';
|
||||||
lpNoValidNumberFormatString = 'No valid number format string.';
|
lpNoValidNumberFormatString = 'No valid number format string.';
|
||||||
lpNoValidDateTimeFormatString = 'No valid date/time format string.';
|
lpNoValidDateTimeFormatString = 'No valid date/time format string.';
|
||||||
lpNoValidCellAddress = '"%s" is not a valid cell address.';
|
lpNoValidCellAddress = '"%s" is not a valid cell address.';
|
||||||
@ -1129,8 +1179,6 @@ begin
|
|||||||
AToCell^.TextRotation := AFromCell^.TextRotation;
|
AToCell^.TextRotation := AFromCell^.TextRotation;
|
||||||
AToCell^.NumberFormat := AFromCell^.NumberFormat;
|
AToCell^.NumberFormat := AFromCell^.NumberFormat;
|
||||||
AToCell^.NumberFormatStr := AFromCell^.NumberFormatStr;
|
AToCell^.NumberFormatStr := AFromCell^.NumberFormatStr;
|
||||||
AToCell^.Decimals := AFromCell^.Decimals;
|
|
||||||
AToCell^.CurrencySymbol := AFromCell^.CurrencySymbol;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -1321,7 +1369,6 @@ begin
|
|||||||
Result^.Col := ACol;
|
Result^.Col := ACol;
|
||||||
Result^.ContentType := cctEmpty;
|
Result^.ContentType := cctEmpty;
|
||||||
Result^.BorderStyles := DEFAULT_BORDERSTYLES;
|
Result^.BorderStyles := DEFAULT_BORDERSTYLES;
|
||||||
Result^.CurrencySymbol := '?';
|
|
||||||
|
|
||||||
Cells.Add(Result);
|
Cells.Add(Result);
|
||||||
end;
|
end;
|
||||||
@ -1503,7 +1550,7 @@ end;
|
|||||||
function TsWorksheet.ReadAsUTF8Text(ACell: PCell): ansistring;
|
function TsWorksheet.ReadAsUTF8Text(ACell: PCell): ansistring;
|
||||||
|
|
||||||
function FloatToStrNoNaN(const Value: Double;
|
function FloatToStrNoNaN(const Value: Double;
|
||||||
ANumberFormat: TsNumberFormat; ANumberFormatStr: string; ADecimals: byte): ansistring;
|
ANumberFormat: TsNumberFormat; ANumberFormatStr: string): ansistring;
|
||||||
var
|
var
|
||||||
fs: TFormatSettings;
|
fs: TFormatSettings;
|
||||||
left, right: String;
|
left, right: String;
|
||||||
@ -1513,12 +1560,12 @@ function TsWorksheet.ReadAsUTF8Text(ACell: PCell): ansistring;
|
|||||||
if IsNan(Value) then
|
if IsNan(Value) then
|
||||||
Result := ''
|
Result := ''
|
||||||
else
|
else
|
||||||
if ANumberFormat = nfSci then
|
|
||||||
Result := SciFloat(Value, ADecimals)
|
|
||||||
else
|
|
||||||
if (ANumberFormat = nfGeneral) or (ANumberFormatStr = '') then
|
if (ANumberFormat = nfGeneral) or (ANumberFormatStr = '') then
|
||||||
Result := FloatToStr(Value, fs)
|
Result := FloatToStr(Value, fs)
|
||||||
else
|
else
|
||||||
|
if ANumberFormat = nfSci then
|
||||||
|
Result := SciFloat(Value, CountDecs(ANumberFormatStr, ['0']), fs)
|
||||||
|
else
|
||||||
if (ANumberFormat = nfPercentage) then
|
if (ANumberFormat = nfPercentage) then
|
||||||
Result := FormatFloat(ANumberFormatStr, Value*100, fs)
|
Result := FormatFloat(ANumberFormatStr, Value*100, fs)
|
||||||
else
|
else
|
||||||
@ -1533,7 +1580,7 @@ function TsWorksheet.ReadAsUTF8Text(ACell: PCell): ansistring;
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
function DateTimeToStrNoNaN(const Value: Double;
|
function DateTimeToStrNoNaN(const Value: Double;
|
||||||
ANumberFormat: TsNumberFormat; ANumberFormatStr: String; ADecimals: Word): ansistring;
|
ANumberFormat: TsNumberFormat; ANumberFormatStr: String): ansistring;
|
||||||
var
|
var
|
||||||
fmtp, fmtn, fmt0: String;
|
fmtp, fmtn, fmt0: String;
|
||||||
begin
|
begin
|
||||||
@ -1564,11 +1611,11 @@ begin
|
|||||||
with ACell^ do
|
with ACell^ do
|
||||||
case ContentType of
|
case ContentType of
|
||||||
cctNumber:
|
cctNumber:
|
||||||
Result := FloatToStrNoNaN(NumberValue, NumberFormat, NumberFormatStr, Decimals);
|
Result := FloatToStrNoNaN(NumberValue, NumberFormat, NumberFormatStr);
|
||||||
cctUTF8String:
|
cctUTF8String:
|
||||||
Result := UTF8StringValue;
|
Result := UTF8StringValue;
|
||||||
cctDateTime:
|
cctDateTime:
|
||||||
Result := DateTimeToStrNoNaN(DateTimeValue, NumberFormat, NumberFormatStr, Decimals);
|
Result := DateTimeToStrNoNaN(DateTimeValue, NumberFormat, NumberFormatStr);
|
||||||
cctBool:
|
cctBool:
|
||||||
Result := IfThen(BoolValue, lpTRUE, lpFALSE);
|
Result := IfThen(BoolValue, lpTRUE, lpFALSE);
|
||||||
cctError:
|
cctError:
|
||||||
@ -1845,33 +1892,22 @@ begin
|
|||||||
WriteNumber(GetCell(ARow, ACol), ANumber, AFormat, ADecimals, ACurrencySymbol);
|
WriteNumber(GetCell(ARow, ACol), ANumber, AFormat, ADecimals, ACurrencySymbol);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TsWorksheet.WriteNumber(ACell: PCell; ANumber: Double;
|
procedure TsWorksheet.WriteNumber(ACell: PCell; ANumber: Double;
|
||||||
AFormat: TsNumberFormat = nfGeneral; ADecimals: Byte = 2;
|
AFormat: TsNumberFormat = nfGeneral; ADecimals: Byte = 2;
|
||||||
ACurrencySymbol: String = '');
|
ACurrencySymbol: String = '');
|
||||||
var
|
|
||||||
fs: TFormatSettings;
|
|
||||||
begin
|
begin
|
||||||
|
if IsDateTimeFormat(AFormat) or IsCurrencyFormat(AFormat) then
|
||||||
|
raise Exception.Create(lpInvalidNumberFormat);
|
||||||
|
|
||||||
if ACell <> nil then begin
|
if ACell <> nil then begin
|
||||||
ACell^.ContentType := cctNumber;
|
ACell^.ContentType := cctNumber;
|
||||||
ACell^.NumberValue := ANumber;
|
ACell^.NumberValue := ANumber;
|
||||||
ACell^.Decimals := ADecimals;
|
|
||||||
|
|
||||||
if IsDateTimeFormat(AFormat) then
|
|
||||||
raise Exception.Create(lpInvalidNumberFormat);
|
|
||||||
|
|
||||||
{
|
|
||||||
if AFormat = nfCustom then
|
|
||||||
raise Exception.Create(lpIllegalNumberformat);
|
|
||||||
}
|
|
||||||
|
|
||||||
if AFormat <> nfGeneral then begin
|
if AFormat <> nfGeneral then begin
|
||||||
Include(ACell^.UsedFormattingFields, uffNumberFormat);
|
Include(ACell^.UsedFormattingFields, uffNumberFormat);
|
||||||
ACell^.NumberFormat := AFormat;
|
ACell^.NumberFormat := AFormat;
|
||||||
ACell^.Decimals := ADecimals;
|
|
||||||
ACell^.CurrencySymbol := ACurrencySymbol;
|
|
||||||
ACell^.NumberFormatStr := BuildNumberFormatString(ACell^.NumberFormat,
|
ACell^.NumberFormatStr := BuildNumberFormatString(ACell^.NumberFormat,
|
||||||
Workbook.FormatSettings, ADecimals, ACurrencySymbol);
|
Workbook.FormatSettings, ADecimals);
|
||||||
end else begin
|
end else begin
|
||||||
Exclude(ACell^.UsedFormattingFields, uffNumberFormat);
|
Exclude(ACell^.UsedFormattingFields, uffNumberFormat);
|
||||||
ACell^.NumberFormat := nfGeneral;
|
ACell^.NumberFormat := nfGeneral;
|
||||||
@ -1888,36 +1924,41 @@ end;
|
|||||||
NOTE that fpspreadsheet may not be able to detect the formatting when reading
|
NOTE that fpspreadsheet may not be able to detect the formatting when reading
|
||||||
the file. }
|
the file. }
|
||||||
procedure TsWorksheet.WriteNumber(ARow, ACol: Cardinal; ANumber: Double;
|
procedure TsWorksheet.WriteNumber(ARow, ACol: Cardinal; ANumber: Double;
|
||||||
AFormatString: String);
|
AFormat: TsNumberFormat; AFormatString: String);
|
||||||
var
|
var
|
||||||
ACell: PCell;
|
ACell: PCell;
|
||||||
parser: TsNumFormatParser;
|
|
||||||
nf: TsNumberFormat;
|
|
||||||
begin
|
begin
|
||||||
parser := TsNumFormatParser.Create(Workbook, AFormatString, nfCustom, cdToFPSpreadsheet);
|
WriteNumber(GetCell(ARow, ACol), ANumber, AFormat, AFormatString);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TsWorksheet.WriteNumber(ACell: PCell; ANumber: Double;
|
||||||
|
AFormat: TsNumberFormat; AFormatString: String);
|
||||||
|
var
|
||||||
|
parser: TsNumFormatParser;
|
||||||
|
begin
|
||||||
|
if ACell <> nil then begin
|
||||||
|
parser := TsNumFormatParser.Create(Workbook, AFormatString);
|
||||||
try
|
try
|
||||||
// Format string ok?
|
// Format string ok?
|
||||||
if parser.Status <> psOK then
|
if parser.Status <> psOK then
|
||||||
raise Exception.Create(lpNoValidNumberFormatString);
|
raise Exception.Create(lpNoValidNumberFormatString);
|
||||||
if IsDateTimeFormat(parser.Builtin_NumFormat)
|
// Make sure that we do not write a date/time value here
|
||||||
|
if parser.IsDateTimeFormat
|
||||||
then raise Exception.Create(lpInvalidNumberFormat);
|
then raise Exception.Create(lpInvalidNumberFormat);
|
||||||
// If format string matches a built-in format use its format identifier,
|
// If format string matches a built-in format use its format identifier,
|
||||||
// All this is considered when calling Builtin_NumFormat of the parser.
|
// All this is considered when calling Builtin_NumFormat of the parser.
|
||||||
nf := parser.Builtin_NumFormat;
|
|
||||||
finally
|
finally
|
||||||
parser.Free;
|
parser.Free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
ACell := GetCell(ARow, ACol);
|
|
||||||
Include(ACell^.UsedFormattingFields, uffNumberFormat);
|
Include(ACell^.UsedFormattingFields, uffNumberFormat);
|
||||||
ACell^.ContentType := cctNumber;
|
ACell^.ContentType := cctNumber;
|
||||||
ACell^.NumberValue := ANumber;
|
ACell^.NumberValue := ANumber;
|
||||||
ACell^.NumberFormat := nf;
|
ACell^.NumberFormat := AFormat; //nfCustom;
|
||||||
ACell^.NumberFormatStr := AFormatString;
|
ACell^.NumberFormatStr := AFormatString;
|
||||||
ACell^.Decimals := 0;
|
|
||||||
ACell^.CurrencySymbol := '';
|
|
||||||
|
|
||||||
ChangedCell(ARow, ACol);
|
ChangedCell(ACell^.Row, ACell^.Col);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{@@
|
{@@
|
||||||
@ -1954,6 +1995,72 @@ begin
|
|||||||
ChangedCell(ARow, ACol);
|
ChangedCell(ARow, ACol);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{@@
|
||||||
|
Writes a currency value to a given cell. Its number format can be provided
|
||||||
|
optionally by specifying these parameters:
|
||||||
|
- ADecimals: number of decimals
|
||||||
|
- APosCurrFormat: code specifying the order of value, currency symbol and spaces
|
||||||
|
(see pcfXXXX constants above)
|
||||||
|
- ANegCurrFormat: code specifying the order of value, currency symbol, spaces
|
||||||
|
and how negative values are shown (see ncfXXXX constants above)
|
||||||
|
- ACurrencySymbol: the string to be shown as currency, such as '$', or 'EUR'
|
||||||
|
}
|
||||||
|
procedure TsWorksheet.WriteCurrency(ARow, ACol: Cardinal; AValue: Double;
|
||||||
|
AFormat: TsNumberFormat = nfCurrency; ADecimals: Integer = 2;
|
||||||
|
ACurrencySymbol: String = '?'; APosCurrFormat: Integer = -1;
|
||||||
|
ANegCurrFormat: Integer = -1);
|
||||||
|
begin
|
||||||
|
WriteCurrency(GetCell(ARow, ACol), AValue, AFormat, ADecimals, ACurrencySymbol,
|
||||||
|
APosCurrFormat, ANegCurrFormat);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TsWorksheet.WriteCurrency(ACell: PCell; AValue: Double;
|
||||||
|
AFormat: TsNumberFormat = nfCurrency; ADecimals: Integer = -1;
|
||||||
|
ACurrencySymbol: String = '?'; APosCurrFormat: Integer = -1;
|
||||||
|
ANegCurrFormat: Integer = -1);
|
||||||
|
var
|
||||||
|
fmt: String;
|
||||||
|
begin
|
||||||
|
if ADecimals = -1 then
|
||||||
|
ADecimals := Workbook.FormatSettings.CurrencyDecimals;
|
||||||
|
if APosCurrFormat = -1 then
|
||||||
|
APosCurrFormat := Workbook.FormatSettings.CurrencyFormat;
|
||||||
|
if ANegCurrFormat = -1 then
|
||||||
|
ANegCurrFormat := Workbook.FormatSettings.NegCurrFormat;
|
||||||
|
if ACurrencySymbol = '?' then
|
||||||
|
ACurrencySymbol := Workbook.FormatSettings.CurrencyString;
|
||||||
|
|
||||||
|
fmt := BuildCurrencyFormatString(
|
||||||
|
Workbook.FormatSettings,
|
||||||
|
ADecimals,
|
||||||
|
APosCurrFormat, ANegCurrFormat,
|
||||||
|
AFormat in [nfCurrencyRed, nfAccountingRed],
|
||||||
|
AFormat in [nfAccounting, nfAccountingRed],
|
||||||
|
ACurrencySymbol);
|
||||||
|
|
||||||
|
WriteCurrency(ACell, AValue, AFormat, fmt);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TsWorksheet.WriteCurrency(ARow, ACol: Cardinal; AValue: Double;
|
||||||
|
AFormat: TsNumberFormat; AFormatString: String);
|
||||||
|
begin
|
||||||
|
WriteCurrency(GetCell(ARow, ACol), AValue, AFormat, AFormatString);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TsWorksheet.WriteCurrency(ACell: PCell; AValue: Double;
|
||||||
|
AFormat: TsNumberFormat; AFormatString: String);
|
||||||
|
begin
|
||||||
|
if (ACell <> nil) and IsCurrencyFormat(AFormat) then begin
|
||||||
|
Include(ACell^.UsedFormattingFields, uffNumberFormat);
|
||||||
|
ACell^.ContentType := cctNumber;
|
||||||
|
ACell^.NumberValue := AValue;
|
||||||
|
ACell^.NumberFormat := AFormat;
|
||||||
|
ACell^.NumberFormatStr := AFormatString;
|
||||||
|
|
||||||
|
ChangedCell(ACell^.Row, ACell^.Col);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
{@@
|
{@@
|
||||||
Writes a date/time value to a determined cell
|
Writes a date/time value to a determined cell
|
||||||
|
|
||||||
@ -1962,24 +2069,23 @@ end;
|
|||||||
@param AValue The date/time/datetime to be written
|
@param AValue The date/time/datetime to be written
|
||||||
@param AFormat The format specifier, e.g. nfShortDate (optional)
|
@param AFormat The format specifier, e.g. nfShortDate (optional)
|
||||||
If not specified format is not changed.
|
If not specified format is not changed.
|
||||||
@param AFormatStr Format string, used only for nfFmtDateTime.
|
@param AFormatStr Format string, used only for nfCustom or nfTimeInterval.
|
||||||
Must follow the rules for "FormatDateTime", or use
|
|
||||||
"dm" as abbreviation for "d/mmm", "my" for "mmm/yy",
|
|
||||||
"ms" for "nn:ss", "msz" for "nn:ss.z" (optional)
|
|
||||||
or use any other free format (at your own risk...)
|
|
||||||
|
|
||||||
Note: at least Excel xls does not recognize a separate datetime cell type:
|
Note: at least Excel xls does not recognize a separate datetime cell type:
|
||||||
a datetime is stored as a (floating point) Number, and the cell is formatted
|
a datetime is stored as a (floating point) number, and the cell is formatted
|
||||||
as a date (either built-in or a custom format).
|
as a date (either built-in or a custom format).
|
||||||
}
|
}
|
||||||
procedure TsWorksheet.WriteDateTime(ARow, ACol: Cardinal; AValue: TDateTime;
|
procedure TsWorksheet.WriteDateTime(ARow, ACol: Cardinal; AValue: TDateTime;
|
||||||
AFormat: TsNumberFormat = nfGeneral; AFormatStr: String = '');
|
AFormat: TsNumberFormat = nfShortDateTime; AFormatStr: String = '');
|
||||||
begin
|
begin
|
||||||
WriteDateTime(GetCell(ARow, ACol), AValue, AFormat, AFormatStr);
|
WriteDateTime(GetCell(ARow, ACol), AValue, AFormat, AFormatStr);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TsWorksheet.WriteDateTime(ACell: PCell; AValue: TDateTime;
|
procedure TsWorksheet.WriteDateTime(ACell: PCell; AValue: TDateTime;
|
||||||
AFormat: TsNumberFormat = nfGeneral; AFormatStr: String = '');
|
AFormat: TsNumberFormat = nfShortDateTime; AFormatStr: String = '');
|
||||||
|
var
|
||||||
|
parser: TsNumFormatParser;
|
||||||
|
nf: TsNumberFormat;
|
||||||
begin
|
begin
|
||||||
if ACell <> nil then begin
|
if ACell <> nil then begin
|
||||||
ACell^.ContentType := cctDateTime;
|
ACell^.ContentType := cctDateTime;
|
||||||
@ -1988,10 +2094,28 @@ begin
|
|||||||
// Date/time is actually a number field in Excel.
|
// Date/time is actually a number field in Excel.
|
||||||
// To make sure it gets saved correctly, set a date format (instead of General).
|
// To make sure it gets saved correctly, set a date format (instead of General).
|
||||||
// The user can choose another date format if he wants to
|
// The user can choose another date format if he wants to
|
||||||
if IsDateTimeFormat(AFormat) then
|
|
||||||
if (AFormat in [nfFmtDateTime, nfTimeInterval]) then
|
if AFormatStr = '' then
|
||||||
AFormatStr := BuildDateTimeFormatString(AFormat, Workbook.FormatSettings, AFormatStr);
|
AFormatStr := BuildDateTimeFormatString(AFormat, Workbook.FormatSettings, AFormatStr);
|
||||||
|
|
||||||
|
// Check whether the formatstring is for date/times.
|
||||||
|
if AFormatStr <> '' then begin
|
||||||
|
parser := TsNumFormatParser.Create(Workbook, AFormatStr);
|
||||||
|
try
|
||||||
|
// Format string ok?
|
||||||
|
if parser.Status <> psOK then
|
||||||
|
raise Exception.Create(lpNoValidNumberFormatString);
|
||||||
|
// Make sure that we do not use a number format for date/times values.
|
||||||
|
if not parser.IsDateTimeFormat
|
||||||
|
then raise Exception.Create(lpInvalidDateTimeFormat);
|
||||||
|
// Avoid possible duplication of standard formats
|
||||||
|
if AFormat = nfCustom then
|
||||||
|
AFormat := parser.NumFormat;
|
||||||
|
finally
|
||||||
|
parser.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
Include(ACell^.UsedFormattingFields, uffNumberFormat);
|
Include(ACell^.UsedFormattingFields, uffNumberFormat);
|
||||||
ACell^.NumberFormat := AFormat;
|
ACell^.NumberFormat := AFormat;
|
||||||
ACell^.NumberFormatStr := AFormatStr;
|
ACell^.NumberFormatStr := AFormatStr;
|
||||||
@ -1999,24 +2123,42 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TsWorksheet.WriteDateTime(ARow, ACol: Cardinal; AValue: TDateTime;
|
||||||
|
AFormatStr: String);
|
||||||
|
begin
|
||||||
|
WriteDateTime(GetCell(ARow, ACol), AValue, AFormatStr);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TsWorksheet.WriteDateTime(ACell: PCell; AValue: TDateTime;
|
||||||
|
AFormatStr: String);
|
||||||
|
begin
|
||||||
|
WriteDateTime(ACell, AValue, nfCustom, AFormatStr);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TsWorksheet.WriteDecimals(ARow, ACol: Cardinal; ADecimals: Byte);
|
procedure TsWorksheet.WriteDecimals(ARow, ACol: Cardinal; ADecimals: Byte);
|
||||||
begin
|
begin
|
||||||
WriteDecimals(FindCell(ARow, ACol), ADecimals);
|
WriteDecimals(FindCell(ARow, ACol), ADecimals);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TsWorksheet.WriteDecimals(ACell: PCell; ADecimals: Byte);
|
procedure TsWorksheet.WriteDecimals(ACell: PCell; ADecimals: Byte);
|
||||||
|
var
|
||||||
|
parser: TsNumFormatParser;
|
||||||
begin
|
begin
|
||||||
if (ACell <> nil) and (ACell^.ContentType = cctNumber) and (ACell^.NumberFormat <> nfCustom)
|
if (ACell <> nil) and (ACell^.ContentType = cctNumber) and (ACell^.NumberFormat <> nfCustom)
|
||||||
then begin
|
then begin
|
||||||
ACell^.Decimals := ADecimals;
|
parser := TsNumFormatParser.Create(Workbook, ACell^.NumberFormatStr);
|
||||||
ACell^.NumberFormatStr := BuildNumberFormatString(ACell^.NumberFormat,
|
try
|
||||||
FWorkbook.FormatSettings, ADecimals, ACell^.CurrencySymbol);
|
parser.Decimals := ADecimals;
|
||||||
|
ACell^.NumberFormatStr := parser.FormatString[nfdDefault];
|
||||||
|
finally
|
||||||
|
parser.Free;
|
||||||
|
end;
|
||||||
ChangedCell(ACell^.Row, ACell^.Col);
|
ChangedCell(ACell^.Row, ACell^.Col);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{@@
|
{@@
|
||||||
Writes a cell with an error.
|
Writes a cell with an error value.
|
||||||
|
|
||||||
@param ARow The row of the cell
|
@param ARow The row of the cell
|
||||||
@param ACol The column of the cell
|
@param ACol The column of the cell
|
||||||
@ -2037,7 +2179,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
{@@
|
{@@
|
||||||
Writes a formula to a determined cell
|
Writes a formula to a given cell
|
||||||
|
|
||||||
@param ARow The row of the cell
|
@param ARow The row of the cell
|
||||||
@param ACol The column of the cell
|
@param ACol The column of the cell
|
||||||
@ -2080,8 +2222,7 @@ begin
|
|||||||
Include(ACell^.UsedFormattingFields, uffNumberFormat);
|
Include(ACell^.UsedFormattingFields, uffNumberFormat);
|
||||||
ACell^.NumberFormat := ANumberFormat;
|
ACell^.NumberFormat := ANumberFormat;
|
||||||
if (AFormatString = '') then
|
if (AFormatString = '') then
|
||||||
ACell^.NumberFormatStr := BuildNumberFormatString(ANumberFormat,
|
ACell^.NumberFormatStr := BuildNumberFormatString(ANumberFormat, Workbook.FormatSettings)
|
||||||
Workbook.FormatSettings, ACell^.Decimals, ACell^.CurrencySymbol)
|
|
||||||
else
|
else
|
||||||
ACell^.NumberFormatStr := AFormatString;
|
ACell^.NumberFormatStr := AFormatString;
|
||||||
ChangedCell(ACell^.Row, ACell^.Col);
|
ChangedCell(ACell^.Row, ACell^.Col);
|
||||||
@ -2521,6 +2662,8 @@ begin
|
|||||||
FDefaultColWidth := 12;
|
FDefaultColWidth := 12;
|
||||||
FDefaultRowHeight := 1;
|
FDefaultRowHeight := 1;
|
||||||
FormatSettings := DefaultFormatSettings;
|
FormatSettings := DefaultFormatSettings;
|
||||||
|
FormatSettings.ShortDateFormat := MakeShortDateFormat(FormatSettings.ShortDateFormat);
|
||||||
|
FormatSettings.LongDateFormat := MakeLongDateFormat(FormatSettings.ShortDateFormat);
|
||||||
FFontList := TFPList.Create;
|
FFontList := TFPList.Create;
|
||||||
SetDefaultFont('Arial', 10.0);
|
SetDefaultFont('Arial', 10.0);
|
||||||
InitFonts;
|
InitFonts;
|
||||||
@ -3194,8 +3337,7 @@ end;
|
|||||||
{ Adds a new number format data to the list and returns the list index of the
|
{ Adds a new number format data to the list and returns the list index of the
|
||||||
new item. }
|
new item. }
|
||||||
function TsCustomNumFormatList.AddFormat(AFormatIndex: Integer;
|
function TsCustomNumFormatList.AddFormat(AFormatIndex: Integer;
|
||||||
AFormatName, AFormatString: String; ANumFormat: TsNumberFormat;
|
AFormatName, AFormatString: String; ANumFormat: TsNumberFormat): Integer;
|
||||||
ADecimals: Byte = 0; ACurrencySymbol: String = ''): Integer;
|
|
||||||
var
|
var
|
||||||
item: TsNumFormatData;
|
item: TsNumFormatData;
|
||||||
begin
|
begin
|
||||||
@ -3203,45 +3345,31 @@ begin
|
|||||||
item.Index := AFormatIndex;
|
item.Index := AFormatIndex;
|
||||||
item.Name := AFormatName;
|
item.Name := AFormatName;
|
||||||
item.NumFormat := ANumFormat;
|
item.NumFormat := ANumFormat;
|
||||||
if AFormatString = '' then begin
|
|
||||||
if IsDateTimeFormat(ANumFormat) then
|
|
||||||
AFormatString := BuildDateTimeFormatString(ANumFormat, Workbook.FormatSettings,
|
|
||||||
AFormatString)
|
|
||||||
else
|
|
||||||
AFormatString := BuildNumberFormatString(ANumFormat, Workbook.FormatSettings,
|
|
||||||
ADecimals, ACurrencySymbol);
|
|
||||||
end;
|
|
||||||
item.FormatString := AFormatString;
|
item.FormatString := AFormatString;
|
||||||
item.Decimals := ADecimals;
|
|
||||||
item.CurrencySymbol := ACurrencySymbol;
|
|
||||||
Result := inherited Add(item);
|
Result := inherited Add(item);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsCustomNumFormatList.AddFormat(AFormatIndex: Integer;
|
function TsCustomNumFormatList.AddFormat(AFormatIndex: Integer;
|
||||||
AFormatString: String; ANumFormat: TsNumberFormat; ADecimals: byte = 0;
|
AFormatString: String; ANumFormat: TsNumberFormat): integer;
|
||||||
ACurrencySymbol: String = ''): integer;
|
|
||||||
begin
|
begin
|
||||||
Result := AddFormat(AFormatIndex, '', AFormatString, ANumFormat, ADecimals, ACurrencySymbol);
|
Result := AddFormat(AFormatIndex, '', AFormatString, ANumFormat);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsCustomNumFormatList.AddFormat(AFormatName, AFormatString: String;
|
function TsCustomNumFormatList.AddFormat(AFormatName, AFormatString: String;
|
||||||
ANumFormat: TsNumberFormat; ADecimals: Byte = 0;
|
ANumFormat: TsNumberFormat): Integer;
|
||||||
ACurrencySymbol: String = ''): Integer;
|
|
||||||
begin
|
begin
|
||||||
if (AFormatString = '') and (ANumFormat <> nfGeneral) then begin
|
if (AFormatString = '') and (ANumFormat <> nfGeneral) then begin
|
||||||
Result := 0;
|
Result := 0;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
Result := AddFormat(FNextFormatIndex, AFormatName, AFormatString, ANumFormat,
|
Result := AddFormat(FNextFormatIndex, AFormatName, AFormatString, ANumFormat);
|
||||||
ADecimals, ACurrencySymbol);
|
|
||||||
inc(FNextFormatIndex);
|
inc(FNextFormatIndex);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsCustomNumFormatList.AddFormat(AFormatString: String;
|
function TsCustomNumFormatList.AddFormat(AFormatString: String;
|
||||||
ANumFormat: TsNumberFormat; ADecimals: Byte = 0;
|
ANumFormat: TsNumberFormat): Integer;
|
||||||
ACurrencySymbol: String = ''): Integer;
|
|
||||||
begin
|
begin
|
||||||
Result := AddFormat('', AFormatString, ANumFormat, ADecimals, ACurrencySymbol);
|
Result := AddFormat('', AFormatString, ANumFormat);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsCustomNumFormatList.AddFormat(AFormatCell: PCell): Integer;
|
function TsCustomNumFormatList.AddFormat(AFormatCell: PCell): Integer;
|
||||||
@ -3256,9 +3384,7 @@ begin
|
|||||||
|
|
||||||
Result := AddFormat(FNextFormatIndex,
|
Result := AddFormat(FNextFormatIndex,
|
||||||
AFormatCell^.NumberFormatStr,
|
AFormatCell^.NumberFormatStr,
|
||||||
AFormatCell^.NumberFormat,
|
AFormatCell^.NumberFormat
|
||||||
AFormatCell^.Decimals,
|
|
||||||
AFormatCell^.CurrencySymbol
|
|
||||||
);
|
);
|
||||||
|
|
||||||
inc(FNextFormatIndex);
|
inc(FNextFormatIndex);
|
||||||
@ -3283,8 +3409,7 @@ end;
|
|||||||
overridden method which known more about the details of the spreadsheet file
|
overridden method which known more about the details of the spreadsheet file
|
||||||
format. }
|
format. }
|
||||||
procedure TsCustomNumFormatList.ConvertAfterReading(AFormatIndex: Integer;
|
procedure TsCustomNumFormatList.ConvertAfterReading(AFormatIndex: Integer;
|
||||||
var AFormatString: String; var ANumFormat: TsNumberFormat;
|
var AFormatString: String; var ANumFormat: TsNumberFormat);
|
||||||
var ADecimals: Byte; var ACurrencySymbol: String);
|
|
||||||
var
|
var
|
||||||
parser: TsNumFormatParser;
|
parser: TsNumFormatParser;
|
||||||
fmt: String;
|
fmt: String;
|
||||||
@ -3302,44 +3427,27 @@ begin
|
|||||||
nf := nfGeneral;
|
nf := nfGeneral;
|
||||||
|
|
||||||
// Analyzes the format string and tries to convert it to fpSpreadsheet format.
|
// Analyzes the format string and tries to convert it to fpSpreadsheet format.
|
||||||
parser := TsNumFormatParser.Create(Workbook, fmt, nf, cdToFPSpreadsheet);
|
parser := TsNumFormatParser.Create(Workbook, fmt); //, nf, cdToFPSpreadsheet);
|
||||||
try
|
try
|
||||||
if parser.Status = psOK then begin
|
if parser.Status = psOK then begin
|
||||||
ANumFormat := parser.Builtin_NumFormat;
|
ANumFormat := parser.NumFormat;
|
||||||
AFormatString := parser.FormatString; // This is the converted string.
|
AFormatString := parser.FormatString[nfdDefault];
|
||||||
if ANumFormat <> nfCustom then begin
|
|
||||||
ADecimals := parser.ParsedSections[0].Decimals;
|
|
||||||
ACurrencySymbol := parser.ParsedSections[0].CurrencySymbol;
|
|
||||||
end else begin
|
end else begin
|
||||||
ADecimals := 0;
|
// Show an error here?
|
||||||
ACurrencySymbol := '';
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
finally
|
finally
|
||||||
parser.Free;
|
parser.Free;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Is called before collection all number formats of the spreadsheet and before
|
{ Is called before collecting all number formats of the spreadsheet and before
|
||||||
writing to file. Its purpose is to convert the format string as used by fpc
|
writing to file. Its purpose is to convert the format string as used by fpc
|
||||||
to a format compatible with the spreadsheet file format. }
|
to a format compatible with the spreadsheet file format.
|
||||||
|
Nothing is changed here. The method needs to be overridden. }
|
||||||
procedure TsCustomNumFormatList.ConvertBeforeWriting(var AFormatString: String;
|
procedure TsCustomNumFormatList.ConvertBeforeWriting(var AFormatString: String;
|
||||||
var ANumFormat: TsNumberFormat; var ADecimals: Byte; var ACurrencySymbol: String);
|
var ANumFormat: TsNumberFormat; var ADecimals: Byte; var ACurrencySymbol: String);
|
||||||
var
|
|
||||||
parser: TsNumFormatParser;
|
|
||||||
fmt: String;
|
|
||||||
begin
|
begin
|
||||||
parser := TsNumFormatParser.Create(Workbook, AFormatString, ANumFormat, cdFromFPSpreadsheet);
|
// nothing to do here. But see, e.g., xlscommon.TsBIFFNumFormatList
|
||||||
try
|
|
||||||
if parser.Status = psOK then begin
|
|
||||||
AFormatString := parser.FormatString;
|
|
||||||
ANumFormat := parser.Builtin_NumFormat;
|
|
||||||
ADecimals := parser.ParsedSections[0].Decimals;
|
|
||||||
ACurrencySymbol := parser.ParsedSections[0].CurrencySymbol;
|
|
||||||
end;
|
|
||||||
finally
|
|
||||||
parser.Free;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Called from the reader when a format item has been read from the file.
|
{ Called from the reader when a format item has been read from the file.
|
||||||
@ -3357,10 +3465,10 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
|
|
||||||
// Analyze & convert the format string, extract infos for internal formatting
|
// Analyze & convert the format string, extract infos for internal formatting
|
||||||
ConvertAfterReading(AFormatIndex, AFormatString, nf, decs, currsym);
|
ConvertAfterReading(AFormatIndex, AFormatString, nf);
|
||||||
|
|
||||||
// Add the new item
|
// Add the new item
|
||||||
AddFormat(AFormatIndex, AFormatString, nf, decs, currSym);
|
AddFormat(AFormatIndex, AFormatString, nf);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Clears the list and frees memory occupied by the format items. }
|
{ Clears the list and frees memory occupied by the format items. }
|
||||||
@ -3383,65 +3491,14 @@ end;
|
|||||||
{ Seeks a format item with the given properties and returns its list index,
|
{ Seeks a format item with the given properties and returns its list index,
|
||||||
or -1 if not found. }
|
or -1 if not found. }
|
||||||
function TsCustomNumFormatList.Find(ANumFormat: TsNumberFormat;
|
function TsCustomNumFormatList.Find(ANumFormat: TsNumberFormat;
|
||||||
AFormatString: String; ADecimals: Byte; ACurrencySymbol: String): Integer;
|
AFormatString: String): Integer;
|
||||||
var
|
var
|
||||||
item: TsNumFormatData;
|
item: TsNumFormatData;
|
||||||
fmt: String;
|
|
||||||
itemfmt: String;
|
|
||||||
begin
|
begin
|
||||||
if (ANumFormat = nfFmtDateTime) then begin
|
|
||||||
fmt := lowercase(AFormatString);
|
|
||||||
for Result := Count-1 downto 0 do begin
|
for Result := Count-1 downto 0 do begin
|
||||||
item := Items[Result];
|
item := Items[Result];
|
||||||
if (item <> nil) and (item.NumFormat = nfFmtDateTime) then begin
|
if (item <> nil) and (item.NumFormat = ANumFormat) and (item.FormatString = AFormatString)
|
||||||
itemfmt := lowercase(item.FormatString);
|
then exit;
|
||||||
if ((itemfmt = 'dm') or (itemfmt = 'd-mmm') or (itemfmt = 'd mmm') or (itemfmt = 'd. mmm') or (itemfmt ='d/mmm'))
|
|
||||||
and ((fmt = 'dm') or (fmt = 'd-mmm') or (fmt = 'd mmm') or (fmt = 'd. mmm') or (fmt = 'd/mmm'))
|
|
||||||
then
|
|
||||||
exit;
|
|
||||||
if ((itemfmt = 'my') or (itemfmt = 'mmm-yy') or (itemfmt = 'mmm yyy') or (itemfmt = 'mmm/yy'))
|
|
||||||
and ((fmt = 'my') or (fmt = 'mmm-yy') or (fmt = 'mmm yy') or (fmt = 'mmm/yy'))
|
|
||||||
then
|
|
||||||
exit;
|
|
||||||
if ((itemfmt = 'ms') or (itemfmt = 'nn:ss') or (itemfmt = 'mm:ss'))
|
|
||||||
and ((fmt = 'ms') or (fmt = 'nn:ss') or (fmt = 'mm:ss'))
|
|
||||||
then
|
|
||||||
exit;
|
|
||||||
if ((itemfmt = 'msz') or (itemfmt = 'mm:ss.z') or (itemfmt = 'mm:ss.0'))
|
|
||||||
and ((fmt = 'msz') or (fmt = 'mm:ss.z') or (fmt = 'mm:ss.0'))
|
|
||||||
then
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
for Result := 0 to Count-1 do begin
|
|
||||||
item := Items[Result];
|
|
||||||
if fmt = lowercase(item.FormatString) then
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
// Check only the format string for nfCustom.
|
|
||||||
if (ANumFormat = nfCustom) then
|
|
||||||
for Result := Count-1 downto 0 do begin
|
|
||||||
item := Items[Result];
|
|
||||||
if (item <> nil)
|
|
||||||
and (item.NumFormat = ANumFormat)
|
|
||||||
and (item.FormatString = AFormatString)
|
|
||||||
then
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
// The other formats can carry additional information
|
|
||||||
for Result := Count-1 downto 0 do begin
|
|
||||||
item := Items[Result];
|
|
||||||
if (item <> nil)
|
|
||||||
and (item.NumFormat = ANumFormat)
|
|
||||||
and (item.FormatString = AFormatString)
|
|
||||||
and (item.Decimals = ADecimals)
|
|
||||||
and (not (item.NumFormat in [nfCurrency, nfCurrencyRed, nfAccounting, nfAccountingRed])
|
|
||||||
or (item.CurrencySymbol = ACurrencySymbol))
|
|
||||||
then
|
|
||||||
exit;
|
|
||||||
end;
|
end;
|
||||||
Result := -1;
|
Result := -1;
|
||||||
end;
|
end;
|
||||||
@ -3499,19 +3556,25 @@ begin
|
|||||||
if AFormatCell = nil then
|
if AFormatCell = nil then
|
||||||
Result := -1
|
Result := -1
|
||||||
else
|
else
|
||||||
Result := Find(AFormatCell^.NumberFormat, AFormatCell^.NumberFormatStr,
|
Result := Find(AFormatCell^.NumberFormat, AFormatCell^.NumberFormatStr);
|
||||||
AFormatCell^.Decimals, AFormatCell^.CurrencySymbol);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Determines the format string to be written into the spreadsheet file.
|
{ Determines the format string to be written into the spreadsheet file. Calls
|
||||||
Needs to be overridden if the format strings are different from the fpc
|
ConvertBeforeWriting in order to convert the fpc format strings to the dialect
|
||||||
convention. }
|
used in the file. }
|
||||||
function TsCustomNumFormatList.FormatStringForWriting(AIndex: Integer): String;
|
function TsCustomNumFormatList.FormatStringForWriting(AIndex: Integer): String;
|
||||||
var
|
var
|
||||||
item: TsNumFormatdata;
|
item: TsNumFormatdata;
|
||||||
|
nf: TsNumberFormat;
|
||||||
|
decs: Byte;
|
||||||
|
cs: String;
|
||||||
begin
|
begin
|
||||||
item := Items[AIndex];
|
item := Items[AIndex];
|
||||||
if item <> nil then Result := item.FormatString else Result := '';
|
if item <> nil then begin
|
||||||
|
Result := item.FormatString;
|
||||||
|
ConvertBeforeWriting(Result, nf, decs, cs);
|
||||||
|
end else
|
||||||
|
Result := '';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsCustomNumFormatList.GetItem(AIndex: Integer): TsNumFormatData;
|
function TsCustomNumFormatList.GetItem(AIndex: Integer): TsNumFormatData;
|
||||||
@ -3641,14 +3704,14 @@ end;
|
|||||||
}
|
}
|
||||||
function TsCustomSpreadWriter.FindFormattingInList(AFormat: PCell): Integer;
|
function TsCustomSpreadWriter.FindFormattingInList(AFormat: PCell): Integer;
|
||||||
var
|
var
|
||||||
i: Integer;
|
i, n: Integer;
|
||||||
b: TsCellBorder;
|
b: TsCellBorder;
|
||||||
equ: Boolean;
|
equ: Boolean;
|
||||||
begin
|
begin
|
||||||
Result := -1;
|
Result := -1;
|
||||||
|
|
||||||
for i := Length(FFormattingStyles) - 1 downto 0 do
|
n := Length(FFormattingStyles);
|
||||||
begin
|
for i := n - 1 downto 0 do begin
|
||||||
if (FFormattingStyles[i].UsedFormattingFields <> AFormat^.UsedFormattingFields) then Continue;
|
if (FFormattingStyles[i].UsedFormattingFields <> AFormat^.UsedFormattingFields) then Continue;
|
||||||
|
|
||||||
if uffHorAlign in AFormat^.UsedFormattingFields then
|
if uffHorAlign in AFormat^.UsedFormattingFields then
|
||||||
@ -3683,18 +3746,7 @@ begin
|
|||||||
|
|
||||||
if uffNumberFormat in AFormat^.UsedFormattingFields then begin
|
if uffNumberFormat in AFormat^.UsedFormattingFields then begin
|
||||||
if (FFormattingStyles[i].NumberFormat <> AFormat^.NumberFormat) then Continue;
|
if (FFormattingStyles[i].NumberFormat <> AFormat^.NumberFormat) then Continue;
|
||||||
case AFormat^.NumberFormat of
|
if (FFormattingStyles[i].NumberFormatStr <> AFormat^.NumberFormatStr) then Continue;
|
||||||
nfFixed, nfFixedTh, nfPercentage, nfExp, nfSci:
|
|
||||||
if (FFormattingStyles[i].Decimals <> AFormat^.Decimals) then Continue;
|
|
||||||
nfCurrency, nfCurrencyRed, nfAccounting, nfAccountingRed:
|
|
||||||
begin
|
|
||||||
if (FFormattingStyles[i].Decimals <> AFormat^.Decimals) then Continue;
|
|
||||||
if (FFormattingStyles[i].CurrencySymbol <> AFormat^.CurrencySymbol) then Continue;
|
|
||||||
end;
|
|
||||||
nfShortDateTime, nfShortDate, nfLongDate, nfShortTime, nfLongTime,
|
|
||||||
nfShortTimeAM, nfLongTimeAM, nfFmtDateTime, nfTimeInterval, nfCustom:
|
|
||||||
if (FFormattingstyles[i].NumberFormatStr <> AFormat^.NumberFormatStr) then Continue;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if uffFont in AFormat^.UsedFormattingFields then
|
if uffFont in AFormat^.UsedFormattingFields then
|
||||||
@ -3740,23 +3792,6 @@ begin
|
|||||||
SetLength(FFormattingStyles, Len+1);
|
SetLength(FFormattingStyles, Len+1);
|
||||||
FFormattingStyles[Len] := ACell^;
|
FFormattingStyles[Len] := ACell^;
|
||||||
|
|
||||||
// Some built-in number formats do not write the format string to the cell
|
|
||||||
// But the FormattingStyles need it for comparison later. --> Add the format string.
|
|
||||||
if IsDateTimeFormat(FFormattingStyles[Len].NumberFormat) then
|
|
||||||
FFormattingStyles[Len].NumberFormatStr := BuildDateTimeFormatString(
|
|
||||||
FFormattingStyles[Len].NumberFormat,
|
|
||||||
Workbook.FormatSettings,
|
|
||||||
FFormattingStyles[Len].NumberFormatStr
|
|
||||||
)
|
|
||||||
else
|
|
||||||
if FFormattingStyles[Len].NumberFormat <> nfCustom then
|
|
||||||
FFormattingstyles[Len].NumberFormatStr := BuildNumberFormatString(
|
|
||||||
FFormattingStyles[Len].NumberFormat,
|
|
||||||
Workbook.FormatSettings,
|
|
||||||
FFormattingStyles[Len].Decimals,
|
|
||||||
FFormattingStyles[Len].CurrencySymbol
|
|
||||||
);
|
|
||||||
|
|
||||||
// We store the index of the XF record that will be assigned to this style in
|
// We store the index of the XF record that will be assigned to this style in
|
||||||
// the "row" of the style. Will be needed when writing the XF record.
|
// the "row" of the style. Will be needed when writing the XF record.
|
||||||
FFormattingStyles[Len].Row := NextXFIndex;
|
FFormattingStyles[Len].Row := NextXFIndex;
|
||||||
@ -3776,6 +3811,7 @@ begin
|
|||||||
for i := 0 to Workbook.GetWorksheetCount - 1 do
|
for i := 0 to Workbook.GetWorksheetCount - 1 do
|
||||||
IterateThroughCells(nil, Workbook.GetWorksheetByIndex(i).Cells, ListAllFormattingStylesCallback);
|
IterateThroughCells(nil, Workbook.GetWorksheetByIndex(i).Cells, ListAllFormattingStylesCallback);
|
||||||
|
|
||||||
|
(*
|
||||||
// Convert the numberformats of the collected styles to be compatible with the destination file
|
// Convert the numberformats of the collected styles to be compatible with the destination file
|
||||||
for i:=0 to High(FFormattingStyles) do
|
for i:=0 to High(FFormattingStyles) do
|
||||||
if (FFormattingStyles[i].NumberFormatStr <> '') and
|
if (FFormattingStyles[i].NumberFormatStr <> '') and
|
||||||
@ -3787,6 +3823,7 @@ begin
|
|||||||
FFormattingStyles[i].Decimals,
|
FFormattingStyles[i].Decimals,
|
||||||
FFormattingStyles[i].CurrencySymbol
|
FFormattingStyles[i].CurrencySymbol
|
||||||
);
|
);
|
||||||
|
*)
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{@@
|
{@@
|
||||||
@ -3797,37 +3834,25 @@ procedure TsCustomSpreadWriter.ListAllNumFormatsCallback(ACell: PCell; AStream:
|
|||||||
var
|
var
|
||||||
fmt: string;
|
fmt: string;
|
||||||
nf: TsNumberFormat;
|
nf: TsNumberFormat;
|
||||||
decs: Byte;
|
|
||||||
cs: String;
|
|
||||||
begin
|
begin
|
||||||
if ACell^.NumberFormat = nfGeneral then
|
if ACell^.NumberFormat = nfGeneral then
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
// The builtin format list is in "file syntax", but the format string of the
|
// The builtin format list is in fpc dialect.
|
||||||
// cells are in "fpc syntax". Therefore, before seeking, we have to convert
|
|
||||||
// the format string of the cell to "file syntax".
|
|
||||||
fmt := ACell^.NumberFormatStr;
|
fmt := ACell^.NumberFormatStr;
|
||||||
nf := ACell^.NumberFormat;
|
nf := ACell^.NumberFormat;
|
||||||
decs := ACell^.Decimals;
|
|
||||||
cs := ACell^.CurrencySymbol;
|
|
||||||
if (nf <> nfCustom) then begin
|
|
||||||
if IsDateTimeFormat(nf) then
|
|
||||||
fmt := BuildDateTimeFormatString(nf, Workbook.FormatSettings, fmt)
|
|
||||||
else
|
|
||||||
fmt := BuildNumberFormatString(nf, Workbook.FormatSettings, decs, cs);
|
|
||||||
FNumFormatList.ConvertBeforeWriting(fmt, nf, decs, cs);
|
|
||||||
end;
|
|
||||||
|
|
||||||
// Seek the format string in the current number format list.
|
// Seek the format string in the current number format list.
|
||||||
// If not found add the format to the list.
|
// If not found add the format to the list.
|
||||||
if FNumFormatList.Find(fmt) = -1 then
|
if FNumFormatList.Find(nf, fmt) = -1 then
|
||||||
FNumFormatList.AddFormat(fmt, nf, decs, cs);
|
FNumFormatList.AddFormat(fmt, nf);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{@@
|
{@@
|
||||||
Iterats through all cells and collects the number formats in
|
Iterates through all cells and collects the number formats in
|
||||||
FNumFormatList (without duplicates).
|
FNumFormatList (without duplicates).
|
||||||
The index of the list item is needed for the field FormatIndex of the XF record. }
|
The index of the list item is needed for the field FormatIndex of the XF record.
|
||||||
|
At the time when the method is called the formats are still in fpc dialect. }
|
||||||
procedure TsCustomSpreadWriter.ListAllNumFormats;
|
procedure TsCustomSpreadWriter.ListAllNumFormats;
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
|
@ -70,22 +70,23 @@ function IfThen(ACondition: Boolean; AValue1,AValue2: TsNumberFormat): TsNumberF
|
|||||||
|
|
||||||
function IsCurrencyFormat(AFormat: TsNumberFormat): Boolean;
|
function IsCurrencyFormat(AFormat: TsNumberFormat): Boolean;
|
||||||
function IsDateTimeFormat(AFormat: TsNumberFormat): Boolean; overload;
|
function IsDateTimeFormat(AFormat: TsNumberFormat): Boolean; overload;
|
||||||
function IsDateTimeFormat(AFormatStr: String): Boolean; overload;
|
//function IsDateTimeFormat(AFormatStr: String): Boolean; overload;
|
||||||
|
|
||||||
function BuildNumberFormatString(ANumberFormat: TsNumberFormat;
|
function BuildCurrencyFormatString(const AFormatSettings: TFormatSettings;
|
||||||
const AFormatSettings: TFormatSettings; ADecimals: Integer = -1;
|
ADecimals, APosCurrFormat, ANegCurrFormat: Integer;
|
||||||
ACurrencySymbol: String = '?'): String;
|
ANegativeValuesRed, AAccountingStyle: Boolean; ACurrencySymbol: String = '?'): String;
|
||||||
function BuildDateTimeFormatString(ANumberFormat: TsNumberFormat;
|
function BuildDateTimeFormatString(ANumberFormat: TsNumberFormat;
|
||||||
const AFormatSettings: TFormatSettings; AFormatString: String = ''): String;
|
const AFormatSettings: TFormatSettings; AFormatString: String = ''): String;
|
||||||
function BuildCurrencyFormatString(const AFormatSettings: TFormatSettings;
|
function BuildNumberFormatString(ANumberFormat: TsNumberFormat;
|
||||||
ADecimals: Integer; ANegativeValuesRed: Boolean; AAccountingStyle: Boolean;
|
const AFormatSettings: TFormatSettings; ADecimals: Integer = -1): String;
|
||||||
ACurrencySymbol: String = '?'): String;
|
|
||||||
|
|
||||||
function AddAMPM(const ATimeFormatString: String;
|
function AddAMPM(const ATimeFormatString: String;
|
||||||
const AFormatSettings: TFormatSettings): String;
|
const AFormatSettings: TFormatSettings): String;
|
||||||
function StripAMPM(const ATimeFormatString: String): String;
|
function StripAMPM(const ATimeFormatString: String): String;
|
||||||
function CountDecs(AFormatString: String; ADecChars: TsDecsChars = ['0']): Byte;
|
function CountDecs(AFormatString: String; ADecChars: TsDecsChars = ['0']): Byte;
|
||||||
function AddIntervalBrackets(AFormatString: String): String;
|
function AddIntervalBrackets(AFormatString: String): String;
|
||||||
|
function MakeLongDateFormat(AShortDateFormat: String): String;
|
||||||
|
function MakeShortDateFormat(AShortDateFormat: String): String;
|
||||||
function SpecialDateTimeFormat(ACode: String;
|
function SpecialDateTimeFormat(ACode: String;
|
||||||
const AFormatSettings: TFormatSettings; ForWriting: Boolean): String;
|
const AFormatSettings: TFormatSettings; ForWriting: Boolean): String;
|
||||||
function SplitAccountingFormatString(const AFormatString: String; ASection: ShortInt;
|
function SplitAccountingFormatString(const AFormatString: String; ASection: ShortInt;
|
||||||
@ -93,7 +94,8 @@ function SplitAccountingFormatString(const AFormatString: String; ASection: Shor
|
|||||||
procedure SplitFormatString(const AFormatString: String; out APositivePart,
|
procedure SplitFormatString(const AFormatString: String; out APositivePart,
|
||||||
ANegativePart, AZeroPart: String);
|
ANegativePart, AZeroPart: String);
|
||||||
|
|
||||||
function SciFloat(AValue: Double; ADecimals: Byte): String;
|
function SciFloat(AValue: Double; ADecimals: Byte): String; overload;
|
||||||
|
function SciFloat(AValue: Double; ADecimals: Byte; AFormatSettings: TFormatSettings): String; overload;
|
||||||
//function TimeIntervalToString(AValue: TDateTime; AFormatStr: String): String;
|
//function TimeIntervalToString(AValue: TDateTime; AFormatStr: String): String;
|
||||||
procedure MakeTimeIntervalMask(Src: String; var Dest: String);
|
procedure MakeTimeIntervalMask(Src: String; var Dest: String);
|
||||||
|
|
||||||
@ -563,53 +565,10 @@ end;
|
|||||||
{ Checks whether the given number format code is for date/times. }
|
{ Checks whether the given number format code is for date/times. }
|
||||||
function IsDateTimeFormat(AFormat: TsNumberFormat): Boolean;
|
function IsDateTimeFormat(AFormat: TsNumberFormat): Boolean;
|
||||||
begin
|
begin
|
||||||
Result := AFormat in [nfFmtDateTime, nfShortDateTime, nfShortDate, nfLongDate,
|
Result := AFormat in [{nfFmtDateTime, }nfShortDateTime, nfShortDate, nfLongDate,
|
||||||
nfShortTime, nfLongTime, nfShortTimeAM, nfLongTimeAM, nfTimeInterval];
|
nfShortTime, nfLongTime, nfShortTimeAM, nfLongTimeAM, nfTimeInterval];
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function IsDateTimeFormat(AFormatStr: string): Boolean;
|
|
||||||
var
|
|
||||||
P, PStart, PEnd: PChar;
|
|
||||||
token: Char;
|
|
||||||
begin
|
|
||||||
if AFormatStr = '' then
|
|
||||||
Result := false
|
|
||||||
else begin
|
|
||||||
PStart := PChar(@AFormatStr[1]);
|
|
||||||
PEnd := PStart + Length(AFormatStr);
|
|
||||||
P := PStart;
|
|
||||||
while P < PEnd do begin
|
|
||||||
token := P^;
|
|
||||||
case token of // Skip quoted text
|
|
||||||
'"': begin
|
|
||||||
inc(P);
|
|
||||||
token := P^;
|
|
||||||
while (P < PEnd) and (token <> '"') do begin
|
|
||||||
inc(P);
|
|
||||||
token := P^;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
{
|
|
||||||
'[': begin
|
|
||||||
inc(P);
|
|
||||||
token := P^;
|
|
||||||
while (P < PEnd) and (token <> ']') do begin
|
|
||||||
inc(P);
|
|
||||||
token := P^;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
}
|
|
||||||
'y', 'Y', 'm', 'M', 'd', 'D', 'h', 'H', 'n', 'N', 's', 'S', ':':
|
|
||||||
begin
|
|
||||||
Result := true;
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
inc(P);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ Builds a date/time format string from the numberformat code. If the format code
|
{ Builds a date/time format string from the numberformat code. If the format code
|
||||||
is nfFmtDateTime the given AFormatString is used. AFormatString can use the
|
is nfFmtDateTime the given AFormatString is used. AFormatString can use the
|
||||||
abbreviations "dm" (for "d/mmm"), "my" (for "mmm/yy"), "ms" (for "mm:ss")
|
abbreviations "dm" (for "d/mmm"), "my" (for "mmm/yy"), "ms" (for "mm:ss")
|
||||||
@ -620,8 +579,10 @@ var
|
|||||||
fmt: String;
|
fmt: String;
|
||||||
begin
|
begin
|
||||||
case ANumberFormat of
|
case ANumberFormat of
|
||||||
|
{
|
||||||
nfFmtDateTime:
|
nfFmtDateTime:
|
||||||
Result := SpecialDateTimeFormat(lowercase(AFormatString), AFormatSettings, false);
|
Result := SpecialDateTimeFormat(lowercase(AFormatString), AFormatSettings, false);
|
||||||
|
}
|
||||||
nfShortDateTime:
|
nfShortDateTime:
|
||||||
Result := AFormatSettings.ShortDateFormat + ' ' + AFormatSettings.ShortTimeFormat;
|
Result := AFormatSettings.ShortDateFormat + ' ' + AFormatSettings.ShortTimeFormat;
|
||||||
// In the DefaultFormatSettings this is: d/m/y hh:nn
|
// In the DefaultFormatSettings this is: d/m/y hh:nn
|
||||||
@ -664,41 +625,44 @@ end;
|
|||||||
This code has to be removed by StripAccountingSymbols before applying to
|
This code has to be removed by StripAccountingSymbols before applying to
|
||||||
FormatFloat. }
|
FormatFloat. }
|
||||||
function BuildCurrencyFormatString(const AFormatSettings: TFormatSettings;
|
function BuildCurrencyFormatString(const AFormatSettings: TFormatSettings;
|
||||||
ADecimals: Integer; ANegativeValuesRed: Boolean; AAccountingStyle: Boolean;
|
ADecimals, APosCurrFormat, ANegCurrFormat: Integer; ANegativeValuesRed: Boolean;
|
||||||
ACurrencySymbol: String = '?'): String;
|
AAccountingStyle: Boolean; ACurrencySymbol: String = '?'): String;
|
||||||
const
|
const
|
||||||
POS_FMT: array[0..3, boolean] of string = ( //0: value, 1: currency symbol
|
POS_FMT: array[0..3, boolean] of string = (
|
||||||
|
// Parameter 0 is "value", parameter 1 is "currency symbol"
|
||||||
|
// AccountingStyle = false --> 1st column, true --> 2nd column
|
||||||
('"%1:s"%0:s', '"%1:s"* %0:s'), // 0: $1
|
('"%1:s"%0:s', '"%1:s"* %0:s'), // 0: $1
|
||||||
('%0:s"%1:s"', '%0:s* "%1:s"'), // 1: 1$
|
('%0:s"%1:s"', '%0:s "%1:s"'), // 1: 1$
|
||||||
('"%1:s" %0:s', '"%1:s"* %0:s'), // 2: $ 1
|
('"%1:s" %0:s', '"%1:s"* %0:s'), // 2: $ 1
|
||||||
('%0:s "%1:s"', '%0:s* "%1:s"') // 3: 1 $
|
('%0:s "%1:s"', '%0:s "%1:s"') // 3: 1 $
|
||||||
);
|
);
|
||||||
NEG_FMT: array[0..15, boolean] of string = (
|
NEG_FMT: array[0..15, boolean] of string = (
|
||||||
('("%1:s"%0:s)', '"%1:s"* (%0:s)'), // 0: ($1)
|
('("%1:s"%0:s)', '"%1:s"* (%0:s)'), // 0: ($1)
|
||||||
('-"%1:s"%0:s', '"%1:s"* -%0:s'), // 1: -$1
|
('-"%1:s"%0:s', '-* "%1:s" %0:s'), // 1: -$1
|
||||||
('"%1:s"-%0:s', '"%1:s"* -%0:s'), // 2: $-1
|
('"%1:s"-%0:s', '"%1:s"* -%0:s'), // 2: $-1
|
||||||
('"%1:s"%0:s-', '"%1:s"* %0:s-'), // 3: $1-
|
('"%1:s"%0:s-', '"%1:s"%0:s-'), // 3: $1-
|
||||||
('(%0:s"%1:s")', '(%0:s)"%1:s"'), // 4: (1$)
|
('(%0:s"%1:s")', '(%0:s)%1:s"'), // 4: (1$)
|
||||||
('-%0:s"%1:s"', '-%0:s"%1:s"'), // 5: -1$
|
('-%0:s"%1:s"', '-* %0:s"%1:s"'), // 5: -1$
|
||||||
('%0:s-"%1:s"', '%0:s-"%1:s"'), // 6: 1-$
|
('%0:s-"%1:s"', '%0:s-"%1:s"'), // 6: 1-$
|
||||||
('%0:s"%1:s"-', '%0:s-"%1:s"'), // 7: 1$-
|
('%0:s"%1:s"-', '%0:s-"%1:s"'), // 7: 1$-
|
||||||
('-%0:s "%1:s"', '-%0:s"%1:s"'), // 8: -1 $
|
('-%0:s "%1:s"', '-* %0:s"%1:s"'), // 8: -1 $
|
||||||
('-"%1:s" %0:s', '"%1:s"* -%0:s'), // 9: -$ 1
|
('-"%1:s" %0:s', '-* "%1:s" -%0:s'), // 9: -$ 1
|
||||||
('%0:s "%1:s"-', '%0:s- "%1:s"'), // 10: 1 $-
|
('%0:s "%1:s"-', '%0:s- "%1:s"'), // 10: 1 $-
|
||||||
('"%1:s" %0:s-', '"%1:s"* %0:s-'), // 11: $ 1-
|
('"%1:s" %0:s-', '"%1:s"* %0:s-'), // 11: $ 1-
|
||||||
('"%1:s" -%0:s', '"%1:s"* -%0:s'), // 12: $ -1
|
('"%1:s" -%0:s', '"%1:s"* -%0:s'), // 12: $ -1
|
||||||
('%0:s- "%1:s"', '%0:s- "%1:s"'), // 13: 1- $
|
('%0:s- "%1:s"', '%0:s- "%1:s"'), // 13: 1- $
|
||||||
('("%1:s" %0:s)', '"%1:s"* (%0:s)'), // 14: ($ 1)
|
('("%1:s" %0:s)', '"%1:s"* (%0:s)'), // 14: ($ 1)
|
||||||
('(%0:s "%1:s")', '(%0:s) "%1:s"') // 15: (1 $)
|
('(%0:s "%1:s")', '(%0:s "%1:s")') // 15: (1 $)
|
||||||
);
|
);
|
||||||
var
|
var
|
||||||
decs: String;
|
decs: String;
|
||||||
cf, ncf: Byte;
|
cf, ncf: Byte;
|
||||||
p, n: String;
|
p, n: String;
|
||||||
begin
|
begin
|
||||||
cf := AFormatSettings.CurrencyFormat;
|
cf := IfThen(APosCurrFormat < 0, AFormatSettings.CurrencyFormat, APosCurrFormat);
|
||||||
ncf := AFormatSettings.NegCurrFormat;
|
ncf := IfThen(ANegCurrFormat < 0, AFormatSettings.NegCurrFormat, ANegCurrFormat);
|
||||||
if ADecimals < 0 then ADecimals := AFormatSettings.CurrencyDecimals;
|
if ADecimals < 0 then
|
||||||
|
ADecimals := AFormatSettings.CurrencyDecimals;
|
||||||
if ACurrencySymbol = '?' then
|
if ACurrencySymbol = '?' then
|
||||||
ACurrencySymbol := AnsiToUTF8(AFormatSettings.CurrencyString);
|
ACurrencySymbol := AnsiToUTF8(AFormatSettings.CurrencyString);
|
||||||
decs := DupeString('0', ADecimals);
|
decs := DupeString('0', ADecimals);
|
||||||
@ -717,7 +681,7 @@ begin
|
|||||||
|
|
||||||
if ACurrencySymbol <> '' then begin
|
if ACurrencySymbol <> '' then begin
|
||||||
Result := Format(p, ['#,##0' + decs, ACurrencySymbol]) + ';'
|
Result := Format(p, ['#,##0' + decs, ACurrencySymbol]) + ';'
|
||||||
+ Format(n, ['#,##0' + decs, ACurrencySymbol]) + ';'
|
+ IfThen(ANegativeValuesRed, '[red]', '') + Format(n, ['#,##0' + decs, ACurrencySymbol]) + ';'
|
||||||
+ Format(p, [IfThen(AAccountingStyle, '-', '0'+decs), ACurrencySymbol]);
|
+ Format(p, [IfThen(AAccountingStyle, '-', '0'+decs), ACurrencySymbol]);
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
@ -731,21 +695,16 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Builds a number format string from the numberformat code, the count of
|
{ Builds a number format string from the number format code, the count of
|
||||||
decimals, and the currencysymbol (if not empty). }
|
decimals, and the currencysymbol (if not empty). }
|
||||||
function BuildNumberFormatString(ANumberFormat: TsNumberFormat;
|
function BuildNumberFormatString(ANumberFormat: TsNumberFormat;
|
||||||
const AFormatSettings: TFormatSettings; ADecimals: Integer = -1;
|
const AFormatSettings: TFormatSettings; ADecimals: Integer = -1): String;
|
||||||
ACurrencySymbol: String = '?'): String;
|
|
||||||
var
|
var
|
||||||
decs: String;
|
decs: String;
|
||||||
cf, ncf: Byte;
|
|
||||||
begin
|
begin
|
||||||
Result := '';
|
Result := '';
|
||||||
cf := AFormatSettings.CurrencyFormat;
|
if ADecimals = -1 then
|
||||||
ncf := AFormatSettings.NegCurrFormat;
|
ADecimals := AFormatSettings.CurrencyDecimals;
|
||||||
if ADecimals = -1 then ADecimals := AFormatSettings.CurrencyDecimals;
|
|
||||||
if ACurrencySymbol = '?' then
|
|
||||||
ACurrencySymbol := AnsiToUTF8(AFormatSettings.CurrencyString);
|
|
||||||
decs := DupeString('0', ADecimals);
|
decs := DupeString('0', ADecimals);
|
||||||
if ADecimals > 0 then decs := '.' + decs;
|
if ADecimals > 0 then decs := '.' + decs;
|
||||||
case ANumberFormat of
|
case ANumberFormat of
|
||||||
@ -760,13 +719,12 @@ begin
|
|||||||
nfPercentage:
|
nfPercentage:
|
||||||
Result := '0' + decs + '%';
|
Result := '0' + decs + '%';
|
||||||
nfCurrency, nfCurrencyRed, nfAccounting, nfAccountingRed:
|
nfCurrency, nfCurrencyRed, nfAccounting, nfAccountingRed:
|
||||||
Result := BuildCurrencyFormatString(
|
raise Exception.Create('BuildNumberFormatString: Use BuildCurrencyFormatString '+
|
||||||
AFormatSettings,
|
'to create a format string for currency values.');
|
||||||
ADecimals,
|
nfShortDateTime, nfShortDate, nfLongDate, nfShortTime, nfLongTime,
|
||||||
ANumberFormat in [nfCurrencyRed, nfAccountingRed],
|
nfShortTimeAM, nfLongTimeAM, nfTimeInterval:
|
||||||
ANumberFormat in [nfAccounting, nfAccountingRed],
|
raise Exception.Create('BuildNumberFormatString: Use BuildDateTimeFormatSstring '+
|
||||||
ACurrencySymbol
|
'to create a format string for date/time values.');
|
||||||
);
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -802,12 +760,18 @@ var
|
|||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
Result := 0;
|
Result := 0;
|
||||||
for i:=Length(AFormatString) downto 1 do begin
|
i := 1;
|
||||||
if AFormatString[i] in ADecChars then inc(Result);
|
while (i <= Length(AFormatString)) do begin
|
||||||
if AFormatString[i] = '.' then exit;
|
if AFormatString[i] = '.' then begin
|
||||||
|
inc(i);
|
||||||
|
while (i <= Length(AFormatString)) and (AFormatString[i] in ADecChars) do begin
|
||||||
|
inc(i);
|
||||||
|
inc(Result);
|
||||||
|
end;
|
||||||
|
exit;
|
||||||
|
end else
|
||||||
|
inc(i);
|
||||||
end;
|
end;
|
||||||
// Comes to this point when there is no decimal separtor.
|
|
||||||
Result := 0;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ The given format string is assumed to be for time intervals, i.e. its first
|
{ The given format string is assumed to be for time intervals, i.e. its first
|
||||||
@ -831,6 +795,64 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ Creates a long date format string out of a short one. Retains the order of
|
||||||
|
year-month-day and the separators, but uses 4 digits for year and 3 digits of m }
|
||||||
|
function MakeLongDateFormat(AShortDateFormat: String): String;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
Result := '';
|
||||||
|
i := 1;
|
||||||
|
while i < Length(AShortDateFormat) do begin
|
||||||
|
case AShortDateFormat[i] of
|
||||||
|
'y', 'Y':
|
||||||
|
begin
|
||||||
|
Result := Result + DupeString(AShortDateFormat[i], 4);
|
||||||
|
while (i < Length(AShortDateFormat)) and (AShortDateFormat[i] in ['y','Y']) do
|
||||||
|
inc(i);
|
||||||
|
end;
|
||||||
|
'm', 'M':
|
||||||
|
begin
|
||||||
|
result := Result + DupeString(AShortDateFormat[i], 3);
|
||||||
|
while (i < Length(AShortDateFormat)) and (AShortDateFormat[i] in ['m','M']) do
|
||||||
|
inc(i);
|
||||||
|
end;
|
||||||
|
else
|
||||||
|
Result := Result + AShortDateFormat[i];
|
||||||
|
inc(i);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ Modifies the short date format such that it has a two-digit year and a two-digit
|
||||||
|
month. Retains the order of year-month-day and the separators. }
|
||||||
|
function MakeShortDateFormat(AShortDateFormat: String): String;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
Result := '';
|
||||||
|
i := 1;
|
||||||
|
while i < Length(AShortDateFormat) do begin
|
||||||
|
case AShortDateFormat[i] of
|
||||||
|
'y', 'Y':
|
||||||
|
begin
|
||||||
|
Result := Result + DupeString(AShortDateFormat[i], 2);
|
||||||
|
while (i < Length(AShortDateFormat)) and (AShortDateFormat[i] in ['y','Y']) do
|
||||||
|
inc(i);
|
||||||
|
end;
|
||||||
|
'm', 'M':
|
||||||
|
begin
|
||||||
|
result := Result + DupeString(AShortDateFormat[i], 2);
|
||||||
|
while (i < Length(AShortDateFormat)) and (AShortDateFormat[i] in ['m','M']) do
|
||||||
|
inc(i);
|
||||||
|
end;
|
||||||
|
else
|
||||||
|
Result := Result + AShortDateFormat[i];
|
||||||
|
inc(i);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
{ Creates the formatstrings for the date/time codes "dm", "my", "ms" and "msz"
|
{ Creates the formatstrings for the date/time codes "dm", "my", "ms" and "msz"
|
||||||
out of the formatsettings. }
|
out of the formatsettings. }
|
||||||
function SpecialDateTimeFormat(ACode: String;
|
function SpecialDateTimeFormat(ACode: String;
|
||||||
@ -991,23 +1013,30 @@ end;
|
|||||||
{ Formats the number AValue in "scientific" format with the given number of
|
{ Formats the number AValue in "scientific" format with the given number of
|
||||||
decimals. "Scientific" is the same as "exponential", but with exponents rounded
|
decimals. "Scientific" is the same as "exponential", but with exponents rounded
|
||||||
to multiples of 3 (like for "kilo" - "Mega" - "Giga" etc.). }
|
to multiples of 3 (like for "kilo" - "Mega" - "Giga" etc.). }
|
||||||
function SciFloat(AValue: Double; ADecimals: Byte): String;
|
function SciFloat(AValue: Double; ADecimals: Byte;
|
||||||
|
AFormatSettings: TFormatSettings): String;
|
||||||
var
|
var
|
||||||
m: Double;
|
m: Double;
|
||||||
ex: Integer;
|
ex: Integer;
|
||||||
begin
|
begin
|
||||||
if AValue = 0 then
|
if AValue = 0 then
|
||||||
Result := '0.0'
|
Result := Format('%0.*fE+0', [ADecimals, 0.0], AFormatSettings)
|
||||||
|
// Excel shows "000.0E+0", but I think the "0.0E+0" shown here is better.
|
||||||
else begin
|
else begin
|
||||||
ex := floor(log10(abs(AValue))); // exponent
|
ex := floor(log10(abs(AValue))); // exponent
|
||||||
// round exponent to multiples of 3
|
// round exponent to multiples of 3
|
||||||
ex := (ex div 3) * 3;
|
ex := (ex div 3) * 3;
|
||||||
if ex < 0 then dec(ex, 3);
|
if ex < 0 then dec(ex, 3);
|
||||||
m := AValue * Power(10, -ex); // mantisse
|
m := AValue * Power(10, -ex); // mantisse
|
||||||
Result := Format('%.*fE%d', [ADecimals, m, ex]);
|
Result := Format('%.*fE+%d', [ADecimals, m, ex], AFormatSettings);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function SciFloat(AValue: Double; ADecimals: Byte): String;
|
||||||
|
begin
|
||||||
|
Result := SciFloat(AValue, ADecimals, DefaultFormatSettings);
|
||||||
|
end;
|
||||||
|
|
||||||
{ Creates a "time interval" format string having the first code identifier
|
{ Creates a "time interval" format string having the first code identifier
|
||||||
in square brackets. }
|
in square brackets. }
|
||||||
procedure MakeTimeIntervalMask(Src: String; var Dest: String);
|
procedure MakeTimeIntervalMask(Src: String; var Dest: String);
|
||||||
|
@ -250,27 +250,27 @@ begin
|
|||||||
SollDates[14]:=SollDates[1]; // #1 formatted as nfLongTime
|
SollDates[14]:=SollDates[1]; // #1 formatted as nfLongTime
|
||||||
SollDates[15]:=SollDates[1]; // #1 formatted as nfShortTimeAM
|
SollDates[15]:=SollDates[1]; // #1 formatted as nfShortTimeAM
|
||||||
SollDates[16]:=SollDates[1]; // #1 formatted as nfLongTimeAM
|
SollDates[16]:=SollDates[1]; // #1 formatted as nfLongTimeAM
|
||||||
SollDates[17]:=SollDates[1]; // #1 formatted as nfFmtDateTime dm
|
SollDates[17]:=SollDates[1]; // #1 formatted as nfCustom dd/mmm
|
||||||
SollDates[18]:=SollDates[1]; // #1 formatted as nfFmtDateTime my
|
SollDates[18]:=SollDates[1]; // #1 formatted as nfCustom mmm/yy
|
||||||
SollDates[19]:=SollDates[1]; // #1 formatted as nfFmtDateTime ms
|
SollDates[19]:=SollDates[1]; // #1 formatted as nfCustom mm:ss
|
||||||
|
|
||||||
SollDates[20]:=SollDates[5]; // #5 formatted as nfShortDateTime
|
SollDates[20]:=SollDates[5]; // #5 formatted as nfShortDateTime
|
||||||
SollDates[21]:=SollDates[5]; // #5 formatted as nfShortTime
|
SollDates[21]:=SollDates[5]; // #5 formatted as nfShortTime
|
||||||
SollDates[22]:=SollDates[5]; // #5 formatted as nfLongTime
|
SollDates[22]:=SollDates[5]; // #5 formatted as nfLongTime
|
||||||
SollDates[23]:=SollDates[5]; // #5 formatted as nfShortTimeAM
|
SollDates[23]:=SollDates[5]; // #5 formatted as nfShortTimeAM
|
||||||
SollDates[24]:=SollDates[5]; // #5 formatted as nfLongTimeAM
|
SollDates[24]:=SollDates[5]; // #5 formatted as nfLongTimeAM
|
||||||
SollDates[25]:=SollDates[5]; // #5 formatted as nfFmtDateTime dm
|
SollDates[25]:=SollDates[5]; // #5 formatted as nfCustom dd:mmm
|
||||||
SollDates[26]:=SollDates[5]; // #5 formatted as nfFmtDateTime my
|
SollDates[26]:=SollDates[5]; // #5 formatted as nfCustom mmm:yy
|
||||||
SollDates[27]:=SollDates[5]; // #5 formatted as nfFmtDateTime ms
|
SollDates[27]:=SollDates[5]; // #5 formatted as nfCustom mm:ss
|
||||||
|
|
||||||
SollDates[28]:=SollDates[11]; // #11 formatted as nfShortDateTime
|
SollDates[28]:=SollDates[11]; // #11 formatted as nfShortDateTime
|
||||||
SollDates[29]:=SollDates[11]; // #11 formatted as nfShortTime
|
SollDates[29]:=SollDates[11]; // #11 formatted as nfShortTime
|
||||||
SollDates[30]:=SollDates[11]; // #11 formatted as nfLongTime
|
SollDates[30]:=SollDates[11]; // #11 formatted as nfLongTime
|
||||||
SollDates[31]:=SollDates[11]; // #11 formatted as nfShortTimeAM
|
SollDates[31]:=SollDates[11]; // #11 formatted as nfShortTimeAM
|
||||||
SollDates[32]:=SollDates[11]; // #11 formatted as nfLongTimeAM
|
SollDates[32]:=SollDates[11]; // #11 formatted as nfLongTimeAM
|
||||||
SollDates[33]:=SollDates[11]; // #11 formatted as nfFmtDateTime dm
|
SollDates[33]:=SollDates[11]; // #11 formatted as nfCustom dd/mmm
|
||||||
SollDates[34]:=SollDates[11]; // #11 formatted as nfFmtDateTime my
|
SollDates[34]:=SollDates[11]; // #11 formatted as nfCustom mmm/yy
|
||||||
SollDates[35]:=SollDates[11]; // #11 formatted as nfFmtDateTime ms
|
SollDates[35]:=SollDates[11]; // #11 formatted as nfCustom mmm:ss
|
||||||
|
|
||||||
SollDates[36]:=EncodeTime(3,45,12,0); // formatted as nfTimeDuration
|
SollDates[36]:=EncodeTime(3,45,12,0); // formatted as nfTimeDuration
|
||||||
SollDates[37]:=EncodeTime(3,45,12,0) + 1 // formatted as nfTimeDuration
|
SollDates[37]:=EncodeTime(3,45,12,0) + 1 // formatted as nfTimeDuration
|
||||||
|
@ -137,10 +137,15 @@ procedure InitSollFmtData;
|
|||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
fs: TFormatSettings;
|
fs: TFormatSettings;
|
||||||
|
myworkbook: TsWorkbook;
|
||||||
begin
|
begin
|
||||||
// Set up norm - MUST match spreadsheet cells exactly
|
// Set up norm - MUST match spreadsheet cells exactly
|
||||||
|
|
||||||
fs := DefaultFormatSettings;
|
// The workbook uses a slightly modified copy of the DefaultFormatSettings
|
||||||
|
// We create a copy here in order to better define the predicted strings.
|
||||||
|
myWorkbook := TsWorkbook.Create;
|
||||||
|
fs := MyWorkbook.FormatSettings;
|
||||||
|
myWorkbook.Free;
|
||||||
|
|
||||||
// Numbers
|
// Numbers
|
||||||
SollNumbers[0] := 0.0;
|
SollNumbers[0] := 0.0;
|
||||||
@ -162,15 +167,15 @@ begin
|
|||||||
SollNumberFormats[8] := nfSci; SollNumberDecimals[8] := 1;
|
SollNumberFormats[8] := nfSci; SollNumberDecimals[8] := 1;
|
||||||
|
|
||||||
for i:=Low(SollNumbers) to High(SollNumbers) do begin
|
for i:=Low(SollNumbers) to High(SollNumbers) do begin
|
||||||
SollNumberStrings[i, 0] := FloatToStr(SollNumbers[i]);
|
SollNumberStrings[i, 0] := FloatToStr(SollNumbers[i], fs);
|
||||||
SollNumberStrings[i, 1] := FormatFloat('0', SollNumbers[i]);
|
SollNumberStrings[i, 1] := FormatFloat('0', SollNumbers[i], fs);
|
||||||
SollNumberStrings[i, 2] := FormatFloat('0.00', SollNumbers[i]);
|
SollNumberStrings[i, 2] := FormatFloat('0.00', SollNumbers[i], fs);
|
||||||
SollNumberStrings[i, 3] := FormatFloat('#,##0', SollNumbers[i]);
|
SollNumberStrings[i, 3] := FormatFloat('#,##0', SollNumbers[i], fs);
|
||||||
SollNumberStrings[i, 4] := FormatFloat('#,##0.00', SollNumbers[i]);
|
SollNumberStrings[i, 4] := FormatFloat('#,##0.00', SollNumbers[i], fs);
|
||||||
SollNumberStrings[i, 5] := FormatFloat('0.00E+00', SollNumbers[i]);
|
SollNumberStrings[i, 5] := FormatFloat('0.00E+00', SollNumbers[i], fs);
|
||||||
SollNumberStrings[i, 6] := FormatFloat('0', SollNumbers[i]*100) + '%';
|
SollNumberStrings[i, 6] := FormatFloat('0', SollNumbers[i]*100, fs) + '%';
|
||||||
SollNumberStrings[i, 7] := FormatFloat('0.00', SollNumbers[i]*100) + '%';
|
SollNumberStrings[i, 7] := FormatFloat('0.00', SollNumbers[i]*100, fs) + '%';
|
||||||
SollNumberStrings[i, 8] := SciFloat(SollNumbers[i], 1);
|
SollNumberStrings[i, 8] := SciFloat(SollNumbers[i], 1, fs);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Date/time values
|
// Date/time values
|
||||||
@ -186,22 +191,22 @@ begin
|
|||||||
SollDateTimeFormats[3] := nfLongTime; SollDateTimeFormatStrings[3] := '';
|
SollDateTimeFormats[3] := nfLongTime; SollDateTimeFormatStrings[3] := '';
|
||||||
SollDateTimeFormats[4] := nfShortTimeAM; SollDateTimeFormatStrings[4] := '';
|
SollDateTimeFormats[4] := nfShortTimeAM; SollDateTimeFormatStrings[4] := '';
|
||||||
SollDateTimeFormats[5] := nfLongTimeAM; SollDateTimeFormatStrings[5] := '';
|
SollDateTimeFormats[5] := nfLongTimeAM; SollDateTimeFormatStrings[5] := '';
|
||||||
SollDateTimeFormats[6] := nfFmtDateTime; SollDateTimeFormatStrings[6] := 'dm';
|
SollDateTimeFormats[6] := nfCustom; SollDateTimeFormatStrings[6] := 'dd/mmm';
|
||||||
SolLDateTimeFormats[7] := nfFmtDateTime; SollDateTimeFormatStrings[7] := 'my';
|
SolLDateTimeFormats[7] := nfCustom; SollDateTimeFormatStrings[7] := 'mmm/yy';
|
||||||
SollDateTimeFormats[8] := nfFmtDateTime; SollDateTimeFormatStrings[8] := 'ms';
|
SollDateTimeFormats[8] := nfCustom; SollDateTimeFormatStrings[8] := 'nn:ss';
|
||||||
SollDateTimeFormats[9] := nfTimeInterval; SollDateTimeFormatStrings[9] := '';
|
SollDateTimeFormats[9] := nfTimeInterval; SollDateTimeFormatStrings[9] := '';
|
||||||
|
|
||||||
for i:=Low(SollDateTimes) to High(SollDateTimes) do begin
|
for i:=Low(SollDateTimes) to High(SollDateTimes) do begin
|
||||||
SollDateTimeStrings[i, 0] := DateToStr(SollDateTimes[i]) + ' ' + FormatDateTime('t', SollDateTimes[i]);
|
SollDateTimeStrings[i, 0] := DateToStr(SollDateTimes[i], fs) + ' ' + FormatDateTime('t', SollDateTimes[i], fs);
|
||||||
SollDateTimeStrings[i, 1] := DateToStr(SollDateTimes[i]);
|
SollDateTimeStrings[i, 1] := DateToStr(SollDateTimes[i], fs);
|
||||||
SollDateTimeStrings[i, 2] := FormatDateTime(fs.ShortTimeFormat, SollDateTimes[i]);
|
SollDateTimeStrings[i, 2] := FormatDateTime(fs.ShortTimeFormat, SollDateTimes[i], fs);
|
||||||
SolLDateTimeStrings[i, 3] := FormatDateTime(fs.LongTimeFormat, SollDateTimes[i]);
|
SolLDateTimeStrings[i, 3] := FormatDateTime(fs.LongTimeFormat, SollDateTimes[i], fs);
|
||||||
SollDateTimeStrings[i, 4] := FormatDateTime(fs.ShortTimeFormat + ' am/pm', SollDateTimes[i]); // dont't use "t" - it does the hours wrong
|
SollDateTimeStrings[i, 4] := FormatDateTime(fs.ShortTimeFormat + ' am/pm', SollDateTimes[i], fs); // dont't use "t" - it does the hours wrong
|
||||||
SollDateTimeStrings[i, 5] := FormatDateTime(fs.LongTimeFormat + ' am/pm', SollDateTimes[i]);
|
SollDateTimeStrings[i, 5] := FormatDateTime(fs.LongTimeFormat + ' am/pm', SollDateTimes[i], fs);
|
||||||
SollDateTimeStrings[i, 6] := FormatDateTime(SpecialDateTimeFormat('dm', fs, false), SollDateTimes[i]);
|
SollDateTimeStrings[i, 6] := FormatDateTime(SpecialDateTimeFormat('dm', fs, false), SollDateTimes[i], fs);
|
||||||
SollDateTimeStrings[i, 7] := FormatDateTime(SpecialDateTimeFormat('my', fs, false), SollDateTimes[i]);
|
SollDateTimeStrings[i, 7] := FormatDateTime(SpecialDateTimeFormat('my', fs, false), SollDateTimes[i], fs);
|
||||||
SollDateTimeStrings[i, 8] := FormatDateTime(SpecialDateTimeFormat('ms', fs, false), SollDateTimes[i]);
|
SollDateTimeStrings[i, 8] := FormatDateTime(SpecialDateTimeFormat('ms', fs, false), SollDateTimes[i], fs);
|
||||||
SollDateTimeStrings[i, 9] := FormatDateTime('[h]:mm:ss', SollDateTimes[i], [fdoInterval]);
|
SollDateTimeStrings[i, 9] := FormatDateTime('[h]:mm:ss', SollDateTimes[i], fs, [fdoInterval]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Column width
|
// Column width
|
||||||
@ -345,7 +350,7 @@ begin
|
|||||||
MyWorksheet := MyWorkbook.AddWorksheet(FmtDateTimesSheet);
|
MyWorksheet := MyWorkbook.AddWorksheet(FmtDateTimesSheet);
|
||||||
for Row := Low(SollDateTimes) to High(SollDateTimes) do
|
for Row := Low(SollDateTimes) to High(SollDateTimes) do
|
||||||
for Col := Low(SollDateTimeFormats) to High(SollDateTimeFormats) do begin
|
for Col := Low(SollDateTimeFormats) to High(SollDateTimeFormats) do begin
|
||||||
if (AFormat = sfExcel2) and (SollDateTimeFormats[Col] in [nfFmtDateTime, nfTimeInterval]) then
|
if (AFormat = sfExcel2) and (SollDateTimeFormats[Col] in [nfCustom, nfTimeInterval]) then
|
||||||
Continue; // The formats nfFmtDateTime and nfTimeInterval are not supported by BIFF2
|
Continue; // The formats nfFmtDateTime and nfTimeInterval are not supported by BIFF2
|
||||||
MyWorksheet.WriteDateTime(Row, Col, SollDateTimes[Row], SollDateTimeFormats[Col], SollDateTimeFormatStrings[Col]);
|
MyWorksheet.WriteDateTime(Row, Col, SollDateTimes[Row], SollDateTimeFormats[Col], SollDateTimeFormatStrings[Col]);
|
||||||
ActualString := MyWorksheet.ReadAsUTF8Text(Row, Col);
|
ActualString := MyWorksheet.ReadAsUTF8Text(Row, Col);
|
||||||
@ -369,7 +374,7 @@ begin
|
|||||||
fail('Error in test code. Failed to get named worksheet');
|
fail('Error in test code. Failed to get named worksheet');
|
||||||
for Row := Low(SollDateTimes) to High(SollDateTimes) do
|
for Row := Low(SollDateTimes) to High(SollDateTimes) do
|
||||||
for Col := Low(SollDateTimeFormats) to High(SollDateTimeFormats) do begin
|
for Col := Low(SollDateTimeFormats) to High(SollDateTimeFormats) do begin
|
||||||
if (AFormat = sfExcel2) and (SollDateTimeFormats[Col] in [nfFmtDateTime, nfTimeInterval]) then
|
if (AFormat = sfExcel2) and (SollDateTimeFormats[Col] in [nfCustom, nfTimeInterval]) then
|
||||||
Continue; // The formats nfFmtDateTime and nfTimeInterval are not supported by BIFF2
|
Continue; // The formats nfFmtDateTime and nfTimeInterval are not supported by BIFF2
|
||||||
ActualString := MyWorksheet.ReadAsUTF8Text(Row,Col);
|
ActualString := MyWorksheet.ReadAsUTF8Text(Row,Col);
|
||||||
CheckEquals(
|
CheckEquals(
|
||||||
|
@ -46,6 +46,7 @@ implementation
|
|||||||
uses
|
uses
|
||||||
TypInfo;
|
TypInfo;
|
||||||
|
|
||||||
|
{ The test will use Excel strings and convert them to fpc dialect }
|
||||||
procedure InitParserTestData;
|
procedure InitParserTestData;
|
||||||
begin
|
begin
|
||||||
// Tests with 1 format section only
|
// Tests with 1 format section only
|
||||||
@ -146,14 +147,16 @@ var
|
|||||||
i: Integer;
|
i: Integer;
|
||||||
parser: TsNumFormatParser;
|
parser: TsNumFormatParser;
|
||||||
MyWorkbook: TsWorkbook;
|
MyWorkbook: TsWorkbook;
|
||||||
|
actual: String;
|
||||||
begin
|
begin
|
||||||
MyWorkbook := TsWorkbook.Create; // needed to provide the FormatSettings for the parser
|
MyWorkbook := TsWorkbook.Create; // needed to provide the FormatSettings for the parser
|
||||||
try
|
try
|
||||||
for i:=0 to 5 do begin
|
for i:=0 to 5 do begin
|
||||||
parser := TsNumFormatParser.Create(MyWorkbook, ParserTestData[i].FormatString, cdToFPSpreadsheet);
|
parser := TsNumFormatParser.Create(MyWorkbook, ParserTestData[i].FormatString);
|
||||||
try
|
try
|
||||||
CheckEquals(ParserTestData[i].SollFormatString, parser.FormatString,
|
actual := parser.FormatString[nfdDefault];
|
||||||
'Test format string ' + ParserTestData[i].FormatString + ' construction mismatch');
|
CheckEquals(ParserTestData[i].SollFormatString, actual,
|
||||||
|
'Test format string ' + ParserTestData[i].SollFormatString + ' construction mismatch');
|
||||||
CheckEquals(ord(ParserTestData[i].SollNumFormat), ord(parser.ParsedSections[0].NumFormat),
|
CheckEquals(ord(ParserTestData[i].SollNumFormat), ord(parser.ParsedSections[0].NumFormat),
|
||||||
'Test format (' + GetEnumName(TypeInfo(TsNumberFormat), integer(ParserTestData[i].SollNumFormat)) +
|
'Test format (' + GetEnumName(TypeInfo(TsNumberFormat), integer(ParserTestData[i].SollNumFormat)) +
|
||||||
') detection mismatch');
|
') detection mismatch');
|
||||||
|
@ -48,9 +48,6 @@
|
|||||||
</Debugging>
|
</Debugging>
|
||||||
</Linking>
|
</Linking>
|
||||||
<Other>
|
<Other>
|
||||||
<CompilerMessages>
|
|
||||||
<MsgFileName Value=""/>
|
|
||||||
</CompilerMessages>
|
|
||||||
<CompilerPath Value="$(CompPath)"/>
|
<CompilerPath Value="$(CompPath)"/>
|
||||||
</Other>
|
</Other>
|
||||||
</CompilerOptions>
|
</CompilerOptions>
|
||||||
@ -173,9 +170,6 @@
|
|||||||
</Optimizations>
|
</Optimizations>
|
||||||
</CodeGeneration>
|
</CodeGeneration>
|
||||||
<Other>
|
<Other>
|
||||||
<CompilerMessages>
|
|
||||||
<MsgFileName Value=""/>
|
|
||||||
</CompilerMessages>
|
|
||||||
<CompilerPath Value="$(CompPath)"/>
|
<CompilerPath Value="$(CompPath)"/>
|
||||||
</Other>
|
</Other>
|
||||||
</CompilerOptions>
|
</CompilerOptions>
|
||||||
|
@ -61,8 +61,7 @@ type
|
|||||||
procedure ApplyCellFormatting(ARow, ACol: Cardinal; XFIndex: Word); override;
|
procedure ApplyCellFormatting(ARow, ACol: Cardinal; XFIndex: Word); override;
|
||||||
procedure CreateNumFormatList; override;
|
procedure CreateNumFormatList; override;
|
||||||
procedure ExtractNumberFormat(AXFIndex: WORD;
|
procedure ExtractNumberFormat(AXFIndex: WORD;
|
||||||
out ANumberFormat: TsNumberFormat; out ADecimals: Byte;
|
out ANumberFormat: TsNumberFormat; out ANumberFormatStr: String); override;
|
||||||
out ACurrencySymbol: String; out ANumberFormatStr: String); override;
|
|
||||||
procedure ReadBlank(AStream: TStream); override;
|
procedure ReadBlank(AStream: TStream); override;
|
||||||
procedure ReadColWidth(AStream: TStream);
|
procedure ReadColWidth(AStream: TStream);
|
||||||
procedure ReadFont(AStream: TStream);
|
procedure ReadFont(AStream: TStream);
|
||||||
@ -139,7 +138,7 @@ var
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Math;
|
Math, fpsNumFormatParser;
|
||||||
|
|
||||||
const
|
const
|
||||||
{ Excel record IDs }
|
{ Excel record IDs }
|
||||||
@ -181,21 +180,23 @@ begin
|
|||||||
ts := fs.ThousandSeparator;
|
ts := fs.ThousandSeparator;
|
||||||
cs := fs.CurrencyString;
|
cs := fs.CurrencyString;
|
||||||
AddFormat( 0, '', nfGeneral);
|
AddFormat( 0, '', nfGeneral);
|
||||||
AddFormat( 1, '0', nfFixed, 0);
|
AddFormat( 1, '0', nfFixed);
|
||||||
AddFormat( 2, '0'+ds+'00', nfFixed, 2); // 0.00
|
AddFormat( 2, '0'+ds+'00', nfFixed); // 0.00
|
||||||
AddFormat( 3, '#'+ts+'##0', nfFixedTh, 0); // #,##0
|
AddFormat( 3, '#'+ts+'##0', nfFixedTh); // #,##0
|
||||||
AddFormat( 4, '#'+ts+'##0'+ds+'00', nfFixedTh, 2); // #,##0.00
|
AddFormat( 4, '#'+ts+'##0'+ds+'00', nfFixedTh); // #,##0.00
|
||||||
AddFormat( 5, UTF8ToAnsi('"'+cs+'"#'+ts+'##0_);("'+cs+'"#'+ts+'##0)'), nfCurrency, 0);
|
AddFormat( 5, UTF8ToAnsi('"'+cs+'"#'+ts+'##0_);("'+cs+'"#'+ts+'##0)'), nfCurrency);
|
||||||
AddFormat( 6, UTF8ToAnsi('"'+cs+'"#'+ts+'##0_);[Red]("'+cs+'"#'+ts+'##0)'), nfCurrencyRed, 2);
|
AddFormat( 6, UTF8ToAnsi('"'+cs+'"#'+ts+'##0_);[Red]("'+cs+'"#'+ts+'##0)'), nfCurrencyRed);
|
||||||
AddFormat( 7, UTF8ToAnsi('"'+cs+'"#'+ts+'##0'+ds+'00_);("'+cs+'"#'+ts+'##0'+ds+'00)'), nfCurrency, 0);
|
AddFormat( 7, UTF8ToAnsi('"'+cs+'"#'+ts+'##0'+ds+'00_);("'+cs+'"#'+ts+'##0'+ds+'00)'), nfCurrency);
|
||||||
AddFormat( 8, UTF8ToAnsi('"'+cs+'"#'+ts+'##0'+ds+'00_);[Red]("'+cs+'"#'+ts+'##0'+ds+'00)'), nfCurrency, 2);
|
AddFormat( 8, UTF8ToAnsi('"'+cs+'"#'+ts+'##0'+ds+'00_);[Red]("'+cs+'"#'+ts+'##0'+ds+'00)'), nfCurrency);
|
||||||
AddFormat( 9, '0%', nfPercentage, 0);
|
AddFormat( 9, '0%', nfPercentage);
|
||||||
AddFormat(10, '0'+ds+'00%', nfPercentage, 2);
|
AddFormat(10, '0'+ds+'00%', nfPercentage);
|
||||||
AddFormat(11, '0'+ds+'00E+00', nfExp, 2);
|
AddFormat(11, '0'+ds+'00E+00', nfExp);
|
||||||
AddFormat(12, fs.ShortDateFormat, nfShortDate);
|
AddFormat(12, fs.ShortDateFormat, nfShortDate);
|
||||||
AddFormat(13, fs.LongDateFormat, nfLongDate);
|
AddFormat(13, fs.LongDateFormat, nfLongDate);
|
||||||
AddFormat(14, SpecialDateTimeFormat('dm', fs, true), nfFmtDateTime);
|
AddFormat(14, 'd/mmm', nfCustom);
|
||||||
AddFormat(15, SpecialDateTimeFormat('my', fs, true), nfFmtDateTime);
|
AddFormat(15, 'mmm/yy', nfCustom);
|
||||||
|
//AddFormat(14, SpecialDateTimeFormat('dm', fs, true), nfFmtDateTime);
|
||||||
|
//AddFormat(15, SpecialDateTimeFormat('my', fs, true), nfFmtDateTime);
|
||||||
AddFormat(16, AddAMPM(fs.ShortTimeFormat, fs), nfShortTimeAM);
|
AddFormat(16, AddAMPM(fs.ShortTimeFormat, fs), nfShortTimeAM);
|
||||||
AddFormat(17, AddAMPM(fs.LongTimeFormat, fs), nfLongTimeAM);
|
AddFormat(17, AddAMPM(fs.LongTimeFormat, fs), nfLongTimeAM);
|
||||||
AddFormat(18, fs.ShortTimeFormat, nfShortTime);
|
AddFormat(18, fs.ShortTimeFormat, nfShortTime);
|
||||||
@ -223,6 +224,7 @@ begin
|
|||||||
if ADecimals > 0 then ADecimals := 2;
|
if ADecimals > 0 then ADecimals := 2;
|
||||||
ANumFormat := nfExp;
|
ANumFormat := nfExp;
|
||||||
end;
|
end;
|
||||||
|
{
|
||||||
nfFmtDateTime:
|
nfFmtDateTime:
|
||||||
begin
|
begin
|
||||||
fmt := lowercase(AFormatString);
|
fmt := lowercase(AFormatString);
|
||||||
@ -248,6 +250,7 @@ begin
|
|||||||
else
|
else
|
||||||
ANumFormat := nfShortDateTime;
|
ANumFormat := nfShortDateTime;
|
||||||
end;
|
end;
|
||||||
|
}
|
||||||
nfCustom, nfTimeInterval:
|
nfCustom, nfTimeInterval:
|
||||||
begin
|
begin
|
||||||
ANumFormat := nfGeneral;
|
ANumFormat := nfGeneral;
|
||||||
@ -261,18 +264,28 @@ end;
|
|||||||
function TsBIFF2NumFormatList.FindFormatOf(AFormatCell: PCell): Integer;
|
function TsBIFF2NumFormatList.FindFormatOf(AFormatCell: PCell): Integer;
|
||||||
var
|
var
|
||||||
fmt: String;
|
fmt: String;
|
||||||
|
parser: TsNumFormatParser;
|
||||||
|
decs: Integer;
|
||||||
|
dt: string;
|
||||||
begin
|
begin
|
||||||
|
parser := TsNumFormatParser.Create(Workbook, AFormatCell^.NumberFormatStr);
|
||||||
|
try
|
||||||
|
decs := parser.Decimals;
|
||||||
|
dt := parser.GetDateTimeCode(0);
|
||||||
|
finally
|
||||||
|
parser.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
case AFormatCell^.NumberFormat of
|
case AFormatCell^.NumberFormat of
|
||||||
nfGeneral,
|
nfGeneral,
|
||||||
nfCustom,
|
|
||||||
nfTimeInterval : Result := 0;
|
nfTimeInterval : Result := 0;
|
||||||
nfFixed : Result := IfThen(AFormatCell^.Decimals = 0, 1, 2);
|
nfFixed : Result := IfThen(decs = 0, 1, 2);
|
||||||
nfFixedTh : Result := IfThen(AFormatCell^.Decimals = 0, 3, 4);
|
nfFixedTh : Result := IfThen(decs = 0, 3, 4);
|
||||||
nfCurrency,
|
nfCurrency,
|
||||||
nfAccounting : Result := IfThen(AFormatCell^.Decimals = 0, 5, 7);
|
nfAccounting : Result := IfThen(decs = 0, 5, 7);
|
||||||
nfCurrencyRed,
|
nfCurrencyRed,
|
||||||
nfAccountingRed : Result := IfThen(AFormatCell^.Decimals = 0, 6, 8);
|
nfAccountingRed : Result := IfThen(decs = 0, 6, 8);
|
||||||
nfPercentage : Result := IfThen(AFormatCell^.Decimals = 0, 9, 10);
|
nfPercentage : Result := IfThen(decs = 0, 9, 10);
|
||||||
nfExp, nfSci : Result := 11;
|
nfExp, nfSci : Result := 11;
|
||||||
nfShortDate : Result := 12;
|
nfShortDate : Result := 12;
|
||||||
nfLongDate : Result := 13;
|
nfLongDate : Result := 13;
|
||||||
@ -281,38 +294,8 @@ begin
|
|||||||
nfShortTime : Result := 18;
|
nfShortTime : Result := 18;
|
||||||
nfLongTime : Result := 19;
|
nfLongTime : Result := 19;
|
||||||
nfShortDateTime : Result := 20;
|
nfShortDateTime : Result := 20;
|
||||||
nfFmtDateTime : begin
|
nfCustom : if dt = 'dm' then Result := 14 else
|
||||||
fmt := lowercase(AFormatCell^.NumberFormatStr);
|
if dt = 'my' then Result := 15;
|
||||||
if (fmt = 'd-mmm') or (fmt = 'd/mmm') or
|
|
||||||
(fmt = 'd-mm') or (fmt = 'd/mm') or
|
|
||||||
(fmt = 'dd-mm') or (fmt = 'dd/mm') or
|
|
||||||
(fmt = 'dd-mmm') or (fmt = 'dd/mmm')
|
|
||||||
then
|
|
||||||
Result := 14
|
|
||||||
else
|
|
||||||
if (fmt = 'mmm-yy') or (fmt = 'mmm/yy') or
|
|
||||||
(fmt = 'mm-yy') or (fmt = 'mm/yy') or
|
|
||||||
(fmt = 'm-yy') or (fmt = 'm/y') or
|
|
||||||
(fmt = 'mmm-yyyy') or (fmt = 'mmm/yyyy') or
|
|
||||||
(fmt = 'mm-yyyy') or (fmt = 'mm/yyyy') or
|
|
||||||
(fmt = 'm-yyyy') or (fmt = 'm/yyyy')
|
|
||||||
then
|
|
||||||
Result := 15
|
|
||||||
else
|
|
||||||
if (fmt = 'nn:ss') or (fmt = 'mm:ss') or
|
|
||||||
(fmt = 'n:ss') or (fmt = 'm:ss')
|
|
||||||
then
|
|
||||||
Result := 19
|
|
||||||
else
|
|
||||||
if (fmt = 'nn:ss.z') or (fmt = 'mm:ss.z') or
|
|
||||||
(fmt = 'n:ss.z') or (fmt = 'm:ss.z') or
|
|
||||||
(fmt = 'nn:ss.zzz') or (fmt = 'mm:ss.zzz') or
|
|
||||||
(fmt = 'n:ss.zzz') or (fmt = 'm:ss.zzz')
|
|
||||||
then
|
|
||||||
Result := 19
|
|
||||||
else
|
|
||||||
Result := 20;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -383,8 +366,7 @@ end;
|
|||||||
{ Extracts the number format data from an XF record indexed by AXFIndex.
|
{ Extracts the number format data from an XF record indexed by AXFIndex.
|
||||||
Note that BIFF2 supports only 21 formats. }
|
Note that BIFF2 supports only 21 formats. }
|
||||||
procedure TsSpreadBIFF2Reader.ExtractNumberFormat(AXFIndex: WORD;
|
procedure TsSpreadBIFF2Reader.ExtractNumberFormat(AXFIndex: WORD;
|
||||||
out ANumberFormat: TsNumberFormat; out ADecimals: Byte;
|
out ANumberFormat: TsNumberFormat; out ANumberFormatStr: String);
|
||||||
out ACurrencySymbol: String; out ANumberFormatStr: String);
|
|
||||||
var
|
var
|
||||||
lNumFormatData: TsNumFormatData;
|
lNumFormatData: TsNumFormatData;
|
||||||
begin
|
begin
|
||||||
@ -392,13 +374,9 @@ begin
|
|||||||
if lNumFormatData <> nil then begin
|
if lNumFormatData <> nil then begin
|
||||||
ANumberFormat := lNumFormatData.NumFormat;
|
ANumberFormat := lNumFormatData.NumFormat;
|
||||||
ANumberFormatStr := lNumFormatData.FormatString;
|
ANumberFormatStr := lNumFormatData.FormatString;
|
||||||
ADecimals := lNumFormatData.Decimals;
|
|
||||||
ACurrencySymbol := lNumFormatData.CurrencySymbol;
|
|
||||||
end else begin
|
end else begin
|
||||||
ANumberFormat := nfGeneral;
|
ANumberFormat := nfGeneral;
|
||||||
ANumberFormatStr := '';
|
ANumberFormatStr := '';
|
||||||
ADecimals := 0;
|
|
||||||
ACurrencySymbol := '';
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -575,11 +553,11 @@ begin
|
|||||||
Move(Data[0], formulaResult, SizeOf(Data));
|
Move(Data[0], formulaResult, SizeOf(Data));
|
||||||
|
|
||||||
{Find out what cell type, set content type and value}
|
{Find out what cell type, set content type and value}
|
||||||
ExtractNumberFormat(XF, nf, nd, ncs, nfs);
|
ExtractNumberFormat(XF, nf, nfs);
|
||||||
if IsDateTime(formulaResult, nf, dt) then
|
if IsDateTime(formulaResult, nf, nfs, dt) then
|
||||||
FWorksheet.WriteDateTime(ARow, ACol, dt, nf, nfs)
|
FWorksheet.WriteDateTime(ARow, ACol, dt, nf, nfs)
|
||||||
else
|
else
|
||||||
FWorksheet.WriteNumber(ARow, ACol, formulaResult, nf, nd, ncs);
|
FWorksheet.WriteNumber(ARow, ACol, formulaResult, nf, nfs);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Formula token array }
|
{ Formula token array }
|
||||||
@ -645,11 +623,11 @@ begin
|
|||||||
AStream.ReadBuffer(value, 8);
|
AStream.ReadBuffer(value, 8);
|
||||||
|
|
||||||
{Find out what cell type, set content type and value}
|
{Find out what cell type, set content type and value}
|
||||||
ExtractNumberFormat(XF, nf, nd, ncs, nfs);
|
ExtractNumberFormat(XF, nf, nfs);
|
||||||
if IsDateTime(value, nf, dt) then
|
if IsDateTime(value, nf, nfs, dt) then
|
||||||
FWorksheet.WriteDateTime(ARow, ACol, dt, nf, nfs)
|
FWorksheet.WriteDateTime(ARow, ACol, dt, nf, nfs)
|
||||||
else
|
else
|
||||||
FWorksheet.WriteNumber(ARow, ACol, value, nf, nd, ncs);
|
FWorksheet.WriteNumber(ARow, ACol, value, nf, nfs);
|
||||||
|
|
||||||
{ Apply formatting to cell }
|
{ Apply formatting to cell }
|
||||||
ApplyCellFormatting(ARow, ACol, XF);
|
ApplyCellFormatting(ARow, ACol, XF);
|
||||||
@ -902,6 +880,7 @@ begin
|
|||||||
// but the number format list of the writer is in Excel syntax.
|
// but the number format list of the writer is in Excel syntax.
|
||||||
// And for BIFF2, there is only a limited number of formats.
|
// And for BIFF2, there is only a limited number of formats.
|
||||||
lCell := ACell^;
|
lCell := ACell^;
|
||||||
|
{
|
||||||
with lCell do begin
|
with lCell do begin
|
||||||
if IsDateTimeFormat(NumberFormat) then
|
if IsDateTimeFormat(NumberFormat) then
|
||||||
NumberFormatStr := BuildDateTimeFormatString(NumberFormat,
|
NumberFormatStr := BuildDateTimeFormatString(NumberFormat,
|
||||||
@ -911,6 +890,7 @@ begin
|
|||||||
Workbook.FormatSettings, Decimals, CurrencySymbol);
|
Workbook.FormatSettings, Decimals, CurrencySymbol);
|
||||||
NumFormatList.ConvertBeforeWriting(NumberFormatStr, NumberFormat, Decimals, CurrencyString);
|
NumFormatList.ConvertBeforeWriting(NumberFormatStr, NumberFormat, Decimals, CurrencyString);
|
||||||
end;
|
end;
|
||||||
|
}
|
||||||
lIndex := FindFormattingInList(@lCell);
|
lIndex := FindFormattingInList(@lCell);
|
||||||
|
|
||||||
// Carefully check the index
|
// Carefully check the index
|
||||||
@ -925,14 +905,13 @@ var
|
|||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
inherited ListAllFormattingStyles;
|
inherited ListAllFormattingStyles;
|
||||||
|
{
|
||||||
for i:=0 to High(FFormattingStyles) do
|
for i:=0 to High(FFormattingStyles) do
|
||||||
FNumFormatList.ConvertBeforeWriting(
|
FNumFormatList.ConvertBeforeWriting(
|
||||||
FFormattingStyles[i].NumberFormatStr,
|
FFormattingStyles[i].NumberFormatStr,
|
||||||
FFormattingStyles[i].NumberFormat,
|
FFormattingStyles[i].NumberFormat
|
||||||
FFormattingStyles[i].Decimals,
|
|
||||||
FFormattingStyles[i].CurrencySymbol
|
|
||||||
);
|
);
|
||||||
|
}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Builds up the list of number formats to be written to the biff2 file.
|
{ Builds up the list of number formats to be written to the biff2 file.
|
||||||
|
@ -310,6 +310,8 @@ begin
|
|||||||
|
|
||||||
// Now apply the modifications.
|
// Now apply the modifications.
|
||||||
if uffNumberFormat in FFormattingStyles[i].UsedFormattingFields then begin
|
if uffNumberFormat in FFormattingStyles[i].UsedFormattingFields then begin
|
||||||
|
// The number formats in the FormattingStyles are still in fpc dialect
|
||||||
|
// They will be converted to Excel syntax immediately before writing.
|
||||||
j := NumFormatList.FindFormatOf(@FFormattingStyles[i]);
|
j := NumFormatList.FindFormatOf(@FFormattingStyles[i]);
|
||||||
if j > -1 then
|
if j > -1 then
|
||||||
lFormatIndex := NumFormatList[j].Index;
|
lFormatIndex := NumFormatList[j].Index;
|
||||||
|
@ -357,6 +357,9 @@ type
|
|||||||
TsBIFFNumFormatList = class(TsCustomNumFormatList)
|
TsBIFFNumFormatList = class(TsCustomNumFormatList)
|
||||||
protected
|
protected
|
||||||
procedure AddBuiltinFormats; override;
|
procedure AddBuiltinFormats; override;
|
||||||
|
procedure ConvertBeforeWriting(var AFormatString: String;
|
||||||
|
var ANumFormat: TsNumberFormat; var ADecimals: Byte;
|
||||||
|
var ACurrencySymbol: String); override;
|
||||||
public
|
public
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -375,13 +378,15 @@ type
|
|||||||
function DecodeRKValue(const ARK: DWORD): Double;
|
function DecodeRKValue(const ARK: DWORD): Double;
|
||||||
// Returns the numberformat for a given XF record
|
// Returns the numberformat for a given XF record
|
||||||
procedure ExtractNumberFormat(AXFIndex: WORD;
|
procedure ExtractNumberFormat(AXFIndex: WORD;
|
||||||
out ANumberFormat: TsNumberFormat; out ADecimals: Byte;
|
out ANumberFormat: TsNumberFormat; //out ADecimals: Byte;
|
||||||
out ACurrencySymbol: String; out ANumberFormatStr: String); virtual;
|
//out ACurrencySymbol: String;
|
||||||
|
out ANumberFormatStr: String); virtual;
|
||||||
// Finds format record for XF record pointed to by cell
|
// Finds format record for XF record pointed to by cell
|
||||||
// Will not return info for built-in formats
|
// Will not return info for built-in formats
|
||||||
function FindNumFormatDataForCell(const AXFIndex: Integer): TsNumFormatData;
|
function FindNumFormatDataForCell(const AXFIndex: Integer): TsNumFormatData;
|
||||||
// Tries to find if a number cell is actually a date/datetime/time cell and retrieves the value
|
// Tries to find if a number cell is actually a date/datetime/time cell and retrieves the value
|
||||||
function IsDateTime(Number: Double; ANumberFormat: TsNumberFormat; var ADateTime: TDateTime): Boolean;
|
function IsDateTime(Number: Double; ANumberFormat: TsNumberFormat;
|
||||||
|
ANumberFormatStr: String; var ADateTime: TDateTime): Boolean;
|
||||||
// Here we can add reading of records which didn't change across BIFF5-8 versions
|
// Here we can add reading of records which didn't change across BIFF5-8 versions
|
||||||
procedure ReadCodePage(AStream: TStream);
|
procedure ReadCodePage(AStream: TStream);
|
||||||
// Read column info
|
// Read column info
|
||||||
@ -708,48 +713,50 @@ end;
|
|||||||
|
|
||||||
{ These are the built-in number formats as expected in the biff spreadsheet file.
|
{ These are the built-in number formats as expected in the biff spreadsheet file.
|
||||||
In BIFF5+ they are not written to file but they are used for lookup of the
|
In BIFF5+ they are not written to file but they are used for lookup of the
|
||||||
number format that Excel used. They have to be converted to fpspreadsheet format. }
|
number format that Excel used. They are specified here in fpc dialect. }
|
||||||
procedure TsBIFFNumFormatList.AddBuiltinFormats;
|
procedure TsBIFFNumFormatList.AddBuiltinFormats;
|
||||||
var
|
var
|
||||||
|
fs: TFormatSettings;
|
||||||
cs: String;
|
cs: String;
|
||||||
begin
|
begin
|
||||||
|
fs := Workbook.FormatSettings;
|
||||||
cs := AnsiToUTF8(Workbook.FormatSettings.CurrencyString);
|
cs := AnsiToUTF8(Workbook.FormatSettings.CurrencyString);
|
||||||
|
|
||||||
AddFormat( 0, '', nfGeneral);
|
AddFormat( 0, '', nfGeneral);
|
||||||
AddFormat( 1, '0', nfFixed, 0);
|
AddFormat( 1, '0', nfFixed);
|
||||||
AddFormat( 2, '0.00', nfFixed, 2);
|
AddFormat( 2, '0.00', nfFixed);
|
||||||
AddFormat( 3, '#,##0', nfFixedTh, 0);
|
AddFormat( 3, '#,##0', nfFixedTh);
|
||||||
AddFormat( 4, '#,##0.00', nfFixedTh, 2);
|
AddFormat( 4, '#,##0.00', nfFixedTh);
|
||||||
AddFormat( 5, '"'+cs+'"#,##0_);("'+cs+'"#,##0)', nfCurrency, 0);
|
AddFormat( 5, '"'+cs+'"#,##0_);("'+cs+'"#,##0)', nfCurrency);
|
||||||
AddFormat( 6, '"'+cs+'"#,##0_);[Red]("'+cs+'"#,##0)', nfCurrencyRed, 0);
|
AddFormat( 6, '"'+cs+'"#,##0_);[Red]("'+cs+'"#,##0)', nfCurrencyRed);
|
||||||
AddFormat( 7, '"'+cs+'"#,##0.00_);("'+cs+'"#,##0.00)', nfCurrency, 2);
|
AddFormat( 7, '"'+cs+'"#,##0.00_);("'+cs+'"#,##0.00)', nfCurrency);
|
||||||
AddFormat( 8, '"'+cs+'"#,##0.00_);[Red]("'+cs+'"#,##0.00)', nfCurrencyRed, 2);
|
AddFormat( 8, '"'+cs+'"#,##0.00_);[Red]("'+cs+'"#,##0.00)', nfCurrencyRed);
|
||||||
AddFormat( 9, '0%', nfPercentage, 0);
|
AddFormat( 9, '0%', nfPercentage);
|
||||||
AddFormat(10, '0.00%', nfPercentage, 2);
|
AddFormat(10, '0.00%', nfPercentage);
|
||||||
AddFormat(11, '0.00E+00', nfExp, 2);
|
AddFormat(11, '0.00E+00', nfExp);
|
||||||
// fraction formats 12 ('# ?/?') and 13 ('# ??/??') not supported
|
// fraction formats 12 ('# ?/?') and 13 ('# ??/??') not supported
|
||||||
AddFormat(14, 'M/D/YY', nfShortDate);
|
AddFormat(14, fs.ShortDateFormat, nfShortDate); // 'M/D/YY'
|
||||||
AddFormat(15, 'D-MMM-YY', nfLongDate);
|
AddFormat(15, fs.LongDateFormat, nfLongDate); // 'D-MMM-YY'
|
||||||
AddFormat(16, 'D-MMM', nfFmtDateTime);
|
AddFormat(16, 'd/mmm', nfCustom); // 'D-MMM'
|
||||||
AddFormat(17, 'MMM-YY', nfFmtDateTime);
|
AddFormat(17, 'mmm/yy', nfCustom); // 'MMM-YY'
|
||||||
AddFormat(18, 'h:mm AM/PM', nfShortTimeAM);
|
AddFormat(18, AddAMPM(fs.ShortTimeFormat, fs), nfShortTimeAM); // 'h:mm AM/PM'
|
||||||
AddFormat(19, 'h:mm:ss AM/PM', nfLongTimeAM);
|
AddFormat(19, AddAMPM(fs.LongTimeFormat, fs), nfLongTimeAM); // 'h:mm:ss AM/PM'
|
||||||
AddFormat(20, 'h:mm', nfShortTime);
|
AddFormat(20, fs.ShortTimeFormat, nfShortTime); // 'h:mm'
|
||||||
AddFormat(21, 'h:mm:ss', nfLongTime);
|
AddFormat(21, fs.LongTimeFormat, nfLongTime); // 'h:mm:ss'
|
||||||
AddFormat(22, 'M/D/YY h:mm', nfShortDateTime);
|
AddFormat(22, fs.ShortDateFormat + ' ' + fs.ShortTimeFormat, nfShortDateTime); // 'M/D/YY h:mm' (localized)
|
||||||
// 23..36 not supported
|
// 23..36 not supported
|
||||||
AddFormat(37, '_(#,##0_);(#,##0)', nfCurrency, 0);
|
AddFormat(37, '_(#,##0_);(#,##0)', nfCurrency);
|
||||||
AddFormat(38, '_(#,##0_);[Red](#,##0)', nfCurrencyRed, 0);
|
AddFormat(38, '_(#,##0_);[Red](#,##0)', nfCurrencyRed);
|
||||||
AddFormat(39, '_(#,##0.00_);(#,##0.00)', nfCurrency, 2);
|
AddFormat(39, '_(#,##0.00_);(#,##0.00)', nfCurrency);
|
||||||
AddFormat(40, '_(#,##0.00_);[Red](#,##0.00)', nfCurrencyRed, 2);
|
AddFormat(40, '_(#,##0.00_);[Red](#,##0.00)', nfCurrencyRed);
|
||||||
AddFormat(41, '_("'+cs+'"* #,##0_);_("'+cs+'"* (#,##0);_("'+cs+'"* "-"_);_(@_)', nfAccounting, 0);
|
AddFormat(41, '_("'+cs+'"* #,##0_);_("'+cs+'"* (#,##0);_("'+cs+'"* "-"_);_(@_)', nfAccounting);
|
||||||
AddFormat(42, '_(* #,##0_);_(* (#,##0);_(* "-"_);_(@_)', nfAccounting, 0);
|
AddFormat(42, '_(* #,##0_);_(* (#,##0);_(* "-"_);_(@_)', nfAccounting);
|
||||||
AddFormat(43, '_("'+cs+'"* #,##0.00_);_("'+cs+'"* (#,##0.00);_("'+cs+'"* "-"??_);_(@_)', nfAccounting, 2);
|
AddFormat(43, '_("'+cs+'"* #,##0.00_);_("'+cs+'"* (#,##0.00);_("'+cs+'"* "-"??_);_(@_)', nfAccounting);
|
||||||
AddFormat(44, '_(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(@_)', nfAccounting, 2);
|
AddFormat(44, '_(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(@_)', nfAccounting);
|
||||||
AddFormat(45, 'mm:ss', nfFmtDateTime);
|
AddFormat(45, 'nn:ss', nfCustom);
|
||||||
AddFormat(46, '[h]:mm:ss', nfTimeInterval);
|
AddFormat(46, '[h]:nn:ss', nfTimeInterval);
|
||||||
AddFormat(47, 'mm:ss.0', nfFmtDateTime);
|
AddFormat(47, 'nn:ss.z', nfCustom);
|
||||||
AddFormat(48, '##0.0E+00', nfSci, 1);
|
AddFormat(48, '##0.0E+00', nfSci);
|
||||||
// 49 ("Text") not supported
|
// 49 ("Text") not supported
|
||||||
|
|
||||||
// All indexes from 0 to 163 are reserved for built-in formats.
|
// All indexes from 0 to 163 are reserved for built-in formats.
|
||||||
@ -758,6 +765,26 @@ begin
|
|||||||
FNextFormatIndex := 164;
|
FNextFormatIndex := 164;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TsBIFFNumFormatList.ConvertBeforeWriting(var AFormatString: String;
|
||||||
|
var ANumFormat: TsNumberFormat; var ADecimals: Byte; var ACurrencySymbol: String);
|
||||||
|
var
|
||||||
|
parser: TsNumFormatParser;
|
||||||
|
fmt: String;
|
||||||
|
begin
|
||||||
|
parser := TsNumFormatParser.Create(Workbook, AFormatString);
|
||||||
|
try
|
||||||
|
if parser.Status = psOK then begin
|
||||||
|
// We convert the fpc format string to Excel dialect
|
||||||
|
AFormatString := parser.FormatString[nfdExcel];
|
||||||
|
ANumFormat := parser.NumFormat;
|
||||||
|
ADecimals := parser.Decimals;
|
||||||
|
ACurrencySymbol := parser.CurrencySymbol;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
parser.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
{ TsSpreadBIFFReader }
|
{ TsSpreadBIFFReader }
|
||||||
|
|
||||||
@ -840,12 +867,14 @@ var
|
|||||||
begin
|
begin
|
||||||
FreeAndNil(FNumFormatList);
|
FreeAndNil(FNumFormatList);
|
||||||
FNumFormatList := TsBIFFNumFormatList.Create(Workbook);
|
FNumFormatList := TsBIFFNumFormatList.Create(Workbook);
|
||||||
|
(*
|
||||||
// Convert builtin formats to fps syntax
|
// Convert builtin formats to fps syntax
|
||||||
for i:=0 to FNumFormatList.Count-1 do begin
|
for i:=0 to FNumFormatList.Count-1 do begin
|
||||||
item := FNumFormatList[i];
|
item := FNumFormatList[i];
|
||||||
FNumFormatList.ConvertAfterReading(item.Index, item.FormatString,
|
FNumFormatList.ConvertAfterReading(item.Index, item.FormatString,
|
||||||
item.NumFormat, item.Decimals, item.CurrencySymbol);
|
item.NumFormat, item.Decimals, item.CurrencySymbol);
|
||||||
end;
|
end;
|
||||||
|
*)
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Extracts a number out of an RK value.
|
{ Extracts a number out of an RK value.
|
||||||
@ -883,8 +912,9 @@ end;
|
|||||||
{ Extracts number format data from an XF record index by AXFIndex.
|
{ Extracts number format data from an XF record index by AXFIndex.
|
||||||
Valid for BIFF5-BIFF8. Needs to be overridden for BIFF2 }
|
Valid for BIFF5-BIFF8. Needs to be overridden for BIFF2 }
|
||||||
procedure TsSpreadBIFFReader.ExtractNumberFormat(AXFIndex: WORD;
|
procedure TsSpreadBIFFReader.ExtractNumberFormat(AXFIndex: WORD;
|
||||||
out ANumberFormat: TsNumberFormat; out ADecimals: Byte;
|
out ANumberFormat: TsNumberFormat; //out ADecimals: Byte;
|
||||||
out ACurrencySymbol: String; out ANumberFormatStr: String);
|
//out ACurrencySymbol: String;
|
||||||
|
out ANumberFormatStr: String);
|
||||||
var
|
var
|
||||||
lNumFormatData: TsNumFormatData;
|
lNumFormatData: TsNumFormatData;
|
||||||
begin
|
begin
|
||||||
@ -892,13 +922,13 @@ begin
|
|||||||
if lNumFormatData <> nil then begin
|
if lNumFormatData <> nil then begin
|
||||||
ANumberFormat := lNumFormatData.NumFormat;
|
ANumberFormat := lNumFormatData.NumFormat;
|
||||||
ANumberFormatStr := lNumFormatData.FormatString;
|
ANumberFormatStr := lNumFormatData.FormatString;
|
||||||
ADecimals := lNumFormatData.Decimals;
|
// ADecimals := lNumFormatData.Decimals;
|
||||||
ACurrencySymbol := lNumFormatData.CurrencySymbol;
|
// ACurrencySymbol := lNumFormatData.CurrencySymbol;
|
||||||
end else begin
|
end else begin
|
||||||
ANumberFormat := nfGeneral;
|
ANumberFormat := nfGeneral;
|
||||||
ANumberFormatStr := '';
|
ANumberFormatStr := '';
|
||||||
ADecimals := 0;
|
// ADecimals := 0;
|
||||||
ACurrencySymbol := '';
|
// ACurrencySymbol := '';
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -918,22 +948,30 @@ end;
|
|||||||
|
|
||||||
{ Convert the number to a date/time and return that if it is }
|
{ Convert the number to a date/time and return that if it is }
|
||||||
function TsSpreadBIFFReader.IsDateTime(Number: Double;
|
function TsSpreadBIFFReader.IsDateTime(Number: Double;
|
||||||
ANumberFormat: TsNumberFormat; var ADateTime: TDateTime): boolean;
|
ANumberFormat: TsNumberFormat; ANumberFormatStr: String;
|
||||||
|
var ADateTime: TDateTime): boolean;
|
||||||
|
var
|
||||||
|
parser: TsNumFormatParser;
|
||||||
begin
|
begin
|
||||||
|
Result := true;
|
||||||
if ANumberFormat in [
|
if ANumberFormat in [
|
||||||
nfShortDateTime, nfFmtDateTime, nfShortDate, nfLongDate,
|
nfShortDateTime, {nfFmtDateTime, }nfShortDate, nfLongDate,
|
||||||
nfShortTime, nfLongTime, nfShortTimeAM, nfLongTimeAM] then
|
nfShortTime, nfLongTime, nfShortTimeAM, nfLongTimeAM]
|
||||||
begin
|
then
|
||||||
ADateTime := ConvertExcelDateTimeToDateTime(Number, FDateMode);
|
ADateTime := ConvertExcelDateTimeToDateTime(Number, FDateMode)
|
||||||
Result := true;
|
else
|
||||||
end else
|
if ANumberFormat = nfTimeInterval then
|
||||||
if ANumberFormat = nfTimeInterval then begin
|
ADateTime := Number
|
||||||
ADateTime := Number;
|
else begin
|
||||||
Result := true;
|
parser := TsNumFormatParser.Create(Workbook, ANumberFormatStr);
|
||||||
end else
|
try
|
||||||
begin
|
if (parser.Status = psOK) and parser.IsDateTimeFormat then
|
||||||
ADateTime := 0;
|
ADateTime := ConvertExcelDateTimeToDateTime(Number, FDateMode)
|
||||||
|
else
|
||||||
Result := false;
|
Result := false;
|
||||||
|
finally
|
||||||
|
parser.Free;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1108,11 +1146,11 @@ begin
|
|||||||
Move(Data[0], ResultFormula, SizeOf(Data));
|
Move(Data[0], ResultFormula, SizeOf(Data));
|
||||||
|
|
||||||
{Find out what cell type, set content type and value}
|
{Find out what cell type, set content type and value}
|
||||||
ExtractNumberFormat(XF, nf, nd, ncs, nfs);
|
ExtractNumberFormat(XF, nf, nfs);
|
||||||
if IsDateTime(ResultFormula, nf, dt) then
|
if IsDateTime(ResultFormula, nf, nfs, dt) then
|
||||||
FWorksheet.WriteDateTime(ARow, ACol, dt, nf, nfs)
|
FWorksheet.WriteDateTime(ARow, ACol, dt, nf, nfs)
|
||||||
else
|
else
|
||||||
FWorksheet.WriteNumber(ARow, ACol, ResultFormula, nf, nd, ncs);
|
FWorksheet.WriteNumber(ARow, ACol, ResultFormula, nf, nfs); //, nd, ncs);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Formula token array }
|
{ Formula token array }
|
||||||
@ -1174,11 +1212,11 @@ begin
|
|||||||
RK := DWordLEtoN(AStream.ReadDWord);
|
RK := DWordLEtoN(AStream.ReadDWord);
|
||||||
lNumber := DecodeRKValue(RK);
|
lNumber := DecodeRKValue(RK);
|
||||||
{Find out what cell type, set contenttype and value}
|
{Find out what cell type, set contenttype and value}
|
||||||
ExtractNumberFormat(XF, nf, nd, ncs, nfs);
|
ExtractNumberFormat(XF, nf, nfs);
|
||||||
if IsDateTime(lNumber, nf, lDateTime) then
|
if IsDateTime(lNumber, nf, nfs, lDateTime) then
|
||||||
FWorksheet.WriteDateTime(ARow, fc, lDateTime, nf, nfs)
|
FWorksheet.WriteDateTime(ARow, fc, lDateTime, nf, nfs)
|
||||||
else
|
else
|
||||||
FWorksheet.WriteNumber(ARow, fc, lNumber, nf, nd, ncs);
|
FWorksheet.WriteNumber(ARow, fc, lNumber, nf, nfs);
|
||||||
inc(fc);
|
inc(fc);
|
||||||
dec(pending, SizeOf(XF) + SizeOf(RK));
|
dec(pending, SizeOf(XF) + SizeOf(RK));
|
||||||
end;
|
end;
|
||||||
@ -1210,13 +1248,11 @@ begin
|
|||||||
AStream.ReadBuffer(value, 8);
|
AStream.ReadBuffer(value, 8);
|
||||||
|
|
||||||
{Find out what cell type, set content type and value}
|
{Find out what cell type, set content type and value}
|
||||||
ExtractNumberFormat(XF, nf, nd, ncs, nfs);
|
ExtractNumberFormat(XF, nf, nfs);
|
||||||
if IsDateTime(value, nf, dt) then
|
if IsDateTime(value, nf, nfs, dt) then
|
||||||
FWorksheet.WriteDateTime(ARow, ACol, dt) //, nf, nfs)
|
FWorksheet.WriteDateTime(ARow, ACol, dt, nf, nfs)
|
||||||
else
|
else
|
||||||
//if nf <> nfCustom then // why was this here?
|
FWorksheet.WriteNumber(ARow, ACol, value, nf, nfs);
|
||||||
FWorksheet.WriteNumber(ARow, ACol, value, nf, nd, ncs);
|
|
||||||
FWorksheet.WriteNumberFormat(ARow, ACol, nf, nfs); // override built-in format string
|
|
||||||
|
|
||||||
{ Add attributes to cell }
|
{ Add attributes to cell }
|
||||||
ApplyCellFormatting(ARow, ACol, XF);
|
ApplyCellFormatting(ARow, ACol, XF);
|
||||||
@ -1297,17 +1333,17 @@ begin
|
|||||||
Number := DecodeRKValue(RK);
|
Number := DecodeRKValue(RK);
|
||||||
|
|
||||||
{Find out what cell type, set contenttype and value}
|
{Find out what cell type, set contenttype and value}
|
||||||
ExtractNumberFormat(XF, nf, nd, ncs, nfs);
|
ExtractNumberFormat(XF, nf, nfs);
|
||||||
if IsDateTime(Number, nf, lDateTime) then
|
if IsDateTime(Number, nf, nfs, lDateTime) then
|
||||||
FWorksheet.WriteDateTime(ARow, ACol, lDateTime, nf, nfs)
|
FWorksheet.WriteDateTime(ARow, ACol, lDateTime, nf, nfs)
|
||||||
else
|
else
|
||||||
FWorksheet.WriteNumber(ARow, ACol, Number, nf, nd, ncs);
|
FWorksheet.WriteNumber(ARow, ACol, Number, nf, nfs);
|
||||||
|
|
||||||
{Add attributes}
|
{Add attributes}
|
||||||
ApplyCellFormatting(ARow, ACol, XF);
|
ApplyCellFormatting(ARow, ACol, XF);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Read the part of the ROW record that is common to all BIFF versions
|
// Read the part of the ROW record that is common to BIFF3-8 versions
|
||||||
procedure TsSpreadBIFFReader.ReadRowInfo(AStream: TStream);
|
procedure TsSpreadBIFFReader.ReadRowInfo(AStream: TStream);
|
||||||
type
|
type
|
||||||
TRowRecord = packed record
|
TRowRecord = packed record
|
||||||
@ -1325,6 +1361,21 @@ var
|
|||||||
h: word;
|
h: word;
|
||||||
begin
|
begin
|
||||||
AStream.ReadBuffer(rowrec, SizeOf(TRowRecord));
|
AStream.ReadBuffer(rowrec, SizeOf(TRowRecord));
|
||||||
|
|
||||||
|
// if bit 6 is set in the flags row height does not match the font size.
|
||||||
|
// Only for this case we create a row record for fpspreadsheet
|
||||||
|
if rowrec.Flags and $00000040 <> 0 then begin
|
||||||
|
lRow := FWorksheet.GetRow(WordLEToN(rowrec.RowIndex));
|
||||||
|
// row height is encoded into the 15 lower bits in units "twips" (1/20 pt)
|
||||||
|
// we need it in "lines", i.e. we divide the points by the point size of the default font
|
||||||
|
h := WordLEToN(rowrec.Height) and $7FFF;
|
||||||
|
lRow^.Height := TwipsToPts(h) / FWorkbook.GetDefaultFontSize;
|
||||||
|
if lRow^.Height > ROW_HEIGHT_CORRECTION then
|
||||||
|
lRow^.Height := lRow^.Height - ROW_HEIGHT_CORRECTION
|
||||||
|
else
|
||||||
|
lRow^.Height := 0;
|
||||||
|
end;
|
||||||
|
{
|
||||||
h := WordLEToN(rowrec.Height);
|
h := WordLEToN(rowrec.Height);
|
||||||
if h and $8000 = 0 then begin // if this bit were set, rowheight would be default
|
if h and $8000 = 0 then begin // if this bit were set, rowheight would be default
|
||||||
lRow := FWorksheet.GetRow(WordLEToN(rowrec.RowIndex));
|
lRow := FWorksheet.GetRow(WordLEToN(rowrec.RowIndex));
|
||||||
@ -1336,6 +1387,7 @@ begin
|
|||||||
else
|
else
|
||||||
lRow^.Height := 0;
|
lRow^.Height := 0;
|
||||||
end;
|
end;
|
||||||
|
}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Reads the cell address used in an RPN formula element. Evaluates the corresponding
|
{ Reads the cell address used in an RPN formula element. Evaluates the corresponding
|
||||||
@ -2118,6 +2170,7 @@ begin
|
|||||||
// But we have to consider that the number formats of the cell is in fpc syntax,
|
// But we have to consider that the number formats of the cell is in fpc syntax,
|
||||||
// but the number format list of the writer is in Excel syntax.
|
// but the number format list of the writer is in Excel syntax.
|
||||||
lCell := ACell^;
|
lCell := ACell^;
|
||||||
|
(*
|
||||||
with lCell do begin
|
with lCell do begin
|
||||||
if NumberFormat <> nfCustom then begin
|
if NumberFormat <> nfCustom then begin
|
||||||
if IsDateTimeFormat(NumberFormat) then
|
if IsDateTimeFormat(NumberFormat) then
|
||||||
@ -2126,9 +2179,10 @@ begin
|
|||||||
else
|
else
|
||||||
NumberFormatStr := BuildNumberFormatString(NumberFormat,
|
NumberFormatStr := BuildNumberFormatString(NumberFormat,
|
||||||
Workbook.FormatSettings, Decimals, CurrencySymbol);
|
Workbook.FormatSettings, Decimals, CurrencySymbol);
|
||||||
NumFormatList.ConvertBeforeWriting(NumberFormatStr, NumberFormat, Decimals, CurrencyString);
|
//NumFormatList.ConvertBeforeWriting(NumberFormatStr, NumberFormat, Decimals, CurrencyString);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
*)
|
||||||
lIndex := FindFormattingInList(@lCell);
|
lIndex := FindFormattingInList(@lCell);
|
||||||
|
|
||||||
// Carefully check the index
|
// Carefully check the index
|
||||||
|
Reference in New Issue
Block a user