You've already forked lazarus-ccr
fpspreadsheet: add support for writing currency formats to ods files. Fix "red" option for negative numbers.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3186 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -44,6 +44,9 @@ begin
|
|||||||
|
|
||||||
MyWorksheet := MyWorkbook.AddWorksheet(Str_Worksheet1);
|
MyWorksheet := MyWorkbook.AddWorksheet(Str_Worksheet1);
|
||||||
MyWorksheet.Options := MyWorksheet.Options - [soShowGridLines];
|
MyWorksheet.Options := MyWorksheet.Options - [soShowGridLines];
|
||||||
|
|
||||||
|
number := 10000;
|
||||||
|
(*
|
||||||
{
|
{
|
||||||
MyWorksheet.Options := MyWorksheet.Options + [soHasFrozenPanes];
|
MyWorksheet.Options := MyWorksheet.Options + [soHasFrozenPanes];
|
||||||
myWorksheet.LeftPaneWidth := 1;
|
myWorksheet.LeftPaneWidth := 1;
|
||||||
@ -307,12 +310,12 @@ begin
|
|||||||
MyWorksheet.WriteCurrency(r, 1, number, nfCurrency, 0, 'USD');
|
MyWorksheet.WriteCurrency(r, 1, number, nfCurrency, 0, 'USD');
|
||||||
MyWorksheet.WriteCurrency(r, 2, -number, nfCurrency, 0, 'USD');
|
MyWorksheet.WriteCurrency(r, 2, -number, nfCurrency, 0, 'USD');
|
||||||
MyWorksheet.WriteCurrency(r, 3, 0.0, nfCurrency, 0, 'USD');
|
MyWorksheet.WriteCurrency(r, 3, 0.0, nfCurrency, 0, 'USD');
|
||||||
inc(r);
|
inc(r); *)
|
||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfCurrencyRed, 0 decs');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfCurrencyRed, 0 decs');
|
||||||
MyWorksheet.WriteCurrency(r, 1, number, nfCurrencyRed, 0, 'USD');
|
MyWorksheet.WriteCurrency(r, 1, number, nfCurrencyRed, 0, 'USD');
|
||||||
MyWorksheet.WriteCurrency(r, 2, -number, nfCurrencyRed, 0, 'USD');
|
MyWorksheet.WriteCurrency(r, 2, -number, nfCurrencyRed, 0, 'USD');
|
||||||
MyWorksheet.WriteCurrency(r, 3, 0.0, nfCurrencyRed, 0, 'USD');
|
MyWorksheet.WriteCurrency(r, 3, 0.0, nfCurrencyRed, 0, 'USD');
|
||||||
inc(r);
|
inc(r); (*
|
||||||
MyWorksheet.WriteUTF8Text(r, 0, 'nfAccounting, 0 decs');
|
MyWorksheet.WriteUTF8Text(r, 0, 'nfAccounting, 0 decs');
|
||||||
MyWorksheet.WriteCurrency(r, 1, number, nfAccounting, 0, 'USD');
|
MyWorksheet.WriteCurrency(r, 1, number, nfAccounting, 0, 'USD');
|
||||||
MyWorksheet.WriteCurrency(r, 2, -number, nfAccounting, 0, 'USD');
|
MyWorksheet.WriteCurrency(r, 2, -number, nfAccounting, 0, 'USD');
|
||||||
@ -413,7 +416,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;
|
||||||
|
@ -36,7 +36,7 @@ begin
|
|||||||
MyWorksheet := MyWorkbook.AddWorksheet('My Worksheet');
|
MyWorksheet := MyWorkbook.AddWorksheet('My Worksheet');
|
||||||
|
|
||||||
// Write some cells
|
// Write some cells
|
||||||
MyWorksheet.WriteNumber(0, 0, 1.0);// A1
|
//MyWorksheet.WriteNumber(0, 0, 1.0);// 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
|
||||||
MyWorksheet.WriteNumber(0, 3, 4.0);// D1
|
MyWorksheet.WriteNumber(0, 3, 4.0);// D1
|
||||||
@ -191,6 +191,26 @@ begin
|
|||||||
MyWorksheet.WriteNumber(row, 6, number6, nfSci, 2);
|
MyWorksheet.WriteNumber(row, 6, number6, nfSci, 2);
|
||||||
MyWorksheet.WriteNumber(row, 7, number7, nfSci, 2);
|
MyWorksheet.WriteNumber(row, 7, number7, nfSci, 2);
|
||||||
MyWorksheet.WriteNumber(row, 8, number8, nfSci, 2);
|
MyWorksheet.WriteNumber(row, 8, number8, nfSci, 2);
|
||||||
|
inc(row);
|
||||||
|
MyWorksheet.WriteUTF8Text(row, 0, 'nfCurrency, 2 decimals');
|
||||||
|
MyWorksheet.WriteCurrency(row, 1, number1, nfCurrency, 2, '$');
|
||||||
|
MyWorksheet.WriteCurrency(row, 2, number2, nfCurrency, 2, '$');
|
||||||
|
MyWorksheet.WriteCurrency(row, 3, number3, nfCurrency, 2, '$');
|
||||||
|
MyWorksheet.WriteCurrency(row, 4, number4, nfCurrency, 2, '$');
|
||||||
|
MyWorksheet.WriteCurrency(row, 5, number5, nfCurrency, 2, '$');
|
||||||
|
MyWorksheet.WriteCurrency(row, 6, number6, nfCurrency, 2, '$');
|
||||||
|
MyWorksheet.WriteCurrency(row, 7, number7, nfCurrency, 2, '$');
|
||||||
|
MyWorksheet.WriteCurrency(row, 8, number8, nfCurrency, 2, '$');
|
||||||
|
inc(row);
|
||||||
|
MyWorksheet.WriteUTF8Text(row, 0, 'nfCurrencyRed, 2 decimals, +:$ 1000, -:($ 1000)');
|
||||||
|
MyWorksheet.WriteCurrency(row, 1, number1, nfCurrencyRed, 2, '$', pcfCSV, ncfBCSVB);
|
||||||
|
MyWorksheet.WriteCurrency(row, 2, number2, nfCurrencyRed, 2, '$', pcfCSV, ncfBCSVB);
|
||||||
|
MyWorksheet.WriteCurrency(row, 3, number3, nfCurrencyRed, 2, '$', pcfCSV, ncfBCSVB);
|
||||||
|
MyWorksheet.WriteCurrency(row, 4, number4, nfCurrencyRed, 2, '$', pcfCSV, ncfBCSVB);
|
||||||
|
MyWorksheet.WriteCurrency(row, 5, number5, nfCurrencyRed, 2, '$', pcfCSV, ncfBCSVB);
|
||||||
|
MyWorksheet.WriteCurrency(row, 6, number6, nfCurrencyRed, 2, '$', pcfCSV, ncfBCSVB);
|
||||||
|
MyWorksheet.WriteCurrency(row, 7, number7, nfCurrencyRed, 2, '$', pcfCSV, ncfBCSVB);
|
||||||
|
MyWorksheet.WriteCurrency(row, 8, number8, nfCurrencyRed, 2, '$', pcfCSV, ncfBCSVB);
|
||||||
|
|
||||||
// Creates a new worksheet
|
// Creates a new worksheet
|
||||||
MyWorksheet := MyWorkbook.AddWorksheet('My Worksheet 2');
|
MyWorksheet := MyWorkbook.AddWorksheet('My Worksheet 2');
|
||||||
|
@ -73,6 +73,7 @@ type
|
|||||||
FStart: PChar;
|
FStart: PChar;
|
||||||
FEnd: PChar;
|
FEnd: PChar;
|
||||||
FCurrSection: Integer;
|
FCurrSection: Integer;
|
||||||
|
FHasRedSection: Boolean;
|
||||||
FStatus: Integer;
|
FStatus: Integer;
|
||||||
function GetCurrencySymbol: String;
|
function GetCurrencySymbol: String;
|
||||||
function GetDecimals: byte;
|
function GetDecimals: byte;
|
||||||
@ -126,13 +127,13 @@ type
|
|||||||
// NumberFormat
|
// NumberFormat
|
||||||
procedure EvalNumFormatOfSection(ASection: Integer; out ANumFormat: TsNumberFormat;
|
procedure EvalNumFormatOfSection(ASection: Integer; out ANumFormat: TsNumberFormat;
|
||||||
out ADecimals: byte; out ACurrencySymbol: String; out AColor: TsColor);
|
out ADecimals: byte; out ACurrencySymbol: String; out AColor: TsColor);
|
||||||
function IsCurrencyAt(ASection, AIndex: Integer; out ANumFormat: TsNumberFormat;
|
function IsCurrencyAt(ASection: Integer; out ANumFormat: TsNumberFormat;
|
||||||
out ADecimals: byte; out ACurrencySymbol: String; out AColor: TsColor): Boolean;
|
out ADecimals: byte; out ACurrencySymbol: String; out AColor: TsColor): Boolean;
|
||||||
function IsDateAt(ASection,AIndex: Integer; var ANumberFormat: TsNumberFormat;
|
function IsDateAt(ASection,AIndex: Integer; var ANumberFormat: TsNumberFormat;
|
||||||
var ANextIndex: Integer): Boolean;
|
var ANextIndex: Integer): Boolean;
|
||||||
function IsNumberAt(ASection,AIndex: Integer; var ANumberFormat: TsNumberFormat;
|
function IsNumberAt(ASection,AIndex: Integer; var ANumberFormat: TsNumberFormat;
|
||||||
var ADecimals: Byte; var ANextIndex: Integer): Boolean;
|
var ADecimals: Byte; var ANextIndex: Integer): Boolean;
|
||||||
function IsSciAt(ASection,AIndex: Integer; var ANumberFormat: TsNumberFormat;
|
function IsSciAt(ASection, AIndex: Integer; var ANumberFormat: TsNumberFormat;
|
||||||
var ADecimals: Byte; var ANextIndex: Integer): Boolean;
|
var ADecimals: Byte; var ANextIndex: Integer): Boolean;
|
||||||
function IsTextAt(AText: string; ASection, AIndex: Integer): Boolean;
|
function IsTextAt(AText: string; ASection, AIndex: Integer): Boolean;
|
||||||
function IsTimeAt(ASection,AIndex: Integer; var ANumberFormat: TsNumberFormat;
|
function IsTimeAt(ASection,AIndex: Integer; var ANumberFormat: TsNumberFormat;
|
||||||
@ -140,8 +141,10 @@ type
|
|||||||
function IsTokenAt(AToken: TsNumFormatToken; ASection,AIndex: Integer): Boolean;
|
function IsTokenAt(AToken: TsNumFormatToken; ASection,AIndex: Integer): Boolean;
|
||||||
|
|
||||||
public
|
public
|
||||||
constructor Create(AWorkbook: TsWorkbook; const AFormatString: String);
|
constructor Create(AWorkbook: TsWorkbook; const AFormatString: String;
|
||||||
|
const ANumFormat: TsNumberFormat = nfGeneral);
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
procedure ClearAll;
|
||||||
function GetDateTimeCode(ASection: Integer): String;
|
function GetDateTimeCode(ASection: Integer): String;
|
||||||
function IsDateTimeFormat: Boolean;
|
function IsDateTimeFormat: Boolean;
|
||||||
procedure LimitDecimals;
|
procedure LimitDecimals;
|
||||||
@ -170,19 +173,24 @@ const
|
|||||||
{ TsNumFormatParser }
|
{ TsNumFormatParser }
|
||||||
|
|
||||||
{ 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. }
|
from a spreadsheet file.
|
||||||
|
In case of "red" number formats we also have to specify the number format
|
||||||
|
because the format string might not contain the color information, and we
|
||||||
|
extract it from the NumFormat in this case. }
|
||||||
constructor TsNumFormatParser.Create(AWorkbook: TsWorkbook;
|
constructor TsNumFormatParser.Create(AWorkbook: TsWorkbook;
|
||||||
const AFormatString: String);
|
const AFormatString: String; const ANumFormat: TsNumberFormat = nfGeneral);
|
||||||
begin
|
begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
FCreateMethod := 0;
|
FCreateMethod := 0;
|
||||||
FWorkbook := AWorkbook;
|
FWorkbook := AWorkbook;
|
||||||
|
FHasRedSection := (ANumFormat in [nfCurrencyRed, nfAccountingRed]);
|
||||||
Parse(AFormatString);
|
Parse(AFormatString);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TsNumFormatParser.Destroy;
|
destructor TsNumFormatParser.Destroy;
|
||||||
begin
|
begin
|
||||||
FSections := nil;
|
FSections := nil;
|
||||||
|
// ClearAll;
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -295,8 +303,10 @@ function TsNumFormatParser.BuildFormatStringFromSection(ASection: Integer;
|
|||||||
var
|
var
|
||||||
element: TsNumFormatElement;
|
element: TsNumFormatElement;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
|
colorAdded: Boolean;
|
||||||
begin
|
begin
|
||||||
Result := '';
|
Result := '';
|
||||||
|
colorAdded := false;
|
||||||
|
|
||||||
if (ASection < 0) and (ASection >= GetParsedSectionCount) then
|
if (ASection < 0) and (ASection >= GetParsedSectionCount) then
|
||||||
exit;
|
exit;
|
||||||
@ -354,7 +364,7 @@ begin
|
|||||||
nftRepeat:
|
nftRepeat:
|
||||||
if element.TextValue <> '' then Result := Result + '*' + element.TextValue;
|
if element.TextValue <> '' then Result := Result + '*' + element.TextValue;
|
||||||
nftColor:
|
nftColor:
|
||||||
if ADialect = nfdExcel then
|
if ADialect = nfdExcel then begin
|
||||||
case element.IntValue of
|
case element.IntValue of
|
||||||
scBlack : Result := '[black]';
|
scBlack : Result := '[black]';
|
||||||
scWhite : Result := '[white]';
|
scWhite : Result := '[white]';
|
||||||
@ -366,8 +376,17 @@ begin
|
|||||||
scCyan : Result := '[cyan]';
|
scCyan : Result := '[cyan]';
|
||||||
else Result := Format('[Color%d]', [element.IntValue]);
|
else Result := Format('[Color%d]', [element.IntValue]);
|
||||||
end;
|
end;
|
||||||
|
colorAdded := true;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
end;
|
||||||
|
{
|
||||||
|
if (ADialect = nfdExcel)
|
||||||
|
and (not colorAdded) and
|
||||||
|
(FSections[ASection].NumFormat in [nfCurrencyRed, nfAccountingRed])
|
||||||
|
then
|
||||||
|
Result := '[red]'+Result;
|
||||||
|
}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TsNumFormatParser.CheckSections;
|
procedure TsNumFormatParser.CheckSections;
|
||||||
@ -459,6 +478,20 @@ begin
|
|||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TsNumFormatParser.ClearAll;
|
||||||
|
var
|
||||||
|
i, j: Integer;
|
||||||
|
begin
|
||||||
|
for i:=0 to Length(FSections)-1 do begin
|
||||||
|
for j:=0 to Length(FSections[i].Elements) do
|
||||||
|
if FSections[i].Elements <> nil then
|
||||||
|
FSections[i].Elements[j].TextValue := '';
|
||||||
|
FSections[i].Elements := nil;
|
||||||
|
FSections[i].CurrencySymbol := '';
|
||||||
|
end;
|
||||||
|
FSections := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TsNumFormatParser.DeleteElement(ASection, AIndex: Integer);
|
procedure TsNumFormatParser.DeleteElement(ASection, AIndex: Integer);
|
||||||
var
|
var
|
||||||
i, n: Integer;
|
i, n: Integer;
|
||||||
@ -562,15 +595,16 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
// nfCurrency
|
|
||||||
if IsCurrencyAt(ASection, 0, ANumFormat, ADecimals, ACurrencySymbol, AColor)
|
|
||||||
then exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Look for scientific format
|
// Look for scientific format
|
||||||
if IsSciAt(ASection, 0, ANumFormat, ADecimals, next) then
|
if IsSciAt(ASection, 0, ANumFormat, ADecimals, next) then
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
|
// Currency?
|
||||||
|
if IsCurrencyAt(ASection, ANumFormat, ADecimals, ACurrencySymbol, AColor)
|
||||||
|
then exit;
|
||||||
|
|
||||||
// Look for date formats
|
// Look for date formats
|
||||||
if IsDateAt(ASection, 0, ANumFormat, next) then begin
|
if IsDateAt(ASection, 0, ANumFormat, next) then begin
|
||||||
if (next = Length(Elements)) then
|
if (next = Length(Elements)) then
|
||||||
@ -658,11 +692,14 @@ begin
|
|||||||
Result := FSections[0].NumFormat;
|
Result := FSections[0].NumFormat;
|
||||||
if (Result in [nfCurrency, nfAccounting]) then begin
|
if (Result in [nfCurrency, nfAccounting]) then begin
|
||||||
if Length(FSections) = 2 then begin
|
if Length(FSections) = 2 then begin
|
||||||
|
Result := FSections[1].NumFormat;
|
||||||
if FSections[1].CurrencySymbol <> FSections[0].CurrencySymbol then begin
|
if FSections[1].CurrencySymbol <> FSections[0].CurrencySymbol then begin
|
||||||
Result := nfCustom;
|
Result := nfCustom;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
if (FSections[0].NumFormat = nfCurrency) and (FSections[1].NumFormat = nfCurrency) then
|
if (FSections[0].NumFormat in [nfCurrency, nfCurrencyRed]) and
|
||||||
|
(FSections[1].NumFormat in [nfCurrency, nfCurrencyRed])
|
||||||
|
then
|
||||||
exit;
|
exit;
|
||||||
if FSections[1].NumFormat = nfAccounting then begin
|
if FSections[1].NumFormat = nfAccounting then begin
|
||||||
Result := nfAccounting;
|
Result := nfAccounting;
|
||||||
@ -670,14 +707,16 @@ begin
|
|||||||
end;
|
end;
|
||||||
end else
|
end else
|
||||||
if Length(FSections) = 3 then begin
|
if Length(FSections) = 3 then begin
|
||||||
|
Result := FSections[1].NumFormat;
|
||||||
if (FSections[0].CurrencySymbol <> FSections[1].CurrencySymbol) or
|
if (FSections[0].CurrencySymbol <> FSections[1].CurrencySymbol) or
|
||||||
(FSections[1].CurrencySymbol <> FSections[2].CurrencySymbol)
|
(FSections[1].CurrencySymbol <> FSections[2].CurrencySymbol)
|
||||||
then begin
|
then begin
|
||||||
Result := nfCustom;
|
Result := nfCustom;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
if (FSections[0].NumFormat = nfCurrency) and (FSections[1].NumFormat = nfCurrency) and
|
if (FSections[0].NumFormat in [nfCurrency, nfCurrencyRed]) and
|
||||||
(FSections[2].NumFormat = nfCurrency)
|
(FSections[1].NumFormat in [nfCurrency, nfCurrencyRed]) and
|
||||||
|
(FSections[2].NumFormat in [nfCurrency, nfCurrencyRed])
|
||||||
then
|
then
|
||||||
exit;
|
exit;
|
||||||
if (FSections[1].NumFormat = nfAccounting) and
|
if (FSections[1].NumFormat = nfAccounting) and
|
||||||
@ -709,13 +748,15 @@ end;
|
|||||||
the numberformat code, the count of decimals, the currency sambol, and the
|
the numberformat code, the count of decimals, the currency sambol, and the
|
||||||
color.
|
color.
|
||||||
Note that the check is not very exact, but should cover most cases. }
|
Note that the check is not very exact, but should cover most cases. }
|
||||||
function TsNumFormatParser.IsCurrencyAt(ASection, AIndex: Integer;
|
function TsNumFormatParser.IsCurrencyAt(ASection: Integer;
|
||||||
out ANumFormat: TsNumberFormat; out ADecimals: byte;
|
out ANumFormat: TsNumberFormat; out ADecimals: byte;
|
||||||
out ACurrencySymbol: String; out AColor: TsColor): Boolean;
|
out ACurrencySymbol: String; out AColor: TsColor): Boolean;
|
||||||
var
|
var
|
||||||
isAccounting : Boolean;
|
isAccounting : Boolean;
|
||||||
hasCurrSymbol: Boolean;
|
hasCurrSymbol: Boolean;
|
||||||
|
hasColor: Boolean;
|
||||||
next: Integer;
|
next: Integer;
|
||||||
|
el: Integer;
|
||||||
begin
|
begin
|
||||||
Result := false;
|
Result := false;
|
||||||
|
|
||||||
@ -723,7 +764,75 @@ begin
|
|||||||
ACurrencySymbol := '';
|
ACurrencySymbol := '';
|
||||||
ADecimals := 0;
|
ADecimals := 0;
|
||||||
AColor := scNotDefined;
|
AColor := scNotDefined;
|
||||||
|
isAccounting := false;
|
||||||
|
hasColor := false;
|
||||||
|
|
||||||
|
// Looking for the currency symbol: it is the unique identifier of the
|
||||||
|
// currency format.
|
||||||
|
for el := 0 to High(FSections[ASection].Elements) do
|
||||||
|
if FSections[ASection].Elements[el].Token = nftCurrSymbol then begin
|
||||||
|
Result := true;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if not Result then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
{ When the format string comes from fpc it does not contain a color token.
|
||||||
|
Color would be lost when saving. Therefore, we take the color from the
|
||||||
|
knowledge of the NumFormat passed on creation: nfCurrencyRed has color red
|
||||||
|
in the second section! }
|
||||||
|
if (ASection = 1) and FHasRedSection then
|
||||||
|
AColor := scRed;
|
||||||
|
|
||||||
|
// Now that we know that it is a currency format analyze the elements again
|
||||||
|
// and determine color, decimals and currency symbol.
|
||||||
|
el := 0;
|
||||||
|
while (el < Length(FSections[ASection].Elements)) do begin
|
||||||
|
case FSections[ASection].Elements[el].Token of
|
||||||
|
nftColor:
|
||||||
|
begin
|
||||||
|
AColor := FSections[ASection].Elements[el].IntValue;
|
||||||
|
hasColor := true;
|
||||||
|
end;
|
||||||
|
nftRepeat:
|
||||||
|
isAccounting := true;
|
||||||
|
nftCurrSymbol:
|
||||||
|
ACurrencySymbol := FSections[ASection].Elements[el].TextValue;
|
||||||
|
nftOptDigit:
|
||||||
|
if IsNumberAt(ASection, el, ANumFormat, ADecimals, el) then
|
||||||
|
dec(el)
|
||||||
|
else begin
|
||||||
|
Result := false;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
nftDigit:
|
||||||
|
if IsNumberAt(ASection, el, ANumFormat, ADecimals, el) then
|
||||||
|
dec(el)
|
||||||
|
else begin
|
||||||
|
Result := false;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
inc(el);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (ASection = 1) and FHasRedSection and not hasColor then
|
||||||
|
InsertElement(ASection, 0, nftColor, scRed);
|
||||||
|
|
||||||
|
Result := hasCurrSymbol and ((ANumFormat = nfFixedTh) or (ASection = 2));
|
||||||
|
if Result then begin
|
||||||
|
if isAccounting then begin
|
||||||
|
if AColor = scNotDefined then ANumFormat := nfAccounting else
|
||||||
|
if AColor = scRed then ANumFormat := nfAccountingRed;
|
||||||
|
end else begin
|
||||||
|
if AColor = scNotDefined then ANumFormat := nfCurrency else
|
||||||
|
if AColor = scRed then ANumFormat := nfCurrencyRed;
|
||||||
|
end;
|
||||||
|
end else
|
||||||
|
ANumFormat := nfCustom;
|
||||||
|
|
||||||
|
(*
|
||||||
if IsTokenAt(nftColor, ASection, AIndex) then begin
|
if IsTokenAt(nftColor, ASection, AIndex) then begin
|
||||||
AIndex := AIndex + 1;
|
AIndex := AIndex + 1;
|
||||||
AColor := FSections[ASection].Elements[AIndex].IntValue;
|
AColor := FSections[ASection].Elements[AIndex].IntValue;
|
||||||
@ -760,6 +869,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
end else
|
end else
|
||||||
ANumFormat := nfCustom;
|
ANumFormat := nfCustom;
|
||||||
|
*)
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsNumFormatParser.IsDateAt(ASection,AIndex: Integer;
|
function TsNumFormatParser.IsDateAt(ASection,AIndex: Integer;
|
||||||
|
@ -299,12 +299,14 @@ type
|
|||||||
procedure TsSpreadOpenDocNumFormatList.AddBuiltinFormats;
|
procedure TsSpreadOpenDocNumFormatList.AddBuiltinFormats;
|
||||||
begin
|
begin
|
||||||
AddFormat('N0', '', nfGeneral);
|
AddFormat('N0', '', nfGeneral);
|
||||||
|
{
|
||||||
AddFormat('N1', '0', nfFixed);
|
AddFormat('N1', '0', nfFixed);
|
||||||
AddFormat('N2', '0.00', nfFixed);
|
AddFormat('N2', '0.00', nfFixed);
|
||||||
AddFormat('N3', '#,##0', nfFixedTh);
|
AddFormat('N3', '#,##0', nfFixedTh);
|
||||||
AddFormat('N4', '#,##0.00', nfFixed);
|
AddFormat('N4', '#,##0.00', nfFixedTh);
|
||||||
AddFormat('N10', '0%', nfPercentage);
|
AddFormat('N10', '0%', nfPercentage);
|
||||||
AddFormat('N11', '0.00%', nfPercentage);
|
AddFormat('N11', '0.00%', nfPercentage);
|
||||||
|
}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -313,10 +315,14 @@ end;
|
|||||||
function TsSpreadOpenDocNumFormatParser.BuildXMLAsString(AIndent,
|
function TsSpreadOpenDocNumFormatParser.BuildXMLAsString(AIndent,
|
||||||
AFormatName: String): String;
|
AFormatName: String): String;
|
||||||
var
|
var
|
||||||
i, ns: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
Result := '';
|
Result := '';
|
||||||
for i := Length(FSections)-1 downto 0 do
|
{ When there is only one section the next statement is the only one executed.
|
||||||
|
When there are several sections the file contains at first the
|
||||||
|
positive section (index 0), then the negative section (index 1), and
|
||||||
|
finally the zero section (index 2) which contains the style-map. }
|
||||||
|
for i:=0 to Length(FSections)-1 do
|
||||||
Result := Result + BuildXMLAsStringFromSection(i, AIndent, AFormatName);
|
Result := Result + BuildXMLAsStringFromSection(i, AIndent, AFormatName);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -333,6 +339,8 @@ var
|
|||||||
ns: Integer;
|
ns: Integer;
|
||||||
clr: TsColorvalue;
|
clr: TsColorvalue;
|
||||||
el: Integer;
|
el: Integer;
|
||||||
|
s: String;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
Result := '';
|
Result := '';
|
||||||
sGrouping := '';
|
sGrouping := '';
|
||||||
@ -340,20 +348,23 @@ begin
|
|||||||
sStyleMap := '';
|
sStyleMap := '';
|
||||||
|
|
||||||
ns := Length(FSections);
|
ns := Length(FSections);
|
||||||
|
if (ns = 0) then
|
||||||
|
exit;
|
||||||
|
|
||||||
if (ns > 1) then begin
|
if (ns > 1) then begin
|
||||||
if (ASection = ns - 1) then
|
if (ASection = ns - 1) then
|
||||||
case ns of
|
case ns of
|
||||||
2: sStyleMap := AIndent +
|
2: sStyleMap := AIndent +
|
||||||
' <style:map ' +
|
' <style:map ' +
|
||||||
'style:apply-style-name="' + AFormatName + 'P0" ' +
|
'style:apply-style-name="' + AFormatName + 'P0" ' +
|
||||||
'style:condition="value()>=0" />' + LineEnding; // >= 0
|
'style:condition="value()>=0" />' + LineEnding; // >= 0
|
||||||
3: sStyleMap := AIndent +
|
3: sStyleMap := AIndent +
|
||||||
' <style:map '+
|
' <style:map '+
|
||||||
'style:apply-style-name="' + AFormatName + 'P0" ' + // > 0
|
'style:apply-style-name="' + AFormatName + 'P0" ' + // > 0
|
||||||
'style:condition="value()>0" />' + LineEnding + AIndent +
|
'style:condition="value()>0" />' + LineEnding + AIndent +
|
||||||
' <style:map '+
|
' <style:map '+
|
||||||
'style:apply-style-name="' + AFormatName + 'P1" ' + // < 0
|
'style:apply-style-name="' + AFormatName + 'P1" ' + // < 0
|
||||||
'style:condition="value()<0" />' + LineEnding;
|
'style:condition="value()<0" />' + LineEnding;
|
||||||
else
|
else
|
||||||
raise Exception.Create('At most 3 format sections allowed.');
|
raise Exception.Create('At most 3 format sections allowed.');
|
||||||
end
|
end
|
||||||
@ -427,14 +438,17 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// nfSci: not supported by ods, use nfExp instead.
|
// If the program gets here the format can only be nfSci, nfCurrency/Accounting,
|
||||||
|
// or date/time.
|
||||||
el := 0;
|
el := 0;
|
||||||
decs := 0;
|
decs := 0;
|
||||||
while el < Length(Elements) do begin
|
while el < Length(Elements) do begin
|
||||||
case Elements[el].Token of
|
case Elements[el].Token of
|
||||||
nftDecs:
|
nftDecs:
|
||||||
decs := Elements[el].IntValue;
|
decs := Elements[el].IntValue;
|
||||||
|
|
||||||
nftExpChar:
|
nftExpChar:
|
||||||
|
// nfSci: not supported by ods, use nfExp instead.
|
||||||
begin
|
begin
|
||||||
while el < Length(Elements) do begin
|
while el < Length(Elements) do begin
|
||||||
if Elements[el].Token = nftExpDigits then begin
|
if Elements[el].Token = nftExpDigits then begin
|
||||||
@ -453,6 +467,57 @@ begin
|
|||||||
end;
|
end;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
nftCurrSymbol:
|
||||||
|
begin
|
||||||
|
Result := AIndent +
|
||||||
|
'<number:currency-style style:name="' + AFormatName + '">' + LineEnding;
|
||||||
|
el := 0;
|
||||||
|
while el < Length(Elements) do begin
|
||||||
|
case Elements[el].Token of
|
||||||
|
nftColor:
|
||||||
|
begin
|
||||||
|
clr := FWorkbook.GetPaletteColor(Elements[el].IntValue);
|
||||||
|
Result := Result + AIndent +
|
||||||
|
' <style:text-properties fo:color="' + ColorToHTMLColorStr(clr) + '" />' + LineEnding;
|
||||||
|
inc(el);
|
||||||
|
end;
|
||||||
|
nftSign, nftSignBracket:
|
||||||
|
begin
|
||||||
|
Result := Result + AIndent +
|
||||||
|
' <number:text>' + Elements[el].TextValue + '</number:text>' + LineEnding;
|
||||||
|
inc(el);
|
||||||
|
end;
|
||||||
|
nftSpace:
|
||||||
|
begin
|
||||||
|
Result := Result + AIndent +
|
||||||
|
' <number:text><![CDATA[ ]]></number:text>' + LineEnding;
|
||||||
|
inc(el);
|
||||||
|
end;
|
||||||
|
nftCurrSymbol:
|
||||||
|
begin
|
||||||
|
Result := Result + AIndent +
|
||||||
|
' <number:currency-symbol>' + Elements[el].TextValue +
|
||||||
|
'</number:currency-symbol>' + LineEnding;
|
||||||
|
inc(el);
|
||||||
|
end;
|
||||||
|
nftOptDigit:
|
||||||
|
if IsNumberAt(ASection, el, nf, decs, el) then
|
||||||
|
Result := Result + AIndent +
|
||||||
|
' <number:number decimal-places="' + IntToStr(decs) +
|
||||||
|
'" number:min-integer-digits="1" number:grouping="true" />'
|
||||||
|
+ LineEnding;
|
||||||
|
nftDigit:
|
||||||
|
if IsNumberAt(ASection, el, nf, decs, el) then
|
||||||
|
Result := Result + AIndent +
|
||||||
|
' <number:number decimal-places="' + IntToStr(decs) +
|
||||||
|
'" number:min-integer-digits="1" />' + LineEnding;
|
||||||
|
else
|
||||||
|
inc(el);
|
||||||
|
end; // case
|
||||||
|
end; // while
|
||||||
|
Result := Result + sStyleMap + AIndent + '</number:currency-style>' + LineEnding;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
inc(el);
|
inc(el);
|
||||||
end;
|
end;
|
||||||
@ -2096,9 +2161,10 @@ var
|
|||||||
lRowStylesCode: String;
|
lRowStylesCode: String;
|
||||||
lNumFmtCode: String;
|
lNumFmtCode: String;
|
||||||
begin
|
begin
|
||||||
|
ListAllNumFormats;
|
||||||
|
ListAllFormattingStyles;
|
||||||
ListAllColumnStyles;
|
ListAllColumnStyles;
|
||||||
ListAllRowStyles;
|
ListAllRowStyles;
|
||||||
ListAllFormattingStyles;
|
|
||||||
|
|
||||||
lNumFmtCode := WriteNumFormatsXMLAsString;
|
lNumFmtCode := WriteNumFormatsXMLAsString;
|
||||||
|
|
||||||
@ -2347,10 +2413,10 @@ var
|
|||||||
parser: TsSpreadOpenDocNumFormatParser;
|
parser: TsSpreadOpenDocNumFormatParser;
|
||||||
begin
|
begin
|
||||||
Result := '';
|
Result := '';
|
||||||
ListAllNumFormats;
|
|
||||||
for i:=0 to FNumFormatList.Count-1 do begin
|
for i:=0 to FNumFormatList.Count-1 do begin
|
||||||
fmtItem := FNumFormatList.Items[i];
|
fmtItem := FNumFormatList.Items[i];
|
||||||
parser := TsSpreadOpenDocNumFormatParser.Create(Workbook, fmtItem.FormatString);
|
parser := TsSpreadOpenDocNumFormatParser.Create(Workbook, fmtItem.FormatString,
|
||||||
|
fmtItem.NumFormat);
|
||||||
try
|
try
|
||||||
numFmtXML := parser.BuildXMLAsString(' ', fmtItem.Name);
|
numFmtXML := parser.BuildXMLAsString(' ', fmtItem.Name);
|
||||||
if numFmtXML <> '' then
|
if numFmtXML <> '' then
|
||||||
@ -2888,7 +2954,9 @@ begin
|
|||||||
lIndex := FindFormattingInList(ACell);
|
lIndex := FindFormattingInList(ACell);
|
||||||
lStyle := ' table:style-name="ce' + IntToStr(lIndex) + '" ';
|
lStyle := ' table:style-name="ce' + IntToStr(lIndex) + '" ';
|
||||||
if pos('%', ACell^.NumberFormatStr) <> 0 then
|
if pos('%', ACell^.NumberFormatStr) <> 0 then
|
||||||
valType := 'percentage';
|
valType := 'percentage'
|
||||||
|
else if IsCurrencyFormat(ACell^.NumberFormat) then
|
||||||
|
valType := 'currency';
|
||||||
end else
|
end else
|
||||||
lStyle := '';
|
lStyle := '';
|
||||||
|
|
||||||
|
@ -545,6 +545,7 @@ type
|
|||||||
function GetLastRowNumber: Cardinal; deprecated 'Use GetLastRowIndex';
|
function GetLastRowNumber: Cardinal; deprecated 'Use GetLastRowIndex';
|
||||||
|
|
||||||
{ Data manipulation methods - For Rows and Cols }
|
{ Data manipulation methods - For Rows and Cols }
|
||||||
|
function CalcAutoRowHeight(ARow: Cardinal): Single;
|
||||||
function FindRow(ARow: Cardinal): PRow;
|
function FindRow(ARow: Cardinal): PRow;
|
||||||
function FindCol(ACol: Cardinal): PCol;
|
function FindCol(ACol: Cardinal): PCol;
|
||||||
function GetCellCountInRow(ARow: Cardinal): Cardinal;
|
function GetCellCountInRow(ARow: Cardinal): Cardinal;
|
||||||
@ -2505,6 +2506,22 @@ begin
|
|||||||
Result := FWorkbook.FormatSettings;
|
Result := FWorkbook.FormatSettings;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TsWorksheet.CalcAutoRowHeight(ARow: Cardinal): Single;
|
||||||
|
var
|
||||||
|
cell: PCell;
|
||||||
|
fnt: TsFont;
|
||||||
|
col: Integer;
|
||||||
|
h0: Single;
|
||||||
|
begin
|
||||||
|
Result := 0;
|
||||||
|
h0 := Workbook.GetDefaultFontSize;
|
||||||
|
for col := 0 to GetLastColIndex do begin
|
||||||
|
cell := FindCell(ARow, col);
|
||||||
|
if cell <> nil then
|
||||||
|
Result := Max(Result, Workbook.GetFont(cell^.FontIndex).Size / h0);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
function TsWorksheet.FindRow(ARow: Cardinal): PRow;
|
function TsWorksheet.FindRow(ARow: Cardinal): PRow;
|
||||||
var
|
var
|
||||||
LElement: TRow;
|
LElement: TRow;
|
||||||
@ -2614,7 +2631,7 @@ begin
|
|||||||
if row <> nil then
|
if row <> nil then
|
||||||
Result := row^.Height
|
Result := row^.Height
|
||||||
else
|
else
|
||||||
Result := FWorkbook.DefaultRowHeight;
|
Result := CalcAutoRowHeight(ARow); //FWorkbook.DefaultRowHeight;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TsWorksheet.RemoveAllRows;
|
procedure TsWorksheet.RemoveAllRows;
|
||||||
|
@ -764,7 +764,7 @@ var
|
|||||||
parser: TsNumFormatParser;
|
parser: TsNumFormatParser;
|
||||||
fmt: String;
|
fmt: String;
|
||||||
begin
|
begin
|
||||||
parser := TsNumFormatParser.Create(Workbook, AFormatString);
|
parser := TsNumFormatParser.Create(Workbook, AFormatString, ANumFormat);
|
||||||
try
|
try
|
||||||
if parser.Status = psOK then begin
|
if parser.Status = psOK then begin
|
||||||
// For writing, we have to convert the fpc format string to Excel dialect
|
// For writing, we have to convert the fpc format string to Excel dialect
|
||||||
|
Reference in New Issue
Block a user