fpspreadsheet: Fix defined names for ranges with several cells.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@9403 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz 2024-07-25 17:26:35 +00:00
parent 6a7f67931b
commit 52a79e952f
3 changed files with 77 additions and 31 deletions

View File

@ -19,23 +19,29 @@ begin
try
wb.Options := [boAutoCalc, boReadFormulas];
wb.ReadFromFile(fn);
ws := wb.GetFirstWorksheet;
WriteLn('FILE: ', fn, LineEnding);
wb.ReadFromFile(fn);
WriteLn('DEFINED NAMES');
WriteLn('DEFINED NAMES (GLOBAL)');
for i := 0 to wb.DefinedNames.Count-1 do
WriteLn(wb.DefinedNames[i].Name, ' --> ', wb.DefinedNames[i].RangeAsString(wb));
WriteLn(' ', wb.DefinedNames[i].Name, ' --> ', wb.DefinedNames[i].RangeAsString(wb));
WriteLn;
WriteLn('CELLS');
for cell in ws.Cells do
WriteLn('--------------------------------------------------------');
for i := 0 to wb.GetWorksheetCount - 1 do
begin
Write(GetCellString(cell^.Row, cell^.Col), ' --> ', ws.ReadAsText(cell));
if HasFormula(cell) then
Write(' (formula: ', ws.GetFormula(cell)^.Text, ')');
WriteLn;
ws := wb.GetWorksheetByIndex(i);
WriteLn('WORKSHEET "', ws.Name, '"');
WriteLn(' CELLS');
for cell in ws.Cells do
begin
Write(' ', GetCellString(cell^.Row, cell^.Col), ' --> ', ws.ReadAsText(cell));
if HasFormula(cell) then
Write(' (formula: "=', ws.GetFormula(cell)^.Text, '")');
WriteLn;
end;
WriteLn('--------------------------------------------------------');
end;
finally

View File

@ -10,7 +10,11 @@ begin
wb := TsWorkbook.Create;
try
wb.Options := [boAutoCalc];
ws := wb.AddWorksheet('Test');
{----------}
// Single cell defined names
ws := wb.AddWorksheet('Simple');
wsIdx := wb.GetWorksheetIndex(ws);
wb.DefinedNames.Add('distance', wsIdx, 1, 2);
@ -22,6 +26,29 @@ begin
wb.DefinedNames.Add('speed', wsIdx, 3, 2);
ws.WriteText(3, 1, 'speed'); ws.WriteFormula(3, 2, '=distance/time');
{----------}
// Cell range as defined name
ws := wb.AddWorksheet('Range');
wsIdx := wb.GetWorksheetIndex(ws);
ws.WriteText(0, 0, 'Data');
ws.WriteNumber(1, 0, 1.0);
ws.WriteNumber(2, 0, 2.0);
ws.WriteNumber(3, 0, 3.0);
wb.DefinedNames.Add('data', wsIdx, wsIdx, 1, 0, 3, 0);
ws.WriteFormula(4, 0, '=SUM(data)');
{----------}
// Defined name in other sheet
ws := wb.AddWorksheet('Range-2');
wb.DefinedNames.Add('data', wsIdx, wsIdx, 1, 0, 3, 0); // wsIdx refers to sheet "Range"
ws.WriteFormula(4, 0, '=SUM(data)');
{----------}
wb.WriteToFile('test_defnames.xlsx', true);
wb.WriteToFile('test_defnames.ods', true);
finally

View File

@ -3986,29 +3986,42 @@ procedure TsIdentifierExprNode.GetNodeValue(out AResult: TsExpressionResult);
var
book: TsWorkbook;
sheet: TsWorksheet;
sheetIdx1, sheetIdx2: Integer;
r1, c1, r2, c2: Cardinal;
cell: PCell;
begin
book := TsWorkbook(TsWorksheet(Parser.Worksheet).Workbook);
if PResult^.ResultType = rtCellRange then
begin
with PResult^.ResCellRange do
if (Sheet1 = Sheet2) and (Row1 = Row2) and ((Col1 = Col2) or (Col2 = Col1+1)) then
begin
book := TsWorkbook(TsWorksheet(Parser.Worksheet).Workbook);
sheet := book.GetWorksheetByIndex(Sheet1);
cell := sheet.FindCell(Row1, Col2);
if cell <> nil then
case cell^.ContentType of
cctNumber: AResult := FloatResult(cell^.NumberValue);
cctDateTime: AResult := DateTimeResult(cell^.DateTimeValue);
cctUTF8String: AResult := StringResult(cell^.UTF8StringValue);
cctBool: AResult := BooleanResult(cell^.BoolValue);
cctError: AResult := ErrorResult(cell^.ErrorValue);
cctEmpty: AResult := EmptyResult;
end
else
AResult := ErrorResult(errIllegalRef);
end else
AResult := CellRangeResult(PResult^.Worksheet, Sheet1, Sheet2, Row1, Col1, Row2, Col2);
begin
sheetIdx1 := Sheet1;
sheetIdx2 := Sheet2;
r1 := Row1;
c1 := Col1;
r2 := Row2;
c2 := Col2;
end;
if (sheetIdx1 = sheetIdx2) and (r1 = r2) and ((c1 = c2) or (c2 = c1+1)) then
begin
sheet := book.GetWorksheetByIndex(sheetIdx1);
cell := sheet.FindCell(r1, c2);
if cell <> nil then
case cell^.ContentType of
cctNumber: AResult := FloatResult(cell^.NumberValue);
cctDateTime: AResult := DateTimeResult(cell^.DateTimeValue);
cctUTF8String: AResult := StringResult(cell^.UTF8StringValue);
cctBool: AResult := BooleanResult(cell^.BoolValue);
cctError: AResult := ErrorResult(cell^.ErrorValue);
cctEmpty: AResult := EmptyResult;
end
else
AResult := ErrorResult(errIllegalRef);
end else
begin
sheet := TsWorksheet(Parser.Worksheet);
AResult := CellRangeResult(sheet, sheetIdx1, sheetIdx2, r1, c1, r2, c2);
end;
end else
begin
AResult := PResult^;