fpspreadsheet: Improved detection of the ambivalent symbol "m" in format strings.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3077 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2014-05-22 10:09:35 +00:00
parent 169dbe7b4f
commit c70b1db64f
2 changed files with 56 additions and 19 deletions

View File

@ -19,6 +19,7 @@ const
psErrNoUsableFormat = 5; psErrNoUsableFormat = 5;
psErrNoValidNumberFormat = 6; psErrNoValidNumberFormat = 6;
psErrNoValidDateTimeFormat = 7; psErrNoValidDateTimeFormat = 7;
psAmbiguousSymbol = 8;
{ TsNumFormatParser } { TsNumFormatParser }
@ -524,10 +525,13 @@ var
nf: TsNumberFormat; nf: TsNumberFormat;
partStr: String; partStr: String;
isAMPM: Boolean; isAMPM: Boolean;
isDate: Boolean; // to distinguish whether "m" means "month" or "minute" (along with FIsTime)
P: PChar;
begin begin
done := false; done := false;
s := ''; s := '';
isAMPM := false; isAMPM := false;
isDate := false;
while (FCurrent <= FEnd) and (FStatus = psOK) and (not done) do begin while (FCurrent <= FEnd) and (FStatus = psOK) and (not done) do begin
token := FCurrent^; token := FCurrent^;
@ -535,54 +539,87 @@ begin
'\': // means that the next character is taken literally '\': // means that the next character is taken literally
begin begin
inc(FCurrent); // skip the "\"... inc(FCurrent); // skip the "\"...
token := FCurrent^; // and take the next character if FCurrent <= FEnd then begin
s := s + token; token := FCurrent^; // and take the next character
s := s + token;
end;
end; end;
'Y', 'y': 'Y', 'y':
begin begin
ScanDateTimeParts(token, token, s); ScanDateTimeParts(token, token, s);
FIsTime := false; FIsTime := false;
isDate := true;
end; end;
'M': 'm', 'M':
if FConversionDirection = cdToFPSpreadsheet then if (token = 'M') and (FConversionDirection = cdToFPSpreadsheet) then
// Uppercase "M" in Excel = "month" --> "m" in fpspreadsheet
ScanDateTimeParts(token, 'm', s) ScanDateTimeParts(token, 'm', s)
else begin else begin
if FIsTime then ScanDateTimeParts(token, 'm', s) else ScanDateTimeParts(token, 'M', s); // not clear if "m" means "month" or "minute" -> look for next symbols
if (not isDate) and (not FIsTime) then begin
P := FCurrent;
inc(P);
while (P <= FEnd) and not done do begin
token := P^;
case token of
'd','D','y','Y':
begin
isDate := true; // ok - it means "month"
FIsTime := false;
break;
end;
'h','H','s','S':
begin
isDate := false;
FIsTime := true; // ok - it means "minute"
break;
end;
else
inc(P);
end;
end;
if P > FEnd then begin
// Special case of isolated "m" --> Error
FStatus := psAmbiguousSymbol;
break;
end;
end;
if FIsTime then // is "minute"
case FConversionDirection of
cdToFPSpreadsheet : ScanDateTimeParts(token, 'n', s);
cdFromFPSpreadsheet: ScanDateTimeParts(token, 'm', s);
end
else if isDate then // is "month"
case FConversionDirection of
cdToFPSpreadsheet : ScanDateTimeParts(token, 'm', s);
cdFromFPSpreadsheet: ScanDateTimeParts(token, 'M', s);
end;
end; end;
'm':
if FConversionDirection = cdToFPSpreadsheet then
ScanDateTimeParts(token, 'n', s)
else
ScanDateTimeParts(token, 'm', s);
{
if FConversionDirection = cdToFPSpreadsheet then begin
if FIsTime then ScanDateTimeParts(token, 'n', s) else ScanDateTimeParts(token, 'm', s)
end else begin
if FIsTime then ScanDateTimeParts(token, 'm', s) else ScanDateTimeParts(token, 'M', s);
end;
}
'N', 'n': 'N', 'n':
if FConversionDirection = cdToFPSpreadsheet then begin if FConversionDirection = cdToFPSpreadsheet then begin
// "n" is not used by file format --> stop scanning date/time // "n" is not used by file format --> stop scanning date/time
done := true; done := true;
dec(FCurrent); dec(FCurrent);
end else end else
// "n", in fpc, stands for "minute". // "n", in fpc, stands for "minute". Excel wants "m"
ScanDateTimeParts(token, 'm', s); ScanDateTimeParts(token, 'm', s);
'D', 'd': 'D', 'd':
begin begin
ScanDateTimeParts(token, token, s); ScanDateTimeParts(token, token, s);
FIsTime := false; FIsTime := false;
isDate := true;
end; end;
'H', 'h': 'H', 'h':
begin begin
ScanDateTimeParts(token, token, s); ScanDateTimeParts(token, token, s);
FIsTime := true; FIsTime := true;
isDate := false;
end; end;
'S', 's': 'S', 's':
begin begin
ScanDateTimeParts(token, token, s); ScanDateTimeParts(token, token, s);
FIsTime := true; FIsTime := true;
isDate := false;
end; end;
'/', ':', '.', ']', '[', ' ': '/', ':', '.', ']', '[', ' ':
s := s + token; s := s + token;

View File

@ -1937,7 +1937,7 @@ begin
// 2 var. Number format string (Unicode string, 16-bit string length, ➜2.5.3) // 2 var. Number format string (Unicode string, 16-bit string length, ➜2.5.3)
fmtString := ReadWideString(AStream, False); fmtString := ReadWideString(AStream, False);
// Add to the list // Analyze the format string and add format to the list
NumFormatList.AnalyzeAndAdd(fmtIndex, fmtString); NumFormatList.AnalyzeAndAdd(fmtIndex, fmtString);
end; end;