You've already forked lazarus-ccr
fpspreadsheet: Writing of number formats for xlsx (date/time not working yet)
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3318 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -5172,7 +5172,7 @@ end;
|
|||||||
ConvertBeforeWriting in order to convert the fpc format strings to the dialect
|
ConvertBeforeWriting in order to convert the fpc format strings to the dialect
|
||||||
used in the file.
|
used in the file.
|
||||||
|
|
||||||
@param AIndex The number format at this item is considered.
|
@param AIndex Index of the format item under consideration.
|
||||||
@return String of formatting codes that will be written to the file. }
|
@return String of formatting codes that will be written to the file. }
|
||||||
function TsCustomNumFormatList.FormatStringForWriting(AIndex: Integer): String;
|
function TsCustomNumFormatList.FormatStringForWriting(AIndex: Integer): String;
|
||||||
var
|
var
|
||||||
|
@ -44,15 +44,10 @@ type
|
|||||||
{ TsOOXMLFormatList }
|
{ TsOOXMLFormatList }
|
||||||
TsOOXMLNumFormatList = class(TsCustomNumFormatList)
|
TsOOXMLNumFormatList = class(TsCustomNumFormatList)
|
||||||
protected
|
protected
|
||||||
{
|
|
||||||
procedure AddBuiltinFormats; override;
|
procedure AddBuiltinFormats; override;
|
||||||
procedure Analyze(AFormatIndex: Integer; var AFormatString: String;
|
|
||||||
var ANumFormat: TsNumberFormat; var ADecimals: Word); override;
|
|
||||||
}
|
|
||||||
public
|
public
|
||||||
{
|
procedure ConvertBeforeWriting(var AFormatString: String;
|
||||||
function FormatStringForWriting(AIndex: Integer): String; override;
|
var ANumFormat: TsNumberFormat); override;
|
||||||
}
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TsSpreadOOXMLWriter }
|
{ TsSpreadOOXMLWriter }
|
||||||
@ -79,6 +74,7 @@ type
|
|||||||
procedure WriteBorderList(AStream: TStream);
|
procedure WriteBorderList(AStream: TStream);
|
||||||
procedure WriteFillList(AStream: TStream);
|
procedure WriteFillList(AStream: TStream);
|
||||||
procedure WriteFontList(AStream: TStream);
|
procedure WriteFontList(AStream: TStream);
|
||||||
|
procedure WriteNumFormatList(AStream: TStream);
|
||||||
procedure WriteStyleList(AStream: TStream; ANodeName: String);
|
procedure WriteStyleList(AStream: TStream; ANodeName: String);
|
||||||
protected
|
protected
|
||||||
{ Streams with the contents of files }
|
{ Streams with the contents of files }
|
||||||
@ -115,7 +111,7 @@ type
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
variants;
|
variants, fpsNumFormatParser;
|
||||||
|
|
||||||
const
|
const
|
||||||
{ OOXML general XML constants }
|
{ OOXML general XML constants }
|
||||||
@ -157,6 +153,81 @@ const
|
|||||||
MIME_STRINGS = MIME_SPREADML + '.sharedStrings+xml';
|
MIME_STRINGS = MIME_SPREADML + '.sharedStrings+xml';
|
||||||
|
|
||||||
|
|
||||||
|
{ TsOOXMLNumFormatList }
|
||||||
|
|
||||||
|
{ These are the built-in number formats as expected in the biff spreadsheet file.
|
||||||
|
Identical to BIFF8. These formats are not written to file but they are used
|
||||||
|
for lookup of the number format that Excel used. They are specified here in
|
||||||
|
fpc dialect. }
|
||||||
|
procedure TsOOXMLNumFormatList.AddBuiltinFormats;
|
||||||
|
var
|
||||||
|
fs: TFormatSettings;
|
||||||
|
cs: String;
|
||||||
|
begin
|
||||||
|
fs := Workbook.FormatSettings;
|
||||||
|
cs := AnsiToUTF8(Workbook.FormatSettings.CurrencyString);
|
||||||
|
|
||||||
|
AddFormat( 0, '', nfGeneral);
|
||||||
|
AddFormat( 1, '0', nfFixed);
|
||||||
|
AddFormat( 2, '0.00', nfFixed);
|
||||||
|
AddFormat( 3, '#,##0', nfFixedTh);
|
||||||
|
AddFormat( 4, '#,##0.00', nfFixedTh);
|
||||||
|
AddFormat( 5, '"'+cs+'"#,##0_);("'+cs+'"#,##0)', nfCurrency);
|
||||||
|
AddFormat( 6, '"'+cs+'"#,##0_);[Red]("'+cs+'"#,##0)', nfCurrencyRed);
|
||||||
|
AddFormat( 7, '"'+cs+'"#,##0.00_);("'+cs+'"#,##0.00)', nfCurrency);
|
||||||
|
AddFormat( 8, '"'+cs+'"#,##0.00_);[Red]("'+cs+'"#,##0.00)', nfCurrencyRed);
|
||||||
|
AddFormat( 9, '0%', nfPercentage);
|
||||||
|
AddFormat(10, '0.00%', nfPercentage);
|
||||||
|
AddFormat(11, '0.00E+00', nfExp);
|
||||||
|
// fraction formats 12 ('# ?/?') and 13 ('# ??/??') not supported
|
||||||
|
AddFormat(14, fs.ShortDateFormat, nfShortDate); // 'M/D/YY'
|
||||||
|
AddFormat(15, fs.LongDateFormat, nfLongDate); // 'D-MMM-YY'
|
||||||
|
AddFormat(16, 'd/mmm', nfCustom); // 'D-MMM'
|
||||||
|
AddFormat(17, 'mmm/yy', nfCustom); // 'MMM-YY'
|
||||||
|
AddFormat(18, AddAMPM(fs.ShortTimeFormat, fs), nfShortTimeAM); // 'h:mm AM/PM'
|
||||||
|
AddFormat(19, AddAMPM(fs.LongTimeFormat, fs), nfLongTimeAM); // 'h:mm:ss AM/PM'
|
||||||
|
AddFormat(20, fs.ShortTimeFormat, nfShortTime); // 'h:mm'
|
||||||
|
AddFormat(21, fs.LongTimeFormat, nfLongTime); // 'h:mm:ss'
|
||||||
|
AddFormat(22, fs.ShortDateFormat + ' ' + fs.ShortTimeFormat, nfShortDateTime); // 'M/D/YY h:mm' (localized)
|
||||||
|
// 23..36 not supported
|
||||||
|
AddFormat(37, '_(#,##0_);(#,##0)', nfCurrency);
|
||||||
|
AddFormat(38, '_(#,##0_);[Red](#,##0)', nfCurrencyRed);
|
||||||
|
AddFormat(39, '_(#,##0.00_);(#,##0.00)', nfCurrency);
|
||||||
|
AddFormat(40, '_(#,##0.00_);[Red](#,##0.00)', nfCurrencyRed);
|
||||||
|
AddFormat(41, '_("'+cs+'"* #,##0_);_("'+cs+'"* (#,##0);_("'+cs+'"* "-"_);_(@_)', nfCustom);
|
||||||
|
AddFormat(42, '_(* #,##0_);_(* (#,##0);_(* "-"_);_(@_)', nfCustom);
|
||||||
|
AddFormat(43, '_("'+cs+'"* #,##0.00_);_("'+cs+'"* (#,##0.00);_("'+cs+'"* "-"??_);_(@_)', nfCustom);
|
||||||
|
AddFormat(44, '_(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(@_)', nfCustom);
|
||||||
|
AddFormat(45, 'nn:ss', nfCustom);
|
||||||
|
AddFormat(46, '[h]:nn:ss', nfTimeInterval);
|
||||||
|
AddFormat(47, 'nn:ss.z', nfCustom);
|
||||||
|
AddFormat(48, '##0.0E+00', nfCustom);
|
||||||
|
// 49 ("Text") not supported
|
||||||
|
|
||||||
|
// All indexes from 0 to 163 are reserved for built-in formats.
|
||||||
|
// The first user-defined format starts at 164.
|
||||||
|
FFirstFormatIndexInFile := 164;
|
||||||
|
FNextFormatIndex := 164;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TsOOXMLNumFormatList.ConvertBeforeWriting(var AFormatString: String;
|
||||||
|
var ANumFormat: TsNumberFormat);
|
||||||
|
var
|
||||||
|
parser: TsNumFormatParser;
|
||||||
|
begin
|
||||||
|
parser := TsNumFormatParser.Create(Workbook, AFormatString, ANumFormat);
|
||||||
|
try
|
||||||
|
if parser.Status = psOK then begin
|
||||||
|
// For writing, we have to convert the fpc format string to Excel dialect
|
||||||
|
AFormatString := parser.FormatString[nfdExcel];
|
||||||
|
ANumFormat := parser.NumFormat;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
parser.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
{ TsSpreadOOXMLWriter }
|
{ TsSpreadOOXMLWriter }
|
||||||
|
|
||||||
{ Adds built-in styles:
|
{ Adds built-in styles:
|
||||||
@ -452,6 +523,38 @@ begin
|
|||||||
'</fonts>');
|
'</fonts>');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ Writes all number formats to the stream. Saving starts at the item with the
|
||||||
|
FirstFormatIndexInFile. }
|
||||||
|
procedure TsSpreadOOXMLWriter.WriteNumFormatList(AStream: TStream);
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
item: TsNumFormatData;
|
||||||
|
s: String;
|
||||||
|
n: Integer;
|
||||||
|
fmt: String;
|
||||||
|
begin
|
||||||
|
s := '';
|
||||||
|
n := 0;
|
||||||
|
i := NumFormatList.FindByIndex(NumFormatList.FirstFormatIndexInFile);
|
||||||
|
if i > -1 then begin
|
||||||
|
while i < NumFormatList.Count do begin
|
||||||
|
item := NumFormatList[i];
|
||||||
|
if item <> nil then begin
|
||||||
|
s := s + Format('<numFmt numFmtId="%d" formatCode="%s" />',
|
||||||
|
[item.Index, UTF8TextToXMLText(NumFormatList.FormatStringForWriting(i))]);
|
||||||
|
inc(n);
|
||||||
|
end;
|
||||||
|
inc(i);
|
||||||
|
end;
|
||||||
|
if n > 0 then
|
||||||
|
AppendToStream(AStream, Format(
|
||||||
|
'<numFmts count="%d">', [n]),
|
||||||
|
s,
|
||||||
|
'</numFmts>'
|
||||||
|
);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
{ Writes the style list which the writer has collected in FFormattingStyles. }
|
{ Writes the style list which the writer has collected in FFormattingStyles. }
|
||||||
procedure TsSpreadOOXMLWriter.WriteStyleList(AStream: TStream; ANodeName: String);
|
procedure TsSpreadOOXMLWriter.WriteStyleList(AStream: TStream; ANodeName: String);
|
||||||
var
|
var
|
||||||
@ -461,6 +564,7 @@ var
|
|||||||
numFmtId: Integer;
|
numFmtId: Integer;
|
||||||
fillId: Integer;
|
fillId: Integer;
|
||||||
borderId: Integer;
|
borderId: Integer;
|
||||||
|
idx: Integer;
|
||||||
begin
|
begin
|
||||||
AppendToStream(AStream, Format(
|
AppendToStream(AStream, Format(
|
||||||
'<%s count="%d">', [ANodeName, Length(FFormattingStyles)]));
|
'<%s count="%d">', [ANodeName, Length(FFormattingStyles)]));
|
||||||
@ -470,8 +574,13 @@ begin
|
|||||||
sAlign := '';
|
sAlign := '';
|
||||||
|
|
||||||
{ Number format }
|
{ Number format }
|
||||||
numFmtId := 0;
|
if (uffNumberFormat in styleCell.UsedFormattingFields) then begin
|
||||||
s := s + Format('numFmtId="%d" ', [numFmtId]);
|
idx := NumFormatList.FindFormatOf(@styleCell);
|
||||||
|
if idx > -1 then begin
|
||||||
|
numFmtID := NumFormatList[idx].Index;
|
||||||
|
s := s + Format('numFmtId="%d" applyNumberFormat="1" ', [numFmtId]);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
{ Font }
|
{ Font }
|
||||||
fontId := 0;
|
fontId := 0;
|
||||||
@ -586,6 +695,9 @@ begin
|
|||||||
AppendToStream(FSStyles, Format(
|
AppendToStream(FSStyles, Format(
|
||||||
'<styleSheet xmlns="%s">', [SCHEMAS_SPREADML]));
|
'<styleSheet xmlns="%s">', [SCHEMAS_SPREADML]));
|
||||||
|
|
||||||
|
// Number formats
|
||||||
|
WriteNumFormatList(FSStyles);
|
||||||
|
|
||||||
// Fonts
|
// Fonts
|
||||||
WriteFontList(FSStyles);
|
WriteFontList(FSStyles);
|
||||||
|
|
||||||
@ -594,16 +706,7 @@ begin
|
|||||||
|
|
||||||
// Borders
|
// Borders
|
||||||
WriteBorderList(FSStyles);
|
WriteBorderList(FSStyles);
|
||||||
{
|
|
||||||
AppendToStream(FSStyles,
|
|
||||||
'<borders count="1">');
|
|
||||||
AppendToStream(FSStyles,
|
|
||||||
'<border>',
|
|
||||||
'<left /><right /><top /><bottom /><diagonal />',
|
|
||||||
'</border>');
|
|
||||||
AppendToStream(FSStyles,
|
|
||||||
'</borders>');
|
|
||||||
}
|
|
||||||
// Style records
|
// Style records
|
||||||
AppendToStream(FSStyles,
|
AppendToStream(FSStyles,
|
||||||
'<cellStyleXfs count="1">',
|
'<cellStyleXfs count="1">',
|
||||||
@ -1088,13 +1191,14 @@ procedure TsSpreadOOXMLWriter.WriteNumber(AStream: TStream; const ARow,
|
|||||||
var
|
var
|
||||||
CellPosText: String;
|
CellPosText: String;
|
||||||
CellValueText: String;
|
CellValueText: String;
|
||||||
//S: String;
|
lStyleIndex: Integer;
|
||||||
begin
|
begin
|
||||||
Unused(AStream, ACell);
|
Unused(AStream, ACell);
|
||||||
CellPosText := TsWorksheet.CellPosToText(ARow, ACol);
|
CellPosText := TsWorksheet.CellPosToText(ARow, ACol);
|
||||||
CellValueText := Format('%g', [AValue], FPointSeparatorSettings);
|
CellValueText := Format('%g', [AValue], FPointSeparatorSettings);
|
||||||
|
lStyleIndex := GetStyleIndex(ACell);
|
||||||
AppendToStream(AStream, Format(
|
AppendToStream(AStream, Format(
|
||||||
'<c r="%s" s="0" t="n"><v>%s</v></c>', [CellPosText, CellValueText]));
|
'<c r="%s" s="%d" t="n"><v>%s</v></c>', [CellPosText, lStyleIndex, CellValueText]));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{*******************************************************************
|
{*******************************************************************
|
||||||
|
Reference in New Issue
Block a user