You've already forked lazarus-ccr
fpspreadsheet: Add support for number formats splitting off thousands, (Excel syntax "0.0,"), millions ("0.0,,"), etc.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4130 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -127,7 +127,7 @@ type
|
||||
implementation
|
||||
|
||||
uses
|
||||
TypInfo, LazUTF8, fpsutils, fpsCurrency;
|
||||
TypInfo, Math, LazUTF8, fpsutils, fpsCurrency;
|
||||
|
||||
|
||||
function CreateNumFormatParams(AWorkbook: TsWorkbook;
|
||||
@ -315,6 +315,13 @@ begin
|
||||
FStatus := psErrMultipleExpChars
|
||||
else
|
||||
section^.Kind := section^.Kind + [nfkExp];
|
||||
nftFactor:
|
||||
if section^.Elements[el].IntValue <> 0 then
|
||||
begin
|
||||
section^.Elements[el].FloatValue := IntPower(10, -3*section^.Elements[el].IntValue);
|
||||
section^.Factor := section^.Elements[el].FloatValue;
|
||||
section^.Kind := section^.Kind + [nfkHasFactor];
|
||||
end;
|
||||
nftFracSymbol:
|
||||
if (nfkFraction in section^.Kind) then
|
||||
FStatus := psErrMultipleFracSymbols
|
||||
@ -941,6 +948,8 @@ end;
|
||||
procedure TsNumFormatParser.ScanAndCount(ATestChar: Char; out ACount: Integer);
|
||||
begin
|
||||
ACount := 0;
|
||||
if FToken <> ATestChar then
|
||||
exit;
|
||||
repeat
|
||||
inc(ACount);
|
||||
FToken := NextToken;
|
||||
@ -1236,7 +1245,7 @@ procedure TsNumFormatParser.ScanNumber;
|
||||
var
|
||||
hasDecSep: Boolean;
|
||||
isFrac: Boolean;
|
||||
n: Integer;
|
||||
n, m: Integer;
|
||||
el: Integer;
|
||||
savedCurrent: PChar;
|
||||
begin
|
||||
@ -1254,12 +1263,13 @@ begin
|
||||
savedCurrent := FCurrent;
|
||||
if not (hasDecSep or isFrac) and (n = 1) and (FToken = ',') then
|
||||
begin
|
||||
m := 0;
|
||||
FToken := NextToken;
|
||||
ScanAndCount('#', n);
|
||||
case n of
|
||||
0: begin
|
||||
FToken := PrevToken;
|
||||
ScanAndCount('0', n);
|
||||
ScanAndCount(',', m);
|
||||
FToken := prevToken;
|
||||
if n = 3 then
|
||||
AddElement(nftIntTh, 3)
|
||||
@ -1268,6 +1278,7 @@ begin
|
||||
end;
|
||||
1: begin
|
||||
ScanAndCount('0', n);
|
||||
ScanAndCount(',', m);
|
||||
FToken := prevToken;
|
||||
if n = 2 then
|
||||
AddElement(nftIntTh, 2)
|
||||
@ -1276,6 +1287,7 @@ begin
|
||||
end;
|
||||
2: begin
|
||||
ScanAndCount('0', n);
|
||||
ScanAndCount(',', m);
|
||||
FToken := prevToken;
|
||||
if (n = 1) then
|
||||
AddElement(nftIntTh, 1)
|
||||
@ -1283,6 +1295,8 @@ begin
|
||||
FCurrent := savedCurrent;
|
||||
end;
|
||||
end;
|
||||
if m > 0 then
|
||||
AddElement(nftFactor, m);
|
||||
end else
|
||||
begin
|
||||
FToken := PrevToken;
|
||||
@ -1297,6 +1311,7 @@ begin
|
||||
end;
|
||||
'0': begin
|
||||
ScanAndCount('0', n);
|
||||
ScanAndCount(',', m);
|
||||
FToken := PrevToken;
|
||||
if hasDecSep then
|
||||
AddElement(nftZeroDecs, n)
|
||||
@ -1305,6 +1320,8 @@ begin
|
||||
AddElement(nftFracDenomZeroDigit, n)
|
||||
else
|
||||
AddElement(nftIntZeroDigit, n);
|
||||
if m > 0 then
|
||||
AddElement(nftFactor, m);
|
||||
end;
|
||||
'1'..'9':
|
||||
begin
|
||||
|
@ -620,6 +620,9 @@ begin
|
||||
nftPercent:
|
||||
Result := Result + '<number:text>%</number:text>';
|
||||
|
||||
nftFactor:
|
||||
;
|
||||
|
||||
nftCurrSymbol:
|
||||
Result := Result + '<number:currency-symbol>' + Elements[el].TextValue + '</number:currency-symbol>';
|
||||
|
||||
@ -635,6 +638,8 @@ begin
|
||||
end else
|
||||
if (el = nel-1) or (Elements[el+1].Token <> nftDecSep) then
|
||||
Result := Result + ' number:decimal-places="0"';
|
||||
if (nfkHasFactor in Kind) and (Factor <> 0) then
|
||||
Result := Result + Format(' number:display-factor="%.0f"', [1.0/Factor]);
|
||||
Result := Result + ' />';
|
||||
end;
|
||||
|
||||
@ -740,6 +745,8 @@ begin
|
||||
Result := Result + ' number:min-integer-digits="' + IntToStr(n) + '"';
|
||||
n := IfThen(Elements[el+2].Token = nftZeroDecs, Elements[el+2].IntValue, 1);
|
||||
Result := Result + ' number:decimal-places="' + IntToStr(n) + '"';
|
||||
if (nfkHasFactor in Kind) and (Factor <> 0) then
|
||||
Result := Result + Format(' number:display-factor="%.0f"', [1.0/Factor]);
|
||||
Result := Result + ' />';
|
||||
inc(el, 2);
|
||||
end
|
||||
@ -750,6 +757,8 @@ begin
|
||||
Result := Result + '<number:number number:decimal-places="0"';
|
||||
n := IfThen(Elements[el].Token = nftIntZeroDigit, Elements[el].IntValue, 1);
|
||||
Result := Result + ' number:min-integer-digits="' + IntToStr(n) + '"';
|
||||
if (nfkHasFactor in Kind) and (Factor <> 0) then
|
||||
Result := Result + Format(' number:display-factor="%.0f"', [1.0/Factor]);
|
||||
Result := Result + ' />';
|
||||
end;
|
||||
end;
|
||||
@ -2227,6 +2236,7 @@ procedure TsSpreadOpenDocReader.ReadNumFormats(AStylesNode: TDOMNode);
|
||||
nfs: String;
|
||||
decs: Byte;
|
||||
s: String;
|
||||
f: Double;
|
||||
fracInt, fracNum, fracDenom: Integer;
|
||||
grouping: Boolean;
|
||||
nex: Integer;
|
||||
@ -2253,8 +2263,18 @@ procedure TsSpreadOpenDocReader.ReadNumFormats(AStylesNode: TDOMNode);
|
||||
if s = '' then s := GetAttrValue(node, 'decimal-places');
|
||||
if s <> '' then decs := StrToInt(s) else decs := 0;
|
||||
grouping := GetAttrValue(node, 'number:grouping') = 'true';
|
||||
s := GetAttrValue(node, 'number:display-factor');
|
||||
if s <> '' then f := StrToFloat(s, FPointSeparatorSettings) else f := 1.0;
|
||||
nf := IfThen(grouping, nfFixedTh, nfFixed);
|
||||
nfs := nfs + BuildNumberFormatString(nf, Workbook.FormatSettings, decs);
|
||||
if f <> 1.0 then begin
|
||||
nf := nfCustom;
|
||||
while (f > 1.0) do
|
||||
begin
|
||||
nfs := nfs + ',';
|
||||
f := f / 1000;
|
||||
end;
|
||||
end;
|
||||
end else
|
||||
if nodeName = 'number:fraction' then
|
||||
begin
|
||||
|
@ -473,6 +473,7 @@ type
|
||||
nftExpSign, // '+' or '-' in exponent
|
||||
nftExpDigits, // '0' digits in exponent, count stored in IntValue
|
||||
nftPercent, // '%' percent symbol
|
||||
nftFactor, // thousand separators at end of format string, each one divides value by 1000
|
||||
nftFracSymbol, // '/' fraction symbol
|
||||
nftFracNumOptDigit, // '#' in numerator, count stored in IntValue
|
||||
nftFracNumSpaceDigit, // '?' in numerator, count stored in IntValue
|
||||
@ -502,7 +503,7 @@ type
|
||||
TsNumFormatElements = array of TsNumFormatElement;
|
||||
|
||||
TsNumFormatKind = (nfkPercent, nfkExp, nfkCurrency, nfkFraction,
|
||||
nfkDate, nfkTime, nfkTimeInterval, nfkHasColor, nfkHasThSep);
|
||||
nfkDate, nfkTime, nfkTimeInterval, nfkHasColor, nfkHasThSep, nfkHasFactor);
|
||||
TsNumFormatKinds = set of TsNumFormatKind;
|
||||
|
||||
TsNumFormatSection = record
|
||||
@ -510,6 +511,7 @@ type
|
||||
Kind: TsNumFormatKinds;
|
||||
NumFormat: TsNumberFormat;
|
||||
Decimals: Byte;
|
||||
Factor: Double;
|
||||
FracInt: Integer;
|
||||
FracNumerator: Integer;
|
||||
FracDenominator: Integer;
|
||||
@ -721,7 +723,6 @@ const
|
||||
HEADER_FOOTER_INDEX_FIRST = 0;
|
||||
HEADER_FOOTER_INDEX_ODD = 1;
|
||||
HEADER_FOOTER_INDEX_EVEN = 2;
|
||||
HEADER_FOOTER_INDEX_ODDEVEN = 1;
|
||||
HEADER_FOOTER_INDEX_ALL = 1;
|
||||
|
||||
function BuildFormatStringFromSection(const ASection: TsNumFormatSection): String;
|
||||
@ -907,7 +908,7 @@ end;
|
||||
function BuildFormatStringFromSection(const ASection: TsNumFormatSection): String;
|
||||
var
|
||||
element: TsNumFormatElement;
|
||||
i: Integer;
|
||||
i, n: Integer;
|
||||
begin
|
||||
Result := '';
|
||||
|
||||
@ -940,6 +941,16 @@ begin
|
||||
Result := Result + '/';
|
||||
nftPercent:
|
||||
Result := Result + '%';
|
||||
nftFactor:
|
||||
if element.IntValue <> 0 then
|
||||
begin
|
||||
n := element.IntValue;
|
||||
while (n > 0) do
|
||||
begin
|
||||
Result := Result + ',';
|
||||
dec(n);
|
||||
end;
|
||||
end;
|
||||
nftSpace:
|
||||
Result := Result + ' ';
|
||||
nftText:
|
||||
@ -1075,6 +1086,10 @@ begin
|
||||
exit;
|
||||
if Sections[i].Decimals <> ASections[i].Decimals then
|
||||
exit;
|
||||
{
|
||||
if Sections[i].Factor <> ASections[i].Factor then
|
||||
exit;
|
||||
}
|
||||
if Sections[i].FracInt <> ASections[i].FracInt then
|
||||
exit;
|
||||
if Sections[i].FracNumerator <> ASections[i].FracNumerator then
|
||||
@ -1099,7 +1114,7 @@ begin
|
||||
nftHour, nftMinute, nftSecond, nftMilliseconds,
|
||||
nftMonthMinute,
|
||||
nftIntOptDigit, nftIntZeroDigit, nftIntSpaceDigit, nftIntTh,
|
||||
nftZeroDecs, nftOptDecs, nftSpaceDecs, nftExpDigits,
|
||||
nftZeroDecs, nftOptDecs, nftSpaceDecs, nftExpDigits, nftFactor,
|
||||
nftFracNumOptDigit, nftFracNumSpaceDigit, nftFracNumZeroDigit,
|
||||
nftFracDenomOptDigit, nftFracDenomSpaceDigit, nftFracDenomZeroDigit,
|
||||
nftColor:
|
||||
|
@ -2967,6 +2967,8 @@ begin
|
||||
|
||||
if nfkPercent in section.Kind then
|
||||
AValue := AValue * 100.0;
|
||||
if nfkHasFactor in section.Kind then
|
||||
AValue := AValue * section.Factor;
|
||||
if nfkTime in section.Kind then
|
||||
DecodeTime(AValue, hr, min, sec, ms);
|
||||
if nfkDate in section.Kind then
|
||||
|
Reference in New Issue
Block a user