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

View File

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