fpspreadsheet: Add support for xlsx files written by OpenXML (using namespace x) - see forum https://forum.lazarus.freepascal.org/index.php?topic=43159.msg301884).

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@6726 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2018-11-12 23:34:56 +00:00
parent d5d6a6fae9
commit d8735a174e
3 changed files with 116 additions and 85 deletions

View File

@ -131,7 +131,8 @@ begin
while (not complete) and (not Matches(AWorksheet, ARow, ACol)) do while (not complete) and (not Matches(AWorksheet, ARow, ACol)) do
begin begin
if soBackward in FSearchParams.Options then if soBackward in FSearchParams.Options then
complete := not GotoPrev(AWorkSheet, ARow, ACol) else complete := not GotoPrev(AWorkSheet, ARow, ACol)
else
complete := not GotoNext(AWorkSheet, ARow, ACol); complete := not GotoNext(AWorkSheet, ARow, ACol);
// Avoid infinite loop if search phrase does not exist in document. // Avoid infinite loop if search phrase does not exist in document.
if (AWorksheet = sheet) and (ARow = r) and (ACol = c) then if (AWorksheet = sheet) and (ARow = r) and (ACol = c) then

View File

@ -859,13 +859,14 @@ type
TsSearchOptions = set of TsSearchOption; TsSearchOptions = set of TsSearchOption;
{@@ Defines which part of document is scanned } {@@ Defines which part of document is scanned }
TsSearchWithin = (swWorkbook, swWorksheet, swColumn, swRow); TsSearchWithin = (swWorkbook, swWorksheet, swColumn, swRow, swColumns, swRows);
{@@ Search parameters } {@@ Search parameters }
TsSearchParams = record TsSearchParams = record
SearchText: String; SearchText: String;
Options: TsSearchOptions; Options: TsSearchOptions;
Within: TsSearchWithin; Within: TsSearchWithin;
ColsRows: String;
end; end;
{@@ Replace option } {@@ Replace option }

View File

@ -512,11 +512,15 @@ procedure TsSpreadOOXMLReader.ReadActiveSheet(ANode: TDOMNode;
var var
S: string; S: string;
i: Integer; i: Integer;
node: TDOMNode;
begin begin
ActiveSheetIndex := -1; ActiveSheetIndex := -1;
if ANode = nil then if ANode = nil then
Exit; Exit;
S := GetAttrValue(ANode.FindNode('workbookView'), 'activeTab'); node := ANode.FindNode('workbookView');
if node = nil then
node := ANode.FindNode('x:workbookView');
S := GetAttrValue(node, 'activeTab');
if TryStrToInt(S, i) then if TryStrToInt(S, i) then
ActiveSheetIndex := i; ActiveSheetIndex := i;
end; end;
@ -568,7 +572,7 @@ procedure TsSpreadOOXMLReader.ReadBorders(ANode: TDOMNode);
colorNode := ANode.FirstChild; colorNode := ANode.FirstChild;
while Assigned(colorNode) do begin while Assigned(colorNode) do begin
nodeName := colorNode.NodeName; nodeName := colorNode.NodeName;
if nodeName = 'color' then if (nodeName = 'color') or (nodename = 'x:color') then
ABorderStyle.Color := ReadColor(colorNode); ABorderStyle.Color := ReadColor(colorNode);
colorNode := colorNode.NextSibling; colorNode := colorNode.NextSibling;
end; end;
@ -592,7 +596,7 @@ begin
borderNode := ANode.FirstChild; borderNode := ANode.FirstChild;
while Assigned(borderNode) do begin while Assigned(borderNode) do begin
nodeName := borderNode.NodeName; nodeName := borderNode.NodeName;
if nodeName = 'border' then begin if (nodeName = 'border') or (nodeName = 'x:border') then begin
borders := []; borders := [];
s := GetAttrValue(borderNode, 'diagonalUp'); s := GetAttrValue(borderNode, 'diagonalUp');
if strIsTrue(s) then if strIsTrue(s) then
@ -603,23 +607,23 @@ begin
edgeNode := borderNode.FirstChild; edgeNode := borderNode.FirstChild;
while Assigned(edgeNode) do begin while Assigned(edgeNode) do begin
nodeName := edgeNode.NodeName; nodeName := edgeNode.NodeName;
if nodeName = 'left' then begin if (nodeName = 'left') or (nodeName = 'x:left') then begin
if ReadBorderStyle(edgeNode, borderStyles[cbWest]) then if ReadBorderStyle(edgeNode, borderStyles[cbWest]) then
Include(borders, cbWest); Include(borders, cbWest);
end end
else if nodeName = 'right' then begin else if (nodeName = 'right') or (nodeName = 'x:right') then begin
if ReadBorderStyle(edgeNode, borderStyles[cbEast]) then if ReadBorderStyle(edgeNode, borderStyles[cbEast]) then
Include(borders, cbEast); Include(borders, cbEast);
end end
else if nodeName = 'top' then begin else if (nodeName = 'top') or (nodeName = 'x:top') then begin
if ReadBorderStyle(edgeNode, borderStyles[cbNorth]) then if ReadBorderStyle(edgeNode, borderStyles[cbNorth]) then
Include(borders, cbNorth); Include(borders, cbNorth);
end end
else if nodeName = 'bottom' then begin else if (nodeName = 'bottom') or (nodename = 'x:bottom') then begin
if ReadBorderStyle(edgeNode, borderStyles[cbSouth]) then if ReadBorderStyle(edgeNode, borderStyles[cbSouth]) then
Include(borders, cbSouth); Include(borders, cbSouth);
end end
else if nodeName = 'diagonal' then begin else if (nodeName = 'diagonal') or (nodeName = 'x:diagonal') then begin
if ReadBorderStyle(edgeNode, borderStyles[cbDiagUp]) then if ReadBorderStyle(edgeNode, borderStyles[cbDiagUp]) then
borderStyles[cbDiagDown] := borderStyles[cbDiagUp]; borderStyles[cbDiagDown] := borderStyles[cbDiagUp];
end; end;
@ -697,20 +701,20 @@ begin
while Assigned(datanode) do while Assigned(datanode) do
begin begin
nodeName := datanode.NodeName; nodeName := datanode.NodeName;
if nodeName = 'v' then if (nodeName = 'v') or (nodeName = 'x:v') then
dataStr := GetNodeValue(datanode) dataStr := GetNodeValue(datanode)
else else
if nodeName = 'is' then if (nodeName = 'is') or (nodeName = 'x:is') then
begin begin
tnode := datanode.FirstChild; tnode := datanode.FirstChild;
while Assigned(tnode) do begin while Assigned(tnode) do begin
nodename := tnode.NodeName; nodename := tnode.NodeName;
if nodename = 't' then if (nodename = 't') or (nodeName = 'x:t') then
dataStr := dataStr + GetNodeValue(tnode); dataStr := dataStr + GetNodeValue(tnode);
tnode := tnode.NextSibling; tnode := tnode.NextSibling;
end; end;
end; end;
if (boReadFormulas in book.Options) and (nodeName = 'f') then if (boReadFormulas in book.Options) and ((nodeName = 'f') or (nodeName = 'x:f'))then
begin begin
// Formula to cell // Formula to cell
formulaStr := GetNodeValue(datanode); formulaStr := GetNodeValue(datanode);
@ -861,13 +865,16 @@ var
cp: TsCellProtections; cp: TsCellProtections;
book: TsWorkbook; book: TsWorkbook;
begin begin
if ANode = nil then
exit;
book := FWorkbook as TsWorkbook; book := FWorkbook as TsWorkbook;
node := ANode.FirstChild; node := ANode.FirstChild;
while Assigned(node) do while Assigned(node) do
begin begin
nodeName := node.NodeName; nodeName := node.NodeName;
if nodeName = 'xf' then if (nodeName = 'xf') or (nodeName = 'x:xf') then
begin begin
InitFormatRecord(fmt); InitFormatRecord(fmt);
fmt.ID := FCellFormatList.Count; fmt.ID := FCellFormatList.Count;
@ -951,7 +958,7 @@ begin
childNode := node.FirstChild; childNode := node.FirstChild;
while Assigned(childNode) do begin while Assigned(childNode) do begin
nodeName := childNode.NodeName; nodeName := childNode.NodeName;
if nodeName = 'alignment' then begin if (nodeName = 'alignment') or (nodeName = 'x:alignment') then begin
s1 := GetAttrValue(childNode, 'horizontal'); s1 := GetAttrValue(childNode, 'horizontal');
if s1 = 'left' then if s1 = 'left' then
fmt.HorAlignment := haLeft fmt.HorAlignment := haLeft
@ -1004,7 +1011,7 @@ begin
childNode := node.FirstChild; childNode := node.FirstChild;
while Assigned(childNode) do begin while Assigned(childNode) do begin
nodeName := childNode.NodeName; nodeName := childNode.NodeName;
if nodeName = 'protection' then if (nodeName = 'protection') or (nodeName = 'x:protection') then
begin begin
s1 := GetAttrValue(childNode, 'locked'); s1 := GetAttrValue(childNode, 'locked');
if StrIsFalse(s1) then if StrIsFalse(s1) then
@ -1045,12 +1052,14 @@ var
idx: Integer; idx: Integer;
tint: Double; tint: Double;
n, i: Integer; n, i: Integer;
nodename: String;
begin begin
Assert(ANode <> nil); Assert(ANode <> nil);
s := Lowercase(GetAttrValue(ANode, 'auto')); s := Lowercase(GetAttrValue(ANode, 'auto'));
if (s = '1') or (s = 'true') then begin if (s = '1') or (s = 'true') then begin
if ANode.NodeName = 'fgColor' then nodename := ANode.NodeName;
if (nodeName = 'fgColor') or (nodename = 'x:fgColor') then
Result := scBlack Result := scBlack
else else
Result := scTransparent; Result := scTransparent;
@ -1139,7 +1148,7 @@ begin
colNode := ANode.FirstChild; colNode := ANode.FirstChild;
while Assigned(colNode) do begin while Assigned(colNode) do begin
nodeName := colNode.NodeName; nodeName := colNode.NodeName;
if nodename = 'col' then if (nodename = 'col') or (nodeName = 'x:col') then
begin begin
s := GetAttrValue(colNode, 'min'); s := GetAttrValue(colNode, 'min');
if s <> '' then col1 := StrToInt(s)-1 else col1 := 0; if s <> '' then col1 := StrToInt(s)-1 else col1 := 0;
@ -1212,7 +1221,7 @@ begin
rchild := rNode.FirstChild; rchild := rNode.FirstChild;
while rchild <> nil do begin while rchild <> nil do begin
nodename := rchild.NodeName; nodename := rchild.NodeName;
if nodename = 't' then begin if (nodename = 't') or (nodename = 'x:t') then begin
s := GetNodeValue(rchild); s := GetNodeValue(rchild);
if comment = '' then comment := s else comment := comment + s; if comment = '' then comment := s else comment := comment + s;
end; end;
@ -1260,7 +1269,7 @@ begin
node := ANode.FirstChild; node := ANode.FirstChild;
while node <> nil do begin while node <> nil do begin
nodename := node.NodeName; nodename := node.NodeName;
if nodename = 'definedName' then if (nodename = 'definedName') or (nodename = 'x:definedName') then
begin begin
localSheetID := GetAttrValue(node, 'localSheetId'); localSheetID := GetAttrValue(node, 'localSheetId');
if (localSheetID = '') or not TryStrToInt(localSheetID, id) then if (localSheetID = '') or not TryStrToInt(localSheetID, id) then
@ -1380,17 +1389,17 @@ begin
patternNode := fillNode.FirstChild; patternNode := fillNode.FirstChild;
while Assigned(patternNode) do begin while Assigned(patternNode) do begin
nodename := patternNode.NodeName; nodename := patternNode.NodeName;
if nodename = 'patternFill' then begin if (nodename = 'patternFill') or (nodename = 'x:patternFill') then begin
patt := GetAttrValue(patternNode, 'patternType'); patt := GetAttrValue(patternNode, 'patternType');
fgclr := scWhite; fgclr := scWhite;
bgclr := scBlack; bgclr := scBlack;
colorNode := patternNode.FirstChild; colorNode := patternNode.FirstChild;
while Assigned(colorNode) do begin while Assigned(colorNode) do begin
nodeName := colorNode.NodeName; nodeName := colorNode.NodeName;
if nodeName = 'fgColor' then if (nodeName = 'fgColor') or (nodeName = 'x:fgColor')then
fgclr := ReadColor(colorNode) fgclr := ReadColor(colorNode)
else else
if nodeName = 'bgColor' then if (nodeName = 'bgColor') or (nodeName = 'x:bgColor') then
bgclr := ReadColor(colorNode); bgclr := ReadColor(colorNode);
colorNode := colorNode.NextSibling; colorNode := colorNode.NextSibling;
end; end;
@ -1402,7 +1411,7 @@ begin
fillData.BgColor := bgclr; fillData.BgColor := bgclr;
FFillList.Add(fillData); FFillList.Add(fillData);
end else end else
if nodeName = 'gradientFill' then if (nodeName = 'gradientFill') or (nodeName = 'x:gradientFill') then
begin begin
// We do not support gradient fills yet. As a replacement, we read // We do not support gradient fills yet. As a replacement, we read
// the first color of the gradient and use it for a solid fill // the first color of the gradient and use it for a solid fill
@ -1410,11 +1419,11 @@ begin
stopNode := patternNode.FirstChild; stopNode := patternNode.FirstChild;
while Assigned(stopNode) do begin while Assigned(stopNode) do begin
nodeName := stopNode.NodeName; nodeName := stopNode.NodeName;
if nodeName = 'stop' then begin if (nodeName = 'stop') or (nodeName = 'x:stop') then begin
colorNode := stopNode.FirstChild; colorNode := stopNode.FirstChild;
while Assigned(colorNode) do begin while Assigned(colorNode) do begin
nodeName := colorNode.NodeName; nodeName := colorNode.NodeName;
if nodeName = 'color' then if (nodeName = 'color') or (nodeName = 'x:color') then
begin begin
bgclr := ReadColor(colorNode); bgclr := ReadColor(colorNode);
fgclr := bgclr; fgclr := bgclr;
@ -1490,48 +1499,49 @@ begin
while node <> nil do while node <> nil do
begin begin
nodename := node.NodeName; nodename := node.NodeName;
if (nodename = 'name') or (nodename = 'rFont') then if (nodename = 'name') or (nodename = 'x:name') or
(nodename = 'rFont') or (nodename = 'x:rFont') then
begin begin
s := GetAttrValue(node, 'val'); s := GetAttrValue(node, 'val');
if s <> '' then fntName := s; if s <> '' then fntName := s;
if nodename = 'rFont' then acceptDuplicates := false; if (nodename = 'rFont') or (nodename = 'x:rFont') then acceptDuplicates := false;
end end
else else
if nodename = 'sz' then if (nodename = 'sz') or (nodeName = 'x:sz') then
begin begin
s := GetAttrValue(node, 'val'); s := GetAttrValue(node, 'val');
if s <> '' then fntSize := StrToFloat(s, FPointSeparatorSettings); if s <> '' then fntSize := StrToFloat(s, FPointSeparatorSettings);
end end
else else
if nodename = 'b' then if (nodename = 'b') or (nodename = 'x:b') then
begin begin
s := GetAttrValue(node, 'val'); s := GetAttrValue(node, 'val');
if (s = '') or StrIsTrue(s) then // if GetAttrValue(node, 'val') <> 'false' then if (s = '') or StrIsTrue(s) then // if GetAttrValue(node, 'val') <> 'false' then
fntStyles := fntStyles + [fssBold]; fntStyles := fntStyles + [fssBold];
end end
else else
if nodename = 'i' then if (nodename = 'i') or (nodename = 'x:i') then
begin begin
s := GetAttrValue(node, 'val'); s := GetAttrValue(node, 'val');
if (s = '') or StrIsTrue(s) then // if GetAttrValue(node, 'val') <> 'false' then if (s = '') or StrIsTrue(s) then // if GetAttrValue(node, 'val') <> 'false' then
fntStyles := fntStyles + [fssItalic]; fntStyles := fntStyles + [fssItalic];
end end
else else
if nodename = 'u' then if (nodename = 'u') or (nodename = 'x:u') then
begin begin
s := GetAttrValue(node, 'val'); s := GetAttrValue(node, 'val');
if not StrIsFalse(s) then // can have many values, not just booleans if not StrIsFalse(s) then // can have many values, not just booleans
fntStyles := fntStyles+ [fssUnderline] fntStyles := fntStyles+ [fssUnderline]
end end
else else
if nodename = 'strike' then if (nodename = 'strike') or (nodename = 'x:strike') then
begin begin
s := GetAttrValue(node, 'val'); s := GetAttrValue(node, 'val');
if not StrIsFalse(s) then // can have several values, not just booleans if not StrIsFalse(s) then // can have several values, not just booleans
fntStyles := fntStyles + [fssStrikeout]; fntStyles := fntStyles + [fssStrikeout];
end end
else else
if nodename = 'vertAlign' then if (nodename = 'vertAlign') or (nodename = 'x:vertAlign') then
begin begin
s := GetAttrValue(node, 'val'); s := GetAttrValue(node, 'val');
if s = 'superscript' then if s = 'superscript' then
@ -1543,7 +1553,7 @@ begin
fntPos := fpNormal; fntPos := fpNormal;
end end
else else
if nodename = 'color' then if (nodename = 'color') or (nodename = 'x:color') then
fntColor := ReadColor(node); fntColor := ReadColor(node);
node := node.NextSibling; node := node.NextSibling;
end; end;
@ -1585,6 +1595,9 @@ procedure TsSpreadOOXMLReader.ReadFonts(ANode: TDOMNode);
var var
node: TDOMNode; node: TDOMNode;
begin begin
if ANode = nil then
exit;
node := ANode.FirstChild; node := ANode.FirstChild;
while node <> nil do begin while node <> nil do begin
ReadFont(node); ReadFont(node);
@ -1621,6 +1634,7 @@ begin
while node <> nil do while node <> nil do
begin begin
nodeName := node.NodeName; nodeName := node.NodeName;
if pos('x:', nodename) = 1 then Delete(nodeName, 1, 2);
case nodeName of case nodeName of
'firstHeader': sheet.PageLayout.Headers[0] := FixLineEnding(GetNodeValue(node)); 'firstHeader': sheet.PageLayout.Headers[0] := FixLineEnding(GetNodeValue(node));
'oddHeader' : sheet.PageLayout.Headers[1] := FixLineEnding(GetNodeValue(node)); 'oddHeader' : sheet.PageLayout.Headers[1] := FixLineEnding(GetNodeValue(node));
@ -1655,13 +1669,13 @@ var
begin begin
if Assigned(ANode) then begin if Assigned(ANode) then begin
nodename := ANode.NodeName; nodename := ANode.NodeName;
if nodename = 'hyperlinks' then if (nodename = 'hyperlinks') or (nodename = 'x:hyperlinks') then
begin begin
node := ANode.FirstChild; node := ANode.FirstChild;
while Assigned(node) do while Assigned(node) do
begin begin
nodename := node.NodeName; nodename := node.NodeName;
if nodename = 'hyperlink' then begin if (nodename = 'hyperlink') or (nodename = 'x:hyperlink') then begin
hyperlinkData := THyperlinkListData.Create; hyperlinkData := THyperlinkListData.Create;
hyperlinkData.CellRef := GetAttrValue(node, 'ref'); hyperlinkData.CellRef := GetAttrValue(node, 'ref');
hyperlinkData.ID := GetAttrValue(node, 'r:id'); hyperlinkData.ID := GetAttrValue(node, 'r:id');
@ -1674,13 +1688,13 @@ begin
node := node.NextSibling; node := node.NextSibling;
end; end;
end else end else
if nodename = 'Relationship' then if (nodename = 'Relationship') or (nodename = 'x:Relationship') then
begin begin
node := ANode; node := ANode;
while Assigned(node) do while Assigned(node) do
begin begin
nodename := node.NodeName; nodename := node.NodeName;
if nodename = 'Relationship' then if (nodename = 'Relationship') or (nodename = 'x:Relationship') then
begin begin
s := GetAttrValue(node, 'Type'); s := GetAttrValue(node, 'Type');
if s = SCHEMAS_HYPERLINK then if s = SCHEMAS_HYPERLINK then
@ -1720,7 +1734,7 @@ begin
while Assigned(node) do while Assigned(node) do
begin begin
nodename := node.NodeName; nodename := node.NodeName;
if nodename = 'mergeCell' then begin if (nodename = 'mergeCell') or (nodename = 'x:mergeCell') then begin
s := GetAttrValue(node, 'ref'); s := GetAttrValue(node, 'ref');
if s <> '' then if s <> '' then
(AWorksheet as TsWorksheet).MergeCells(s); (AWorksheet as TsWorksheet).MergeCells(s);
@ -1744,7 +1758,7 @@ begin
while Assigned(node) do while Assigned(node) do
begin begin
nodeName := node.NodeName; nodeName := node.NodeName;
if nodeName = 'numFmt' then if (nodeName = 'numFmt') or (nodeName = 'x:numFmt') then
begin begin
fmtStr := GetAttrValue(node, 'formatCode'); fmtStr := GetAttrValue(node, 'formatCode');
idStr := GetAttrValue(node, 'numFmtId'); idStr := GetAttrValue(node, 'numFmtId');
@ -1891,13 +1905,13 @@ begin
while Assigned(node) do while Assigned(node) do
begin begin
nodename := node.NodeName; nodename := node.NodeName;
if nodename = 'indexedColors' then if (nodename = 'indexedColors') or (nodename = 'x:indexedColors') then
begin begin
colornode := node.FirstChild; colornode := node.FirstChild;
while Assigned(colornode) do while Assigned(colornode) do
begin begin
nodename := colornode.NodeName; nodename := colornode.NodeName;
if nodename = 'rgbColor' then begin if (nodename = 'rgbColor') or (nodename = 'x:rgbColor') then begin
s := GetAttrValue(colornode, 'rgb'); s := GetAttrValue(colornode, 'rgb');
if s <> '' then begin if s <> '' then begin
rgb := HTMLColorStrToColor('#' + s); rgb := HTMLColorStrToColor('#' + s);
@ -2003,28 +2017,30 @@ var
fnt: TsFont; fnt: TsFont;
begin begin
while Assigned(ANode) do begin while Assigned(ANode) do begin
if ANode.NodeName = 'si' then begin nodename := ANode.NodeName;
if (nodeName = 'si') or (nodeName = 'x:si') then begin
totaltxt := ''; totaltxt := '';
SetLength(rtParams, 0); SetLength(rtParams, 0);
valuenode := ANode.FirstChild; valuenode := ANode.FirstChild;
while valuenode <> nil do begin while valuenode <> nil do begin
nodename := valuenode.NodeName; nodename := valuenode.NodeName;
if nodename = 't' then if (nodename = 't') or (nodename = 'x:t') then
// this is unformatted text // this is unformatted text
totaltxt := GetNodeValue(valuenode) totaltxt := GetNodeValue(valuenode)
else else
if nodename = 'r' then begin if (nodename = 'r') or (nodename = 'x:r') then begin
// all rich-text formatted texts are defined by r nodes // all rich-text formatted texts are defined by r nodes
fntIndex := -1; fntIndex := -1;
childnode := valuenode.FirstChild; childnode := valuenode.FirstChild;
while childnode <> nil do begin while childnode <> nil do begin
nodename := childnode.NodeName; nodename := childnode.NodeName;
if nodename = 't' then if (nodename = 't') or (nodename = 'x:t') then
begin begin
sval := GetNodeValue(childNode); sval := GetNodeValue(childNode);
totaltxt := totaltxt + sval; totaltxt := totaltxt + sval;
end end
else if nodename = 'rPr' then begin else
if (nodename = 'rPr') or (nodename = 'x:rPr') then begin
fntIndex := ReadFont(childnode); fntIndex := ReadFont(childnode);
// Here we store the font in the internal font list of the reader. // Here we store the font in the internal font list of the reader.
// But this fontindex may be different from the one needed for the // But this fontindex may be different from the one needed for the
@ -2085,10 +2101,13 @@ var
nodename: String; nodename: String;
sheetData: TSheetData; sheetData: TSheetData;
begin begin
if ANode = nil then
exit;
node := ANode.FirstChild; node := ANode.FirstChild;
while node <> nil do begin while node <> nil do begin
nodename := node.NodeName; nodename := node.NodeName;
if nodename = 'sheet' then if (nodename = 'sheet') or (nodename = 'x:sheet') then
begin begin
sheetData := TSheetData.Create; sheetData := TSheetData.Create;
sheetData.Name := GetAttrValue(node, 'name'); sheetData.Name := GetAttrValue(node, 'name');
@ -2276,7 +2295,7 @@ begin
sheetViewNode := ANode.FirstChild; sheetViewNode := ANode.FirstChild;
while Assigned(sheetViewNode) do begin while Assigned(sheetViewNode) do begin
nodeName := sheetViewNode.NodeName; nodeName := sheetViewNode.NodeName;
if nodeName = 'sheetView' then begin if (nodeName = 'sheetView') or (nodeName = 'x:sheetView') then begin
s := GetAttrValue(sheetViewNode, 'showGridLines'); s := GetAttrValue(sheetViewNode, 'showGridLines');
if StrIsFalse(s) then //(s = '0') or (s = 'false') then if StrIsFalse(s) then //(s = '0') or (s = 'false') then
sheet.Options := AWorksheet.Options - [soShowGridLines]; sheet.Options := AWorksheet.Options - [soShowGridLines];
@ -2306,7 +2325,7 @@ begin
childNode := sheetViewNode.FirstChild; childNode := sheetViewNode.FirstChild;
while Assigned(childNode) do begin while Assigned(childNode) do begin
nodeName := childNode.NodeName; nodeName := childNode.NodeName;
if nodeName = 'pane' then begin if (nodeName = 'pane') or (nodeName = 'x:pane') then begin
s := GetAttrValue(childNode, 'state'); s := GetAttrValue(childNode, 'state');
if s = 'frozen' then begin if s = 'frozen' then begin
sheet.Options := sheet.Options + [soHasFrozenPanes]; sheet.Options := sheet.Options + [soHasFrozenPanes];
@ -2318,7 +2337,7 @@ begin
sheet.TopPaneHeight := round(StrToFloat(s, FPointSeparatorSettings)); sheet.TopPaneHeight := round(StrToFloat(s, FPointSeparatorSettings));
end; end;
end else end else
if nodeName = 'selection' then begin if (nodeName = 'selection') or (nodeName = 'x:selection') then begin
s := GetAttrValue(childnode, 'activeCell'); s := GetAttrValue(childnode, 'activeCell');
if s <> '' then if s <> '' then
begin begin
@ -2415,12 +2434,12 @@ var
wbc: TsCryptoInfo; wbc: TsCryptoInfo;
wbp: TsWorkbookProtections; wbp: TsWorkbookProtections;
begin begin
s := '';
wbp := [];
if ANode = nil then if ANode = nil then
Exit; Exit;
s := '';
wbp := [];
InitCryptoInfo(wbc); InitCryptoInfo(wbc);
s := GetAttrValue(ANode, 'workbookPassword'); s := GetAttrValue(ANode, 'workbookPassword');
if s <> '' then if s <> '' then
@ -2480,14 +2499,17 @@ procedure TsSpreadOOXMLReader.ReadWorksheet(ANode: TDOMNode;
var var
rownode: TDOMNode; rownode: TDOMNode;
cellnode: TDOMNode; cellnode: TDOMNode;
nodename: String;
begin begin
rownode := ANode.FirstChild; rownode := ANode.FirstChild;
while Assigned(rownode) do begin while Assigned(rownode) do begin
if rownode.NodeName = 'row' then begin nodeName := rownode.NodeName;
if (nodeName = 'row') or (nodeName = 'x:row') then begin
ReadRow(rownode, AWorksheet); ReadRow(rownode, AWorksheet);
cellnode := rownode.FirstChild; cellnode := rownode.FirstChild;
while Assigned(cellnode) do begin while Assigned(cellnode) do begin
if cellnode.NodeName = 'c' then nodename := cellnode.NodeName;
if (nodeName = 'c') or (nodeName = 'x:c') then
ReadCell(cellnode, AWorksheet); ReadCell(cellnode, AWorksheet);
cellnode := cellnode.NextSibling; cellnode := cellnode.NextSibling;
end; end;
@ -2520,6 +2542,13 @@ var
Result := TMemoryStream.Create; Result := TMemoryStream.Create;
end; end;
function Doc_FindNode(ANodeName: String): TDOMNode;
begin
Result := Doc.DocumentElement.FindNode(ANodeName);
if Result = nil then
Result := Doc.DocumentElement.FindNode('x:' + ANodeName);
end;
begin begin
Unused(APassword, AParams); Unused(APassword, AParams);
Doc := nil; Doc := nil;
@ -2544,12 +2573,12 @@ begin
if not UnzipToStream(AStream, OOXML_PATH_XL_WORKBOOK, XMLStream) then if not UnzipToStream(AStream, OOXML_PATH_XL_WORKBOOK, XMLStream) then
raise EFPSpreadsheetReader.CreateFmt(rsDefectiveInternalFileStructure, ['xlsx']); raise EFPSpreadsheetReader.CreateFmt(rsDefectiveInternalFileStructure, ['xlsx']);
ReadXMLStream(Doc, XMLStream); ReadXMLStream(Doc, XMLStream);
ReadFileVersion(Doc.DocumentElement.FindNode('fileVersion')); ReadFileVersion(Doc_FindNode('fileVersion'));
ReadDateMode(Doc.DocumentElement.FindNode('workbookPr')); ReadDateMode(Doc_FindNode('workbookPr'));
ReadWorkbookProtection(Doc.DocumentElement.FindNode('workbookProtection')); ReadWorkbookProtection(Doc_FindNode('workbookProtection'));
ReadSheetList(Doc.DocumentElement.FindNode('sheets')); ReadSheetList(Doc_FindNode('sheets'));
//ReadDefinedNames(Doc.DocumentElement.FindNode('definedNames')); -- don't read here because sheets do not yet exist //ReadDefinedNames(Doc.DocumentElement.FindNode('definedNames')); -- don't read here because sheets do not yet exist
ReadActiveSheet(Doc.DocumentElement.FindNode('bookViews'), actSheetIndex); ReadActiveSheet(Doc_FindNode('bookViews'), actSheetIndex);
FreeAndNil(Doc); FreeAndNil(Doc);
finally finally
XMLStream.Free; XMLStream.Free;
@ -2562,12 +2591,12 @@ begin
if UnzipToStream(AStream, OOXML_PATH_XL_STYLES, XMLStream) then if UnzipToStream(AStream, OOXML_PATH_XL_STYLES, XMLStream) then
begin begin
ReadXMLStream(Doc, XMLStream); ReadXMLStream(Doc, XMLStream);
ReadPalette(Doc.DocumentElement.FindNode('colors')); ReadPalette(Doc_FindNode('colors'));
ReadFonts(Doc.DocumentElement.FindNode('fonts')); ReadFonts(Doc_FindNode('fonts'));
ReadFills(Doc.DocumentElement.FindNode('fills')); ReadFills(Doc_FindNode('fills'));
ReadBorders(Doc.DocumentElement.FindNode('borders')); ReadBorders(Doc_FindNode('borders'));
ReadNumFormats(Doc.DocumentElement.FindNode('numFmts')); ReadNumFormats(Doc_FindNode('numFmts'));
ReadCellXfs(Doc.DocumentElement.FindNode('cellXfs')); ReadCellXfs(Doc_FindNode('cellXfs'));
FreeAndNil(Doc); FreeAndNil(Doc);
end; end;
finally finally
@ -2581,7 +2610,7 @@ begin
if UnzipToStream(AStream, OOXML_PATH_XL_STRINGS, XMLStream) then if UnzipToStream(AStream, OOXML_PATH_XL_STRINGS, XMLStream) then
begin begin
ReadXMLStream(Doc, XMLStream); ReadXMLStream(Doc, XMLStream);
ReadSharedStrings(Doc.DocumentElement.FindNode('si')); ReadSharedStrings(Doc_FindNode('si'));
FreeAndNil(Doc); FreeAndNil(Doc);
end; end;
finally finally
@ -2616,18 +2645,18 @@ begin
FSharedFormulaBaseList.Clear; FSharedFormulaBaseList.Clear;
// Sheet data, formats, etc. // Sheet data, formats, etc.
ReadDimension(Doc.DocumentElement.FindNode('dimension'), FWorksheet); ReadDimension(Doc_FindNode('dimension'), FWorksheet);
ReadSheetViews(Doc.DocumentElement.FindNode('sheetViews'), FWorksheet); ReadSheetViews(Doc_FindNode('sheetViews'), FWorksheet);
ReadSheetFormatPr(Doc.DocumentElement.FindNode('sheetFormatPr'), FWorksheet); ReadSheetFormatPr(Doc_FindNode('sheetFormatPr'), FWorksheet);
ReadCols(Doc.DocumentElement.FindNode('cols'), FWorksheet); ReadCols(Doc_FindNode('cols'), FWorksheet);
ReadWorksheet(Doc.DocumentElement.FindNode('sheetData'), FWorksheet); ReadWorksheet(Doc_FindNode('sheetData'), FWorksheet);
ReadSheetProtection(Doc.DocumentElement.FindNode('sheetProtection'), FWorksheet); ReadSheetProtection(Doc_FindNode('sheetProtection'), FWorksheet);
ReadMergedCells(Doc.DocumentElement.FindNode('mergeCells'), FWorksheet); ReadMergedCells(Doc_FindNode('mergeCells'), FWorksheet);
ReadHyperlinks(Doc.DocumentElement.FindNode('hyperlinks')); ReadHyperlinks(Doc_FindNode('hyperlinks'));
ReadPrintOptions(Doc.DocumentElement.FindNode('printOptions'), FWorksheet); ReadPrintOptions(Doc_FindNode('printOptions'), FWorksheet);
ReadPageMargins(Doc.DocumentElement.FindNode('pageMargins'), FWorksheet); ReadPageMargins(Doc_FindNode('pageMargins'), FWorksheet);
ReadPageSetup(Doc.DocumentElement.FindNode('pageSetup'), FWorksheet); ReadPageSetup(Doc_FindNode('pageSetup'), FWorksheet);
ReadHeaderFooter(Doc.DocumentElement.FindNode('headerFooter'), FWorksheet); ReadHeaderFooter(Doc_FindNode('headerFooter'), FWorksheet);
FreeAndNil(Doc); FreeAndNil(Doc);
@ -2643,7 +2672,7 @@ begin
begin begin
// Find exact name of comments<n>.xml file // Find exact name of comments<n>.xml file
ReadXMLStream(Doc, XMLStream); ReadXMLStream(Doc, XMLStream);
RelsNode := Doc.DocumentElement.FindNode('Relationship'); RelsNode := Doc_FindNode('Relationship');
fn_comments := FindCommentsFileName(RelsNode); fn_comments := FindCommentsFileName(RelsNode);
// Get hyperlink data // Get hyperlink data
ReadHyperlinks(RelsNode); ReadHyperlinks(RelsNode);
@ -2670,7 +2699,7 @@ begin
if UnzipToStream(AStream, fn, XMLStream) then if UnzipToStream(AStream, fn, XMLStream) then
begin begin
ReadXMLStream(Doc, XMLStream); ReadXMLStream(Doc, XMLStream);
ReadComments(Doc.DocumentElement.FindNode('commentList'), FWorksheet); ReadComments(Doc_FindNode('commentList'), FWorksheet);
FreeAndNil(Doc); FreeAndNil(Doc);
end; end;
finally finally
@ -2693,7 +2722,7 @@ begin
if not UnzipToStream(AStream, OOXML_PATH_XL_WORKBOOK, XMLStream) then if not UnzipToStream(AStream, OOXML_PATH_XL_WORKBOOK, XMLStream) then
raise EFPSpreadsheetReader.CreateFmt(rsDefectiveInternalFileStructure, ['xlsx']); raise EFPSpreadsheetReader.CreateFmt(rsDefectiveInternalFileStructure, ['xlsx']);
ReadXMLStream(Doc, XMLStream); ReadXMLStream(Doc, XMLStream);
ReadDefinedNames(Doc.DocumentElement.FindNode('definedNames')); ReadDefinedNames(Doc_FindNode('definedNames'));
FreeAndNil(Doc); FreeAndNil(Doc);
finally finally
XMLStream.Free; XMLStream.Free;