fpspreadsheet: Quote sheet names if they contain illegal characters for the expression parser.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@6607 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2018-08-17 12:00:02 +00:00
parent 4f1ce39ac9
commit f8f096dcf8
2 changed files with 48 additions and 20 deletions

View File

@ -61,7 +61,7 @@ type
ttNumber, ttString, ttIdentifier, ttSpreadsheetAddress, ttNumber, ttString, ttIdentifier, ttSpreadsheetAddress,
ttPlus, ttMinus, ttMul, ttDiv, ttConcat, ttPercent, ttPower, ttLeft, ttRight, ttPlus, ttMinus, ttMul, ttDiv, ttConcat, ttPercent, ttPower, ttLeft, ttRight,
ttLessThan, ttLargerThan, ttEqual, ttNotEqual, ttLessThanEqual, ttLargerThanEqual, ttLessThan, ttLargerThan, ttEqual, ttNotEqual, ttLessThanEqual, ttLargerThanEqual,
ttListSep, ttTrue, ttFalse, ttMissingArg, ttError, ttEOF ttListSep, ttQuote, ttTrue, ttFalse, ttMissingArg, ttError, ttEOF
); );
TsExprFloat = Double; TsExprFloat = Double;
@ -563,6 +563,7 @@ type
function GetCol: Cardinal; function GetCol: Cardinal;
function GetRow: Cardinal; function GetRow: Cardinal;
procedure GetNodeValue(out AResult: TsExpressionResult); override; procedure GetNodeValue(out AResult: TsExpressionResult); override;
function GetQuotedSheetName: String;
public public
constructor Create(AParser: TsExpressionParser; AWorksheet: TsBasicWorksheet; constructor Create(AParser: TsExpressionParser; AWorksheet: TsBasicWorksheet;
ASheetName: String; ARow, ACol: Cardinal; AFlags: TsRelFlags); ASheetName: String; ARow, ACol: Cardinal; AFlags: TsRelFlags);
@ -1110,12 +1111,15 @@ function TsExpressionScanner.DoIdentifier: TsTokenType;
var var
C: Char; C: Char;
S: String; S: String;
isQuoted: Boolean;
begin begin
C := CurrentChar; C := CurrentChar;
while (not IsWordDelim(C)) and (C <> cNULL) do isQuoted := C = '''';
while ((not IsWordDelim(C)) or IsQuoted) and (C <> cNULL) do
begin begin
FToken := FToken + C; FToken := FToken + C;
C := NextPos; C := NextPos;
if C = '''' then isQuoted := false;
end; end;
if ParseCellRangeString(FToken, FSheet1, FSheet2, if ParseCellRangeString(FToken, FSheet1, FSheet2,
@ -1311,7 +1315,7 @@ begin
Result := DoNumber Result := DoNumber
else if (C = cError) then else if (C = cError) then
Result := DoError Result := DoError
else if IsAlpha(C) or (C = '$') then else if IsAlpha(C) or (C = '$') or (C = '''') then
Result := DoIdentifier Result := DoIdentifier
else else
ScanError(Format(rsUnknownCharacter, [FPos, C])); ScanError(Format(rsUnknownCharacter, [FPos, C]));
@ -3922,17 +3926,17 @@ begin
r := Getrow; r := Getrow;
c := GetCol; c := GetCol;
if Has3dLink then if Has3dLink then begin
case FParser.Dialect of case FParser.Dialect of
fdExcelA1: fdExcelA1:
Result := Format('%s!%s', [GetSheetName, GetCellString(r, c, FFlags)]); Result := Format('%s!%s', [GetQuotedSheetName, GetCellString(r, c, FFlags)]);
fdExcelR1C1: fdExcelR1C1:
Result := Format('%s!%s', [GetSheetName, Result := Format('%s!%s', [GetQuotedSheetName,
GetCellString_R1C1(r, c, FFlags, FParser.FSourceCell^.Row, FParser.FSourceCell^.Col)]); GetCellString_R1C1(r, c, FFlags, FParser.FSourceCell^.Row, FParser.FSourceCell^.Col)]);
fdOpenDocument: fdOpenDocument:
Result := Format('[%s.%s]', [GetSheetName, GetCellString(r, c, FFlags)]); Result := Format('[%s.%s]', [GetQuotedSheetName, GetCellString(r, c, FFlags)]);
end end
else end else
case FParser.Dialect of case FParser.Dialect of
fdExcelA1: fdExcelA1:
Result := GetCellString(GetRow, GetCol, FFlags); Result := GetCellString(GetRow, GetCol, FFlags);
@ -4002,6 +4006,12 @@ begin
AResult.Worksheet := GetSheet; AResult.Worksheet := GetSheet;
end; end;
function TsCellExprNode.GetQuotedSheetName: String;
begin
Result := GetSheetName;
if SheetNameNeedsQuotes(Result) then
Result := QuotedStr(Result);
end;
{ See: GetCol } { See: GetCol }
function TsCellExprNode.GetRow: Cardinal; function TsCellExprNode.GetRow: Cardinal;
@ -4168,10 +4178,14 @@ begin
s1 := FWorksheet.Name s1 := FWorksheet.Name
else else
s1 := (Workbook as TsWorkbook).GetWorksheetByIndex(FSheetIndex[1]).Name; s1 := (Workbook as TsWorkbook).GetWorksheetByIndex(FSheetIndex[1]).Name;
if SheetNameNeedsQuotes(s1) then s1 := QuotedStr(s1);
if FSheetIndex[2] = -1 then if FSheetIndex[2] = -1 then
s2 := FWorksheet.Name s2 := FWorksheet.Name
else else
s2 := (Workbook as TsWorkbook).GetWorksheetByIndex(FSheetIndex[2]).Name; s2 := (Workbook as TsWorkbook).GetWorksheetByIndex(FSheetIndex[2]).Name;
if SheetNameNeedsQuotes(s2) then s2 := QuotedStr(s2);
r1 := GetRow(1); r1 := GetRow(1);
c1 := GetCol(1); c1 := GetCol(1);
r2 := GetRow(2); r2 := GetRow(2);

View File

@ -112,7 +112,9 @@ function GetCellRangeString_R1C1(ASheet1, ASheet2: String;
ARow1, ACol1, ARow2, ACol2: Cardinal; AFlags: TsRelFlags = [rfRelRow, rfRelCol]; ARow1, ACol1, ARow2, ACol2: Cardinal; AFlags: TsRelFlags = [rfRelRow, rfRelCol];
ARefRow: Cardinal = Cardinal(-1); ARefCol: Cardinal = Cardinal(-1)): String; overload; ARefRow: Cardinal = Cardinal(-1); ARefCol: Cardinal = Cardinal(-1)): String; overload;
// OpenDocument Syntax function SheetNameNeedsQuotes(ASheet: String): Boolean;
// OpenDocument Syntax
function GetCellRangeString_ODS(ASheet1, ASheet2: String; ARow1, ACol1, ARow2, ACol2: Cardinal; function GetCellRangeString_ODS(ASheet1, ASheet2: String; ARow1, ACol1, ARow2, ACol2: Cardinal;
AFlags: TsRelFlags = rfAllRel): String; overload; AFlags: TsRelFlags = rfAllRel): String; overload;
function GetCellRangeString_ODS(ARow1, ACol1, ARow2, ACol2: Cardinal; function GetCellRangeString_ODS(ARow1, ACol1, ARow2, ACol2: Cardinal;
@ -944,10 +946,10 @@ begin
s2 := Copy(AStr, p+1, MaxInt); s2 := Copy(AStr, p+1, MaxInt);
p := pos(':', s1); p := pos(':', s1);
if p = 0 then if p = 0 then
ASheet1 := s1 ASheet1 := UnquoteStr(s1)
else begin else begin
ASheet1 := copy(s1, 1, p-1); ASheet1 := UnquoteStr(copy(s1, 1, p-1));
ASheet2 := copy(s1, p+1, MaxInt); ASheet2 := UnquoteStr(copy(s1, p+1, MaxInt));
end; end;
end; end;
@ -1162,20 +1164,32 @@ begin
]); ]);
end; end;
function SheetNameNeedsQuotes(ASheet: String): Boolean;
begin
if ASheet <> '' then begin
Result := true;
if (ASheet[1] in ['0'..'9', '.']) then exit;
if (pos(' ', ASheet) > 0) then exit;
end;
Result := false;
end;
function GetCellRangeString(ASheet1, ASheet2: String; ARow1, ACol1, ARow2, ACol2: Cardinal; function GetCellRangeString(ASheet1, ASheet2: String; ARow1, ACol1, ARow2, ACol2: Cardinal;
AFlags: TsRelFlags = rfAllRel; Compact: Boolean = false): String; AFlags: TsRelFlags = rfAllRel; Compact: Boolean = false): String;
var
s: String;
begin begin
s := GetCellRangeString(ARow1, ACol1, ARow2, ACol2, AFlags, Compact); Result := GetCellRangeString(ARow1, ACol1, ARow2, ACol2, AFlags, Compact);
if (ASheet1 = '') and (ASheet2 = '') then if (ASheet1 = '') and (ASheet2 = '') then
Result := s exit;
else if ASheet2 = '' then
Result := Format('%s!%s', [ASheet1, s]) if SheetNameNeedsQuotes(ASheet1) then ASheet1 := QuotedStr(ASheet1);
if SheetNameNeedsQuotes(ASheet2) then ASheet2 := QuotedStr(ASheet2);
if ASheet2 = '' then
Result := Format('%s!%s', [ASheet1, Result])
else if Compact and (ASheet1 = ASheet2) then else if Compact and (ASheet1 = ASheet2) then
Result := Format('%s!%s', [ASheet1, s]) Result := Format('%s!%s', [ASheet1, Result])
else else
Result := Format('%s:%s!%s', [ASheet1, ASheet2, s]); Result := Format('%s:%s!%s', [ASheet1, ASheet2, Result]);
end; end;