You've already forked lazarus-ccr
fpspreadsheet: Integrate number format parser into fpspreadsheet. Some regressions in format detection...
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3068 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -29,7 +29,8 @@ var
|
|||||||
number: Double;
|
number: Double;
|
||||||
lCell: PCell;
|
lCell: PCell;
|
||||||
lCol: TCol;
|
lCol: TCol;
|
||||||
i, r: Integer;
|
i: Integer;
|
||||||
|
r: Integer = 10;
|
||||||
begin
|
begin
|
||||||
MyDir := ExtractFilePath(ParamStr(0));
|
MyDir := ExtractFilePath(ParamStr(0));
|
||||||
|
|
||||||
@ -53,7 +54,7 @@ begin
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write some cells
|
// Write some cells
|
||||||
// MyWorksheet.WriteNumber(0, 0, 1.0);// A1
|
MyWorksheet.WriteDateTime(0, 20, now, nfShortTime); //1.0);// A1
|
||||||
MyWorksheet.WriteNumber(0, 0, 1.0, nfFixed, 3);// A1
|
MyWorksheet.WriteNumber(0, 0, 1.0, nfFixed, 3);// A1
|
||||||
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
|
||||||
@ -206,10 +207,6 @@ begin
|
|||||||
inc(r);
|
inc(r);
|
||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfFmtDateTime, mm:ss.zzz');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfFmtDateTime, mm:ss.zzz');
|
||||||
MyWorksheet.WriteDateTime(r, 1, now, nfFmtDateTime, 'mm:ss.zzz');
|
MyWorksheet.WriteDateTime(r, 1, now, nfFmtDateTime, 'mm:ss.zzz');
|
||||||
// NOTE: The upper option "MSZ" = "mm:ss.z" should result only in 1 decimal.
|
|
||||||
// This is true for writing, but in reading always 3 decimals are displayed.
|
|
||||||
// This is due to fpc's SysUtile.FormatDateTime which does not distinguish
|
|
||||||
// both cases.
|
|
||||||
|
|
||||||
// Write formatted numbers
|
// Write formatted numbers
|
||||||
number := 12345.67890123456789;
|
number := 12345.67890123456789;
|
||||||
@ -252,7 +249,6 @@ begin
|
|||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfFixedTh, 3 decs');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfFixedTh, 3 decs');
|
||||||
MyWorksheet.WriteNumber(r, 1, number, nfFixedTh, 3);
|
MyWorksheet.WriteNumber(r, 1, number, nfFixedTh, 3);
|
||||||
MyWorksheet.WriteNumber(r, 2, -number, nfFixedTh, 3);
|
MyWorksheet.WriteNumber(r, 2, -number, nfFixedTh, 3);
|
||||||
|
|
||||||
inc(r,2);
|
inc(r,2);
|
||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfSci, 1 dec');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfSci, 1 dec');
|
||||||
MyWorksheet.WriteNumber(r, 1, number, nfSci, 1);
|
MyWorksheet.WriteNumber(r, 1, number, nfSci, 1);
|
||||||
|
@ -137,8 +137,7 @@
|
|||||||
<Unit2>
|
<Unit2>
|
||||||
<Filename Value="..\..\fpspreadsheet.pas"/>
|
<Filename Value="..\..\fpspreadsheet.pas"/>
|
||||||
<UnitName Value="fpspreadsheet"/>
|
<UnitName Value="fpspreadsheet"/>
|
||||||
<IsVisibleTab Value="True"/>
|
<EditorIndex Value="5"/>
|
||||||
<EditorIndex Value="6"/>
|
|
||||||
<WindowIndex Value="0"/>
|
<WindowIndex Value="0"/>
|
||||||
<TopLine Value="132"/>
|
<TopLine Value="132"/>
|
||||||
<CursorPos X="16" Y="164"/>
|
<CursorPos X="16" Y="164"/>
|
||||||
@ -148,7 +147,7 @@
|
|||||||
<Unit3>
|
<Unit3>
|
||||||
<Filename Value="..\..\fpspreadsheetgrid.pas"/>
|
<Filename Value="..\..\fpspreadsheetgrid.pas"/>
|
||||||
<UnitName Value="fpspreadsheetgrid"/>
|
<UnitName Value="fpspreadsheetgrid"/>
|
||||||
<EditorIndex Value="8"/>
|
<EditorIndex Value="6"/>
|
||||||
<WindowIndex Value="0"/>
|
<WindowIndex Value="0"/>
|
||||||
<TopLine Value="636"/>
|
<TopLine Value="636"/>
|
||||||
<CursorPos X="20" Y="647"/>
|
<CursorPos X="20" Y="647"/>
|
||||||
@ -286,10 +285,11 @@
|
|||||||
<Unit20>
|
<Unit20>
|
||||||
<Filename Value="..\..\xlscommon.pas"/>
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
<UnitName Value="xlscommon"/>
|
<UnitName Value="xlscommon"/>
|
||||||
|
<IsVisibleTab Value="True"/>
|
||||||
<EditorIndex Value="4"/>
|
<EditorIndex Value="4"/>
|
||||||
<WindowIndex Value="0"/>
|
<WindowIndex Value="0"/>
|
||||||
<TopLine Value="1181"/>
|
<TopLine Value="650"/>
|
||||||
<CursorPos X="31" Y="1194"/>
|
<CursorPos X="16" Y="662"/>
|
||||||
<UsageCount Value="88"/>
|
<UsageCount Value="88"/>
|
||||||
<Bookmarks Count="1">
|
<Bookmarks Count="1">
|
||||||
<Item0 X="41" Y="1209" ID="1"/>
|
<Item0 X="41" Y="1209" ID="1"/>
|
||||||
@ -577,143 +577,139 @@
|
|||||||
</Unit57>
|
</Unit57>
|
||||||
<Unit58>
|
<Unit58>
|
||||||
<Filename Value="d:\lazarus-svn\fpc\2.6.2\source\rtl\objpas\sysutils\dati.inc"/>
|
<Filename Value="d:\lazarus-svn\fpc\2.6.2\source\rtl\objpas\sysutils\dati.inc"/>
|
||||||
<EditorIndex Value="5"/>
|
|
||||||
<WindowIndex Value="0"/>
|
<WindowIndex Value="0"/>
|
||||||
<TopLine Value="890"/>
|
<TopLine Value="890"/>
|
||||||
<CursorPos X="16" Y="796"/>
|
<CursorPos X="16" Y="796"/>
|
||||||
<UsageCount Value="15"/>
|
<UsageCount Value="15"/>
|
||||||
<Loaded Value="True"/>
|
|
||||||
</Unit58>
|
</Unit58>
|
||||||
<Unit59>
|
<Unit59>
|
||||||
<Filename Value="d:\lazarus-svn\fpc\2.6.2\source\rtl\objpas\sysutils\sysinth.inc"/>
|
<Filename Value="d:\lazarus-svn\fpc\2.6.2\source\rtl\objpas\sysutils\sysinth.inc"/>
|
||||||
<EditorIndex Value="7"/>
|
|
||||||
<WindowIndex Value="0"/>
|
<WindowIndex Value="0"/>
|
||||||
<TopLine Value="36"/>
|
<TopLine Value="36"/>
|
||||||
<CursorPos X="5" Y="43"/>
|
<CursorPos X="5" Y="43"/>
|
||||||
<UsageCount Value="13"/>
|
<UsageCount Value="13"/>
|
||||||
<Loaded Value="True"/>
|
|
||||||
</Unit59>
|
</Unit59>
|
||||||
</Units>
|
</Units>
|
||||||
<JumpHistory Count="30" HistoryIndex="29">
|
<JumpHistory Count="30" HistoryIndex="29">
|
||||||
<Position1>
|
<Position1>
|
||||||
<Filename Value="..\..\fpspreadsheet.pas"/>
|
<Filename Value="..\..\fpspreadsheet.pas"/>
|
||||||
<Caret Line="1" Column="1" TopLine="1"/>
|
<Caret Line="164" Column="60" TopLine="132"/>
|
||||||
</Position1>
|
</Position1>
|
||||||
<Position2>
|
<Position2>
|
||||||
<Filename Value="..\..\fpspreadsheet.pas"/>
|
<Filename Value="..\..\fpspreadsheet.pas"/>
|
||||||
<Caret Line="164" Column="60" TopLine="132"/>
|
<Caret Line="1511" Column="15" TopLine="1478"/>
|
||||||
</Position2>
|
</Position2>
|
||||||
<Position3>
|
<Position3>
|
||||||
<Filename Value="..\..\fpspreadsheet.pas"/>
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
<Caret Line="1511" Column="15" TopLine="1478"/>
|
<Caret Line="1170" Column="36" TopLine="1170"/>
|
||||||
</Position3>
|
</Position3>
|
||||||
<Position4>
|
<Position4>
|
||||||
<Filename Value="..\..\xlscommon.pas"/>
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
<Caret Line="1170" Column="36" TopLine="1170"/>
|
<Caret Line="1" Column="1" TopLine="1"/>
|
||||||
</Position4>
|
</Position4>
|
||||||
<Position5>
|
<Position5>
|
||||||
<Filename Value="..\..\xlscommon.pas"/>
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
<Caret Line="1" Column="1" TopLine="1"/>
|
<Caret Line="940" Column="14" TopLine="908"/>
|
||||||
</Position5>
|
</Position5>
|
||||||
<Position6>
|
<Position6>
|
||||||
<Filename Value="..\..\xlscommon.pas"/>
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
<Caret Line="940" Column="14" TopLine="908"/>
|
<Caret Line="960" Column="14" TopLine="928"/>
|
||||||
</Position6>
|
</Position6>
|
||||||
<Position7>
|
<Position7>
|
||||||
<Filename Value="..\..\xlscommon.pas"/>
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
<Caret Line="960" Column="14" TopLine="928"/>
|
<Caret Line="1013" Column="14" TopLine="982"/>
|
||||||
</Position7>
|
</Position7>
|
||||||
<Position8>
|
<Position8>
|
||||||
<Filename Value="..\..\xlscommon.pas"/>
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
<Caret Line="1013" Column="14" TopLine="982"/>
|
<Caret Line="1059" Column="14" TopLine="1027"/>
|
||||||
</Position8>
|
</Position8>
|
||||||
<Position9>
|
<Position9>
|
||||||
<Filename Value="..\..\xlscommon.pas"/>
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
<Caret Line="1059" Column="14" TopLine="1027"/>
|
<Caret Line="1081" Column="41" TopLine="1049"/>
|
||||||
</Position9>
|
</Position9>
|
||||||
<Position10>
|
<Position10>
|
||||||
<Filename Value="..\..\xlscommon.pas"/>
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
<Caret Line="1081" Column="41" TopLine="1049"/>
|
<Caret Line="1089" Column="43" TopLine="1057"/>
|
||||||
</Position10>
|
</Position10>
|
||||||
<Position11>
|
<Position11>
|
||||||
<Filename Value="..\..\xlscommon.pas"/>
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
<Caret Line="1089" Column="43" TopLine="1057"/>
|
<Caret Line="1093" Column="14" TopLine="1061"/>
|
||||||
</Position11>
|
</Position11>
|
||||||
<Position12>
|
<Position12>
|
||||||
<Filename Value="..\..\xlscommon.pas"/>
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
<Caret Line="1093" Column="14" TopLine="1061"/>
|
<Caret Line="1157" Column="14" TopLine="1126"/>
|
||||||
</Position12>
|
</Position12>
|
||||||
<Position13>
|
<Position13>
|
||||||
<Filename Value="..\..\xlscommon.pas"/>
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
<Caret Line="1157" Column="14" TopLine="1126"/>
|
<Caret Line="1197" Column="20" TopLine="1177"/>
|
||||||
</Position13>
|
</Position13>
|
||||||
<Position14>
|
<Position14>
|
||||||
<Filename Value="..\..\xlscommon.pas"/>
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
<Caret Line="1197" Column="20" TopLine="1177"/>
|
<Caret Line="403" Column="16" TopLine="397"/>
|
||||||
</Position14>
|
</Position14>
|
||||||
<Position15>
|
<Position15>
|
||||||
<Filename Value="..\..\xlscommon.pas"/>
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
<Caret Line="403" Column="16" TopLine="397"/>
|
<Caret Line="924" Column="14" TopLine="893"/>
|
||||||
</Position15>
|
</Position15>
|
||||||
<Position16>
|
<Position16>
|
||||||
<Filename Value="..\..\xlscommon.pas"/>
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
<Caret Line="924" Column="14" TopLine="893"/>
|
<Caret Line="413" Column="19" TopLine="402"/>
|
||||||
</Position16>
|
</Position16>
|
||||||
<Position17>
|
<Position17>
|
||||||
<Filename Value="..\..\xlscommon.pas"/>
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
<Caret Line="413" Column="19" TopLine="402"/>
|
<Caret Line="414" Column="33" TopLine="388"/>
|
||||||
</Position17>
|
</Position17>
|
||||||
<Position18>
|
<Position18>
|
||||||
<Filename Value="..\..\xlscommon.pas"/>
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
<Caret Line="414" Column="33" TopLine="388"/>
|
<Caret Line="854" Column="39" TopLine="825"/>
|
||||||
</Position18>
|
</Position18>
|
||||||
<Position19>
|
<Position19>
|
||||||
<Filename Value="..\..\xlscommon.pas"/>
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
<Caret Line="854" Column="39" TopLine="825"/>
|
<Caret Line="672" Column="1" TopLine="648"/>
|
||||||
</Position19>
|
</Position19>
|
||||||
<Position20>
|
<Position20>
|
||||||
<Filename Value="..\..\xlscommon.pas"/>
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
<Caret Line="672" Column="1" TopLine="648"/>
|
<Caret Line="870" Column="1" TopLine="832"/>
|
||||||
</Position20>
|
</Position20>
|
||||||
<Position21>
|
<Position21>
|
||||||
<Filename Value="..\..\xlscommon.pas"/>
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
<Caret Line="870" Column="1" TopLine="832"/>
|
<Caret Line="867" Column="24" TopLine="848"/>
|
||||||
</Position21>
|
</Position21>
|
||||||
<Position22>
|
<Position22>
|
||||||
<Filename Value="..\..\xlscommon.pas"/>
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
<Caret Line="867" Column="24" TopLine="848"/>
|
<Caret Line="926" Column="34" TopLine="907"/>
|
||||||
</Position22>
|
</Position22>
|
||||||
<Position23>
|
<Position23>
|
||||||
<Filename Value="..\..\xlscommon.pas"/>
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
<Caret Line="926" Column="34" TopLine="907"/>
|
<Caret Line="956" Column="1" TopLine="937"/>
|
||||||
</Position23>
|
</Position23>
|
||||||
<Position24>
|
<Position24>
|
||||||
<Filename Value="..\..\xlscommon.pas"/>
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
<Caret Line="956" Column="1" TopLine="937"/>
|
<Caret Line="1024" Column="63" TopLine="1006"/>
|
||||||
</Position24>
|
</Position24>
|
||||||
<Position25>
|
<Position25>
|
||||||
<Filename Value="..\..\xlscommon.pas"/>
|
<Filename Value="..\..\fpspreadsheet.pas"/>
|
||||||
<Caret Line="1024" Column="63" TopLine="1006"/>
|
<Caret Line="1478" Column="48" TopLine="1478"/>
|
||||||
</Position25>
|
</Position25>
|
||||||
<Position26>
|
<Position26>
|
||||||
<Filename Value="..\..\fpspreadsheet.pas"/>
|
<Filename Value="..\..\fpspreadsheet.pas"/>
|
||||||
<Caret Line="1478" Column="48" TopLine="1478"/>
|
<Caret Line="1" Column="1" TopLine="1"/>
|
||||||
</Position26>
|
</Position26>
|
||||||
<Position27>
|
<Position27>
|
||||||
<Filename Value="..\..\fpspreadsheet.pas"/>
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
<Caret Line="1" Column="1" TopLine="1"/>
|
<Caret Line="1058" Column="9" TopLine="1039"/>
|
||||||
</Position27>
|
</Position27>
|
||||||
<Position28>
|
<Position28>
|
||||||
<Filename Value="..\..\xlscommon.pas"/>
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
<Caret Line="1058" Column="9" TopLine="1039"/>
|
<Caret Line="1055" Column="44" TopLine="1039"/>
|
||||||
</Position28>
|
</Position28>
|
||||||
<Position29>
|
<Position29>
|
||||||
<Filename Value="..\..\xlscommon.pas"/>
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
<Caret Line="1055" Column="44" TopLine="1039"/>
|
<Caret Line="1135" Column="22" TopLine="1120"/>
|
||||||
</Position29>
|
</Position29>
|
||||||
<Position30>
|
<Position30>
|
||||||
<Filename Value="..\..\xlscommon.pas"/>
|
<Filename Value="..\..\fpspreadsheet.pas"/>
|
||||||
<Caret Line="1135" Column="22" TopLine="1120"/>
|
<Caret Line="164" Column="16" TopLine="132"/>
|
||||||
</Position30>
|
</Position30>
|
||||||
</JumpHistory>
|
</JumpHistory>
|
||||||
</ProjectOptions>
|
</ProjectOptions>
|
||||||
@ -743,15 +739,6 @@
|
|||||||
</Other>
|
</Other>
|
||||||
</CompilerOptions>
|
</CompilerOptions>
|
||||||
<Debugging>
|
<Debugging>
|
||||||
<BreakPoints Count="1">
|
|
||||||
<Item1>
|
|
||||||
<Kind Value="bpkSource"/>
|
|
||||||
<WatchScope Value="wpsLocal"/>
|
|
||||||
<WatchKind Value="wpkWrite"/>
|
|
||||||
<Source Value="..\..\xlscommon.pas"/>
|
|
||||||
<Line Value="664"/>
|
|
||||||
</Item1>
|
|
||||||
</BreakPoints>
|
|
||||||
<Watches Count="2">
|
<Watches Count="2">
|
||||||
<Item1>
|
<Item1>
|
||||||
<Expression Value="recordtype"/>
|
<Expression Value="recordtype"/>
|
||||||
|
@ -27,6 +27,8 @@ type
|
|||||||
coEqual, coNotEqual, coLess, coGreater, coLessEqual, coGreaterEqual
|
coEqual, coNotEqual, coLess, coGreater, coLessEqual, coGreaterEqual
|
||||||
);
|
);
|
||||||
|
|
||||||
|
TsConversionDirection = (cdToFPSpreadsheet, cdFromFPSpreadsheet);
|
||||||
|
|
||||||
TsNumFormatSection = record
|
TsNumFormatSection = record
|
||||||
FormatString: String;
|
FormatString: String;
|
||||||
CompareOperation: TsCompareOperation;
|
CompareOperation: TsCompareOperation;
|
||||||
@ -38,17 +40,23 @@ type
|
|||||||
NumFormat: TsNumberFormat;
|
NumFormat: TsNumberFormat;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
TsNumFormatSections = array of TsNumFormatSection;
|
||||||
|
|
||||||
TsNumFormatParser = class
|
TsNumFormatParser = class
|
||||||
private
|
private
|
||||||
|
FCreateMethod: Byte;
|
||||||
FWorkbook: TsWorkbook;
|
FWorkbook: TsWorkbook;
|
||||||
FCurrent: PChar;
|
FCurrent: PChar;
|
||||||
FStart: PChar;
|
FStart: PChar;
|
||||||
FEnd: PChar;
|
FEnd: PChar;
|
||||||
FCurrSection: Integer;
|
FCurrSection: Integer;
|
||||||
FSections: array of TsNumFormatSection;
|
FSections: TsNumFormatSections;
|
||||||
FFormatSettings: TFormatSettings;
|
FFormatSettings: TFormatSettings;
|
||||||
FFormatString: String;
|
FFormatString: String;
|
||||||
|
FNumFormat: TsNumberFormat;
|
||||||
|
FConversionDirection: TsConversionDirection;
|
||||||
FStatus: Integer;
|
FStatus: Integer;
|
||||||
|
function GetFormatString: String;
|
||||||
function GetParsedSectionCount: Integer;
|
function GetParsedSectionCount: Integer;
|
||||||
function GetParsedSections(AIndex: Integer): TsNumFormatSection;
|
function GetParsedSections(AIndex: Integer): TsNumFormatSection;
|
||||||
|
|
||||||
@ -58,6 +66,8 @@ type
|
|||||||
procedure AnalyzeBracket(const AValue: String);
|
procedure AnalyzeBracket(const AValue: String);
|
||||||
procedure AnalyzeText(const AValue: String);
|
procedure AnalyzeText(const AValue: String);
|
||||||
procedure CheckSections;
|
procedure CheckSections;
|
||||||
|
function CreateFormatStringFromSection(ASection: Integer): String; virtual;
|
||||||
|
function CreateFormatStringFromSections: String;
|
||||||
procedure Parse(const AFormatString: String);
|
procedure Parse(const AFormatString: String);
|
||||||
procedure ScanAMPM(var s: String);
|
procedure ScanAMPM(var s: String);
|
||||||
procedure ScanBrackets;
|
procedure ScanBrackets;
|
||||||
@ -68,9 +78,16 @@ type
|
|||||||
procedure ScanText;
|
procedure ScanText;
|
||||||
|
|
||||||
public
|
public
|
||||||
constructor Create(AWorkbook: TsWorkbook; const AFormatString: String);
|
constructor Create(AWorkbook: TsWorkbook; const AFormatString: String;
|
||||||
|
AConversionDirection: TsConversionDirection = cdToFPSpreadsheet); overload;
|
||||||
|
constructor Create(AWorkbook: TsWorkbook; const AFormatSections: TsNumFormatSections;
|
||||||
|
AConversionDirection: TsConversionDirection = cdFromFPSpreadsheet); overload;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
property FormatString: String read FFormatString;
|
procedure CopySections(const FromSections: TsNumFormatSections;
|
||||||
|
var ToSections: TsNumFormatSections);
|
||||||
|
procedure CopySectionsTo(var ADestination: TsNumFormatSections);
|
||||||
|
property Builtin_NumFormat: TsNumberFormat read FNumFormat;
|
||||||
|
property FormatString: String read GetFormatString;
|
||||||
property ParsedSectionCount: Integer read GetParsedSectionCount;
|
property ParsedSectionCount: Integer read GetParsedSectionCount;
|
||||||
property ParsedSections[AIndex: Integer]: TsNumFormatSection read GetParsedSections;
|
property ParsedSections[AIndex: Integer]: TsNumFormatSection read GetParsedSections;
|
||||||
property Status: Integer read FStatus;
|
property Status: Integer read FStatus;
|
||||||
@ -88,10 +105,15 @@ const
|
|||||||
|
|
||||||
{ TsNumFormatParser }
|
{ TsNumFormatParser }
|
||||||
|
|
||||||
|
{ Creates a number format parser for analyzing a formatstring that has been read
|
||||||
|
from a spreadsheet file. The conversion, by default, will go FROM the file TO
|
||||||
|
the fpspreadsheet procedures. }
|
||||||
constructor TsNumFormatParser.Create(AWorkbook: TsWorkbook;
|
constructor TsNumFormatParser.Create(AWorkbook: TsWorkbook;
|
||||||
const AFormatString: String);
|
const AFormatString: String; AConversionDirection: TsConversionDirection = cdToFPSpreadsheet);
|
||||||
begin
|
begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
|
FCreateMethod := 0;
|
||||||
|
FConversionDirection := AConversionDirection;
|
||||||
FWorkbook := AWorkbook;
|
FWorkbook := AWorkbook;
|
||||||
FFormatSettings := DefaultFormatSettings;
|
FFormatSettings := DefaultFormatSettings;
|
||||||
FFormatSettings.DecimalSeparator := '.';
|
FFormatSettings.DecimalSeparator := '.';
|
||||||
@ -99,6 +121,22 @@ begin
|
|||||||
Parse(AFormatString);
|
Parse(AFormatString);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ Creates a number format parser to create a format string from the individual
|
||||||
|
format sections given in "AFormatSections". It is assumed by default that the
|
||||||
|
format string will be written to file. Therefore, it can contain features of
|
||||||
|
the destination file format and, in general, will not work if called by
|
||||||
|
fpspreadsheet. }
|
||||||
|
constructor TsNumFormatParser.Create(AWorkbook: TsWorkbook;
|
||||||
|
const AFormatSections: TsNumFormatSections;
|
||||||
|
AConversionDirection: TsConversionDirection = cdFromFPSpreadsheet);
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
FCreateMethod := 1;
|
||||||
|
FConversionDirection := AConversionDirection;
|
||||||
|
FWorkbook := AWorkbook;
|
||||||
|
CopySections(AFormatSections, FSections);
|
||||||
|
end;
|
||||||
|
|
||||||
destructor TsNumFormatParser.Destroy;
|
destructor TsNumFormatParser.Destroy;
|
||||||
begin
|
begin
|
||||||
FSections := nil;
|
FSections := nil;
|
||||||
@ -119,7 +157,7 @@ begin
|
|||||||
FormatString := '';
|
FormatString := '';
|
||||||
CompareOperation := coNotUsed;
|
CompareOperation := coNotUsed;
|
||||||
CompareValue := 0.0;
|
CompareValue := 0.0;
|
||||||
Color := scBlack;
|
Color := scNotDefined;
|
||||||
CountryCode := '';
|
CountryCode := '';
|
||||||
CurrencySymbol := '';
|
CurrencySymbol := '';
|
||||||
Decimals := 0;
|
Decimals := 0;
|
||||||
@ -221,6 +259,7 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// Check format strings
|
||||||
case FSections[i].NumFormat of
|
case FSections[i].NumFormat of
|
||||||
nfGeneral, nfFixed, nfFixedTh, nfPercentage, nfExp, nfSci, nfCurrency:
|
nfGeneral, nfFixed, nfFixedTh, nfPercentage, nfExp, nfSci, nfCurrency:
|
||||||
try
|
try
|
||||||
@ -241,6 +280,29 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// Extract built-in NumFormat identifier for currency (needs several entries in
|
||||||
|
// three sections).
|
||||||
|
if (ns = 3) and
|
||||||
|
(FSections[0].NumFormat = nfCurrency) and
|
||||||
|
(FSections[1].NumFormat = nfCurrency) and
|
||||||
|
(FSections[2].NumFormat = nfCurrency)
|
||||||
|
then begin
|
||||||
|
if ((FSections[2].FormatString = '-') or (FSections[2].FormatString = '"-"')) then begin
|
||||||
|
if (FSections[1].Color = scRed) then
|
||||||
|
FNumFormat := nfCurrencyDashRed
|
||||||
|
else
|
||||||
|
FNumFormat := nfCurrencyDash;
|
||||||
|
end else begin
|
||||||
|
if (FSections[1].Color = scRed) then
|
||||||
|
FNumFormat := nfCurrencyRed;
|
||||||
|
end;
|
||||||
|
end else
|
||||||
|
// If there are other multi-section formatstrings they must be a custom format
|
||||||
|
if (ns > 1) then
|
||||||
|
FNumFormat := nfCustom
|
||||||
|
else
|
||||||
|
FNumFormat := FSections[0].NumFormat;
|
||||||
|
|
||||||
if ns = 2 then
|
if ns = 2 then
|
||||||
FFormatString := Format('%s;%s;%s', [
|
FFormatString := Format('%s;%s;%s', [
|
||||||
FSections[0].FormatString,
|
FSections[0].FormatString,
|
||||||
@ -256,33 +318,79 @@ begin
|
|||||||
FStatus := psErrNoUsableFormat;
|
FStatus := psErrNoUsableFormat;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{
|
procedure TsNumFormatParser.CopySections(
|
||||||
function TsNumFormatParser.GetNumFormat: TsNumberFormat;
|
const FromSections: TsNumFormatSections; var ToSections: TsNumformatSections);
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
if FStatus <> psOK then
|
SetLength(ToSections, Length(FromSections));
|
||||||
Result := nfGeneral
|
for i:= 0 to High(FromSections) do begin
|
||||||
else
|
ToSections[i].FormatString := FromSections[i].FormatString;
|
||||||
if (FSections[0].NumFormat = nfCurrency) and (FSections[1].NumFormat = nfCurrency) and
|
ToSections[i].CompareOperation := FromSections[i].CompareOperation;
|
||||||
(FSections[2].NumFormat = nfCurrency)
|
ToSections[i].CompareValue := FromSections[i].CompareValue;
|
||||||
then begin
|
ToSections[i].Color := FromSections[i].Color;
|
||||||
if (FSections[1].Color = scNotDefined) then begin
|
ToSections[i].CurrencySymbol := FromSections[i].CurrencySymbol;
|
||||||
if (FSections[2].FormatString = '-') then
|
ToSections[i].Decimals := FromSections[i].Decimals;
|
||||||
Result := nfCurrencyDash
|
ToSections[i].NumFormat := FromSections[i].NumFormat;
|
||||||
else
|
end;
|
||||||
Result := nfCurrency;
|
end;
|
||||||
end else
|
|
||||||
if FSections[1].Color = scRed then begin
|
procedure TsNumFormatParser.CopySectionsTo(var ADestination: TsNumFormatSections);
|
||||||
if (FSections[2].Formatstring = '-') then
|
begin
|
||||||
Result := nfCurrencyDashRed
|
CopySections(FSections, ADestination);
|
||||||
else
|
end;
|
||||||
Result := nfCurrencyRed;
|
|
||||||
|
function TsNumFormatParser.CreateFormatStringFromSections: String;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
if Length(FSections) = 0 then
|
||||||
|
Result := ''
|
||||||
|
else begin
|
||||||
|
Result := CreateFormatStringFromSection(0);
|
||||||
|
for i:=1 to High(FSections) do
|
||||||
|
Result := Result + ';' + CreateFormatStringFromSection(i);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TsNumFormatParser.CreateFormatStringFromSection(ASection: Integer): String;
|
||||||
|
begin
|
||||||
|
with FSections[ASection] do
|
||||||
|
if (NumFormat = nfFmtDateTime) or (NumFormat = nfCustom) then begin
|
||||||
|
Result := FormatString;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Result := BuildNumberFormatString(FSections[ASection].NumFormat,
|
||||||
|
FWorkbook.FormatSettings,
|
||||||
|
FSections[ASection].Decimals,
|
||||||
|
FSections[ASection].CurrencySymbol
|
||||||
|
);
|
||||||
|
if FConversionDirection = cdFromFPSpreadsheet then begin
|
||||||
|
// This is typical of Excel, but is valid for all others as well.
|
||||||
|
// Override if you need to change
|
||||||
|
if FSections[ASection].Color < 8 then
|
||||||
|
Result := Format('[%s]%s', [FWorkbook.GetColorName(FSections[ASection].Color), Result])
|
||||||
|
else
|
||||||
|
if FSections[ASection].Color < scNotDefined then
|
||||||
|
Result := Format('[Color%d]%s', [FSections[ASection].Color, Result]);
|
||||||
|
|
||||||
|
if FSections[ASection].CompareOperation <> coNotUsed then
|
||||||
|
Result := Format('[%s%g]%s', [
|
||||||
|
COMPARE_STR[FSections[ASection].CompareOperation],
|
||||||
|
FSections[ASection].CompareValue,
|
||||||
|
Result
|
||||||
|
]);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TsNumFormatParser.GetFormatString: String;
|
||||||
|
begin
|
||||||
|
case FCreateMethod of
|
||||||
|
0: Result := FFormatString;
|
||||||
|
1: Result := CreateFormatStringFromSections;
|
||||||
end;
|
end;
|
||||||
end else
|
|
||||||
Result := FSections[0].NumFormat;
|
|
||||||
end;
|
end;
|
||||||
}
|
|
||||||
|
|
||||||
function TsNumFormatParser.GetParsedSectionCount: Integer;
|
function TsNumFormatParser.GetParsedSectionCount: Integer;
|
||||||
begin
|
begin
|
||||||
@ -355,39 +463,51 @@ begin
|
|||||||
while (FCurrent <= FEnd) and (FStatus = psOK) and (not done) do begin
|
while (FCurrent <= FEnd) and (FStatus = psOK) and (not done) do begin
|
||||||
token := FCurrent^;
|
token := FCurrent^;
|
||||||
case token of
|
case token of
|
||||||
'\' : begin
|
'\':
|
||||||
|
begin
|
||||||
inc(FCurrent);
|
inc(FCurrent);
|
||||||
token := FCurrent^;
|
token := FCurrent^;
|
||||||
s := s + token;
|
s := s + token;
|
||||||
end;
|
end;
|
||||||
'Y', 'y' : begin
|
'Y', 'y':
|
||||||
|
begin
|
||||||
ScanDateTimeParts(token, token, s);
|
ScanDateTimeParts(token, token, s);
|
||||||
isTime := false;
|
isTime := false;
|
||||||
end;
|
end;
|
||||||
'M', 'm' : if isTime then // help fpc to separate "month" and "minute"
|
'M', 'm':
|
||||||
|
ScanDateTimeParts(token, token, s);
|
||||||
|
{if isTime then // help fpc to separate "month" and "minute"
|
||||||
ScanDateTimeParts(token, 'n', s)
|
ScanDateTimeParts(token, 'n', s)
|
||||||
else // both "month" and "minute" work in fpc to some degree
|
else // both "month" and "minute" work in fpc to some degree
|
||||||
ScanDateTimeParts(token, token, s);
|
ScanDateTimeParts(token, token, s);}
|
||||||
'D', 'd' : begin
|
'N', 'n':
|
||||||
|
ScanDateTimeParts(token, 'n', s); // fpc dialect for "minutes"
|
||||||
|
'D', 'd':
|
||||||
|
begin
|
||||||
ScanDateTimeParts(token, token, s);
|
ScanDateTimeParts(token, token, s);
|
||||||
isTime := false;
|
isTime := false;
|
||||||
end;
|
end;
|
||||||
'H', 'h' : begin
|
'H', 'h':
|
||||||
|
begin
|
||||||
ScanDateTimeParts(token, token, s);
|
ScanDateTimeParts(token, token, s);
|
||||||
isTime := true;
|
isTime := true;
|
||||||
end;
|
end;
|
||||||
'S', 's' : begin
|
'S', 's':
|
||||||
|
begin
|
||||||
ScanDateTimeParts(token, token, s);
|
ScanDateTimeParts(token, token, s);
|
||||||
isTime := true;
|
isTime := true;
|
||||||
end;
|
end;
|
||||||
'/', ':', '.', ']', '[', ' '
|
'/', ':', '.', ']', '[', ' ':
|
||||||
: s := s + token;
|
s := s + token;
|
||||||
'0' : ScanDateTimeParts(token, 'z', s);
|
'0', 'z', 'Z':
|
||||||
'A', 'a' : begin
|
ScanDateTimeParts(token, token, s);
|
||||||
|
'A', 'a':
|
||||||
|
begin
|
||||||
ScanAMPM(s);
|
ScanAMPM(s);
|
||||||
isAMPM := true;
|
isAMPM := true;
|
||||||
end;
|
end;
|
||||||
else begin
|
else
|
||||||
|
begin
|
||||||
done := true;
|
done := true;
|
||||||
dec(FCurrent);
|
dec(FCurrent);
|
||||||
// char pointer must be at end of date/time mask.
|
// char pointer must be at end of date/time mask.
|
||||||
@ -398,31 +518,22 @@ begin
|
|||||||
|
|
||||||
FSections[FCurrSection].FormatString := FSections[FCurrSection].FormatString + s;
|
FSections[FCurrSection].FormatString := FSections[FCurrSection].FormatString + s;
|
||||||
s := FSections[FCurrSection].FormatString;
|
s := FSections[FCurrSection].FormatString;
|
||||||
|
|
||||||
// Check format
|
|
||||||
try
|
|
||||||
if s <> '' then begin
|
if s <> '' then begin
|
||||||
FormatDateTime(s, now);
|
|
||||||
// !!!! MODIFY TO USE EXTENDED SYNTAX !!!!!
|
|
||||||
|
|
||||||
if s = FWorkbook.FormatSettings.LongDateFormat then
|
if s = FWorkbook.FormatSettings.LongDateFormat then
|
||||||
nf := nfLongDate
|
nf := nfLongDate
|
||||||
else
|
else
|
||||||
if s = FWorkbook.FormatSettings.ShortDateFormat then
|
if s = FWorkbook.FormatSettings.ShortDateFormat then
|
||||||
nf := nfShortDate
|
nf := nfShortDate
|
||||||
else
|
else
|
||||||
if s = FWorkbook.FormatSettings.LongTimeFormat then
|
if s = StripAMPM(FWorkbook.FormatSettings.LongTimeFormat) then
|
||||||
nf := nfLongTime
|
nf := IfThen(isAMPM, nfLongTimeAM, nfLongTime)
|
||||||
else
|
else
|
||||||
if s = FWorkbook.FormatSettings.ShortTimeFormat then
|
if s = StripAMPM(FWorkbook.FormatSettings.ShortTimeFormat) then
|
||||||
nf := nfShortTime
|
nf := IfThen(isAMPM, nfShortTimeAM, nfShortTime)
|
||||||
else
|
else
|
||||||
nf := nfFmtDateTime;
|
nf := nfFmtDateTime;
|
||||||
FSections[FCurrSection].NumFormat := nf;
|
|
||||||
end;
|
|
||||||
|
|
||||||
except
|
FSections[FCurrSection].NumFormat := nf;
|
||||||
FStatus := psErrNoValidDateTimeFormat;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -470,17 +581,23 @@ begin
|
|||||||
token := FCurrent^;
|
token := FCurrent^;
|
||||||
case token of
|
case token of
|
||||||
// Strip Excel's formatting symbols
|
// Strip Excel's formatting symbols
|
||||||
'\', '*' : ;
|
'\', '*':
|
||||||
'_' : inc(FCurrent);
|
;
|
||||||
'"' : begin
|
'_':
|
||||||
|
inc(FCurrent);
|
||||||
|
'"':
|
||||||
|
begin
|
||||||
inc(FCurrent);
|
inc(FCurrent);
|
||||||
ScanText;
|
ScanText;
|
||||||
end;
|
end;
|
||||||
'0', '#', '.', ',', '-': ScanNumber;
|
'0', '#', '.', ',', '-':
|
||||||
'y', 'Y', 'm', 'M',
|
ScanNumber;
|
||||||
'd', 'D', 'h', 's', '[': ScanDateTime;
|
'y', 'Y', 'm', 'M', 'd', 'D', 'h', 'N', 'n', 's', '[':
|
||||||
' ' : AddChar(token);
|
ScanDateTime;
|
||||||
';' : begin
|
' ':
|
||||||
|
AddChar(token);
|
||||||
|
';':
|
||||||
|
begin
|
||||||
done := true;
|
done := true;
|
||||||
dec(FCurrent);
|
dec(FCurrent);
|
||||||
// Cursor must stay on the ";"
|
// Cursor must stay on the ";"
|
||||||
|
@ -184,7 +184,7 @@ end;
|
|||||||
procedure TsSpreadOpenDocReader.CreateNumFormatList;
|
procedure TsSpreadOpenDocReader.CreateNumFormatList;
|
||||||
begin
|
begin
|
||||||
FreeAndNil(FNumFormatList);
|
FreeAndNil(FNumFormatList);
|
||||||
FNumFormatList := TsSpreadOpenDocNumFormatList.Create;
|
FNumFormatList := TsSpreadOpenDocNumFormatList.Create(Workbook);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsSpreadOpenDocReader.GetAttrValue(ANode : TDOMNode; AAttrName : string) : string;
|
function TsSpreadOpenDocReader.GetAttrValue(ANode : TDOMNode; AAttrName : string) : string;
|
||||||
@ -471,7 +471,7 @@ end;
|
|||||||
procedure TsSpreadOpenDocWriter.CreateNumFormatList;
|
procedure TsSpreadOpenDocWriter.CreateNumFormatList;
|
||||||
begin
|
begin
|
||||||
FreeAndNil(FNumFormatList);
|
FreeAndNil(FNumFormatList);
|
||||||
FNumFormatList := TsSpreadOpenDocNumFormatList.Create;
|
FNumFormatList := TsSpreadOpenDocNumFormatList.Create(Workbook);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TsSpreadOpenDocWriter.WriteMimetype;
|
procedure TsSpreadOpenDocWriter.WriteMimetype;
|
||||||
|
@ -362,16 +362,21 @@ type
|
|||||||
FOnChangeCell: TsCellEvent;
|
FOnChangeCell: TsCellEvent;
|
||||||
FOnChangeFont: TsCellEvent;
|
FOnChangeFont: TsCellEvent;
|
||||||
procedure RemoveCallback(data, arg: pointer);
|
procedure RemoveCallback(data, arg: pointer);
|
||||||
|
|
||||||
protected
|
protected
|
||||||
procedure ChangedCell(ARow, ACol: Cardinal);
|
procedure ChangedCell(ARow, ACol: Cardinal);
|
||||||
procedure ChangedFont(ARow, ACol: Cardinal);
|
procedure ChangedFont(ARow, ACol: Cardinal);
|
||||||
|
|
||||||
public
|
public
|
||||||
Name: string;
|
Name: string;
|
||||||
|
|
||||||
{ Base methods }
|
{ Base methods }
|
||||||
constructor Create;
|
constructor Create;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
|
||||||
{ Utils }
|
{ Utils }
|
||||||
class function CellPosToText(ARow, ACol: Cardinal): string;
|
class function CellPosToText(ARow, ACol: Cardinal): string;
|
||||||
|
|
||||||
{ Data manipulation methods - For Cells }
|
{ Data manipulation methods - For Cells }
|
||||||
procedure CopyCell(AFromRow, AFromCol, AToRow, AToCol: Cardinal; AFromWorksheet: TsWorksheet);
|
procedure CopyCell(AFromRow, AFromCol, AToRow, AToCol: Cardinal; AFromWorksheet: TsWorksheet);
|
||||||
procedure CopyFormat(AFormat: PCell; AToRow, AToCol: Cardinal);
|
procedure CopyFormat(AFormat: PCell; AToRow, AToCol: Cardinal);
|
||||||
@ -390,35 +395,25 @@ 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;
|
procedure RemoveAllCells;
|
||||||
|
|
||||||
{ Writing of values }
|
{ Writing of values }
|
||||||
procedure WriteUTF8Text(ARow, ACol: Cardinal; AText: ansistring);
|
procedure WriteBlank(ARow, ACol: Cardinal);
|
||||||
|
procedure WriteBoolValue(ARow, ACol: Cardinal; AValue: Boolean);
|
||||||
|
procedure WriteDateTime(ARow, ACol: Cardinal; AValue: TDateTime;
|
||||||
|
AFormat: TsNumberFormat = nfShortDateTime; AFormatStr: String = '');
|
||||||
|
procedure WriteErrorValue(ARow, ACol: Cardinal; AValue: TErrorValue);
|
||||||
|
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(ARow, ACol: Cardinal; ANumber: double;
|
procedure WriteNumber(ARow, ACol: Cardinal; ANumber: double;
|
||||||
AFormatString: String); overload;
|
AFormatString: String); overload;
|
||||||
procedure WriteBlank(ARow, ACol: Cardinal);
|
|
||||||
procedure WriteBoolValue(ARow, ACol: Cardinal; AValue: Boolean);
|
|
||||||
procedure WriteDateTime(ARow, ACol: Cardinal; AValue: TDateTime;
|
|
||||||
AFormat: TsNumberFormat = nfShortDateTime; AFormatStr: String = '');
|
|
||||||
procedure WriteDecimals(ARow, ACol: Cardinal; ADecimals: byte); overload;
|
|
||||||
procedure WriteDecimals(ACell: PCell; ADecimals: Byte); overload;
|
|
||||||
procedure WriteErrorValue(ARow, ACol: Cardinal; AValue: TErrorValue);
|
|
||||||
procedure WriteFormula(ARow, ACol: Cardinal; AFormula: TsFormula);
|
|
||||||
procedure WriteRPNFormula(ARow, ACol: Cardinal; AFormula: TsRPNFormula);
|
procedure WriteRPNFormula(ARow, ACol: Cardinal; AFormula: TsRPNFormula);
|
||||||
|
procedure WriteUTF8Text(ARow, ACol: Cardinal; AText: ansistring);
|
||||||
|
|
||||||
{ Writing of cell attributes }
|
{ Writing of cell attributes }
|
||||||
procedure WriteNumberFormat(ARow, ACol: Cardinal; ANumberFormat: TsNumberFormat;
|
|
||||||
const AFormatString: String = '');
|
|
||||||
function WriteFont(ARow, ACol: Cardinal; const AFontName: String;
|
|
||||||
AFontSize: Single; AFontStyle: TsFontStyles; AFontColor: TsColor): Integer; overload;
|
|
||||||
procedure WriteFont(ARow, ACol: Cardinal; AFontIndex: Integer); overload;
|
|
||||||
function WriteFontColor(ARow, ACol: Cardinal; AFontColor: TsColor): Integer;
|
|
||||||
function WriteFontName(ARow, ACol: Cardinal; AFontName: String): Integer;
|
|
||||||
function WriteFontSize(ARow, ACol: Cardinal; ASize: Single): Integer;
|
|
||||||
function WriteFontStyle(ARow, ACol: Cardinal; AStyle: TsFontStyles): Integer;
|
|
||||||
procedure WriteTextRotation(ARow, ACol: Cardinal; ARotation: TsTextRotation);
|
|
||||||
procedure WriteUsedFormatting(ARow, ACol: Cardinal; AUsedFormatting: TsUsedFormattingFields);
|
|
||||||
procedure WriteBackgroundColor(ARow, ACol: Cardinal; AColor: TsColor);
|
procedure WriteBackgroundColor(ARow, ACol: Cardinal; AColor: TsColor);
|
||||||
|
|
||||||
procedure WriteBorderColor(ARow, ACol: Cardinal; ABorder: TsCellBorder; AColor: TsColor);
|
procedure WriteBorderColor(ARow, ACol: Cardinal; ABorder: TsCellBorder; AColor: TsColor);
|
||||||
procedure WriteBorderLineStyle(ARow, ACol: Cardinal; ABorder: TsCellBorder;
|
procedure WriteBorderLineStyle(ARow, ACol: Cardinal; ABorder: TsCellBorder;
|
||||||
ALineStyle: TsLineStyle);
|
ALineStyle: TsLineStyle);
|
||||||
@ -428,9 +423,31 @@ type
|
|||||||
procedure WriteBorderStyle(ARow, ACol: Cardinal; ABorder: TsCellBorder;
|
procedure WriteBorderStyle(ARow, ACol: Cardinal; ABorder: TsCellBorder;
|
||||||
ALineStyle: TsLineStyle; AColor: TsColor); overload;
|
ALineStyle: TsLineStyle; AColor: TsColor); overload;
|
||||||
procedure WriteBorderStyles(ARow, ACol: Cardinal; const AStyles: TsCellBorderStyles);
|
procedure WriteBorderStyles(ARow, ACol: Cardinal; const AStyles: TsCellBorderStyles);
|
||||||
|
|
||||||
|
procedure WriteDecimals(ARow, ACol: Cardinal; ADecimals: byte); overload;
|
||||||
|
procedure WriteDecimals(ACell: PCell; ADecimals: Byte); overload;
|
||||||
|
|
||||||
|
function WriteFont(ARow, ACol: Cardinal; const AFontName: String;
|
||||||
|
AFontSize: Single; AFontStyle: TsFontStyles; AFontColor: TsColor): Integer; overload;
|
||||||
|
procedure WriteFont(ARow, ACol: Cardinal; AFontIndex: Integer); overload;
|
||||||
|
function WriteFontColor(ARow, ACol: Cardinal; AFontColor: TsColor): Integer;
|
||||||
|
function WriteFontName(ARow, ACol: Cardinal; AFontName: String): Integer;
|
||||||
|
function WriteFontSize(ARow, ACol: Cardinal; ASize: Single): Integer;
|
||||||
|
function WriteFontStyle(ARow, ACol: Cardinal; AStyle: TsFontStyles): Integer;
|
||||||
|
|
||||||
procedure WriteHorAlignment(ARow, ACol: Cardinal; AValue: TsHorAlignment);
|
procedure WriteHorAlignment(ARow, ACol: Cardinal; AValue: TsHorAlignment);
|
||||||
|
|
||||||
|
procedure WriteNumberFormat(ARow, ACol: Cardinal; ANumberFormat: TsNumberFormat;
|
||||||
|
const AFormatString: String = '');
|
||||||
|
|
||||||
|
procedure WriteTextRotation(ARow, ACol: Cardinal; ARotation: TsTextRotation);
|
||||||
|
|
||||||
|
procedure WriteUsedFormatting(ARow, ACol: Cardinal; AUsedFormatting: TsUsedFormattingFields);
|
||||||
|
|
||||||
procedure WriteVertAlignment(ARow, ACol: Cardinal; AValue: TsVertAlignment);
|
procedure WriteVertAlignment(ARow, ACol: Cardinal; AValue: TsVertAlignment);
|
||||||
|
|
||||||
procedure WriteWordwrap(ARow, ACol: Cardinal; AValue: boolean);
|
procedure WriteWordwrap(ARow, ACol: Cardinal; AValue: boolean);
|
||||||
|
|
||||||
{ 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;
|
||||||
@ -442,11 +459,13 @@ type
|
|||||||
procedure WriteRowHeight(ARow: Cardinal; AHeight: Single);
|
procedure WriteRowHeight(ARow: Cardinal; AHeight: Single);
|
||||||
procedure WriteColInfo(ACol: Cardinal; AData: TCol);
|
procedure WriteColInfo(ACol: Cardinal; AData: TCol);
|
||||||
procedure WriteColWidth(ACol: Cardinal; AWidth: Single);
|
procedure WriteColWidth(ACol: Cardinal; AWidth: Single);
|
||||||
|
|
||||||
{ Properties }
|
{ Properties }
|
||||||
property Cells: TAVLTree read FCells;
|
property Cells: TAVLTree read FCells;
|
||||||
property Cols: TIndexedAVLTree read FCols;
|
property Cols: TIndexedAVLTree read FCols;
|
||||||
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 fpspreadsheetgrid.
|
||||||
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;
|
||||||
@ -547,7 +566,7 @@ type
|
|||||||
var ACurrencySymbol: String); virtual;
|
var ACurrencySymbol: String); virtual;
|
||||||
procedure RemoveFormat(AIndex: Integer);
|
procedure RemoveFormat(AIndex: Integer);
|
||||||
public
|
public
|
||||||
constructor Create;
|
constructor Create(AWorkbook: TsWorkbook);
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
function AddFormat(AFormatCell: PCell): Integer; overload;
|
function AddFormat(AFormatCell: PCell): Integer; overload;
|
||||||
function AddFormat(AFormatIndex: Integer; ANumFormat: TsNumberFormat;
|
function AddFormat(AFormatIndex: Integer; ANumFormat: TsNumberFormat;
|
||||||
@ -718,7 +737,7 @@ procedure MakeLEPalette(APalette: PsPalette; APaletteSize: Integer);
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Math, StrUtils, fpsutils;
|
Math, StrUtils, fpsUtils, fpsNumFormatParser;
|
||||||
|
|
||||||
{ Translatable strings }
|
{ Translatable strings }
|
||||||
resourcestring
|
resourcestring
|
||||||
@ -727,6 +746,9 @@ resourcestring
|
|||||||
lpNoValidSpreadsheetFile = '"%s" is not a valid spreadsheet file';
|
lpNoValidSpreadsheetFile = '"%s" is not a valid spreadsheet file';
|
||||||
lpUnknownSpreadsheetFormat = 'unknown format';
|
lpUnknownSpreadsheetFormat = 'unknown format';
|
||||||
lpInvalidFontIndex = 'Invalid font index';
|
lpInvalidFontIndex = 'Invalid font index';
|
||||||
|
lpInvalidNumberFormat = 'Trying to use an incompatible number format.';
|
||||||
|
lpNoValidNumberFormatString = 'No valid number format string.';
|
||||||
|
lpNoValidDateTimeFormatString = 'No valid date/time format string.';
|
||||||
lpTRUE = 'TRUE';
|
lpTRUE = 'TRUE';
|
||||||
lpFALSE = 'FALSE';
|
lpFALSE = 'FALSE';
|
||||||
lpErrEmptyIntersection = '#NULL!';
|
lpErrEmptyIntersection = '#NULL!';
|
||||||
@ -1407,14 +1429,19 @@ begin
|
|||||||
ACell^.ContentType := cctNumber;
|
ACell^.ContentType := cctNumber;
|
||||||
ACell^.NumberValue := ANumber;
|
ACell^.NumberValue := ANumber;
|
||||||
ACell^.Decimals := ADecimals;
|
ACell^.Decimals := ADecimals;
|
||||||
|
|
||||||
|
if IsDateTimeFormat(AFormat) then
|
||||||
|
raise Exception.Create(lpInvalidNumberFormat);
|
||||||
|
|
||||||
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^.Decimals := ADecimals;
|
||||||
ACell^.CurrencySymbol := ACurrencySymbol;
|
ACell^.CurrencySymbol := ACurrencySymbol;
|
||||||
ACell^.NumberFormatStr := BuildNumFormatString(ACell^.NumberFormat,
|
ACell^.NumberFormatStr := BuildNumberFormatString(ACell^.NumberFormat,
|
||||||
Workbook.FormatSettings, ADecimals, ACurrencySymbol);
|
Workbook.FormatSettings, ADecimals, ACurrencySymbol);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
ChangedCell(ARow, ACol);
|
ChangedCell(ARow, ACol);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1427,13 +1454,32 @@ procedure TsWorksheet.WriteNumber(ARow, ACol: Cardinal; ANumber: Double;
|
|||||||
AFormatString: String);
|
AFormatString: String);
|
||||||
var
|
var
|
||||||
ACell: PCell;
|
ACell: PCell;
|
||||||
|
parser: TsNumFormatParser;
|
||||||
|
nf: TsNumberFormat;
|
||||||
begin
|
begin
|
||||||
|
parser := TsNumFormatParser.Create(Workbook, AFormatString, cdToFPSpreadsheet);
|
||||||
|
try
|
||||||
|
// Format string ok?
|
||||||
|
if parser.Status <> psOK then
|
||||||
|
raise Exception.Create(lpNoValidNumberFormatString);
|
||||||
|
if IsDateTimeFormat(parser.Builtin_NumFormat)
|
||||||
|
then raise Exception.Create(lpInvalidNumberFormat);
|
||||||
|
// If format string matches a built-in format use its format identifier,
|
||||||
|
// All this is considered when calling Builtin_NumFormat of the parser.
|
||||||
|
nf := parser.Builtin_NumFormat;
|
||||||
|
finally
|
||||||
|
parser.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
ACell := GetCell(ARow, ACol);
|
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 := nfCustom;
|
ACell^.NumberFormat := nf;
|
||||||
ACell^.NumberFormatStr := AFormatString;
|
ACell^.NumberFormatStr := AFormatString;
|
||||||
|
ACell^.Decimals := 0;
|
||||||
|
ACell^.CurrencySymbol := '';
|
||||||
|
|
||||||
ChangedCell(ARow, ACol);
|
ChangedCell(ARow, ACol);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1482,6 +1528,7 @@ end;
|
|||||||
Must follow the rules for "FormatDateTime", or use
|
Must follow the rules for "FormatDateTime", or use
|
||||||
"dm" as abbreviation for "d/mmm", "my" for "mmm/yy",
|
"dm" as abbreviation for "d/mmm", "my" for "mmm/yy",
|
||||||
"ms" for "nn:ss", "msz" for "nn:ss.z" (optional)
|
"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
|
||||||
@ -1494,9 +1541,25 @@ procedure TsWorksheet.WriteDateTime(ARow, ACol: Cardinal; AValue: TDateTime;
|
|||||||
var
|
var
|
||||||
ACell: PCell;
|
ACell: PCell;
|
||||||
fmt: String;
|
fmt: String;
|
||||||
|
parser: TsNumFormatParser;
|
||||||
begin
|
begin
|
||||||
ACell := GetCell(ARow, ACol);
|
if AFormat = nfFmtDateTime then begin
|
||||||
|
AFormatStr := BuildDateTimeFormatString(AFormat, Workbook.FormatSettings, AFormatStr);
|
||||||
|
parser := TsNumFormatParser.Create(Workbook, AFormatStr, cdToFPSpreadsheet);
|
||||||
|
try
|
||||||
|
// Check that the format string can be reckognized.
|
||||||
|
if parser.Status <> psOK then
|
||||||
|
raise Exception.Create(lpNoValidNumberFormatString);
|
||||||
|
// Check that the format string belongs to date/time values
|
||||||
|
if not (IsDateTimeFormat(parser.Builtin_NumFormat) or (parser.Builtin_NumFormat = nfFmtDateTime))
|
||||||
|
then raise Exception.Create(lpNoValidDateTimeFormatString);
|
||||||
|
AFormatStr := parser.FormatString;
|
||||||
|
finally
|
||||||
|
parser.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
ACell := GetCell(ARow, ACol);
|
||||||
ACell^.ContentType := cctDateTime;
|
ACell^.ContentType := cctDateTime;
|
||||||
ACell^.DateTimeValue := AValue;
|
ACell^.DateTimeValue := AValue;
|
||||||
// Date/time is actually a number field in Excel.
|
// Date/time is actually a number field in Excel.
|
||||||
@ -1504,34 +1567,8 @@ begin
|
|||||||
// The user can choose another date format if he wants to
|
// The user can choose another date format if he wants to
|
||||||
Include(ACell^.UsedFormattingFields, uffNumberFormat);
|
Include(ACell^.UsedFormattingFields, uffNumberFormat);
|
||||||
ACell^.NumberFormat := AFormat;
|
ACell^.NumberFormat := AFormat;
|
||||||
case AFormat of
|
ACell^.NumberFormatStr := AFormatStr;
|
||||||
nfShortDateTime:
|
|
||||||
ACell^.NumberFormatStr := FormatSettings.ShortDateFormat + ' ' + FormatSettings.ShortTimeFormat;
|
|
||||||
nfShortDate:
|
|
||||||
ACell^.NumberFormatStr := FormatSettings.ShortDateFormat;
|
|
||||||
nfLongDate:
|
|
||||||
ACell^.NumberFormatStr := 'dd/mmm/yyyy';
|
|
||||||
nfShortTime:
|
|
||||||
ACell^.NumberFormatStr := 't';
|
|
||||||
nfLongTime:
|
|
||||||
ACell^.NumberFormatStr := 'tt';
|
|
||||||
nfShortTimeAM:
|
|
||||||
ACell^.NumberFormatStr := 'hh:nn AM/PM';
|
|
||||||
nfLongTimeAM:
|
|
||||||
ACell^.NumberFormatStr := 'hh:nn:ss AM/PM';
|
|
||||||
nfFmtDateTime:
|
|
||||||
begin
|
|
||||||
fmt := lowercase(AFormatStr);
|
|
||||||
if fmt = 'dm' then ACell^.NumberFormatStr := 'd/mmm'
|
|
||||||
else if fmt = 'my' then ACell^.NumberFormatStr := 'mmm/yy'
|
|
||||||
else if fmt = 'ms' then ACell^.NumberFormatStr := 'nn:ss'
|
|
||||||
else if fmt = 'msz' then ACell^.NumberFormatStr := 'nn:ss.z'
|
|
||||||
else ACell^.NumberFormatStr := AFormatStr;
|
|
||||||
end;
|
|
||||||
nfTimeInterval:
|
|
||||||
if AFormatStr = '' then ACell^.NumberFormatStr := '[h]:nn:ss'
|
|
||||||
else ACell^.NumberFormatStr := AFormatStr;
|
|
||||||
end;
|
|
||||||
ChangedCell(ARow, ACol);
|
ChangedCell(ARow, ACol);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1544,7 +1581,7 @@ procedure TsWorksheet.WriteDecimals(ACell: PCell; ADecimals: Byte);
|
|||||||
begin
|
begin
|
||||||
if (ACell <> nil) and (ACell^.ContentType = cctNumber) then begin
|
if (ACell <> nil) and (ACell^.ContentType = cctNumber) then begin
|
||||||
ACell^.Decimals := ADecimals;
|
ACell^.Decimals := ADecimals;
|
||||||
ACell^.NumberFormatStr := BuildNumFormatString(ACell^.NumberFormat,
|
ACell^.NumberFormatStr := BuildNumberFormatString(ACell^.NumberFormat,
|
||||||
FWorkbook.FormatSettings, ADecimals, ACell^.CurrencySymbol);
|
FWorkbook.FormatSettings, ADecimals, ACell^.CurrencySymbol);
|
||||||
ChangedCell(ACell^.Row, ACell^.Col);
|
ChangedCell(ACell^.Row, ACell^.Col);
|
||||||
end;
|
end;
|
||||||
@ -1603,7 +1640,7 @@ begin
|
|||||||
Include(ACell^.UsedFormattingFields, uffNumberFormat);
|
Include(ACell^.UsedFormattingFields, uffNumberFormat);
|
||||||
ACell^.NumberFormat := ANumberFormat;
|
ACell^.NumberFormat := ANumberFormat;
|
||||||
if (AFormatString = '') then
|
if (AFormatString = '') then
|
||||||
ACell^.NumberFormatStr := BuildNumFormatString(ANumberFormat,
|
ACell^.NumberFormatStr := BuildNumberFormatString(ANumberFormat,
|
||||||
Workbook.FormatSettings, ACell^.Decimals, ACell^.CurrencySymbol)
|
Workbook.FormatSettings, ACell^.Decimals, ACell^.CurrencySymbol)
|
||||||
else
|
else
|
||||||
ACell^.NumberFormatStr := AFormatString;
|
ACell^.NumberFormatStr := AFormatString;
|
||||||
@ -2577,9 +2614,10 @@ end;
|
|||||||
|
|
||||||
{ TsCustomNumFormatList }
|
{ TsCustomNumFormatList }
|
||||||
|
|
||||||
constructor TsCustomNumFormatList.Create;
|
constructor TsCustomNumFormatList.Create(AWorkbook: TsWorkbook);
|
||||||
begin
|
begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
|
FWorkbook := AWorkbook;
|
||||||
AddBuiltinFormats;
|
AddBuiltinFormats;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -2599,6 +2637,13 @@ begin
|
|||||||
item := TsNumFormatData.Create;
|
item := TsNumFormatData.Create;
|
||||||
item.Index := AFormatIndex;
|
item.Index := AFormatIndex;
|
||||||
item.NumFormat := ANumFormat;
|
item.NumFormat := ANumFormat;
|
||||||
|
if IsDateTimeFormat(ANumFormat) then
|
||||||
|
AFormatString := BuildDateTimeFormatString(ANumFormat, Workbook.FormatSettings,
|
||||||
|
AFormatString)
|
||||||
|
else
|
||||||
|
if item.NumFormat <> nfCustom then
|
||||||
|
AFormatString := BuildNumberFormatString(ANumFormat, Workbook.FormatSettings,
|
||||||
|
ADecimals, ACurrencySymbol);
|
||||||
item.FormatString := AFormatString;
|
item.FormatString := AFormatString;
|
||||||
item.Decimals := ADecimals;
|
item.Decimals := ADecimals;
|
||||||
item.CurrencySymbol := ACurrencySymbol;
|
item.CurrencySymbol := ACurrencySymbol;
|
||||||
@ -2644,6 +2689,38 @@ end;
|
|||||||
If the format string cannot be directly handled by fpc it has to be transformed
|
If the format string cannot be directly handled by fpc it has to be transformed
|
||||||
to make it compatible. Can be done in overridden versions which know more
|
to make it compatible. Can be done in overridden versions which know more
|
||||||
about the structure of the string in the actual file format. }
|
about the structure of the string in the actual file format. }
|
||||||
|
procedure TsCustomNumFormatList.Analyze(AFormatIndex: Integer;
|
||||||
|
var AFormatString: String; var ANumFormat: TsNumberFormat;
|
||||||
|
var ADecimals: Byte; var ACurrencySymbol: String);
|
||||||
|
var
|
||||||
|
parser: TsNumFormatParser;
|
||||||
|
fmt: String;
|
||||||
|
lFormatData: TsNumFormatData;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
i := Find(AFormatIndex);
|
||||||
|
if i > 0 then begin
|
||||||
|
lFormatData := Items[i];
|
||||||
|
fmt := lFormatData.FormatString;
|
||||||
|
end else
|
||||||
|
fmt := AFormatString;
|
||||||
|
|
||||||
|
parser := TsNumFormatParser.Create(Workbook, fmt, cdToFPSpreadsheet);
|
||||||
|
try
|
||||||
|
if parser.Status = psOK then begin
|
||||||
|
ANumFormat := parser.Builtin_NumFormat;
|
||||||
|
AFormatString := parser.FormatString;
|
||||||
|
if not (parser.Builtin_NumFormat in [nfCustom, nfFmtDateTime]) then begin
|
||||||
|
ADecimals := parser.ParsedSections[0].Decimals;
|
||||||
|
ACurrencySymbol := parser.ParsedSections[0].CurrencySymbol;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
parser.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
(*
|
||||||
procedure TsCustomNumFormatList.Analyze(AFormatIndex: Integer;
|
procedure TsCustomNumFormatList.Analyze(AFormatIndex: Integer;
|
||||||
var AFormatString: String; var ANumFormat: TsNumberFormat;
|
var AFormatString: String; var ANumFormat: TsNumberFormat;
|
||||||
var ADecimals: Byte; var ACurrencySymbol: String);
|
var ADecimals: Byte; var ACurrencySymbol: String);
|
||||||
@ -2749,6 +2826,7 @@ begin
|
|||||||
ANumFormat := nfCustom;
|
ANumFormat := nfCustom;
|
||||||
end;
|
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.
|
||||||
Determines the numFormat type, format string etc and stores the format in the
|
Determines the numFormat type, format string etc and stores the format in the
|
||||||
@ -2816,8 +2894,8 @@ begin
|
|||||||
item := Items[Result];
|
item := Items[Result];
|
||||||
if (item <> nil) and (item.NumFormat = ANumFormat) then
|
if (item <> nil) and (item.NumFormat = ANumFormat) then
|
||||||
exit;
|
exit;
|
||||||
end
|
end;
|
||||||
else
|
|
||||||
if (ANumFormat = nfFmtDateTime) then begin
|
if (ANumFormat = nfFmtDateTime) then begin
|
||||||
fmt := lowercase(AFormatString);
|
fmt := lowercase(AFormatString);
|
||||||
for Result := 0 to Count-1 do begin
|
for Result := 0 to Count-1 do begin
|
||||||
@ -2847,9 +2925,10 @@ begin
|
|||||||
if fmt = lowercase(item.FormatString) then
|
if fmt = lowercase(item.FormatString) then
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
end else
|
end;
|
||||||
|
|
||||||
// Check only the format string for nfCustom.
|
// Check only the format string for nfCustom.
|
||||||
if (ANumFormat = nfCustom) then begin
|
if (ANumFormat = nfCustom) then
|
||||||
for Result := 0 to Count-1 do begin
|
for Result := 0 to Count-1 do begin
|
||||||
item := Items[Result];
|
item := Items[Result];
|
||||||
if (item <> nil)
|
if (item <> nil)
|
||||||
@ -2858,7 +2937,7 @@ begin
|
|||||||
then
|
then
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
end else
|
|
||||||
// The other formats can carry additional information
|
// The other formats can carry additional information
|
||||||
for Result := 0 to Count-1 do begin
|
for Result := 0 to Count-1 do begin
|
||||||
item := Items[Result];
|
item := Items[Result];
|
||||||
@ -3099,7 +3178,8 @@ var
|
|||||||
decs: Byte;
|
decs: Byte;
|
||||||
begin
|
begin
|
||||||
if ACell^.NumberFormat = nfFmtDateTime then begin
|
if ACell^.NumberFormat = nfFmtDateTime then begin
|
||||||
if IsTimeFormat(ACell^.NumberFormatStr, isLong, isAMPM, isInterval, decs) then
|
decs := CountDecs(ACell^.NumberFormatStr, ['0', 'z', 'Z']);
|
||||||
|
// if IsTimeFormat(ACell^.NumberFormatStr, isLong, isAMPM, isInterval, decs) then
|
||||||
ACell^.Decimals := decs;
|
ACell^.Decimals := decs;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
@ -17,6 +17,7 @@ uses
|
|||||||
// Exported types
|
// Exported types
|
||||||
type
|
type
|
||||||
TsSelectionDirection = (fpsVerticalSelection, fpsHorizontalSelection);
|
TsSelectionDirection = (fpsVerticalSelection, fpsHorizontalSelection);
|
||||||
|
TsDecsChars = set of char;
|
||||||
|
|
||||||
const
|
const
|
||||||
// Date formatting string for unambiguous date/time display as strings
|
// Date formatting string for unambiguous date/time display as strings
|
||||||
@ -60,19 +61,29 @@ function UTF8TextToXMLText(AText: ansistring): ansistring;
|
|||||||
function TwipsToMillimeters(AValue: Integer): Single;
|
function TwipsToMillimeters(AValue: Integer): Single;
|
||||||
function MillimetersToTwips(AValue: Single): Integer;
|
function MillimetersToTwips(AValue: Single): Integer;
|
||||||
|
|
||||||
|
function IfThen(ACondition: Boolean; AValue1,AValue2: TsNumberFormat): TsNumberFormat; overload;
|
||||||
|
|
||||||
|
function IsDateTimeFormat(AFormat: TsNumberFormat): Boolean;
|
||||||
|
(*
|
||||||
function IsCurrencyFormat(s: String; out Decimals: Byte; out CurrSymbol: String;
|
function IsCurrencyFormat(s: String; out Decimals: Byte; out CurrSymbol: String;
|
||||||
out IsCurrencyRedFmt, IsCurrencyDashFmt: Boolean): Boolean;
|
out IsCurrencyRedFmt, IsCurrencyDashFmt: Boolean): Boolean;
|
||||||
function IsExpNumberFormat(s: String; out Decimals: Byte; out IsSci: Boolean): Boolean;
|
function IsExpNumberFormat(s: String; out Decimals: Byte; out IsSci: Boolean): Boolean;
|
||||||
function IsFixedNumberFormat(s: String; out Decimals: Byte): Boolean;
|
function IsFixedNumberFormat(s: String; out Decimals: Byte): Boolean;
|
||||||
function IsPercentNumberFormat(s: String; out Decimals: Byte): Boolean;
|
function IsPercentNumberFormat(s: String; out Decimals: Byte): Boolean;
|
||||||
function IsThousandSepNumberFormat(s: String; out Decimals: Byte): Boolean;
|
function IsThousandSepNumberFormat(s: String; out Decimals: Byte): Boolean;
|
||||||
function IsDateFormat(s: String; out IsLong: Boolean): Boolean;
|
|
||||||
function IsTimeFormat(s: String; out isLong, isAMPM, isInterval: Boolean;
|
|
||||||
out SecDecimals: Byte): Boolean;
|
|
||||||
|
|
||||||
function BuildNumFormatString(ANumberFormat: TsNumberFormat;
|
function IsDateFormat(s: String; out IsLong: Boolean): Boolean;
|
||||||
|
{function IsTimeFormat(s: String; out isLong, isAMPM, isInterval: Boolean;
|
||||||
|
out SecDecimals: Byte): Boolean;
|
||||||
|
*)
|
||||||
|
|
||||||
|
function BuildNumberFormatString(ANumberFormat: TsNumberFormat;
|
||||||
const AFormatSettings: TFormatSettings; ADecimals: Integer = -1;
|
const AFormatSettings: TFormatSettings; ADecimals: Integer = -1;
|
||||||
ACurrencySymbol: String = '?'): String;
|
ACurrencySymbol: String = '?'): String;
|
||||||
|
function BuildDateTimeFormatString(ANumberFormat: TsNumberFormat;
|
||||||
|
const AFormatSettings: TFormatSettings; AFormatString: String = ''): String;
|
||||||
|
function StripAMPM(const ATimeFormatString: String): String;
|
||||||
|
function CountDecs(AFormatString: String; ADecChars: TsDecsChars = ['0']): Byte;
|
||||||
|
|
||||||
function SciFloat(AValue: Double; ADecimals: Byte): String;
|
function SciFloat(AValue: Double; ADecimals: Byte): String;
|
||||||
//function TimeIntervalToString(AValue: TDateTime; AFormatStr: String): String;
|
//function TimeIntervalToString(AValue: TDateTime; AFormatStr: String): String;
|
||||||
@ -494,8 +505,21 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{ Returns either AValue1 or AValue2, depending on the condition.
|
||||||
|
For reduciton of typing... }
|
||||||
|
function IfThen(ACondition: Boolean; AValue1, AValue2: TsNumberFormat): TsNumberFormat;
|
||||||
|
begin
|
||||||
|
if ACondition then Result := AValue1 else Result := AValue2;
|
||||||
|
end;
|
||||||
|
|
||||||
{ Format checking procedures }
|
{ Format checking procedures }
|
||||||
|
|
||||||
|
function IsDateTimeFormat(AFormat: TsNumberFormat): Boolean;
|
||||||
|
begin
|
||||||
|
Result := AFormat in [nfFmtDateTime, nfShortDateTime, nfShortDate, nfLongDate,
|
||||||
|
nfShortTime. nfLongTime, nfShortTimeAM, nfLongTimeAM, nfTimeInterval];
|
||||||
|
end;
|
||||||
|
(*
|
||||||
{ This simple parsing procedure of the Excel format string checks for a fixed
|
{ This simple parsing procedure of the Excel format string checks for a fixed
|
||||||
float format s, i.e. s can be '0', '0.00', '000', '0,000', and returns the
|
float format s, i.e. s can be '0', '0.00', '000', '0,000', and returns the
|
||||||
number of decimals, i.e. number of zeros behind the decimal point }
|
number of decimals, i.e. number of zeros behind the decimal point }
|
||||||
@ -661,7 +685,7 @@ begin
|
|||||||
if ph > 0 then IsSci := true;
|
if ph > 0 then IsSci := true;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
*)
|
||||||
{ IsDateFormat checks if the format string s corresponds to a date format }
|
{ IsDateFormat checks if the format string s corresponds to a date format }
|
||||||
function IsDateFormat(s: String; out IsLong: Boolean): Boolean;
|
function IsDateFormat(s: String; out IsLong: Boolean): Boolean;
|
||||||
begin
|
begin
|
||||||
@ -744,9 +768,58 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Builds a number format string from the numberformat code and the count of
|
{ Builds a date/time format string from the numberformat code. If the format code
|
||||||
decimals. }
|
is nfFmtDateTime the given AFormatString is used. AFormatString can use the
|
||||||
function BuildNumFormatString(ANumberFormat: TsNumberFormat;
|
abbreviations "dm" (for "d/mmm"), "my" (for "mmm/yy"), "ms" (for "mm:ss")
|
||||||
|
and "msz" (for "mm:ss.z"). }
|
||||||
|
function BuildDateTimeFormatString(ANumberFormat: TsNumberFormat;
|
||||||
|
const AFormatSettings: TFormatSettings; AFormatString: String = '') : string;
|
||||||
|
var
|
||||||
|
fmt: String;
|
||||||
|
begin
|
||||||
|
case ANumberFormat of
|
||||||
|
nfFmtDateTime:
|
||||||
|
begin
|
||||||
|
fmt := lowercase(AFormatString);
|
||||||
|
if (fmt = 'dm') then Result := 'd/mmm'
|
||||||
|
else if (fmt = 'my') then Result := 'mmm/yy'
|
||||||
|
else if (fmt = 'ms') then Result := 'nn:ss'
|
||||||
|
else if (fmt = 'msz') then Result := 'nn:ss.z'
|
||||||
|
else Result := AFormatString;
|
||||||
|
end;
|
||||||
|
nfShortDateTime:
|
||||||
|
Result := AFormatSettings.ShortDateFormat + ' ' + FormatSettings.ShortTimeFormat;
|
||||||
|
nfShortDate:
|
||||||
|
Result := AFormatSettings.ShortDateFormat;
|
||||||
|
nfLongDate:
|
||||||
|
Result := AFormatSettings.LongDateFormat;
|
||||||
|
nfShortTime:
|
||||||
|
Result := StripAMPM(AFormatSettings.ShortTimeFormat);
|
||||||
|
nfLongTime:
|
||||||
|
Result := StripAMPM(AFormatSettings.LongTimeFormat);
|
||||||
|
nfShortTimeAM:
|
||||||
|
begin
|
||||||
|
Result := AFormatSettings.ShortTimeFormat;
|
||||||
|
if pos('a', lowercase(AFormatSettings.ShortTimeFormat)) = 0 then
|
||||||
|
Result := Format('%s %s/%s', [Result, AFormatSettings.TimeAMString, AFormatSettings.TimePMString]);
|
||||||
|
end;
|
||||||
|
nfLongTimeAM:
|
||||||
|
begin
|
||||||
|
Result := AFormatSettings.LongTimeFormat;
|
||||||
|
if pos('a', lowercase(AFormatSettings.LongTimeFormat)) = 0 then
|
||||||
|
Result := Format('%s %s/%s', [Result, AFormatSettings.TimeAMString, AFormatSettings.TimePMString]);
|
||||||
|
end;
|
||||||
|
nfTimeInterval:
|
||||||
|
if AFormatString = '' then
|
||||||
|
Result := '[h]:mm:ss'
|
||||||
|
else
|
||||||
|
Result := AFormatString;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ Builds a number format string from the numberformat code, the count of
|
||||||
|
decimals, and the currencysymbol (if not empty). }
|
||||||
|
function BuildNumberFormatString(ANumberFormat: TsNumberFormat;
|
||||||
const AFormatSettings: TFormatSettings; ADecimals: Integer = -1;
|
const AFormatSettings: TFormatSettings; ADecimals: Integer = -1;
|
||||||
ACurrencySymbol: String = '?'): String;
|
ACurrencySymbol: String = '?'): String;
|
||||||
const
|
const
|
||||||
@ -778,6 +851,7 @@ var
|
|||||||
decs: String;
|
decs: String;
|
||||||
cf, ncf: Byte;
|
cf, ncf: Byte;
|
||||||
begin
|
begin
|
||||||
|
Result := '';
|
||||||
cf := AFormatSettings.CurrencyFormat;
|
cf := AFormatSettings.CurrencyFormat;
|
||||||
ncf := AFormatSettings.NegCurrFormat;
|
ncf := AFormatSettings.NegCurrFormat;
|
||||||
if ADecimals = -1 then ADecimals := AFormatSettings.CurrencyDecimals;
|
if ADecimals = -1 then ADecimals := AFormatSettings.CurrencyDecimals;
|
||||||
@ -824,6 +898,37 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function StripAMPM(const ATimeFormatString: String): String;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
Result := '';
|
||||||
|
i := 1;
|
||||||
|
while i <= Length(ATimeFormatString) do begin
|
||||||
|
if ATimeFormatString[i] in ['a', 'A'] then begin
|
||||||
|
inc(i);
|
||||||
|
while (i <= Length(ATimeFormatString)) and (ATimeFormatString[i] in ['p', 'P', 'm', 'M', '/']) do
|
||||||
|
inc(i);
|
||||||
|
end else
|
||||||
|
Result := Result + ATimeFormatString[i];
|
||||||
|
inc(i);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function CountDecs(AFormatString: String; ADecChars: TsDecsChars = ['0']): Byte;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
Result := 0;
|
||||||
|
for i:=Length(AFormatString) downto 1 do begin
|
||||||
|
if AFormatString[i] in ADecChars then inc(Result);
|
||||||
|
if AFormatString[i] = '.' then exit;
|
||||||
|
end;
|
||||||
|
// Comes to this point when there is no decimal separtor.
|
||||||
|
Result := 0;
|
||||||
|
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.). }
|
||||||
|
@ -352,7 +352,7 @@ end;
|
|||||||
procedure TsWikiTableWriter.CreateNumFormatList;
|
procedure TsWikiTableWriter.CreateNumFormatList;
|
||||||
begin
|
begin
|
||||||
FreeAndNil(FNumFormatList);
|
FreeAndNil(FNumFormatList);
|
||||||
FNumFormatList := TsWikiTableNumFormatList.Create;
|
FNumFormatList := TsWikiTableNumFormatList.Create(Workbook);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TsWikiTableWriter.WriteToStrings(AStrings: TStrings);
|
procedure TsWikiTableWriter.WriteToStrings(AStrings: TStrings);
|
||||||
|
@ -43,7 +43,7 @@ type
|
|||||||
protected
|
protected
|
||||||
procedure AddBuiltinFormats; override;
|
procedure AddBuiltinFormats; override;
|
||||||
public
|
public
|
||||||
constructor Create;
|
constructor Create(AWorkbook: TsWorkbook);
|
||||||
function FormatStringForWriting(AIndex: Integer): String; override;
|
function FormatStringForWriting(AIndex: Integer): String; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -166,9 +166,9 @@ const
|
|||||||
|
|
||||||
{ TsBIFF2NumFormatList }
|
{ TsBIFF2NumFormatList }
|
||||||
|
|
||||||
constructor TsBIFF2NumFormatList.Create;
|
constructor TsBIFF2NumFormatList.Create(AWorkbook: TsWorkbook);
|
||||||
begin
|
begin
|
||||||
inherited Create;
|
inherited Create(AWorkbook);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TsBIFF2NumFormatList.AddBuiltinFormats;
|
procedure TsBIFF2NumFormatList.AddBuiltinFormats;
|
||||||
@ -283,7 +283,7 @@ end;
|
|||||||
procedure TsSpreadBIFF2Reader.CreateNumFormatList;
|
procedure TsSpreadBIFF2Reader.CreateNumFormatList;
|
||||||
begin
|
begin
|
||||||
FreeAndNil(FNumFormatList);
|
FreeAndNil(FNumFormatList);
|
||||||
FNumFormatList := TsBIFF2NumFormatList.Create;
|
FNumFormatList := TsBIFF2NumFormatList.Create(Workbook);
|
||||||
end;
|
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.
|
||||||
@ -701,7 +701,7 @@ end;
|
|||||||
procedure TsSpreadBIFF2Writer.CreateNumFormatList;
|
procedure TsSpreadBIFF2Writer.CreateNumFormatList;
|
||||||
begin
|
begin
|
||||||
FreeAndNil(FNumFormatList);
|
FreeAndNil(FNumFormatList);
|
||||||
FNumFormatList := TsBIFF2NumFormatList.Create;
|
FNumFormatList := TsBIFF2NumFormatList.Create(Workbook);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsSpreadBIFF2Writer.FindXFIndex(ACell: PCell): Word;
|
function TsSpreadBIFF2Writer.FindXFIndex(ACell: PCell): Word;
|
||||||
|
@ -593,13 +593,15 @@ procedure TsBIFFNumFormatList.Analyze(AFormatIndex: Integer;
|
|||||||
var AFormatString: String; var ANumFormat: TsNumberFormat;
|
var AFormatString: String; var ANumFormat: TsNumberFormat;
|
||||||
var ADecimals: Byte; var ACurrencySymbol: String);
|
var ADecimals: Byte; var ACurrencySymbol: String);
|
||||||
var
|
var
|
||||||
parser: TsNumFormatParser;
|
|
||||||
fmt: String;
|
fmt: String;
|
||||||
|
{
|
||||||
|
parser: TsNumFormatParser;
|
||||||
|
sections: TsNumFormatSections;
|
||||||
|
}
|
||||||
begin
|
begin
|
||||||
|
|
||||||
{
|
(*
|
||||||
AFormatString := 'hh:mm AM/PM'; //"€" #,##.0;[red]"$" -#,##.000;-';
|
AFormatString := 'hh:mm:ss.0 AM/PM'; //"€" #,##.0;[red]"$" -#,##.000;-';
|
||||||
|
|
||||||
|
|
||||||
parser := TsNumFormatParser.Create(Workbook, AFormatString);
|
parser := TsNumFormatParser.Create(Workbook, AFormatString);
|
||||||
try
|
try
|
||||||
@ -607,10 +609,18 @@ begin
|
|||||||
ANumFormat := parser.ParsedSections[0].NumFormat;
|
ANumFormat := parser.ParsedSections[0].NumFormat;
|
||||||
ADecimals := parser.ParsedSections[0].Decimals;
|
ADecimals := parser.ParsedSections[0].Decimals;
|
||||||
ACurrencySymbol := parser.ParsedSections[0].CurrencySymbol;
|
ACurrencySymbol := parser.ParsedSections[0].CurrencySymbol;
|
||||||
|
parser.CopySectionsTo(sections);
|
||||||
finally
|
finally
|
||||||
parser.Free;
|
parser.Free;
|
||||||
end;
|
end;
|
||||||
}
|
|
||||||
|
parser := TsNumFormatParser.Create(Workbook, sections);
|
||||||
|
try
|
||||||
|
fmt := parser.FormatString;
|
||||||
|
finally
|
||||||
|
parser.Free;
|
||||||
|
end;
|
||||||
|
*)
|
||||||
|
|
||||||
fmt := Lowercase(AFormatString);
|
fmt := Lowercase(AFormatString);
|
||||||
{ Check the built-in formats first:
|
{ Check the built-in formats first:
|
||||||
@ -660,6 +670,18 @@ function TsBIFFNumFormatList.FormatStringForWriting(AIndex: Integer): String;
|
|||||||
var
|
var
|
||||||
item: TsNumFormatData;
|
item: TsNumFormatData;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
|
|
||||||
|
procedure FixN(var s: String);
|
||||||
|
// The minutes in short time formats are coded by "n" in fpc, but Excel wants "m".
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
for i:=1 to Length(s) do
|
||||||
|
case s[i] of
|
||||||
|
'n', 'N': s[i] := 'm'; // no "M" which will be interpreted as "Month"
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
Result := inherited FormatStringForWriting(AIndex);
|
Result := inherited FormatStringForWriting(AIndex);
|
||||||
item := Items[AIndex];
|
item := Items[AIndex];
|
||||||
@ -670,15 +692,19 @@ begin
|
|||||||
for i:=1 to Length(Result) do begin
|
for i:=1 to Length(Result) do begin
|
||||||
// The milliseccond format contains the symbol "z" in fpc, but Excel wants "0"
|
// The milliseccond format contains the symbol "z" in fpc, but Excel wants "0"
|
||||||
if Result[i] in ['z', 'Z'] then Result[i] := '0';
|
if Result[i] in ['z', 'Z'] then Result[i] := '0';
|
||||||
// The minutes in short time formats are coded by "n" in fpc, but Excel wants "m".
|
|
||||||
if Result[i] in ['n', 'N'] then Result[i] := 'm';
|
|
||||||
end;
|
end;
|
||||||
|
FixN(Result);
|
||||||
end;
|
end;
|
||||||
nfTimeInterval:
|
nfTimeInterval:
|
||||||
|
begin
|
||||||
// Time interval format string could still be without square brackets
|
// Time interval format string could still be without square brackets
|
||||||
// if added by user.
|
// if added by user.
|
||||||
// We check here for safety and add the brackets if not there.
|
// We check here for safety and add the brackets if not there.
|
||||||
MakeTimeIntervalMask(item.FormatString, Result);
|
MakeTimeIntervalMask(item.FormatString, Result);
|
||||||
|
FixN(Result);
|
||||||
|
end;
|
||||||
|
nfShortTime, nfShortTimeAM, nfLongTime, nfLongTimeAM:
|
||||||
|
FixN(Result);
|
||||||
nfCurrencyRed, nfCurrencyDashRed:
|
nfCurrencyRed, nfCurrencyDashRed:
|
||||||
begin
|
begin
|
||||||
i := Pos(';', item.FormatString);
|
i := Pos(';', item.FormatString);
|
||||||
@ -765,7 +791,7 @@ end;
|
|||||||
procedure TsSpreadBIFFReader.CreateNumFormatList;
|
procedure TsSpreadBIFFReader.CreateNumFormatList;
|
||||||
begin
|
begin
|
||||||
FreeAndNil(FNumFormatList);
|
FreeAndNil(FNumFormatList);
|
||||||
FNumFormatList := TsBIFFNumFormatList.Create;
|
FNumFormatList := TsBIFFNumFormatList.Create(Workbook);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Extracts a number out of an RK value.
|
{ Extracts a number out of an RK value.
|
||||||
@ -812,9 +838,11 @@ procedure TsSpreadBIFFReader.ExtractNumberFormat(AXFIndex: WORD;
|
|||||||
decs: Byte;
|
decs: Byte;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
if IsTimeFormat(ANumberFormatStr, isLong, isAMPM, isInterval, decs)
|
decs := CountDecs(ANumberFormatStr, ['0', 'z', 'Z']);
|
||||||
|
{ if IsTimeFormat(ANumberFormatStr, isLong, isAMPM, isInterval, decs)
|
||||||
and (decs > 0)
|
and (decs > 0)
|
||||||
then
|
then }
|
||||||
|
if decs > 0 then
|
||||||
for i:= Length(ANumberFormatStr) downto 1 do
|
for i:= Length(ANumberFormatStr) downto 1 do
|
||||||
case ANumberFormatStr[i] of
|
case ANumberFormatStr[i] of
|
||||||
'0': ANumberFormatStr[i] := 'z';
|
'0': ANumberFormatStr[i] := 'z';
|
||||||
@ -1361,7 +1389,7 @@ end;
|
|||||||
procedure TsSpreadBIFFWriter.CreateNumFormatList;
|
procedure TsSpreadBIFFWriter.CreateNumFormatList;
|
||||||
begin
|
begin
|
||||||
FreeAndNil(FNumFormatList);
|
FreeAndNil(FNumFormatList);
|
||||||
FNumFormatList := TsBIFFNumFormatList.Create;
|
FNumFormatList := TsBIFFNumFormatList.Create(Workbook);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsSpreadBIFFWriter.FormulaElementKindToExcelTokenID(
|
function TsSpreadBIFFWriter.FormulaElementKindToExcelTokenID(
|
||||||
@ -1679,19 +1707,16 @@ end;
|
|||||||
procedure TsSpreadBIFFWriter.WriteFormats(AStream: TStream);
|
procedure TsSpreadBIFFWriter.WriteFormats(AStream: TStream);
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
|
|
||||||
item: TsNumFormatData;
|
item: TsNumFormatData;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
ListAllNumFormats;
|
ListAllNumFormats;
|
||||||
|
|
||||||
item := NumFormatList[20];
|
|
||||||
|
|
||||||
i := NumFormatList.Find(NumFormatList.FirstFormatIndexInFile);
|
i := NumFormatList.Find(NumFormatList.FirstFormatIndexInFile);
|
||||||
if i > -1 then
|
if i > -1 then
|
||||||
while i < NumFormatList.Count do begin
|
while i < NumFormatList.Count do begin
|
||||||
if NumFormatList[i] <> nil then
|
item := NumFormatList[i];
|
||||||
WriteFormat(AStream, NumFormatList[i], i);
|
if item <> nil then begin
|
||||||
|
WriteFormat(AStream, item, i);
|
||||||
|
end;
|
||||||
inc(i);
|
inc(i);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
@ -393,7 +393,7 @@ end;
|
|||||||
procedure TsSpreadOOXMLWriter.CreateNumFormatList;
|
procedure TsSpreadOOXMLWriter.CreateNumFormatList;
|
||||||
begin
|
begin
|
||||||
FreeAndNil(FNumFormatList);
|
FreeAndNil(FNumFormatList);
|
||||||
FNumFormatList := TsOOXMLNumFormatList.Create;
|
FNumFormatList := TsOOXMLNumFormatList.Create(Workbook);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user