You've already forked lazarus-ccr
fpspreadsheet: Cleaning up
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3167 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -141,18 +141,7 @@ type
|
||||
|
||||
public
|
||||
constructor Create(AWorkbook: TsWorkbook; const AFormatString: String);
|
||||
(*
|
||||
constructor Create(AWorkbook: TsWorkbook; const AFormatString: String;
|
||||
ANumFormat: TsNumberFormat); overload;
|
||||
constructor Create(AWorkbook: TsWorkbook; const AFormatSections: TsNumFormatSections;
|
||||
AConversionDirection: TsConversionDirection = cdFromFPSpreadsheet); overload;
|
||||
*)
|
||||
destructor Destroy; override;
|
||||
(*
|
||||
procedure CopySections(const FromSections: TsNumFormatSections;
|
||||
var ToSections: TsNumFormatSections);
|
||||
procedure CopySectionsTo(var ADestination: TsNumFormatSections);
|
||||
*)
|
||||
function GetDateTimeCode(ASection: Integer): String;
|
||||
function IsDateTimeFormat: Boolean;
|
||||
procedure LimitDecimals;
|
||||
@ -190,38 +179,7 @@ begin
|
||||
FWorkbook := AWorkbook;
|
||||
Parse(AFormatString);
|
||||
end;
|
||||
(*
|
||||
constructor TsNumFormatParser.Create(AWorkbook: TsWorkbook;
|
||||
const AFormatString: String; ANumFormat: TsNumberFormat;
|
||||
AConversionDirection: TsConversionDirection = cdToFPSpreadsheet);
|
||||
begin
|
||||
inherited Create;
|
||||
FCreateMethod := 0;
|
||||
FConversionDirection := AConversionDirection;
|
||||
FWorkbook := AWorkbook;
|
||||
FNumFormat := ANumFormat;
|
||||
FFormatSettings := DefaultFormatSettings;
|
||||
FFormatSettings.DecimalSeparator := '.';
|
||||
FFormatSettings.ThousandSeparator := ',';
|
||||
FIsAccounting := (ANumFormat in [nfAccounting, nfAccountingRed]);
|
||||
Parse(AFormatString);
|
||||
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);
|
||||
begin
|
||||
inherited Create;
|
||||
FCreateMethod := 1;
|
||||
FConversionDirection := AConversionDirection;
|
||||
FWorkbook := AWorkbook;
|
||||
CopySections(AFormatSections, FSections);
|
||||
end;
|
||||
*)
|
||||
destructor TsNumFormatParser.Destroy;
|
||||
begin
|
||||
FSections := nil;
|
||||
@ -421,111 +379,9 @@ end;
|
||||
procedure TsNumFormatParser.CheckSections;
|
||||
var
|
||||
i: Integer;
|
||||
{
|
||||
ns: Integer;
|
||||
s: String;
|
||||
isCurr: Boolean;
|
||||
}
|
||||
begin
|
||||
for i:=0 to Length(FSections)-1 do
|
||||
CheckSection(i);
|
||||
(*
|
||||
ns := Length(FSections);
|
||||
|
||||
if (ns > 1) and (FNumFormat in [nfCurrencyRed, nfAccountingRed]) then
|
||||
FSections[1].Color := scRed;
|
||||
|
||||
for i:=0 to ns-1 do begin
|
||||
if FSections[i].FormatString = '' then
|
||||
FSections[i].NumFormat := nfGeneral;
|
||||
|
||||
if (FSections[i].CurrencySymbol <> '') or FIsAccounting then
|
||||
FSections[i].NumFormat := nfCurrency;
|
||||
|
||||
if FSections[i].CompareOperation <> coNotUsed then begin
|
||||
FStatus := psErrConditionalFormattingNotSupported;
|
||||
exit;
|
||||
end;
|
||||
|
||||
// Check format strings
|
||||
case FSections[i].NumFormat of
|
||||
nfGeneral, nfFixed, nfFixedTh, nfPercentage, nfExp, nfSci, nfCurrency, nfAccounting:
|
||||
try
|
||||
s := FormatFloat(FSections[i].FormatString, 1.0, FWorkBook.FormatSettings);
|
||||
except
|
||||
FStatus := psErrNoValidNumberFormat;
|
||||
exit;
|
||||
end;
|
||||
|
||||
nfShortDateTime, nfShortDate, nfShortTime, nfShortTimeAM,
|
||||
nfLongDate, nfLongTime, nfLongTimeAM, nfTimeInterval, nfFmtDateTime:
|
||||
try
|
||||
s := FormatDateTime(FSections[i].FormatString, now(), FWorkbook.FormatSettings, [fdoInterval]);
|
||||
except
|
||||
FStatus := psErrNoValidDateTimeFormat;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
// Extract built-in NumFormat identifier for currency (needs several entries in
|
||||
// three sections).
|
||||
isCurr := ((ns = 2) and (FSections[0].NumFormat = nfCurrency) and (FSections[1].NumFormat = nfCurrency))
|
||||
or ((ns = 3) and (FSections[0].NumFormat = nfCurrency) and (FSections[1].NumFormat = nfCurrency) and
|
||||
((FSections[2].NumFormat = nfCurrency) or (FSections[2].FormatString = '-')) );
|
||||
|
||||
if isCurr then begin
|
||||
if FIsAccounting then
|
||||
FNumFormat := IfThen(FSections[1].Color = scRed, nfAccountingRed, nfAccounting)
|
||||
else
|
||||
FNumFormat := IfThen(FSections[1].Color = scRed, nfCurrency, nfCurrencyRed);
|
||||
end;
|
||||
|
||||
// If there are other multi-section formatstrings they must be a custom format
|
||||
if not isCurr then begin
|
||||
if (ns > 1) then begin
|
||||
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
|
||||
FNumFormat := FSections[0].NumFormat;
|
||||
end;
|
||||
|
||||
// Add colors to section format strings
|
||||
if (FConversionDirection = cdFromFPSpreadsheet) then
|
||||
for i := 0 to High(FSections) do
|
||||
if FSections[i].Color < 8 then
|
||||
FSections[i].FormatString := Format('[%s]%s', [
|
||||
FWorkbook.GetColorName(FSections[i].Color),
|
||||
FSections[i].FormatString
|
||||
])
|
||||
else
|
||||
if FSections[i].Color <> scNotDefined then
|
||||
FSections[i].FormatString := Format('[Color%d]%s', [
|
||||
FSections[i].Color,
|
||||
FSections[i].FormatString
|
||||
]);
|
||||
|
||||
// Construct total format string
|
||||
if ns = 2 then
|
||||
FFormatString := Format('%s;%s;%s', [
|
||||
FSections[0].FormatString,
|
||||
FSections[1].FormatString,
|
||||
FSections[0].FormatString // make sure that fpc understands the "zero"
|
||||
])
|
||||
else
|
||||
if ns > 0 then begin
|
||||
FFormatString := FSections[0].FormatString;
|
||||
for i:=1 to ns-1 do
|
||||
FFormatString := Format('%s;%s', [FFormatString, FSections[i].FormatString]);
|
||||
end else
|
||||
FStatus := psErrNoUsableFormat;
|
||||
*)
|
||||
end;
|
||||
|
||||
procedure TsNumFormatParser.CheckSection(ASection: Integer);
|
||||
@ -608,28 +464,6 @@ begin
|
||||
FSections[ASection].Color
|
||||
);
|
||||
end;
|
||||
(*
|
||||
procedure TsNumFormatParser.CopySections(
|
||||
const FromSections: TsNumFormatSections; var ToSections: TsNumformatSections);
|
||||
var
|
||||
i, j: Integer;
|
||||
begin
|
||||
SetLength(ToSections, Length(FromSections));
|
||||
for i:= 0 to High(FromSections) do begin
|
||||
ToSections[i].NumFormat := FromSections[i].NumFormat;
|
||||
ToSections[i].Decimals := FromSections[i].Decimals;
|
||||
ToSections[i].CurrencySymbol := FromSections[i].CurrencySymbol;
|
||||
SetLength(ToSections[i].Elements, Length(FromSections[i].Elements));
|
||||
for j:=0 to High(ToSections[i].Elements) do
|
||||
ToSections[i].Elements[j] := FromSections[i].Elements[j];
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsNumFormatParser.CopySectionsTo(var ADestination: TsNumFormatSections);
|
||||
begin
|
||||
CopySections(FSections, ADestination);
|
||||
end;
|
||||
*)
|
||||
|
||||
procedure TsNumFormatParser.DeleteElement(ASection, AIndex: Integer);
|
||||
var
|
||||
@ -690,14 +524,7 @@ begin
|
||||
for i:=1 to High(FSections) do
|
||||
Result := Result + ';' + BuildFormatStringFromSection(i, ADialect);
|
||||
end;
|
||||
{
|
||||
case FCreateMethod of
|
||||
0: Result := FFormatString;
|
||||
1: Result := CreateFormatStringFromSections;
|
||||
end;
|
||||
}
|
||||
end;
|
||||
|
||||
|
||||
procedure TsNumFormatParser.EvalNumFormatOfSection(ASection: Integer;
|
||||
out ANumFormat: TsNumberFormat; out ADecimals: byte; out ACurrencySymbol: String;
|
||||
@ -869,16 +696,10 @@ begin
|
||||
Result := nfCustom;
|
||||
exit;
|
||||
end;
|
||||
if Length(FSections) > 1 then begin
|
||||
{
|
||||
if IsDateTimeFormat then
|
||||
Result := nfFmtDateTime
|
||||
else
|
||||
}
|
||||
if Length(FSections) > 1 then
|
||||
Result := nfCustom;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsNumFormatParser.GetParsedSectionCount: Integer;
|
||||
begin
|
||||
@ -1024,18 +845,6 @@ begin
|
||||
if CheckFormat(FWorkbook.FormatSettings.LongDateFormat, ANextIndex) then begin
|
||||
Result := true;
|
||||
ANumberFormat := nfLongDate;
|
||||
{
|
||||
end else begin
|
||||
// If it is neither nfShortDate nor nfLongDate we look for any year, month
|
||||
// or day tokens. If we find one it must be at least nfFmtDateTime.
|
||||
for i:=0 to High(FSections[ASection].Elements) do
|
||||
if FSections[ASection].Elements[i].Token in [nftYear, nftMonth, nftDay] then begin
|
||||
Result := true;
|
||||
ANumberFormat := nfFmtDateTime;
|
||||
exit;
|
||||
end;
|
||||
Result := false;
|
||||
}
|
||||
end else
|
||||
Result := false;
|
||||
end;
|
||||
@ -1386,7 +1195,6 @@ begin
|
||||
until (FToken <> ATestChar) or (FCurrent >= FEnd);
|
||||
end;
|
||||
|
||||
|
||||
{ Extracts the text between square brackets. This can be
|
||||
- a time duration like [hh]
|
||||
- a condition, like [>= 2.0]
|
||||
@ -1527,7 +1335,6 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{ Scans a date/time format. Procedure is left with the cursor at the last char
|
||||
of the date/time format. }
|
||||
procedure TsNumFormatParser.ScanDateTime;
|
||||
|
@ -53,7 +53,6 @@ type
|
||||
protected
|
||||
procedure AddBuiltinFormats; override;
|
||||
public
|
||||
// function FormatStringForWriting(AIndex: Integer): String; override;
|
||||
end;
|
||||
|
||||
{ TsSpreadOpenDocReader }
|
||||
@ -1082,7 +1081,6 @@ procedure TsSpreadOpenDocReader.ReadNumFormats(AStylesNode: TDOMNode);
|
||||
if negfmt <> '' then AFormatStr := AFormatStr + ';' + negfmt;
|
||||
if zerofmt <> '' then AFormatStr := AFormatStr + ';' + zerofmt;
|
||||
|
||||
// if ANumFormat <> nfFmtDateTime then
|
||||
ANumFormat := nfCustom;
|
||||
end;
|
||||
|
||||
@ -1241,7 +1239,6 @@ procedure TsSpreadOpenDocReader.ReadNumFormats(AStylesNode: TDOMNode);
|
||||
node := node.NextSibling;
|
||||
end;
|
||||
|
||||
// nf := IfThen(isInterval, nfTimeInterval, nfFmtDateTime);
|
||||
nf := IfThen(isInterval, nfTimeInterval, nfCustom);
|
||||
node := ANumFormatNode.FindNode('style:map');
|
||||
if node <> nil then
|
||||
@ -1280,11 +1277,6 @@ procedure TsSpreadOpenDocReader.ReadNumFormats(AStylesNode: TDOMNode);
|
||||
node := ANumFormatNode.FindNode('style:map');
|
||||
if node <> nil then
|
||||
ReadStyleMap(node, nf, fmt);
|
||||
{
|
||||
if IsDateTimeFormat(fmt) then
|
||||
nf := nfCustom
|
||||
else
|
||||
}
|
||||
nf := nfCustom;
|
||||
|
||||
NumFormatList.AddFormat(ANumFormatName, fmt, nf);
|
||||
|
@ -4333,19 +4333,18 @@ Number format handling in fpspreadsheet is implemented with the following
|
||||
concept in mind:
|
||||
|
||||
- Formats written into TsWorksheet cells always follow the fpspreadsheet syntax.
|
||||
The exception is for the format nfCustom for which the format strings are
|
||||
left untouched.
|
||||
|
||||
- For writing, the writer creates a TsNumFormatList which stores all formats
|
||||
in file syntax.
|
||||
- The built-in formats of the file types are coded in the file syntax.
|
||||
- The built-in formats of the file types are coded in the fpc syntax.
|
||||
- The method "ConvertBeforeWriting" converts the cell formats from the
|
||||
fpspreadsheet to the file syntax.
|
||||
|
||||
- For reading, the reader creates another TsNumFormatList.
|
||||
- The built-in formats of the file types are coded again in file syntax.
|
||||
- The formats read from the file are added in file syntax.
|
||||
- After reading, the formats are converted to fpspreadsheet syntax
|
||||
("ConvertAfterReading").
|
||||
- The built-in formats of the file types are coded again in fpc syntax.
|
||||
- After reading, the formats are converted to fpc syntax by means of
|
||||
"ConvertAfterReading".
|
||||
|
||||
- Format conversion is done internally by means of the TsNumFormatParser.
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,6 @@ procedure SplitFormatString(const AFormatString: String; out APositivePart,
|
||||
|
||||
function SciFloat(AValue: Double; ADecimals: Byte): String; overload;
|
||||
function SciFloat(AValue: Double; ADecimals: Byte; AFormatSettings: TFormatSettings): String; overload;
|
||||
//function TimeIntervalToString(AValue: TDateTime; AFormatStr: String): String;
|
||||
procedure MakeTimeIntervalMask(Src: String; var Dest: String);
|
||||
|
||||
// These two functions are copies of fpc trunk until they are available in stable fpc.
|
||||
@ -115,7 +114,6 @@ function PtsToMM(AValue: Double): Double;
|
||||
function pxToPts(AValue, AScreenPixelsPerInch: Integer): Double;
|
||||
function PtsToPx(AValue: Double; AScreenPixelsPerInch: Integer): Integer;
|
||||
function HTMLLengthStrToPts(AValue: String): Double;
|
||||
//function HMTLLengthStrToPts(AValue: String): Double;
|
||||
|
||||
function HTMLColorStrToColor(AValue: String): TsColorValue;
|
||||
function ColorToHTMLColorStr(AValue: TsColorValue): String;
|
||||
@ -591,10 +589,6 @@ var
|
||||
fmt: String;
|
||||
begin
|
||||
case ANumberFormat of
|
||||
{
|
||||
nfFmtDateTime:
|
||||
Result := SpecialDateTimeFormat(lowercase(AFormatString), AFormatSettings, false);
|
||||
}
|
||||
nfShortDateTime:
|
||||
Result := AFormatSettings.ShortDateFormat + ' ' + AFormatSettings.ShortTimeFormat;
|
||||
// In the DefaultFormatSettings this is: d/m/y hh:nn
|
||||
@ -1078,6 +1072,147 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Excel's unit of row heights is "twips", i.e. 1/20 point.
|
||||
Converts Twips to points. }
|
||||
function TwipsToPts(AValue: Integer): Single;
|
||||
begin
|
||||
Result := AValue / 20;
|
||||
end;
|
||||
|
||||
{ Converts points to twips (1 twip = 1/20 point) }
|
||||
function PtsToTwips(AValue: Single): Integer;
|
||||
begin
|
||||
Result := round(AValue * 20);
|
||||
end;
|
||||
|
||||
{ Converts centimeters to points (72 pts = 1 inch) }
|
||||
function cmToPts(AValue: Double): Double;
|
||||
begin
|
||||
Result := AValue * 72 / 2.54;
|
||||
end;
|
||||
|
||||
{ Converts points to centimeters }
|
||||
function PtsToCm(AValue: Double): Double;
|
||||
begin
|
||||
Result := AValue / 72 * 2.54;
|
||||
end;
|
||||
|
||||
{ Converts inches to points (72 pts = 1 inch) }
|
||||
function InToPts(AValue: Double): Double;
|
||||
begin
|
||||
Result := AValue * 72;
|
||||
end;
|
||||
|
||||
{ Converts millimeters to points (72 pts = 1 inch) }
|
||||
function mmToPts(AValue: Double): Double;
|
||||
begin
|
||||
Result := AValue * 72 / 25.4;
|
||||
end;
|
||||
|
||||
{ Converts points to millimeters }
|
||||
function PtsToMM(AValue: Double): Double;
|
||||
begin
|
||||
Result := AValue / 72 * 25.4;
|
||||
end;
|
||||
|
||||
{ Converts pixels to points. }
|
||||
function pxToPts(AValue, AScreenPixelsPerInch: Integer): Double;
|
||||
begin
|
||||
Result := (AValue / AScreenPixelsPerInch) * 72;
|
||||
end;
|
||||
|
||||
{ Converts points to pixels }
|
||||
function PtsToPx(AValue: Double; AScreenPixelsPerInch: Integer): Integer;
|
||||
begin
|
||||
Result := Round(AValue / 72 * AScreenPixelsPerInch);
|
||||
end;
|
||||
|
||||
{ converts a HTML length string to points. The units are assumed to be the last
|
||||
two digits of the string }
|
||||
function HTMLLengthStrToPts(AValue: String): Double;
|
||||
var
|
||||
units: String;
|
||||
x: Double;
|
||||
res: Word;
|
||||
begin
|
||||
if (Length(AValue) > 1) and (AValue[Length(AValue)] in ['a'..'z', 'A'..'Z']) then begin
|
||||
units := lowercase(Copy(AValue, Length(AValue)-1, 2));
|
||||
val(copy(AValue, 1, Length(AValue)-2), x, res);
|
||||
// No hasseling with the decimal point...
|
||||
end else begin
|
||||
units := '';
|
||||
val(AValue, x, res);
|
||||
end;
|
||||
if res <> 0 then
|
||||
raise Exception.CreateFmt('No valid number or units (%s)', [AValue]);
|
||||
|
||||
if (units = 'pt') or (units = '') then
|
||||
Result := x
|
||||
else
|
||||
if units = 'in' then
|
||||
Result := InToPts(x)
|
||||
else if units = 'cm' then
|
||||
Result := cmToPts(x)
|
||||
else if units = 'mm' then
|
||||
Result := mmToPts(x)
|
||||
else if units = 'px' then
|
||||
Result := pxToPts(Round(x), ScreenPixelsPerInch)
|
||||
else
|
||||
raise Exception.Create('Unknown length units');
|
||||
end;
|
||||
|
||||
{ converts a HTML color string to a TsColorValue. For ods }
|
||||
function HTMLColorStrToColor(AValue: String): TsColorValue;
|
||||
begin
|
||||
if AValue = '' then
|
||||
Result := scNotDefined
|
||||
else
|
||||
if AValue[1] = '#' then begin
|
||||
AValue[1] := '$';
|
||||
Result := LongRGBToExcelPhysical(StrToInt(AValue));
|
||||
end else begin
|
||||
AValue := lowercase(AValue);
|
||||
if AValue = 'red' then
|
||||
Result := $0000FF
|
||||
else if AValue = 'cyan' then
|
||||
Result := $FFFF00
|
||||
else if AValue = 'blue' then
|
||||
Result := $FF0000
|
||||
else if AValue = 'purple' then
|
||||
Result := $800080
|
||||
else if AValue = 'yellow' then
|
||||
Result := $00FFFF
|
||||
else if AValue = 'lime' then
|
||||
Result := $00FF00
|
||||
else if AValue = 'white' then
|
||||
Result := $FFFFFF
|
||||
else if AValue = 'black' then
|
||||
Result := $000000
|
||||
else if (AValue = 'gray') or (AValue = 'grey') then
|
||||
Result := $808080
|
||||
else if AValue = 'silver' then
|
||||
Result := $C0C0C0
|
||||
else if AValue = 'maroon' then
|
||||
Result := $000080
|
||||
else if AValue = 'green' then
|
||||
Result := $008000
|
||||
else if AValue = 'olive' then
|
||||
Result := $008080;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ converts an rgb color value to a string as used in HTML code (for ods) }
|
||||
function ColorToHTMLColorStr(AValue: TsColorValue): String;
|
||||
type
|
||||
TRGB = record r,g,b,a: Byte end;
|
||||
var
|
||||
rgb: TRGB;
|
||||
begin
|
||||
rgb := TRGB(AValue);
|
||||
Result := Format('#%.2x%.2x%.2x', [rgb.r, rgb.g, rgb.b]);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{******************************************************************************}
|
||||
{******************************************************************************}
|
||||
@ -1442,145 +1577,5 @@ begin
|
||||
DateTimeToString(Result, FormatStr, DateTime, FormatSettings,Options);
|
||||
end;
|
||||
|
||||
{ Excel's unit of row heights is "twips", i.e. 1/20 point.
|
||||
Converts Twips to points. }
|
||||
function TwipsToPts(AValue: Integer): Single;
|
||||
begin
|
||||
Result := AValue / 20;
|
||||
end;
|
||||
|
||||
{ Converts points to twips (1 twip = 1/20 point) }
|
||||
function PtsToTwips(AValue: Single): Integer;
|
||||
begin
|
||||
Result := round(AValue * 20);
|
||||
end;
|
||||
|
||||
{ Converts centimeters to points (72 pts = 1 inch) }
|
||||
function cmToPts(AValue: Double): Double;
|
||||
begin
|
||||
Result := AValue * 72 / 2.54;
|
||||
end;
|
||||
|
||||
{ Converts points to centimeters }
|
||||
function PtsToCm(AValue: Double): Double;
|
||||
begin
|
||||
Result := AValue / 72 * 2.54;
|
||||
end;
|
||||
|
||||
{ Converts inches to points (72 pts = 1 inch) }
|
||||
function InToPts(AValue: Double): Double;
|
||||
begin
|
||||
Result := AValue * 72;
|
||||
end;
|
||||
|
||||
{ Converts millimeters to points (72 pts = 1 inch) }
|
||||
function mmToPts(AValue: Double): Double;
|
||||
begin
|
||||
Result := AValue * 72 / 25.4;
|
||||
end;
|
||||
|
||||
{ Converts points to millimeters }
|
||||
function PtsToMM(AValue: Double): Double;
|
||||
begin
|
||||
Result := AValue / 72 * 25.4;
|
||||
end;
|
||||
|
||||
{ Converts pixels to points. }
|
||||
function pxToPts(AValue, AScreenPixelsPerInch: Integer): Double;
|
||||
begin
|
||||
Result := (AValue / AScreenPixelsPerInch) * 72;
|
||||
end;
|
||||
|
||||
{ Converts points to pixels }
|
||||
function PtsToPx(AValue: Double; AScreenPixelsPerInch: Integer): Integer;
|
||||
begin
|
||||
Result := Round(AValue / 72 * AScreenPixelsPerInch);
|
||||
end;
|
||||
|
||||
{ converts a HTML length string to points. The units are assumed to be the last
|
||||
two digits of the string }
|
||||
function HTMLLengthStrToPts(AValue: String): Double;
|
||||
var
|
||||
units: String;
|
||||
x: Double;
|
||||
res: Word;
|
||||
begin
|
||||
if (Length(AValue) > 1) and (AValue[Length(AValue)] in ['a'..'z', 'A'..'Z']) then begin
|
||||
units := lowercase(Copy(AValue, Length(AValue)-1, 2));
|
||||
val(copy(AValue, 1, Length(AValue)-2), x, res);
|
||||
// No hasseling with the decimal point...
|
||||
end else begin
|
||||
units := '';
|
||||
val(AValue, x, res);
|
||||
end;
|
||||
if res <> 0 then
|
||||
raise Exception.CreateFmt('No valid number or units (%s)', [AValue]);
|
||||
|
||||
if (units = 'pt') or (units = '') then
|
||||
Result := x
|
||||
else
|
||||
if units = 'in' then
|
||||
Result := InToPts(x)
|
||||
else if units = 'cm' then
|
||||
Result := cmToPts(x)
|
||||
else if units = 'mm' then
|
||||
Result := mmToPts(x)
|
||||
else if units = 'px' then
|
||||
Result := pxToPts(Round(x), ScreenPixelsPerInch)
|
||||
else
|
||||
raise Exception.Create('Unknown length units');
|
||||
end;
|
||||
|
||||
{ converts a HTML color string to a TsColorValue. For ods }
|
||||
function HTMLColorStrToColor(AValue: String): TsColorValue;
|
||||
begin
|
||||
if AValue = '' then
|
||||
Result := scNotDefined
|
||||
else
|
||||
if AValue[1] = '#' then begin
|
||||
AValue[1] := '$';
|
||||
Result := LongRGBToExcelPhysical(StrToInt(AValue));
|
||||
end else begin
|
||||
AValue := lowercase(AValue);
|
||||
if AValue = 'red' then
|
||||
Result := $0000FF
|
||||
else if AValue = 'cyan' then
|
||||
Result := $FFFF00
|
||||
else if AValue = 'blue' then
|
||||
Result := $FF0000
|
||||
else if AValue = 'purple' then
|
||||
Result := $800080
|
||||
else if AValue = 'yellow' then
|
||||
Result := $00FFFF
|
||||
else if AValue = 'lime' then
|
||||
Result := $00FF00
|
||||
else if AValue = 'white' then
|
||||
Result := $FFFFFF
|
||||
else if AValue = 'black' then
|
||||
Result := $000000
|
||||
else if (AValue = 'gray') or (AValue = 'grey') then
|
||||
Result := $808080
|
||||
else if AValue = 'silver' then
|
||||
Result := $C0C0C0
|
||||
else if AValue = 'maroon' then
|
||||
Result := $000080
|
||||
else if AValue = 'green' then
|
||||
Result := $008000
|
||||
else if AValue = 'olive' then
|
||||
Result := $008080;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ converts an rgb color value to a string as used in HTML code (for ods) }
|
||||
function ColorToHTMLColorStr(AValue: TsColorValue): String;
|
||||
type
|
||||
TRGB = record r,g,b,a: Byte end;
|
||||
var
|
||||
rgb: TRGB;
|
||||
begin
|
||||
rgb := TRGB(AValue);
|
||||
Result := Format('#%.2x%.2x%.2x', [rgb.r, rgb.g, rgb.b]);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
@ -47,7 +47,6 @@ type
|
||||
function FindFormatOf(AFormatCell: PCell): Integer; override;
|
||||
public
|
||||
constructor Create(AWorkbook: TsWorkbook);
|
||||
function FormatStringForWriting(AIndex: Integer): String; override;
|
||||
end;
|
||||
|
||||
{ TsSpreadBIFF2Reader }
|
||||
@ -106,7 +105,6 @@ type
|
||||
procedure WriteXFRecords(AStream: TStream);
|
||||
protected
|
||||
procedure CreateNumFormatList; override;
|
||||
procedure ListAllFormattingStyles; override;
|
||||
procedure ListAllNumFormats; override;
|
||||
procedure WriteBlank(AStream: TStream; const ARow, ACol: Cardinal; ACell: PCell); override;
|
||||
procedure WriteFormat(AStream: TStream; AFormatData: TsNumFormatData;
|
||||
@ -198,43 +196,12 @@ begin
|
||||
AddFormat(13, fs.LongDateFormat, nfLongDate);
|
||||
AddFormat(14, 'd/mmm', nfCustom);
|
||||
AddFormat(15, 'mmm/yy', nfCustom);
|
||||
//AddFormat(14, SpecialDateTimeFormat('dm', fs, true), nfFmtDateTime);
|
||||
//AddFormat(15, SpecialDateTimeFormat('my', fs, true), nfFmtDateTime);
|
||||
AddFormat(16, AddAMPM(fs.ShortTimeFormat, fs), nfShortTimeAM);
|
||||
AddFormat(17, AddAMPM(fs.LongTimeFormat, fs), nfLongTimeAM);
|
||||
AddFormat(18, fs.ShortTimeFormat, nfShortTime);
|
||||
AddFormat(19, fs.LongTimeFormat, nfLongTime);
|
||||
AddFormat(20, fs.ShortDateFormat + ' ' + fs.ShortTimeFormat, nfShortDateTime);
|
||||
|
||||
(*
|
||||
fs := Workbook.FormatSettings;
|
||||
ds := fs.DecimalSeparator;
|
||||
ts := fs.ThousandSeparator;
|
||||
cs := fs.CurrencyString;
|
||||
AddFormat( 0, '', nfGeneral);
|
||||
AddFormat( 1, '0', nfFixed);
|
||||
AddFormat( 2, '0'+ds+'00', nfFixed); // 0.00
|
||||
AddFormat( 3, '#'+ts+'##0', nfFixedTh); // #,##0
|
||||
AddFormat( 4, '#'+ts+'##0'+ds+'00', nfFixedTh); // #,##0.00
|
||||
AddFormat( 5, UTF8ToAnsi('"'+cs+'"#'+ts+'##0_);("'+cs+'"#'+ts+'##0)'), nfCurrency);
|
||||
AddFormat( 6, UTF8ToAnsi('"'+cs+'"#'+ts+'##0_);[Red]("'+cs+'"#'+ts+'##0)'), nfCurrencyRed);
|
||||
AddFormat( 7, UTF8ToAnsi('"'+cs+'"#'+ts+'##0'+ds+'00_);("'+cs+'"#'+ts+'##0'+ds+'00)'), nfCurrency);
|
||||
AddFormat( 8, UTF8ToAnsi('"'+cs+'"#'+ts+'##0'+ds+'00_);[Red]("'+cs+'"#'+ts+'##0'+ds+'00)'), nfCurrency);
|
||||
AddFormat( 9, '0%', nfPercentage);
|
||||
AddFormat(10, '0'+ds+'00%', nfPercentage);
|
||||
AddFormat(11, '0'+ds+'00E+00', nfExp);
|
||||
AddFormat(12, fs.ShortDateFormat, nfShortDate);
|
||||
AddFormat(13, fs.LongDateFormat, nfLongDate);
|
||||
AddFormat(14, 'd/mmm', nfCustom);
|
||||
AddFormat(15, 'mmm/yy', nfCustom);
|
||||
//AddFormat(14, SpecialDateTimeFormat('dm', fs, true), nfFmtDateTime);
|
||||
//AddFormat(15, SpecialDateTimeFormat('my', fs, true), nfFmtDateTime);
|
||||
AddFormat(16, AddAMPM(fs.ShortTimeFormat, fs), nfShortTimeAM);
|
||||
AddFormat(17, AddAMPM(fs.LongTimeFormat, fs), nfLongTimeAM);
|
||||
AddFormat(18, fs.ShortTimeFormat, nfShortTime);
|
||||
AddFormat(19, fs.LongTimeFormat, nfLongTime);
|
||||
AddFormat(20, fs.ShortDateFormat + ' ' + fs.ShortTimeFormat, nfShortDateTime);
|
||||
*)
|
||||
FFirstFormatIndexInFile := 0; // BIFF2 stores built-in formats to file.
|
||||
FNextFormatIndex := 21; // not needed - there are not user-defined formats
|
||||
end;
|
||||
@ -298,26 +265,6 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Creates formatting strings that are written into the file. These are the
|
||||
strings in the format list. The only exception is the nfGeneral entry which
|
||||
is written as "General". }
|
||||
function TsBIFF2NumFormatList.FormatStringForWriting(AIndex: Integer): String;
|
||||
begin
|
||||
Result := inherited FormatStringForWriting(AIndex);
|
||||
{
|
||||
if Result = '' then
|
||||
Result := 'General'
|
||||
else begin
|
||||
parser := TsNumFormatParser.Create(Workbook, Result);
|
||||
try
|
||||
parser.Localize;
|
||||
Result := Parser.FormatString[nfdExcel];
|
||||
finally
|
||||
end;
|
||||
end;
|
||||
}
|
||||
end;
|
||||
|
||||
|
||||
{ TsSpreadBIFF2Reader }
|
||||
|
||||
@ -893,21 +840,7 @@ begin
|
||||
Result := 15
|
||||
else begin
|
||||
// If not, then we need to search in the list of dynamic formats
|
||||
// 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.
|
||||
// And for BIFF2, there is only a limited number of formats.
|
||||
lCell := ACell^;
|
||||
{
|
||||
with lCell do begin
|
||||
if IsDateTimeFormat(NumberFormat) then
|
||||
NumberFormatStr := BuildDateTimeFormatString(NumberFormat,
|
||||
Workbook.FormatSettings, NumberFormatStr)
|
||||
else
|
||||
NumberFormatStr := BuildNumberFormatString(NumberFormat,
|
||||
Workbook.FormatSettings, Decimals, CurrencySymbol);
|
||||
NumFormatList.ConvertBeforeWriting(NumberFormatStr, NumberFormat, Decimals, CurrencyString);
|
||||
end;
|
||||
}
|
||||
lIndex := FindFormattingInList(@lCell);
|
||||
|
||||
// Carefully check the index
|
||||
@ -917,27 +850,12 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFF2Writer.ListAllFormattingStyles;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
inherited ListAllFormattingStyles;
|
||||
{
|
||||
for i:=0 to High(FFormattingStyles) do
|
||||
FNumFormatList.ConvertBeforeWriting(
|
||||
FFormattingStyles[i].NumberFormatStr,
|
||||
FFormattingStyles[i].NumberFormat
|
||||
);
|
||||
}
|
||||
end;
|
||||
|
||||
{ Builds up the list of number formats to be written to the biff2 file.
|
||||
Unlike biff5+ no formats are added here because biff2 supports only 21
|
||||
standard formats; these formats have been added by the NumFormatList's
|
||||
AddBuiltInFormats.
|
||||
|
||||
NOT CLEAR IF THIS IS TRUE ????
|
||||
|
||||
}
|
||||
// ToDo: check if the BIFF2 format is really restricted to 21 formats.
|
||||
procedure TsSpreadBIFF2Writer.ListAllNumFormats;
|
||||
|
@ -1221,14 +1221,6 @@ begin
|
||||
XFBorderDWord1 := XFBorderDWord1 or ((ord(ABorderStyles[cbNorth].LineStyle)+1) shl 8);
|
||||
if cbSouth in ABorders then
|
||||
XFBorderDWord1 := XFBorderDWord1 or ((ord(ABorderStyles[cbSouth].LineStyle)+1) shl 12);
|
||||
(*
|
||||
XFBorderDWord1 := 8 * $10000 {left line - black} + 8 * $800000 {right line - black};
|
||||
|
||||
if cbNorth in ABorders then XFBorderDWord1 := XFBorderDWord1 or $100;
|
||||
if cbWest in ABorders then XFBorderDWord1 := XFBorderDWord1 or $1;
|
||||
if cbEast in ABorders then XFBorderDWord1 := XFBorderDWord1 or $10;
|
||||
if cbSouth in ABorders then XFBorderDWord1 := XFBorderDWord1 or $1000;
|
||||
*)
|
||||
AStream.WriteDWord(DWordToLE(XFBorderDWord1));
|
||||
|
||||
// Top and Bottom line colors
|
||||
|
@ -450,12 +450,6 @@ type
|
||||
// Write out BLANK cell record
|
||||
procedure WriteBlank(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
ACell: PCell); override;
|
||||
|
||||
{
|
||||
procedure WriteCellBlock(AStream: TStream; ASheet: TsWorksheet;
|
||||
AFirstRow, ALastRow: Cardinal);
|
||||
}
|
||||
|
||||
// Write out used codepage for character encoding
|
||||
procedure WriteCodepage(AStream: TStream; AEncoding: TsEncoding);
|
||||
// Writes out column info(s)
|
||||
@ -766,7 +760,6 @@ end;
|
||||
|
||||
procedure TsBIFFNumFormatList.ConvertBeforeWriting(var AFormatString: String;
|
||||
var ANumFormat: TsNumberFormat);
|
||||
{var ADecimals: Byte; var ACurrencySymbol: String); }
|
||||
var
|
||||
parser: TsNumFormatParser;
|
||||
fmt: String;
|
||||
@ -774,13 +767,9 @@ begin
|
||||
parser := TsNumFormatParser.Create(Workbook, AFormatString);
|
||||
try
|
||||
if parser.Status = psOK then begin
|
||||
// We convert the fpc format string to Excel dialect
|
||||
// For writing, we have to convert the fpc format string to Excel dialect
|
||||
AFormatString := parser.FormatString[nfdExcel];
|
||||
ANumFormat := parser.NumFormat;
|
||||
{
|
||||
ADecimals := parser.Decimals;
|
||||
ACurrencySymbol := parser.CurrencySymbol;
|
||||
}
|
||||
end;
|
||||
finally
|
||||
parser.Free;
|
||||
@ -869,14 +858,6 @@ var
|
||||
begin
|
||||
FreeAndNil(FNumFormatList);
|
||||
FNumFormatList := TsBIFFNumFormatList.Create(Workbook);
|
||||
(*
|
||||
// Convert builtin formats to fps syntax
|
||||
for i:=0 to FNumFormatList.Count-1 do begin
|
||||
item := FNumFormatList[i];
|
||||
FNumFormatList.ConvertAfterReading(item.Index, item.FormatString,
|
||||
item.NumFormat, item.Decimals, item.CurrencySymbol);
|
||||
end;
|
||||
*)
|
||||
end;
|
||||
|
||||
{ Extracts a number out of an RK value.
|
||||
@ -910,7 +891,6 @@ begin
|
||||
Result := Number;
|
||||
end;
|
||||
|
||||
|
||||
{ Extracts number format data from an XF record index by AXFIndex.
|
||||
Valid for BIFF5-BIFF8. Needs to be overridden for BIFF2 }
|
||||
procedure TsSpreadBIFFReader.ExtractNumberFormat(AXFIndex: WORD;
|
||||
@ -924,13 +904,9 @@ begin
|
||||
if lNumFormatData <> nil then begin
|
||||
ANumberFormat := lNumFormatData.NumFormat;
|
||||
ANumberFormatStr := lNumFormatData.FormatString;
|
||||
// ADecimals := lNumFormatData.Decimals;
|
||||
// ACurrencySymbol := lNumFormatData.CurrencySymbol;
|
||||
end else begin
|
||||
ANumberFormat := nfGeneral;
|
||||
ANumberFormatStr := '';
|
||||
// ADecimals := 0;
|
||||
// ACurrencySymbol := '';
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -1321,8 +1297,6 @@ var
|
||||
lDateTime: TDateTime;
|
||||
Number: Double;
|
||||
nf: TsNumberFormat; // Number format
|
||||
nd: Byte; // decimals
|
||||
ncs: String; // Currency symbol
|
||||
nfs: String; // Number format string
|
||||
begin
|
||||
{Retrieve XF record, row and column}
|
||||
@ -2084,7 +2058,6 @@ begin
|
||||
AStream.WriteWord(WordToLE(1)); // only 1 item
|
||||
|
||||
{ Index to first and last row - are the same here }
|
||||
|
||||
AStream.WriteWord(WordTOLE(activeCellRow));
|
||||
AStream.WriteWord(WordTOLE(activeCellRow));
|
||||
|
||||
@ -2172,19 +2145,6 @@ begin
|
||||
// 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.
|
||||
lCell := ACell^;
|
||||
(*
|
||||
with lCell do begin
|
||||
if NumberFormat <> nfCustom then begin
|
||||
if IsDateTimeFormat(NumberFormat) then
|
||||
NumberFormatStr := BuildDateTimeFormatString(NumberFormat,
|
||||
Workbook.FormatSettings, NumberFormatStr)
|
||||
else
|
||||
NumberFormatStr := BuildNumberFormatString(NumberFormat,
|
||||
Workbook.FormatSettings, Decimals, CurrencySymbol);
|
||||
//NumFormatList.ConvertBeforeWriting(NumberFormatStr, NumberFormat, Decimals, CurrencyString);
|
||||
end;
|
||||
end;
|
||||
*)
|
||||
lIndex := FindFormattingInList(@lCell);
|
||||
|
||||
// Carefully check the index
|
||||
|
Reference in New Issue
Block a user