You've already forked lazarus-ccr
fpspreadsheet: Improvements in biff5/8 reading of number formats, a few date/time relatived issues left. biff2 not yet touched.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3073 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -31,6 +31,7 @@ var
|
|||||||
lCol: TCol;
|
lCol: TCol;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
r: Integer = 10;
|
r: Integer = 10;
|
||||||
|
s: String;
|
||||||
begin
|
begin
|
||||||
MyDir := ExtractFilePath(ParamStr(0));
|
MyDir := ExtractFilePath(ParamStr(0));
|
||||||
|
|
||||||
@ -132,7 +133,7 @@ begin
|
|||||||
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
|
||||||
begin
|
begin
|
||||||
@ -141,7 +142,7 @@ begin
|
|||||||
// MyWorksheet.WriteUTF8Text(i, 2, ParamStr(0));
|
// MyWorksheet.WriteUTF8Text(i, 2, ParamStr(0));
|
||||||
MyWorksheet.WriteUTF8Text(i, 3, ParamStr(0));
|
MyWorksheet.WriteUTF8Text(i, 3, ParamStr(0));
|
||||||
end;
|
end;
|
||||||
|
*)
|
||||||
|
|
||||||
// Write the formula E1 = A1 + B1
|
// Write the formula E1 = A1 + B1
|
||||||
SetLength(MyRPNFormula, 3);
|
SetLength(MyRPNFormula, 3);
|
||||||
@ -171,6 +172,8 @@ begin
|
|||||||
nil)))));
|
nil)))));
|
||||||
|
|
||||||
r := 10;
|
r := 10;
|
||||||
|
MyWorksheet.WriteUTF8Text(r, 0, 'Writing current date/time:');
|
||||||
|
inc(r, 2);
|
||||||
// Write current date/time to cells B11:B16
|
// Write current date/time to cells B11:B16
|
||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfShortDate');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfShortDate');
|
||||||
MyWorksheet.WriteDateTime(r, 1, now, nfShortDate);
|
MyWorksheet.WriteDateTime(r, 1, now, nfShortDate);
|
||||||
@ -209,9 +212,11 @@ begin
|
|||||||
MyWorksheet.WriteDateTime(r, 1, now, nfFmtDateTime, 'mm:ss.zzz');
|
MyWorksheet.WriteDateTime(r, 1, now, nfFmtDateTime, 'mm:ss.zzz');
|
||||||
|
|
||||||
// Write formatted numbers
|
// Write formatted numbers
|
||||||
// number := 12345.67890123456789;
|
s := '31415.9265359';
|
||||||
number := 31415.92;
|
val(s, number, i);
|
||||||
inc(r, 2);
|
inc(r, 2);
|
||||||
|
MyWorksheet.WriteUTF8Text(r, 0, 'The number '+s+' is displayed in various formats:');
|
||||||
|
inc(r,2);
|
||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfGeneral');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfGeneral');
|
||||||
MyWorksheet.WriteNumber(r, 1, number, nfGeneral);
|
MyWorksheet.WriteNumber(r, 1, number, nfGeneral);
|
||||||
MyWorksheet.WriteNumber(r, 2, -number, nfGeneral);
|
MyWorksheet.WriteNumber(r, 2, -number, nfGeneral);
|
||||||
@ -318,15 +323,15 @@ begin
|
|||||||
|
|
||||||
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.WriteDateTime(r, 1, number);
|
MyWorksheet.WriteNumber(r, 1, number);
|
||||||
MyWorksheet.WriteNumberFormat(r, 1, nfCustom, '"EUR "#,##0_);("EUR "#,##0)');
|
MyWorksheet.WriteNumberFormat(r, 1, nfCustom, '"EUR "#,##0_);("EUR "#,##0)');
|
||||||
MyWorksheet.WriteDateTime(r, 2, -number);
|
MyWorksheet.WriteNumber(r, 2, -number);
|
||||||
MyWorksheet.WriteNumberFormat(r, 2, nfCustom, '"EUR "#,##0_);("EUR "#,##0)');
|
MyWorksheet.WriteNumberFormat(r, 2, nfCustom, '"EUR "#,##0_);("EUR "#,##0)');
|
||||||
inc(r);
|
inc(r);
|
||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfCustom, "$"#,##0.0_);[Red]("$"#,##0.0)');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfCustom, "$"#,##0.0_);[Red]("$"#,##0.0)');
|
||||||
MyWorksheet.WriteDateTime(r, 1, number);
|
MyWorksheet.WriteNumber(r, 1, number);
|
||||||
MyWorksheet.WriteNumberFormat(r, 1, nfCustom, '"$"#,##0.0_);[Red]("$"#,##0.0)');
|
MyWorksheet.WriteNumberFormat(r, 1, nfCustom, '"$"#,##0.0_);[Red]("$"#,##0.0)');
|
||||||
MyWorksheet.WriteDateTime(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);
|
||||||
@ -368,10 +373,10 @@ begin
|
|||||||
MyWorksheet.WriteDateTime(r, 1, number, nfTimeInterval, 'h');
|
MyWorksheet.WriteDateTime(r, 1, number, nfTimeInterval, 'h');
|
||||||
|
|
||||||
// Set width of columns 0, 1 and 5
|
// Set width of columns 0, 1 and 5
|
||||||
MyWorksheet.WriteColWidth(0, 25);
|
MyWorksheet.WriteColWidth(0, 30);
|
||||||
lCol.Width := 20;
|
lCol.Width := 25;
|
||||||
MyWorksheet.WriteColInfo(1, lCol);
|
MyWorksheet.WriteColInfo(1, lCol);
|
||||||
MyWorksheet.WriteColInfo(2, lCol);
|
MyWorksheet.WriteColWidth(2, 15);
|
||||||
MyWorksheet.WriteColWidth(3, 15);
|
MyWorksheet.WriteColWidth(3, 15);
|
||||||
MyWorksheet.WriteColWidth(4, 15);
|
MyWorksheet.WriteColWidth(4, 15);
|
||||||
lCol.Width := 5;
|
lCol.Width := 5;
|
||||||
@ -379,7 +384,7 @@ begin
|
|||||||
|
|
||||||
// Set height of rows 0
|
// Set height of rows 0
|
||||||
MyWorksheet.WriteRowHeight(0, 30); // 30 mm
|
MyWorksheet.WriteRowHeight(0, 30); // 30 mm
|
||||||
(*
|
|
||||||
// Creates a new worksheet
|
// Creates a new worksheet
|
||||||
MyWorksheet := MyWorkbook.AddWorksheet(Str_Worksheet2);
|
MyWorksheet := MyWorkbook.AddWorksheet(Str_Worksheet2);
|
||||||
|
|
||||||
@ -390,7 +395,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;
|
||||||
|
@ -79,6 +79,8 @@ type
|
|||||||
procedure ScanText;
|
procedure ScanText;
|
||||||
|
|
||||||
public
|
public
|
||||||
|
constructor Create(AWorkbook: TsWorkbook; const AFormatString: String;
|
||||||
|
AConversionDirection: TsConversionDirection = cdToFPSpreadsheet); overload;
|
||||||
constructor Create(AWorkbook: TsWorkbook;
|
constructor Create(AWorkbook: TsWorkbook;
|
||||||
const AFormatString: String; ANumFormat: TsNumberFormat;
|
const AFormatString: String; ANumFormat: TsNumberFormat;
|
||||||
AConversionDirection: TsConversionDirection = cdToFPSpreadsheet); overload;
|
AConversionDirection: TsConversionDirection = cdToFPSpreadsheet); overload;
|
||||||
@ -110,6 +112,20 @@ const
|
|||||||
{ Creates a number format parser for analyzing a formatstring that has been read
|
{ 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
|
from a spreadsheet file. The conversion, by default, will go FROM the file TO
|
||||||
the fpspreadsheet procedures. }
|
the fpspreadsheet procedures. }
|
||||||
|
constructor TsNumFormatParser.Create(AWorkbook: TsWorkbook;
|
||||||
|
const AFormatString: String;
|
||||||
|
AConversionDirection: TsConversionDirection = cdToFPSpreadsheet);
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
FCreateMethod := 0;
|
||||||
|
FConversionDirection := AConversionDirection;
|
||||||
|
FWorkbook := AWorkbook;
|
||||||
|
FFormatSettings := DefaultFormatSettings;
|
||||||
|
FFormatSettings.DecimalSeparator := '.';
|
||||||
|
FFormatSettings.ThousandSeparator := ',';
|
||||||
|
Parse(AFormatString);
|
||||||
|
end;
|
||||||
|
|
||||||
constructor TsNumFormatParser.Create(AWorkbook: TsWorkbook;
|
constructor TsNumFormatParser.Create(AWorkbook: TsWorkbook;
|
||||||
const AFormatString: String; ANumFormat: TsNumberFormat;
|
const AFormatString: String; ANumFormat: TsNumberFormat;
|
||||||
AConversionDirection: TsConversionDirection = cdToFPSpreadsheet);
|
AConversionDirection: TsConversionDirection = cdToFPSpreadsheet);
|
||||||
@ -294,7 +310,7 @@ begin
|
|||||||
nfShortDateTime, nfShortDate, nfShortTime, nfShortTimeAM,
|
nfShortDateTime, nfShortDate, nfShortTime, nfShortTimeAM,
|
||||||
nfLongDate, nfLongTime, nfLongTimeAM, nfTimeInterval, nfFmtDateTime:
|
nfLongDate, nfLongTime, nfLongTimeAM, nfTimeInterval, nfFmtDateTime:
|
||||||
try
|
try
|
||||||
s := FormatDateTimeEx(FSections[i].FormatString, now(), FWorkbook.FormatSettings);
|
s := FormatDateTime(FSections[i].FormatString, now(), FWorkbook.FormatSettings, [fdoInterval]);
|
||||||
except
|
except
|
||||||
FStatus := psErrNoValidDateTimeFormat;
|
FStatus := psErrNoValidDateTimeFormat;
|
||||||
exit;
|
exit;
|
||||||
@ -310,8 +326,9 @@ begin
|
|||||||
if (ns = 3) and
|
if (ns = 3) and
|
||||||
(FSections[0].NumFormat = nfCurrency) and
|
(FSections[0].NumFormat = nfCurrency) and
|
||||||
(FSections[1].NumFormat = nfCurrency) and
|
(FSections[1].NumFormat = nfCurrency) and
|
||||||
(FSections[2].NumFormat = nfCurrency)
|
((FSections[2].NumFormat = nfCurrency) or (FSections[2].FormatString = '-'))
|
||||||
then begin
|
then begin
|
||||||
|
FNumFormat := nfCurrency;
|
||||||
if ((FSections[2].FormatString = '-') or (FSections[2].FormatString = '"-"')) then begin
|
if ((FSections[2].FormatString = '-') or (FSections[2].FormatString = '"-"')) then begin
|
||||||
if (FSections[1].Color = scRed) then
|
if (FSections[1].Color = scRed) then
|
||||||
FNumFormat := nfCurrencyDashRed
|
FNumFormat := nfCurrencyDashRed
|
||||||
@ -323,8 +340,15 @@ begin
|
|||||||
end;
|
end;
|
||||||
end else
|
end else
|
||||||
// If there are other multi-section formatstrings they must be a custom format
|
// If there are other multi-section formatstrings they must be a custom format
|
||||||
if (ns > 1) then
|
if (ns > 1) then begin
|
||||||
FNumFormat := nfCustom
|
for i:=1 to ns-1 do
|
||||||
|
if FSections[i].FormatString <> '' then begin
|
||||||
|
FNumFormat := nfCustom;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
if fNumFormat <> nfCustom then
|
||||||
|
FNumFormat := FSections[0].NumFormat;
|
||||||
|
end
|
||||||
else
|
else
|
||||||
FNumFormat := FSections[0].NumFormat;
|
FNumFormat := FSections[0].NumFormat;
|
||||||
|
|
||||||
@ -721,15 +745,14 @@ begin
|
|||||||
end;
|
end;
|
||||||
'E', 'e':
|
'E', 'e':
|
||||||
begin
|
begin
|
||||||
if hasHash and countdecs then isSci := true else isExp := true;
|
if hasHash then isSci := true else isExp := true;
|
||||||
countdecs := false;
|
countdecs := false;
|
||||||
s := s + token;
|
s := s + token;
|
||||||
end;
|
end;
|
||||||
'+', '-':
|
'+', '-':
|
||||||
s := s + token;
|
s := s + token;
|
||||||
'#': begin
|
'#': begin
|
||||||
hasHash := true;
|
if not countdecs then hasHash := true;
|
||||||
countdecs := false;
|
|
||||||
s := s + token;
|
s := s + token;
|
||||||
end;
|
end;
|
||||||
'%': begin
|
'%': begin
|
||||||
|
@ -1277,9 +1277,9 @@ function TsWorksheet.ReadAsUTF8Text(ARow, ACol: Cardinal): ansistring;
|
|||||||
Result := '';
|
Result := '';
|
||||||
if not IsNaN(Value) then begin
|
if not IsNaN(Value) then begin
|
||||||
if ANumberFormatStr = '' then
|
if ANumberFormatStr = '' then
|
||||||
Result := FormatDateTime('c', Value)
|
ANumberFormatStr := BuildDateTimeFormatString(ANumberFormat,
|
||||||
else
|
Workbook.FormatSettings, ANumberFormatStr);
|
||||||
Result := FormatDateTimeEx(ANumberFormatStr, Value);
|
Result := FormatDateTime(ANumberFormatStr, Value, [fdoInterval]);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1454,8 +1454,10 @@ begin
|
|||||||
if IsDateTimeFormat(AFormat) then
|
if IsDateTimeFormat(AFormat) then
|
||||||
raise Exception.Create(lpInvalidNumberFormat);
|
raise Exception.Create(lpInvalidNumberFormat);
|
||||||
|
|
||||||
|
{
|
||||||
if AFormat = nfCustom then
|
if AFormat = nfCustom then
|
||||||
raise Exception.Create(lpIllegalNumberformat);
|
raise Exception.Create(lpIllegalNumberformat);
|
||||||
|
}
|
||||||
|
|
||||||
if AFormat <> nfGeneral then begin
|
if AFormat <> nfGeneral then begin
|
||||||
Include(ACell^.UsedFormattingFields, uffNumberFormat);
|
Include(ACell^.UsedFormattingFields, uffNumberFormat);
|
||||||
@ -2753,12 +2755,13 @@ begin
|
|||||||
if parser.Status = psOK then begin
|
if parser.Status = psOK then begin
|
||||||
ANumFormat := parser.Builtin_NumFormat;
|
ANumFormat := parser.Builtin_NumFormat;
|
||||||
AFormatString := parser.FormatString; // This is the converted string.
|
AFormatString := parser.FormatString; // This is the converted string.
|
||||||
{
|
if ANumFormat <> nfCustom then begin
|
||||||
if not (parser.Builtin_NumFormat in [nfCustom, nfFmtDateTime]) then begin
|
|
||||||
ADecimals := parser.ParsedSections[0].Decimals;
|
ADecimals := parser.ParsedSections[0].Decimals;
|
||||||
ACurrencySymbol := parser.ParsedSections[0].CurrencySymbol;
|
ACurrencySymbol := parser.ParsedSections[0].CurrencySymbol;
|
||||||
|
end else begin
|
||||||
|
ADecimals := 0;
|
||||||
|
ACurrencySymbol := '';
|
||||||
end;
|
end;
|
||||||
}
|
|
||||||
end;
|
end;
|
||||||
finally
|
finally
|
||||||
parser.Free;
|
parser.Free;
|
||||||
@ -2953,6 +2956,7 @@ var
|
|||||||
fmt: String;
|
fmt: String;
|
||||||
itemfmt: String;
|
itemfmt: String;
|
||||||
begin
|
begin
|
||||||
|
(*
|
||||||
// These are pre-defined formats - no need to check format string & decimals
|
// These are pre-defined formats - no need to check format string & decimals
|
||||||
if ANumFormat in [ nfGeneral, nfShortDateTime, nfShortDate, nfLongDate,
|
if ANumFormat in [ nfGeneral, nfShortDateTime, nfShortDate, nfLongDate,
|
||||||
nfShortTime, nfLongTime, nfShortTimeAM, nfLongTimeAM ]
|
nfShortTime, nfLongTime, nfShortTimeAM, nfLongTimeAM ]
|
||||||
@ -2962,10 +2966,10 @@ begin
|
|||||||
if (item <> nil) and (item.NumFormat = ANumFormat) then
|
if (item <> nil) and (item.NumFormat = ANumFormat) then
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
*)
|
||||||
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 := 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 = nfFmtDateTime) then begin
|
||||||
itemfmt := lowercase(item.FormatString);
|
itemfmt := lowercase(item.FormatString);
|
||||||
@ -2996,7 +3000,7 @@ begin
|
|||||||
|
|
||||||
// Check only the format string for nfCustom.
|
// Check only the format string for nfCustom.
|
||||||
if (ANumFormat = nfCustom) then
|
if (ANumFormat = nfCustom) then
|
||||||
for Result := 0 to Count-1 do begin
|
for Result := Count-1 downto 0 do begin
|
||||||
item := Items[Result];
|
item := Items[Result];
|
||||||
if (item <> nil)
|
if (item <> nil)
|
||||||
and (item.NumFormat = ANumFormat)
|
and (item.NumFormat = ANumFormat)
|
||||||
@ -3006,7 +3010,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
// The other formats can carry additional information
|
// The other formats can carry additional information
|
||||||
for Result := 0 to Count-1 do begin
|
for Result := Count-1 downto 0 do begin
|
||||||
item := Items[Result];
|
item := Items[Result];
|
||||||
if (item <> nil)
|
if (item <> nil)
|
||||||
and (item.NumFormat = ANumFormat)
|
and (item.NumFormat = ANumFormat)
|
||||||
@ -3040,7 +3044,9 @@ function TsCustomNumFormatList.Find(AFormatString: String): integer;
|
|||||||
var
|
var
|
||||||
item: TsNumFormatData;
|
item: TsNumFormatData;
|
||||||
begin
|
begin
|
||||||
for Result := 0 to Count-1 do begin
|
{ We search backwards to find user-defined items first. They usually are
|
||||||
|
more appropriate than built-in items. }
|
||||||
|
for Result := Count-1 downto 0 do begin
|
||||||
item := Items[Result];
|
item := Items[Result];
|
||||||
if item.FormatString = AFormatString then
|
if item.FormatString = AFormatString then
|
||||||
exit;
|
exit;
|
||||||
@ -3192,7 +3198,7 @@ var
|
|||||||
begin
|
begin
|
||||||
Result := -1;
|
Result := -1;
|
||||||
|
|
||||||
for i := 0 to Length(FFormattingStyles) - 1 do
|
for i := Length(FFormattingStyles) - 1 downto 0 do
|
||||||
begin
|
begin
|
||||||
if (FFormattingStyles[i].UsedFormattingFields <> AFormat^.UsedFormattingFields) then Continue;
|
if (FFormattingStyles[i].UsedFormattingFields <> AFormat^.UsedFormattingFields) then Continue;
|
||||||
|
|
||||||
|
@ -19,6 +19,10 @@ type
|
|||||||
TsSelectionDirection = (fpsVerticalSelection, fpsHorizontalSelection);
|
TsSelectionDirection = (fpsVerticalSelection, fpsHorizontalSelection);
|
||||||
TsDecsChars = set of char;
|
TsDecsChars = set of char;
|
||||||
|
|
||||||
|
// to be removed when fpc trunk is stable
|
||||||
|
TFormatDateTimeOption = (fdoInterval);
|
||||||
|
TFormatDateTimeOptions = set of TFormatDateTimeOption;
|
||||||
|
|
||||||
const
|
const
|
||||||
// Date formatting string for unambiguous date/time display as strings
|
// Date formatting string for unambiguous date/time display as strings
|
||||||
// Can be used for text output when date/time cell support is not available
|
// Can be used for text output when date/time cell support is not available
|
||||||
@ -90,9 +94,11 @@ function SciFloat(AValue: Double; ADecimals: Byte): String;
|
|||||||
//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);
|
||||||
|
|
||||||
function FormatDateTimeEx(const FormatStr: string; DateTime: TDateTime): String; overload;
|
// These two functions are copies of fpc trunk until they are available in "stable"
|
||||||
function FormatDateTimeEx(const FormatStr: string; DateTime: TDateTime;
|
function FormatDateTime(const FormatStr: string; DateTime: TDateTime;
|
||||||
AFormatSettings: TFormatSettings): string; overload;
|
Options : TFormatDateTimeOptions = []): string;
|
||||||
|
function FormatDateTime(const FormatStr: string; DateTime: TDateTime;
|
||||||
|
const FormatSettings: TFormatSettings; Options : TFormatDateTimeOptions = []): string;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
@ -1048,21 +1054,20 @@ end;
|
|||||||
{******************************************************************************}
|
{******************************************************************************}
|
||||||
|
|
||||||
// Copied from "fpc/rtl/objpas/sysutils/datei.inc"
|
// Copied from "fpc/rtl/objpas/sysutils/datei.inc"
|
||||||
procedure DateTimeToString(out Result: string; const FormatStr: string; const DateTime: TDateTime; const FormatSettings: TFormatSettings);
|
{ DateTimeToString formats DateTime to the given format in FormatStr }
|
||||||
|
|
||||||
|
procedure DateTimeToString(out Result: string; const FormatStr: string; const DateTime: TDateTime;
|
||||||
|
const FormatSettings: TFormatSettings; Options : TFormatDateTimeOptions = []);
|
||||||
var
|
var
|
||||||
ResultLen: integer;
|
ResultLen: integer;
|
||||||
ResultBuffer: array[0..255] of char;
|
ResultBuffer: array[0..255] of char;
|
||||||
ResultCurrent: pchar;
|
ResultCurrent: pchar;
|
||||||
|
|
||||||
{$IFDEF MSWindows}
|
{$IFDEF MSWindows}
|
||||||
isEnable_E_Format : Boolean;
|
isEnable_E_Format : Boolean;
|
||||||
isEnable_G_Format : Boolean;
|
isEnable_G_Format : Boolean;
|
||||||
eastasiainited : boolean;
|
eastasiainited : boolean;
|
||||||
{$ENDIF MSWindows}
|
{$ENDIF MSWindows}
|
||||||
|
(* ---- not needed here ---
|
||||||
(* This part is in the original code. It is not needed here and avoids a
|
|
||||||
dependency on the unit Windows.
|
|
||||||
|
|
||||||
{$IFDEF MSWindows}
|
{$IFDEF MSWindows}
|
||||||
procedure InitEastAsia;
|
procedure InitEastAsia;
|
||||||
var ALCID : LCID;
|
var ALCID : LCID;
|
||||||
@ -1095,7 +1100,7 @@ var
|
|||||||
eastasiainited :=true;
|
eastasiainited :=true;
|
||||||
end;
|
end;
|
||||||
{$ENDIF MSWindows}
|
{$ENDIF MSWindows}
|
||||||
*)
|
*)
|
||||||
procedure StoreStr(Str: PChar; Len: Integer);
|
procedure StoreStr(Str: PChar; Len: Integer);
|
||||||
begin
|
begin
|
||||||
if ResultLen + Len < SizeOf(ResultBuffer) then
|
if ResultLen + Len < SizeOf(ResultBuffer) then
|
||||||
@ -1136,7 +1141,7 @@ var
|
|||||||
|
|
||||||
var
|
var
|
||||||
Year, Month, Day, DayOfWeek, Hour, Minute, Second, MilliSecond: word;
|
Year, Month, Day, DayOfWeek, Hour, Minute, Second, MilliSecond: word;
|
||||||
|
DT : TDateTime;
|
||||||
|
|
||||||
procedure StoreFormat(const FormatStr: string; Nesting: Integer; TimeFlag: Boolean);
|
procedure StoreFormat(const FormatStr: string; Nesting: Integer; TimeFlag: Boolean);
|
||||||
var
|
var
|
||||||
@ -1226,9 +1231,9 @@ var
|
|||||||
end ;
|
end ;
|
||||||
'/': StoreStr(@FormatSettings.DateSeparator, 1);
|
'/': StoreStr(@FormatSettings.DateSeparator, 1);
|
||||||
':': StoreStr(@FormatSettings.TimeSeparator, 1);
|
':': StoreStr(@FormatSettings.TimeSeparator, 1);
|
||||||
'[': isInterval := true;
|
'[': if (fdoInterval in Options) then isInterval := true else StoreStr(FormatCurrent, 1);
|
||||||
']': isInterval := false;
|
']': if (fdoInterval in Options) then isInterval := false else StoreStr(FormatCurrent, 1);
|
||||||
' ', 'C', 'D', 'H', 'M', 'N', 'S', 'T', 'Y','Z' :
|
' ', 'C', 'D', 'H', 'M', 'N', 'S', 'T', 'Y', 'Z', 'F' :
|
||||||
begin
|
begin
|
||||||
while (P < FormatEnd) and (UpCase(P^) = Token) do
|
while (P < FormatEnd) and (UpCase(P^) = Token) do
|
||||||
Inc(P);
|
Inc(P);
|
||||||
@ -1243,7 +1248,7 @@ var
|
|||||||
end;
|
end;
|
||||||
'M': begin
|
'M': begin
|
||||||
if isInterval and ((prevlasttoken = 'H') or TimeFlag) then
|
if isInterval and ((prevlasttoken = 'H') or TimeFlag) then
|
||||||
StoreInt(Minute + Hour*60 + trunc(DateTime)*24*60, 0)
|
StoreInt(Minute + (Hour + trunc(abs(DateTime))*24)*60, 0)
|
||||||
else
|
else
|
||||||
if (lastformattoken = 'H') or TimeFlag then
|
if (lastformattoken = 'H') or TimeFlag then
|
||||||
begin
|
begin
|
||||||
@ -1276,7 +1281,7 @@ var
|
|||||||
end ;
|
end ;
|
||||||
'H':
|
'H':
|
||||||
if isInterval then
|
if isInterval then
|
||||||
StoreInt(Hour + trunc(DateTime)*24, 0)
|
StoreInt(Hour + trunc(abs(DateTime))*24, 0)
|
||||||
else
|
else
|
||||||
if Clock12 then
|
if Clock12 then
|
||||||
begin
|
begin
|
||||||
@ -1294,14 +1299,14 @@ var
|
|||||||
StoreInt(Hour, 2);
|
StoreInt(Hour, 2);
|
||||||
end;
|
end;
|
||||||
'N': if isInterval then
|
'N': if isInterval then
|
||||||
StoreInt(Minute + 60*Hour + 60*24*trunc(DateTime), 0)
|
StoreInt(Minute + (Hour + trunc(abs(DateTime))*24)*60, 0)
|
||||||
else
|
else
|
||||||
if Count = 1 then
|
if Count = 1 then
|
||||||
StoreInt(Minute, 0)
|
StoreInt(Minute, 0)
|
||||||
else
|
else
|
||||||
StoreInt(Minute, 2);
|
StoreInt(Minute, 2);
|
||||||
'S': if isInterval then
|
'S': if isInterval then
|
||||||
StoreInt(Second + Minute*60 + Hour*60*60 + trunc(DateTime)*24*60*60, 0)
|
StoreInt(Second + (Minute + (Hour + trunc(abs(DateTime))*24)*60)*60, 0)
|
||||||
else
|
else
|
||||||
if Count = 1 then
|
if Count = 1 then
|
||||||
StoreInt(Second, 0)
|
StoreInt(Second, 0)
|
||||||
@ -1323,10 +1328,12 @@ var
|
|||||||
StoreFormat(FormatSettings.LongTimeFormat, Nesting+1, True);
|
StoreFormat(FormatSettings.LongTimeFormat, Nesting+1, True);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
'F': begin
|
||||||
(* This part is in the original code. It is not needed here and avoids a
|
StoreFormat(FormatSettings.ShortDateFormat, Nesting+1, False);
|
||||||
dependency on the unit Windows.
|
StoreString(' ');
|
||||||
|
StoreFormat(FormatSettings.LongTimeFormat, Nesting+1, True);
|
||||||
|
end;
|
||||||
|
(* ------------ not needed here...
|
||||||
{$IFDEF MSWindows}
|
{$IFDEF MSWindows}
|
||||||
'E':
|
'E':
|
||||||
begin
|
begin
|
||||||
@ -1339,6 +1346,7 @@ var
|
|||||||
Count := P - FormatCurrent;
|
Count := P - FormatCurrent;
|
||||||
StoreString(ConvertEraYearString(Count,Year,Month,Day));
|
StoreString(ConvertEraYearString(Count,Year,Month,Day));
|
||||||
end;
|
end;
|
||||||
|
prevlasttoken := lastformattoken;
|
||||||
lastformattoken:=token;
|
lastformattoken:=token;
|
||||||
end;
|
end;
|
||||||
'G':
|
'G':
|
||||||
@ -1352,6 +1360,7 @@ var
|
|||||||
Count := P - FormatCurrent;
|
Count := P - FormatCurrent;
|
||||||
StoreString(ConvertEraString(Count,Year,Month,Day));
|
StoreString(ConvertEraString(Count,Year,Month,Day));
|
||||||
end;
|
end;
|
||||||
|
prevlasttoken := lastformattoken;
|
||||||
lastformattoken:=token;
|
lastformattoken:=token;
|
||||||
end;
|
end;
|
||||||
{$ENDIF MSWindows}
|
{$ENDIF MSWindows}
|
||||||
@ -1383,15 +1392,25 @@ begin
|
|||||||
result := StrPas(@ResultBuffer[0]);
|
result := StrPas(@ResultBuffer[0]);
|
||||||
end ;
|
end ;
|
||||||
|
|
||||||
function FormatDateTimeEx(const FormatStr: string; DateTime: TDateTime): string;
|
procedure DateTimeToString(out Result: string; const FormatStr: string;
|
||||||
|
const DateTime: TDateTime; Options : TFormatDateTimeOptions = []);
|
||||||
begin
|
begin
|
||||||
DateTimeToString(Result, FormatStr, DateTime, DefaultFormatSettings);
|
DateTimeToString(Result, FormatStr, DateTime, DefaultFormatSettings, Options);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function FormatDateTimeEx(const FormatStr: string; DateTime: TDateTime;
|
|
||||||
AFormatSettings: TFormatSettings): string;
|
{ FormatDateTime formats DateTime to the given format string FormatStr }
|
||||||
|
|
||||||
|
function FormatDateTime(const FormatStr: string; DateTime: TDateTime;
|
||||||
|
Options : TFormatDateTimeOptions = []): string;
|
||||||
begin
|
begin
|
||||||
DateTimeToString(Result, FormatStr, DateTime, AFormatSettings);
|
DateTimeToString(Result, FormatStr, DateTime, DefaultFormatSettings,Options);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FormatDateTime(const FormatStr: string; DateTime: TDateTime;
|
||||||
|
const FormatSettings: TFormatSettings; Options : TFormatDateTimeOptions = []): string;
|
||||||
|
begin
|
||||||
|
DateTimeToString(Result, FormatStr, DateTime, FormatSettings,Options);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
@ -189,7 +189,7 @@ begin
|
|||||||
SollDateTimeStrings[i, 6] := FormatDateTime('dd/mmm', SollDateTimes[i]);
|
SollDateTimeStrings[i, 6] := FormatDateTime('dd/mmm', SollDateTimes[i]);
|
||||||
SollDateTimeStrings[i, 7] := FormatDateTime('mmm/yy', SollDateTimes[i]);
|
SollDateTimeStrings[i, 7] := FormatDateTime('mmm/yy', SollDateTimes[i]);
|
||||||
SollDateTimeStrings[i, 8] := FormatDateTime('nn:ss', SollDateTimes[i]);
|
SollDateTimeStrings[i, 8] := FormatDateTime('nn:ss', SollDateTimes[i]);
|
||||||
SollDateTimeStrings[i, 9] := FormatDateTime('[h]:mm:ss', SollDateTimes[i]);
|
SollDateTimeStrings[i, 9] := FormatDateTime('[h]:mm:ss', SollDateTimes[i], [fdoInterval]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Column width
|
// Column width
|
||||||
|
@ -84,6 +84,7 @@ type
|
|||||||
procedure ReadFormat(AStream: TStream); override;
|
procedure ReadFormat(AStream: TStream); override;
|
||||||
procedure ReadLabel(AStream: TStream); override;
|
procedure ReadLabel(AStream: TStream); override;
|
||||||
procedure ReadLabelSST(const AStream: TStream);
|
procedure ReadLabelSST(const AStream: TStream);
|
||||||
|
// procedure ReadNumber() --> xlscommon
|
||||||
procedure ReadRichString(const AStream: TStream);
|
procedure ReadRichString(const AStream: TStream);
|
||||||
procedure ReadSST(const AStream: TStream);
|
procedure ReadSST(const AStream: TStream);
|
||||||
procedure ReadStringRecord(AStream: TStream); override;
|
procedure ReadStringRecord(AStream: TStream); override;
|
||||||
|
@ -835,25 +835,6 @@ end;
|
|||||||
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);
|
||||||
|
|
||||||
procedure FixMilliseconds;
|
|
||||||
var
|
|
||||||
isLong, isAMPM, isInterval: Boolean;
|
|
||||||
decs: Byte;
|
|
||||||
i: Integer;
|
|
||||||
begin
|
|
||||||
decs := CountDecs(ANumberFormatStr, ['0', 'z', 'Z']);
|
|
||||||
{ if IsTimeFormat(ANumberFormatStr, isLong, isAMPM, isInterval, decs)
|
|
||||||
and (decs > 0)
|
|
||||||
then }
|
|
||||||
if decs > 0 then
|
|
||||||
for i:= Length(ANumberFormatStr) downto 1 do
|
|
||||||
case ANumberFormatStr[i] of
|
|
||||||
'0': ANumberFormatStr[i] := 'z';
|
|
||||||
'.': break;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
var
|
var
|
||||||
lNumFormatData: TsNumFormatData;
|
lNumFormatData: TsNumFormatData;
|
||||||
begin
|
begin
|
||||||
@ -863,7 +844,6 @@ begin
|
|||||||
ANumberFormatStr := lNumFormatData.FormatString;
|
ANumberFormatStr := lNumFormatData.FormatString;
|
||||||
ADecimals := lNumFormatData.Decimals;
|
ADecimals := lNumFormatData.Decimals;
|
||||||
ACurrencySymbol := lNumFormatData.CurrencySymbol;
|
ACurrencySymbol := lNumFormatData.CurrencySymbol;
|
||||||
FixMilliseconds;
|
|
||||||
end else begin
|
end else begin
|
||||||
ANumberFormat := nfGeneral;
|
ANumberFormat := nfGeneral;
|
||||||
ANumberFormatStr := '';
|
ANumberFormatStr := '';
|
||||||
@ -1186,9 +1166,11 @@ begin
|
|||||||
{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, nd, ncs, nfs);
|
||||||
if IsDateTime(value, nf, dt) then
|
if IsDateTime(value, nf, dt) then
|
||||||
FWorksheet.WriteDateTime(ARow, ACol, dt, nf, nfs)
|
FWorksheet.WriteDateTime(ARow, ACol, dt) //, nf, nfs)
|
||||||
else
|
else
|
||||||
|
if nf <> nfCustom then
|
||||||
FWorksheet.WriteNumber(ARow, ACol, value, nf, nd, ncs);
|
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);
|
||||||
@ -2055,7 +2037,6 @@ 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^;
|
||||||
// CopyCellFormat(ACell, @lCell);
|
|
||||||
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
|
||||||
|
Reference in New Issue
Block a user