From 8adf987bf9bc0359202270ade5c5e0a8280da506 Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Tue, 19 May 2015 16:18:01 +0000 Subject: [PATCH] fpspreadsheet: Better detection of fraction format by numberformat action. Some clean-up. git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4145 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- .../examples/visual/fpsctrls/main.lfm | 6 +- .../examples/visual/shared/sctrls.pas | 65 ++++ components/fpspreadsheet/fps.inc | 5 - .../fpspreadsheet/fpsnumformatparser.pas | 27 +- components/fpspreadsheet/fpsopendocument.pas | 7 +- components/fpspreadsheet/fpspatches.pas | 336 +----------------- components/fpspreadsheet/fpspreadsheet.pas | 7 +- components/fpspreadsheet/fpsutils.pas | 158 +------- .../fpspreadsheet/tests/formattests.pas | 10 +- 9 files changed, 109 insertions(+), 512 deletions(-) diff --git a/components/fpspreadsheet/examples/visual/fpsctrls/main.lfm b/components/fpspreadsheet/examples/visual/fpsctrls/main.lfm index 822dec533..ca278654b 100644 --- a/components/fpspreadsheet/examples/visual/fpsctrls/main.lfm +++ b/components/fpspreadsheet/examples/visual/fpsctrls/main.lfm @@ -837,21 +837,21 @@ object MainForm: TMainForm WorkbookSource = WorkbookSource Caption = 'Fraction (1 digit)' NumberFormat = nfFraction - NumberFormatString = '# #/#' + NumberFormatString = '# ?/?' end object AcNumFormatFraction2: TsNumberFormatAction Category = 'FPSpreadsheet' WorkbookSource = WorkbookSource Caption = 'Fraction (2 digits)' NumberFormat = nfFraction - NumberFormatString = '# ##/##' + NumberFormatString = '# ??/??' end object AcNumFormatFraction3: TsNumberFormatAction Category = 'FPSpreadsheet' WorkbookSource = WorkbookSource Caption = 'Fraction (3 digits)' NumberFormat = nfFraction - NumberFormatString = '# ###/###' + NumberFormatString = '# ???/???' end object AcNumFormatDateTime: TsNumberFormatAction Category = 'FPSpreadsheet' diff --git a/components/fpspreadsheet/examples/visual/shared/sctrls.pas b/components/fpspreadsheet/examples/visual/shared/sctrls.pas index ed867baca..680e37138 100644 --- a/components/fpspreadsheet/examples/visual/shared/sctrls.pas +++ b/components/fpspreadsheet/examples/visual/shared/sctrls.pas @@ -44,6 +44,71 @@ implementation uses Math, ButtonPanel, fpsUtils; +{@@ ---------------------------------------------------------------------------- + Concatenates the day names specified in ADayNames to a single string. If all + daynames are empty AEmptyStr is returned + + @param ADayNames Array[1..7] of day names as used in the Formatsettings + @param AEmptyStr Is returned if all day names are empty + @return String having all day names concatenated and separated by the + DefaultFormatSettings.ListSeparator +-------------------------------------------------------------------------------} +function DayNamesToString(const ADayNames: TWeekNameArray; + const AEmptyStr: String): String; +var + i: Integer; + isEmpty: Boolean; +begin + isEmpty := true; + for i:=1 to 7 do + if ADayNames[i] <> '' then + begin + isEmpty := false; + break; + end; + + if isEmpty then + Result := AEmptyStr + else + begin + Result := ADayNames[1]; + for i:=2 to 7 do + Result := Result + DefaultFormatSettings.ListSeparator + ' ' + ADayNames[i]; + end; +end; + +{@@ ---------------------------------------------------------------------------- + Concatenates the month names specified in AMonthNames to a single string. + If all month names are empty AEmptyStr is returned + + @param AMonthNames Array[1..12] of month names as used in the Formatsettings + @param AEmptyStr Is returned if all month names are empty + @return String having all month names concatenated and separated by the + DefaultFormatSettings.ListSeparator +-------------------------------------------------------------------------------} +function MonthNamesToString(const AMonthNames: TMonthNameArray; + const AEmptyStr: String): String; +var + i: Integer; + isEmpty: Boolean; +begin + isEmpty := true; + for i:=1 to 12 do + if AMonthNames[i] <> '' then + begin + isEmpty := false; + break; + end; + + if isEmpty then + Result := AEmptyStr + else + begin + Result := AMonthNames[1]; + for i:=2 to 12 do + Result := Result + DefaultFormatSettings.ListSeparator + ' ' + AMonthNames[i]; + end; +end; { TMonthDayNamesEdit } diff --git a/components/fpspreadsheet/fps.inc b/components/fpspreadsheet/fps.inc index 867850b9a..d2dfcae9c 100644 --- a/components/fpspreadsheet/fps.inc +++ b/components/fpspreadsheet/fps.inc @@ -21,11 +21,6 @@ { The next defines activate code duplicated from new compiler versions in case an old compiler is used. } -{ Numberformats require an extended version of FormatDateTime (in SysUtils) - which is not available before FPC 3.0. Define FPS_FORMATDATETIME if the - compiler used is older. } -{$DEFINE FPS_FORMATDATETIME} - { fpspreadsheet requires the function VarIsBool which was introduced by fpc 2.6.4. If an older FPC versions is used define FPS_VARISBOOL. Keep undefined for the current FPC version. } diff --git a/components/fpspreadsheet/fpsnumformatparser.pas b/components/fpspreadsheet/fpsnumformatparser.pas index 1bc0bbc71..7aeafe43d 100644 --- a/components/fpspreadsheet/fpsnumformatparser.pas +++ b/components/fpspreadsheet/fpsnumformatparser.pas @@ -305,10 +305,14 @@ begin section := @FSections[ASection]; section^.Kind := []; + i := 0; + for el := 0 to High(section^.Elements) do case section^.Elements[el].Token of nftZeroDecs: section^.Decimals := section^.Elements[el].IntValue; + nftIntZeroDigit, nftIntOptDigit, nftIntSpaceDigit: + i := section^.Elements[el].IntValue; nftFracNumSpaceDigit, nftFracNumZeroDigit: section^.FracNumerator := section^.Elements[el].IntValue; nftFracDenomSpaceDigit, nftFracDenomZeroDigit: @@ -331,7 +335,10 @@ begin if (nfkFraction in section^.Kind) then FStatus := psErrMultipleFracSymbols else + begin section^.Kind := section^.Kind + [nfkFraction]; + section^.FracInt := i; + end; nftCurrSymbol: begin if (nfkCurrency in section^.Kind) then @@ -405,13 +412,19 @@ begin end else begin nfs := GetFormatString; - formats := [nfFixed, nfFixedTh, nfPercentage, nfExp, nfFraction]; - for nf in formats do begin - nfsTest := BuildNumberFormatString(nf, FWorkbook.FormatSettings, section^.Decimals); - if SameText(nfs, nfsTest) then - begin - section^.NumFormat := nf; - break; + nfsTest := BuildFractionFormatString(section^.FracInt > 0, section^.FracNumerator, section^.FracDenominator); + if sameText(nfs, nfsTest) then + section^.NumFormat := nfFraction + else + begin + formats := [nfFixed, nfFixedTh, nfPercentage, nfExp]; + for nf in formats do begin + nfsTest := BuildNumberFormatString(nf, FWorkbook.FormatSettings, section^.Decimals); + if SameText(nfs, nfsTest) then + begin + section^.NumFormat := nf; + break; + end; end; end; if (section^.NumFormat = nfCustom) and (nfkCurrency in section^.Kind) then diff --git a/components/fpspreadsheet/fpsopendocument.pas b/components/fpspreadsheet/fpsopendocument.pas index 504ecac95..726506987 100755 --- a/components/fpspreadsheet/fpsopendocument.pas +++ b/components/fpspreadsheet/fpsopendocument.pas @@ -230,7 +230,7 @@ implementation uses StrUtils, Variants, LazFileUtils, URIParser, - fpsPatches, fpsStrings, fpsStreams, fpsExprParser; + fpsStrings, fpsStreams, fpsExprParser; const { OpenDocument general XML constants } @@ -5364,6 +5364,7 @@ var r1,c1,r2,c2: Cardinal; fmt: TsCellFormat; numFmtParams: TsNumFormatParams; + h,m,s,ms: Word; begin Unused(ARow, ACol); @@ -5395,7 +5396,9 @@ begin if IsTimeIntervalformat(numFmtParams) then begin - strValue := FormatDateTime(ISO8601FormatHoursOverflow, AValue, [fdoInterval]); + DecodeTime(AValue, h,m,s,ms); + strValue := Format('PT%02dH%02dM%02d.%03dS', [trunc(AValue)*24+h, m, s, ms]); +// strValue := FormatDateTime(ISO8601FormatHoursOverflow, AValue, [fdoInterval]); displayStr := FWorksheet.ReadAsUTF8Text(ACell); // displayStr := FormatDateTime(fmt.NumberFormatStr, AValue, [fdoInterval]); AppendToStream(AStream, Format( diff --git a/components/fpspreadsheet/fpspatches.pas b/components/fpspreadsheet/fpspatches.pas index c40e8b22d..c2dd5a26d 100644 --- a/components/fpspreadsheet/fpspatches.pas +++ b/components/fpspreadsheet/fpspatches.pas @@ -16,13 +16,13 @@ uses Classes, SysUtils; {$IFDEF FPS_VARISBOOL} -{ Needed only if FPC version is < 2.6.4 } + { Needed only if FPC version is < 2.6.4 } function VarIsBool(const V: Variant): Boolean; {$ENDIF} {$IFDEF FPS_LAZUTF8} - // implemented in LazUTF8 in r43348 (Laz 1.2) + // implemented in LazUTF8 of r43348 (Laz 1.2) function UTF8LeftStr(const AText: String; const ACount: Integer): String; function UTF8RightStr(const AText: String; const ACount: Integer): String; function UTF8StringReplace(const S, OldPattern, NewPattern: String; @@ -32,19 +32,6 @@ uses {$ENDIF} -{$IFDEF FPS_FORMATDATETIME} -type - TFormatDateTimeOption = (fdoInterval); - TFormatDateTimeOptions = set of TFormatDateTimeOption; - - // Needed if fpc version is < 3.0. - function FormatDateTime(const FormatStr: string; DateTime: TDateTime; - Options : TFormatDateTimeOptions = []): string; - function FormatDateTime(const FormatStr: string; DateTime: TDateTime; - const FormatSettings: TFormatSettings; Options : TFormatDateTimeOptions = []): string; -{$ENDIF} - - implementation {$IFDEF FPS_VARISBOOL} @@ -1706,325 +1693,6 @@ begin // Final correction of the buffer size SetLength(Result,OutCounter); end; - -{$ENDIF} - - -{$IFDEF FPS_FORMATDATETIME} -{******************************************************************************} -{******************************************************************************} -{ Patch for SysUtils.FormatDateTime } -{******************************************************************************} -{******************************************************************************} - -{@@ ---------------------------------------------------------------------------- - Applies a formatting string to a date/time value and converts the number - to a date/time string. - - This functionality is available in the SysUtils unit. But it is duplicated - here to add a patch which is not available in stable fpc. --------------------------------------------------------------------------------} -procedure DateTimeToString(out Result: string; const FormatStr: string; const DateTime: TDateTime; - const FormatSettings: TFormatSettings; Options : TFormatDateTimeOptions = []); -// Copied from "fpc/rtl/objpas/sysutils/datei.inc" -var - ResultLen: integer; - ResultBuffer: array[0..255] of char; - ResultCurrent: pchar; - - procedure StoreStr(Str: PChar; Len: Integer); - begin - if ResultLen + Len < SizeOf(ResultBuffer) then - begin - StrMove(ResultCurrent, Str, Len); - ResultCurrent := ResultCurrent + Len; - ResultLen := ResultLen + Len; - end; - end; - - procedure StoreString(const Str: string); - var Len: integer; - begin - Len := Length(Str); - if ResultLen + Len < SizeOf(ResultBuffer) then - begin - StrMove(ResultCurrent, pchar(Str), Len); - ResultCurrent := ResultCurrent + Len; - ResultLen := ResultLen + Len; - end; - end; - - procedure StoreInt(Value, Digits: Integer); - var - S: string[16]; - Len: integer; - begin - System.Str(Value:Digits, S); - for Len := 1 to Length(S) do - begin - if S[Len] = ' ' then - S[Len] := '0' - else - Break; - end; - StoreStr(pchar(@S[1]), Length(S)); - end ; - -var - Year, Month, Day, DayOfWeek, Hour, Minute, Second, MilliSecond: word; - - procedure StoreFormat(const FormatStr: string; Nesting: Integer; TimeFlag: Boolean); - var - Token, lastformattoken, prevlasttoken: char; - FormatCurrent: pchar; - FormatEnd: pchar; - Count: integer; - Clock12: boolean; - P: pchar; - tmp: integer; - isInterval: Boolean; - - begin - if Nesting > 1 then // 0 is original string, 1 is included FormatString - Exit; - - FormatCurrent := PChar(FormatStr); - FormatEnd := FormatCurrent + Length(FormatStr); - Clock12 := false; - isInterval := false; - P := FormatCurrent; - // look for unquoted 12-hour clock token - while P < FormatEnd do - begin - Token := P^; - case Token of - '''', '"': - begin - Inc(P); - while (P < FormatEnd) and (P^ <> Token) do - Inc(P); - end; - 'A', 'a': - begin - if (StrLIComp(P, 'A/P', 3) = 0) or - (StrLIComp(P, 'AMPM', 4) = 0) or - (StrLIComp(P, 'AM/PM', 5) = 0) then - begin - Clock12 := true; - break; - end; - end; - end; // case - Inc(P); - end ; - token := #255; - lastformattoken := ' '; - prevlasttoken := 'H'; - while FormatCurrent < FormatEnd do - begin - Token := UpCase(FormatCurrent^); - Count := 1; - P := FormatCurrent + 1; - case Token of - '''', '"': - begin - while (P < FormatEnd) and (p^ <> Token) do - Inc(P); - Inc(P); - Count := P - FormatCurrent; - StoreStr(FormatCurrent + 1, Count - 2); - end ; - 'A': - begin - if StrLIComp(FormatCurrent, 'AMPM', 4) = 0 then - begin - Count := 4; - if Hour < 12 then - StoreString(FormatSettings.TimeAMString) - else - StoreString(FormatSettings.TimePMString); - end - else if StrLIComp(FormatCurrent, 'AM/PM', 5) = 0 then - begin - Count := 5; - if Hour < 12 then StoreStr(FormatCurrent, 2) - else StoreStr(FormatCurrent+3, 2); - end - else if StrLIComp(FormatCurrent, 'A/P', 3) = 0 then - begin - Count := 3; - if Hour < 12 then StoreStr(FormatCurrent, 1) - else StoreStr(FormatCurrent+2, 1); - end - else - raise EConvertError.Create('Illegal character in format string'); - end ; - '/': StoreStr(@FormatSettings.DateSeparator, 1); - ':': StoreStr(@FormatSettings.TimeSeparator, 1); - '[': if (fdoInterval in Options) then isInterval := true else StoreStr(FormatCurrent, 1); - ']': if (fdoInterval in Options) then isInterval := false else StoreStr(FormatCurrent, 1); - ' ', 'C', 'D', 'H', 'M', 'N', 'S', 'T', 'Y', 'Z', 'F' : - begin - while (P < FormatEnd) and (UpCase(P^) = Token) do - Inc(P); - Count := P - FormatCurrent; - case Token of - ' ': StoreStr(FormatCurrent, Count); - 'Y': begin - if Count > 2 then - StoreInt(Year, 4) - else - StoreInt(Year mod 100, 2); - end; - 'M': begin - if isInterval and ((prevlasttoken = 'H') or TimeFlag) then - StoreInt(Minute + (Hour + trunc(abs(DateTime))*24)*60, 0) - else - if (lastformattoken = 'H') or TimeFlag then - begin - if Count = 1 then - StoreInt(Minute, 0) - else - StoreInt(Minute, 2); - end - else - begin - case Count of - 1: StoreInt(Month, 0); - 2: StoreInt(Month, 2); - 3: StoreString(FormatSettings.ShortMonthNames[Month]); - else - StoreString(FormatSettings.LongMonthNames[Month]); - end; - end; - end; - 'D': begin - case Count of - 1: StoreInt(Day, 0); - 2: StoreInt(Day, 2); - 3: StoreString(FormatSettings.ShortDayNames[DayOfWeek]); - 4: StoreString(FormatSettings.LongDayNames[DayOfWeek]); - 5: StoreFormat(FormatSettings.ShortDateFormat, Nesting+1, False); - else - StoreFormat(FormatSettings.LongDateFormat, Nesting+1, False); - end ; - end ; - 'H': - if isInterval then - StoreInt(Hour + trunc(abs(DateTime))*24, 0) - else - if Clock12 then - begin - tmp := hour mod 12; - if tmp=0 then tmp:=12; - if Count = 1 then - StoreInt(tmp, 0) - else - StoreInt(tmp, 2); - end - else begin - if Count = 1 then - StoreInt(Hour, 0) - else - StoreInt(Hour, 2); - end; - 'N': if isInterval then - StoreInt(Minute + (Hour + trunc(abs(DateTime))*24)*60, 0) - else - if Count = 1 then - StoreInt(Minute, 0) - else - StoreInt(Minute, 2); - 'S': if isInterval then - StoreInt(Second + (Minute + (Hour + trunc(abs(DateTime))*24)*60)*60, 0) - else - if Count = 1 then - StoreInt(Second, 0) - else - StoreInt(Second, 2); - 'Z': if Count = 1 then - StoreInt(MilliSecond, 0) - else - StoreInt(MilliSecond, 3); - 'T': if Count = 1 then - StoreFormat(FormatSettings.ShortTimeFormat, Nesting+1, True) - else - StoreFormat(FormatSettings.LongTimeFormat, Nesting+1, True); - 'C': begin - StoreFormat(FormatSettings.ShortDateFormat, Nesting+1, False); - if (Hour<>0) or (Minute<>0) or (Second<>0) then - begin - StoreString(' '); - StoreFormat(FormatSettings.LongTimeFormat, Nesting+1, True); - end; - end; - 'F': begin - StoreFormat(FormatSettings.ShortDateFormat, Nesting+1, False); - StoreString(' '); - StoreFormat(FormatSettings.LongTimeFormat, Nesting+1, True); - end; - end; - prevlasttoken := lastformattoken; - lastformattoken := token; - end; - else - StoreStr(@Token, 1); - end ; - Inc(FormatCurrent, Count); - end; - end; - -begin - DecodeDateFully(DateTime, Year, Month, Day, DayOfWeek); - DecodeTime(DateTime, Hour, Minute, Second, MilliSecond); - ResultLen := 0; - ResultCurrent := @ResultBuffer[0]; - if FormatStr <> '' then - StoreFormat(FormatStr, 0, False) - else - StoreFormat('C', 0, False); - ResultBuffer[ResultLen] := #0; - result := StrPas(@ResultBuffer[0]); -end ; - -{@@ - Applies a formatting string to a date/time value and converts the number - to a date/time string. - - This functionality is available in the SysUtils unit. But it is duplicated - here to add a patch which is not available in stable fpc. -} -procedure DateTimeToString(out Result: string; const FormatStr: string; - const DateTime: TDateTime; Options : TFormatDateTimeOptions = []); -begin - DateTimeToString(Result, FormatStr, DateTime, DefaultFormatSettings, Options); -end; - -{@@ - Applies a formatting string to a date/time value and converts the number - to a date/time string. - - This functionality is available in the SysUtils unit. But it is duplicated - here to add a patch which is not available in stable fpc. -} -function FormatDateTime(const FormatStr: string; DateTime: TDateTime; - Options : TFormatDateTimeOptions = []): string; -begin - DateTimeToString(Result, FormatStr, DateTime, DefaultFormatSettings,Options); -end; - -{@@ - Applies a formatting string to a date/time value and converts the number - to a date/time string. - - This functionality is available in the SysUtils unit. But it is duplicated - here to add a patch which is not available in stable fpc. -} -function FormatDateTime(const FormatStr: string; DateTime: TDateTime; - const FormatSettings: TFormatSettings; Options : TFormatDateTimeOptions = []): string; -begin - DateTimeToString(Result, FormatStr, DateTime, FormatSettings,Options); -end; {$ENDIF} end. diff --git a/components/fpspreadsheet/fpspreadsheet.pas b/components/fpspreadsheet/fpspreadsheet.pas index ec8a49db5..7460ce42f 100755 --- a/components/fpspreadsheet/fpspreadsheet.pas +++ b/components/fpspreadsheet/fpspreadsheet.pas @@ -792,7 +792,7 @@ implementation uses Math, StrUtils, DateUtils, TypInfo, lazutf8, lazFileUtils, URIParser, - fpsPatches, fpsStrings, uvirtuallayer_ole, + fpsStrings, uvirtuallayer_ole, fpsUtils, fpsreaderwriter, fpsCurrency, fpsExprParser, fpsNumFormat, fpsNumFormatParser; @@ -3976,6 +3976,7 @@ var fmt: TsCellFormat; numFmtParams: TsNumFormatParams; maxDig: Integer; + isMixed: Boolean; begin if ACell = nil then exit; @@ -3998,10 +3999,10 @@ begin exit; end; - if TryFractionStrToFloat(AValue, number, maxdig) then + if TryFractionStrToFloat(AValue, number, ismixed, maxdig) then begin WriteNumber(ACell, number); - WriteFractionFormat(ACell, true, maxdig, maxdig); + WriteFractionFormat(ACell, ismixed, maxdig, maxdig); exit; end; diff --git a/components/fpspreadsheet/fpsutils.pas b/components/fpspreadsheet/fpsutils.pas index 6416ae741..7181bb1a3 100644 --- a/components/fpspreadsheet/fpsutils.pas +++ b/components/fpspreadsheet/fpsutils.pas @@ -111,18 +111,10 @@ function AddAMPM(const ATimeFormatString: String; function StripAMPM(const ATimeFormatString: String): String; function CountDecs(AFormatString: String; ADecChars: TsDecsChars = ['0']): Byte; function AddIntervalBrackets(AFormatString: String): String; -function DayNamesToString(const ADayNames: TWeekNameArray; - const AEmptyStr: String): String; function MakeLongDateFormat(ADateFormat: String): String; function MakeShortDateFormat(ADateFormat: String): String; -function MonthNamesToString(const AMonthNames: TMonthNameArray; - const AEmptyStr: String): String; function SpecialDateTimeFormat(ACode: String; const AFormatSettings: TFormatSettings; ForWriting: Boolean): String; -{ -procedure SplitFormatString(const AFormatString: String; out APositivePart, - ANegativePart, AZeroPart: String); - } procedure MakeTimeIntervalMask(Src: String; var Dest: String); function ConvertFloatToStr(AValue: Double; AParams: TsNumFormatParams; @@ -132,10 +124,10 @@ procedure FloatToFraction(AValue: Double; AMaxDenominator: Int64; function TryStrToFloatAuto(AText: String; out ANumber: Double; out ADecimalSeparator, AThousandSeparator: Char; out AWarning: String): Boolean; function TryFractionStrToFloat(AText: String; out ANumber: Double; - out AMaxDigits: Integer): Boolean; + out AIsMixed: Boolean; out AMaxDigits: Integer): Boolean; -function TwipsToPts(AValue: Integer): Single; inline; -function PtsToTwips(AValue: Single): Integer; inline; +function TwipsToPts(AValue: Integer): Single; inline; +function PtsToTwips(AValue: Single): Integer; inline; function cmToPts(AValue: Double): Double; inline; function PtsToCm(AValue: Double): Double; inline; function InToMM(AValue: Double): Double; inline; @@ -1347,39 +1339,6 @@ begin end; end; -{@@ ---------------------------------------------------------------------------- - Concatenates the day names specified in ADayNames to a single string. If all - daynames are empty AEmptyStr is returned - - @param ADayNames Array[1..7] of day names as used in the Formatsettings - @param AEmptyStr Is returned if all day names are empty - @return String having all day names concatenated and separated by the - DefaultFormatSettings.ListSeparator --------------------------------------------------------------------------------} -function DayNamesToString(const ADayNames: TWeekNameArray; - const AEmptyStr: String): String; -var - i: Integer; - isEmpty: Boolean; -begin - isEmpty := true; - for i:=1 to 7 do - if ADayNames[i] <> '' then - begin - isEmpty := false; - break; - end; - - if isEmpty then - Result := AEmptyStr - else - begin - Result := ADayNames[1]; - for i:=2 to 7 do - Result := Result + DefaultFormatSettings.ListSeparator + ' ' + ADayNames[i]; - end; -end; - {@@ ---------------------------------------------------------------------------- Approximates a floating point value as a fraction and returns the values of numerator and denominator. @@ -1532,39 +1491,6 @@ begin end; end; -{@@ ---------------------------------------------------------------------------- - Concatenates the month names specified in AMonthNames to a single string. - If all month names are empty AEmptyStr is returned - - @param AMonthNames Array[1..12] of month names as used in the Formatsettings - @param AEmptyStr Is returned if all month names are empty - @return String having all month names concatenated and separated by the - DefaultFormatSettings.ListSeparator --------------------------------------------------------------------------------} -function MonthNamesToString(const AMonthNames: TMonthNameArray; - const AEmptyStr: String): String; -var - i: Integer; - isEmpty: Boolean; -begin - isEmpty := true; - for i:=1 to 12 do - if AMonthNames[i] <> '' then - begin - isEmpty := false; - break; - end; - - if isEmpty then - Result := AEmptyStr - else - begin - Result := AMonthNames[1]; - for i:=2 to 12 do - Result := Result + DefaultFormatSettings.ListSeparator + ' ' + AMonthNames[i]; - end; -end; - {@@ ---------------------------------------------------------------------------- Creates the formatstrings for the date/time codes "dm", "my", "ms" and "msz" out of the formatsettings. @@ -1610,81 +1536,6 @@ begin Result := ACode; end; -{@@ ---------------------------------------------------------------------------- - Currency formatting strings consist of three parts, separated by - semicolons, which are valid for positive, negative or zero values. - Splits such a formatting string at the positions of the semicolons and - returns the sections. If semicolons are used for other purposed within - sections they have to be quoted by " or escaped by \. If the formatting - string contains less sections than three the missing strings are returned - as empty strings. - - @param AFormatString String of number formatting codes. - @param APositivePart First section of the formatting string which is valid - for positive numbers (or positive and zero, if there - are only two sections) - @param ANegativePart Second section of the formatting string which is valid - for negative numbers - @param AZeroPart Third section of the formatting string for zero. --------------------------------------------------------------------------------} -(* -procedure SplitFormatString(const AFormatString: String; out APositivePart, - ANegativePart, AZeroPart: String); - - procedure AddToken(AToken: Char; AWhere:Byte); - begin - case AWhere of - 0: APositivePart := APositivePart + AToken; - 1: ANegativePart := ANegativePart + AToken; - 2: AZeroPart := AZeroPart + AToken; - end; - end; - -var - P, PStart, PEnd: PChar; - token: Char; - where: Byte; // 0 = positive part, 1 = negative part, 2 = zero part -begin - APositivePart := ''; - ANegativePart := ''; - AZeroPart := ''; - if AFormatString = '' then - exit; - - PStart := PChar(@AFormatString[1]); - PEnd := PStart + Length(AFormatString); - P := PStart; - where := 0; - while P < PEnd do begin - token := P^; - case token of - '"': begin // Let quoted text intact - AddToken(token, where); - inc(P); - token := P^; - while (P < PEnd) and (token <> '"') do begin - AddToken(token, where); - inc(P); - token := P^; - end; - AddToken(token, where); - end; - ';': begin // Separator between parts - inc(where); - if where = 3 then - exit; - end; - '\': begin // Skip "Escape" character and add next char immediately - inc(P); - token := P^; - AddToken(token, where); - end; - else AddToken(token, where); - end; - inc(P); - end; -end; - *) {@@ ---------------------------------------------------------------------------- Creates a "time interval" format string having the first time code identifier in square brackets. @@ -1894,7 +1745,7 @@ end; @example AText := '1 3/4' --> ANumber = 1.75; AMaxDigits = 1; Result = true -------------------------------------------------------------------------------} function TryFractionStrToFloat(AText: String; out ANumber: Double; - out AMaxDigits: Integer): Boolean; + out AIsMixed: Boolean; out AMaxDigits: Integer): Boolean; var p: Integer; s, sInt, sNum, sDenom: String; @@ -1931,6 +1782,7 @@ begin if sInt <> '' then ANumber := ANumber + i; + AIsMixed := (sInt <> ''); AMaxDigits := Length(sDenom); Result := true; diff --git a/components/fpspreadsheet/tests/formattests.pas b/components/fpspreadsheet/tests/formattests.pas index f09ee214c..6d50e5641 100644 --- a/components/fpspreadsheet/tests/formattests.pas +++ b/components/fpspreadsheet/tests/formattests.pas @@ -27,10 +27,10 @@ var SollNumberFormats: array[0..9] of TsNumberFormat; SollNumberDecimals: array[0..9] of word; - SollDateTimeStrings: array[0..4, 0..9] of string; + SollDateTimeStrings: array[0..4, 0..8] of string; SollDateTimes: array[0..4] of TDateTime; - SollDateTimeFormats: array[0..9] of TsNumberFormat; - SollDateTimeFormatStrings: array[0..9] of String; + SollDateTimeFormats: array[0..8] of TsNumberFormat; + SollDateTimeFormatStrings: array[0..8] of String; SollColWidths: array[0..1] of Single; SollRowHeights: Array[0..2] of Single; @@ -256,7 +256,7 @@ begin SollDateTimeFormats[6] := nfCustom; SollDateTimeFormatStrings[6] := 'dd/mmm'; SolLDateTimeFormats[7] := nfCustom; SollDateTimeFormatStrings[7] := 'mmm/yy'; SollDateTimeFormats[8] := nfCustom; SollDateTimeFormatStrings[8] := 'nn:ss'; - SollDateTimeFormats[9] := nfTimeInterval; SollDateTimeFormatStrings[9] := ''; +// SollDateTimeFormats[9] := nfTimeInterval; SollDateTimeFormatStrings[9] := ''; for i:=Low(SollDateTimes) to High(SollDateTimes) do begin @@ -269,7 +269,7 @@ begin SollDateTimeStrings[i, 6] := FormatDateTime(SpecialDateTimeFormat('dm', fs, false), SollDateTimes[i], fs); SollDateTimeStrings[i, 7] := FormatDateTime(SpecialDateTimeFormat('my', fs, false), SollDateTimes[i], fs); SollDateTimeStrings[i, 8] := FormatDateTime(SpecialDateTimeFormat('ms', fs, false), SollDateTimes[i], fs); - SollDateTimeStrings[i, 9] := FormatDateTime('[h]:mm:ss', SollDateTimes[i], fs, [fdoInterval]); +// SollDateTimeStrings[i, 9] := FormatDateTime('[h]:mm:ss', SollDateTimes[i], fs, [fdoInterval]); end; // Column width