fpspreadsheet: Fix reading of defined names in ods (use correct xml attributes)
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@9410 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
parent
12ee2c0b1b
commit
0269bdceff
@ -1,5 +1,4 @@
|
||||
program demo_read_definednames;
|
||||
{$DEFINE ODS}
|
||||
uses
|
||||
SysUtils, fpspreadsheet, fpsTypes, fpsClasses, fpsUtils, fpsAllFormats;
|
||||
var
|
||||
@ -8,14 +7,17 @@ var
|
||||
cell: PCell;
|
||||
i, j: Integer;
|
||||
fn: String;
|
||||
fmt: TsSpreadsheetFormat = sfOpendocument;
|
||||
// fmt: TsSpreadsheetFormat = xlsxOOXML;
|
||||
begin
|
||||
{$IFDEF ODS}
|
||||
fn := 'test_defnames.ods';
|
||||
{$ELSE}
|
||||
fn := 'test_defnames.xlsx';
|
||||
{$ENDIF}
|
||||
|
||||
fn := 'Mappe2.ods';
|
||||
fn := 'test_defnames';
|
||||
fn := 'Mappe_illegalRef';
|
||||
fn := 'Mappe3';
|
||||
case fmt of
|
||||
sfOpenDocument: fn := fn + '.ods';
|
||||
sfOOXML: fn := fn + '.xlsx';
|
||||
else raise Exception.Create('Format not supported:');
|
||||
end;
|
||||
|
||||
wb := TsWorkbook.Create;
|
||||
try
|
||||
@ -28,9 +30,9 @@ begin
|
||||
for i := 0 to wb.DefinedNames.Count-1 do
|
||||
begin
|
||||
Write(' "', wb.DefinedNames[i].Name, '" --> ');
|
||||
case ExtractFileExt(fn) of
|
||||
'.xlsx': WriteLn(wb.DefinedNames[i].RangeAsString(wb));
|
||||
'.ods': WriteLn(wb.DefinedNames[i].RangeAsString_ODS(wb));
|
||||
case fmt of
|
||||
sfOOXML: WriteLn(wb.DefinedNames[i].RangeAsString(wb));
|
||||
sfOpenDocument: WriteLn(wb.DefinedNames[i].RangeAsString_ODS(wb));
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -68,6 +68,17 @@ begin
|
||||
|
||||
{----------}
|
||||
|
||||
// Defined name with illegal reference
|
||||
ws := wb.AddWorksheet('Illegal Ref');
|
||||
wsIdx1 := wb.GetWorksheetIndex(ws);
|
||||
ws.WriteText(0, 0, 'aaa');
|
||||
ws.WriteNumber(1, 0, 123);
|
||||
ws.DefinedNames.Add('aaa', wsIdx1, wsIdx1, 1,0, 1,0);
|
||||
ws.DeleteRow(1); // Delete the named cell --> should be #REF! now.
|
||||
ws.WriteFormula(2, 0, '=aaa'); // Should be #REF!
|
||||
|
||||
{----------}
|
||||
|
||||
wb.WriteToFile('test_defnames.xlsx', true);
|
||||
wb.WriteToFile('test_defnames.ods', true);
|
||||
finally
|
||||
|
@ -1886,13 +1886,14 @@ begin
|
||||
sh1 := book.GetWorksheetByIndex(Sheet1);
|
||||
if IllegalRef then
|
||||
begin
|
||||
Result := Format('$%s!%s', [sh1.Name, STR_ERR_ILLEGAL_REF]); // Is '!' correct?
|
||||
Result := Format('$%s.%s', [sh1.Name, STR_ERR_ILLEGAL_REF]); // Is '!' correct?
|
||||
exit;
|
||||
end;
|
||||
Result := Format('$%s.%s', [sh1.Name, GetCellString(Row1, Col1, [])]);
|
||||
if (Sheet1 <> Sheet2) or (Row1 <> Row2) or (Col1 <> Col2) then
|
||||
begin
|
||||
sh2 := book.GetWorksheetByIndex(Sheet2);
|
||||
if sh2 = nil then sh2 := sh1;
|
||||
Result := Format('%s:$%s.%s', [Result, sh2.Name, GetCellString(Row2, Col2, [])]);
|
||||
end;
|
||||
end;
|
||||
|
@ -2643,12 +2643,23 @@ var
|
||||
defName: String;
|
||||
defAddr: String;
|
||||
defExpr: String;
|
||||
defBaseAddr: String;
|
||||
r1, c1, r2, c2: Cardinal;
|
||||
sheetName1, sheetName2: String;
|
||||
sheetIdx1, sheetIdx2: Integer;
|
||||
sheetIdx1, sheetIdx2, p: Integer;
|
||||
flags: TsRelFlags;
|
||||
err: TsErrorValue;
|
||||
isDefName: Boolean;
|
||||
|
||||
procedure ErrorRange(ASheetName: String);
|
||||
begin
|
||||
sheetName1 := ASheetName;
|
||||
sheetName2 := ASheetName;
|
||||
r1 := UNASSIGNED_ROW_COL_INDEX;
|
||||
c1 := UNASSIGNED_ROW_COL_INDEX;
|
||||
r2 := UNASSIGNED_ROW_COL_INDEX;
|
||||
c2 := UNASSIGNED_ROW_COL_INDEX;
|
||||
end;
|
||||
|
||||
begin
|
||||
if ANode = nil then
|
||||
exit;
|
||||
@ -2663,37 +2674,43 @@ begin
|
||||
while ANode <> nil do
|
||||
begin
|
||||
nodeName := ANode.NodeName;
|
||||
if nodeName = 'table:named-expression' then
|
||||
if (nodeName = 'table:named-range') or (nodeName = 'table:named-expression') then
|
||||
begin
|
||||
defName := GetAttrValue(ANode, 'table:name');
|
||||
defAddr := GetAttrValue(ANode, 'table:cell-range-address');
|
||||
defBaseAddr := GetAttrValue(ANode, 'table:base-cell-address');
|
||||
defExpr := GetAttrValue(ANode, 'table:expression');
|
||||
if TryStrToErrorValue(defExpr, '!', sheetName1, err) then // not clear whether '!' is correct; test file was created from Excel
|
||||
if TryStrToErrorValue(defAddr, err) and (err <> errOK) then
|
||||
begin
|
||||
r1 := UNASSIGNED_ROW_COL_INDEX;
|
||||
c1 := UNASSIGNED_ROW_COL_INDEX;
|
||||
r2 := UNASSIGNED_ROW_COL_INDEX;
|
||||
c2 := UNASSIGNED_ROW_COL_INDEX;
|
||||
sheetName2 := sheetName1;
|
||||
isDefName := true;
|
||||
p := pos('.', defBaseAddr);
|
||||
if p > 0 then
|
||||
sheetName1 := Copy(defBaseAddr, 1, p-1)
|
||||
else
|
||||
sheetName1 := book.GetFirstWorksheet.Name;
|
||||
ErrorRange(sheetName1);
|
||||
end else
|
||||
if (TryStrToErrorValue(defExpr, '!', sheetName1, err) or
|
||||
TryStrToErrorValue(defExpr, '.', sheetName2, err)) and
|
||||
(err <> errOK) then // not clear whether '!' is correct; test file was created from Excel
|
||||
begin
|
||||
ErrorRange(sheetName1);
|
||||
end else
|
||||
if TryStrToCellRange_ODS(defAddr, sheetName1, sheetName2, r1, c1, r2, c2, flags) then
|
||||
isDefName := true
|
||||
else
|
||||
isDefName := false;
|
||||
if isDefName then
|
||||
begin
|
||||
if (sheetName1 <> '') and (sheetName1[1] = '$') then Delete(sheetName1, 1,1);
|
||||
if (sheetName2 <> '') and (sheetName2[1] = '$') then Delete(sheetName2, 1,1);
|
||||
sheetIdx1 := book.GetWorksheetIndex(sheetName1);
|
||||
sheetIdx2 := book.GetWorksheetIndex(sheetName2);
|
||||
if AWorksheet = nil then
|
||||
// global defined names
|
||||
book.DefinedNames.Add(defName, sheetIdx1, sheetIdx2, r1, c1, r2, c2)
|
||||
else
|
||||
// local defined names
|
||||
TsWorksheet(AWorksheet).DefinedNames.Add(defName, sheetIdx1, sheetIdx2, r1, c1, r2, c2);
|
||||
end;
|
||||
;
|
||||
end else
|
||||
Continue;
|
||||
|
||||
if (sheetName1 <> '') and (sheetName1[1] = '$') then Delete(sheetName1, 1,1);
|
||||
if (sheetName2 <> '') and (sheetName2[1] = '$') then Delete(sheetName2, 1,1);
|
||||
sheetIdx1 := book.GetWorksheetIndex(sheetName1);
|
||||
sheetIdx2 := book.GetWorksheetIndex(sheetName2);
|
||||
if AWorksheet = nil then
|
||||
// global defined names
|
||||
book.DefinedNames.Add(defName, sheetIdx1, sheetIdx2, r1, c1, r2, c2)
|
||||
else
|
||||
// local defined names
|
||||
TsWorksheet(AWorksheet).DefinedNames.Add(defName, sheetIdx1, sheetIdx2, r1, c1, r2, c2);
|
||||
end;
|
||||
ANode := ANode.NextSibling;
|
||||
end;
|
||||
@ -8813,13 +8830,22 @@ begin
|
||||
sheet1 := book.GetWorksheetByIndex(ADefinedName.Range.Sheet1);
|
||||
sheet2 := book.GetWorksheetByIndex(ADefinedName.Range.Sheet2);
|
||||
|
||||
Result := Format(
|
||||
'<table:named-range ' +
|
||||
'table:name="%s" ' +
|
||||
'table:base-cell-address="$%s.$A$1" ' +
|
||||
'table:cell-range-address="%s" />',
|
||||
[ ADefinedName.Name, sheet1.Name, ADefinedName.RangeAsString_ODS(FWorkbook) ]
|
||||
);
|
||||
if ADefinedName.IllegalRef then
|
||||
Result := Format(
|
||||
'<table:named-expression '+
|
||||
'table:name="%s" ' +
|
||||
// 'table:base-cell-address="$%s.$A$1" ' +
|
||||
'table:expression="$%s.#REF!" />',
|
||||
[ ADefinedName.Name, {sheet1.Name, }sheet1.Name ]
|
||||
)
|
||||
else
|
||||
Result := Format(
|
||||
'<table:named-range ' +
|
||||
'table:name="%s" ' +
|
||||
// 'table:base-cell-address="$%s.$A$1" ' + // needed when we support relative defined names.
|
||||
'table:cell-range-address="%s" />',
|
||||
[ ADefinedName.Name, {sheet1.Name, }ADefinedName.RangeAsString_ODS(FWorkbook) ]
|
||||
);
|
||||
end;
|
||||
|
||||
procedure TsSpreadOpenDocWriter.WriteError(AStream: TStream;
|
||||
|
@ -1365,6 +1365,8 @@ begin
|
||||
begin
|
||||
cell1str := Copy(AStr, 1, p-1);
|
||||
cell2Str := Copy(AStr, p+1, MaxInt);
|
||||
if (cell2Str <> '') and (cell2Str[1] = '.') then
|
||||
System.Delete(cell2str, 1, 1);
|
||||
end;
|
||||
|
||||
p := pos('.', cell1Str);
|
||||
@ -3022,7 +3024,7 @@ function Range3D(ASheetIdx1, ASheetIdx2: Integer;
|
||||
var
|
||||
rng: TsCellRange;
|
||||
begin
|
||||
rng := Range(ARow1, ACol1, ARow2, ACol2);
|
||||
rng := Range(ARow1, ACol1, ARow2, ACol2); // Make sure that the indices are ordered.
|
||||
Result.Row1 := rng.Row1;
|
||||
Result.Col1 := rng.Col1;
|
||||
Result.Row2 := rng.Row2;
|
||||
|
Loading…
Reference in New Issue
Block a user