You've already forked lazarus-ccr
fpspreadsheet: Support of some more features by Excel2003/XML reader. Display PrintRanges, repeated rows and columns by SpreadsheetInspector.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7042 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@@ -93,11 +93,14 @@ function GetCellRangeString(ARange: TsCellRange;
|
|||||||
function GetCellString(ARow,ACol: Cardinal;
|
function GetCellString(ARow,ACol: Cardinal;
|
||||||
AFlags: TsRelFlags = [rfRelRow, rfRelCol]): String;
|
AFlags: TsRelFlags = [rfRelRow, rfRelCol]): String;
|
||||||
function GetColString(AColIndex: Integer): String;
|
function GetColString(AColIndex: Integer): String;
|
||||||
|
function GetRowString(ARowIndex: Integer): String;
|
||||||
|
|
||||||
// -- "R1C1" syntax
|
// -- "R1C1" syntax
|
||||||
function ParseCellRangeString_R1C1(const AStr: string; ABaseRow, ABaseCol: Cardinal;
|
function ParseCellRangeString_R1C1(const AStr: string; ABaseRow, ABaseCol: Cardinal;
|
||||||
out AFirstCellRow, AFirstCellCol, ALastCellRow, ALastCellCol: Cardinal;
|
out AFirstCellRow, AFirstCellCol, ALastCellRow, ALastCellCol: Cardinal;
|
||||||
out AFlags: TsRelFlags): Boolean;
|
out AFlags: TsRelFlags): Boolean;
|
||||||
|
function ParseCellString_R1C1(const AStr: String; ABaseRow, ABaseCol: Cardinal;
|
||||||
|
out ASheet: String; out ACellRow, ACellCol: Cardinal; out AFlags: TsRelFlags): Boolean; overload;
|
||||||
function ParseCellString_R1C1(const AStr: String; ABaseRow, ABaseCol: Cardinal;
|
function ParseCellString_R1C1(const AStr: String; ABaseRow, ABaseCol: Cardinal;
|
||||||
out ACellRow, ACellCol: Cardinal; out AFlags: TsRelFlags): Boolean; overload;
|
out ACellRow, ACellCol: Cardinal; out AFlags: TsRelFlags): Boolean; overload;
|
||||||
function ParseCellString_R1C1(const AStr: string; ABaseRow, ABaseCol: Cardinal;
|
function ParseCellString_R1C1(const AStr: string; ABaseRow, ABaseCol: Cardinal;
|
||||||
@@ -701,6 +704,22 @@ begin
|
|||||||
if rfRelCol in f then Include(AFlags, rfRelCol2);
|
if rfRelCol in f then Include(AFlags, rfRelCol2);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function ParseCellString_R1C1(const AStr: String; ABaseRow, ABaseCol: Cardinal;
|
||||||
|
out ASheet: String; out ACellRow, ACellCol: Cardinal;
|
||||||
|
out AFlags: TsRelFlags): Boolean;
|
||||||
|
var
|
||||||
|
p: Integer;
|
||||||
|
begin
|
||||||
|
p := pos('!', AStr);
|
||||||
|
if p > 0 then begin
|
||||||
|
ASheet := Copy(AStr, 1, p-1);
|
||||||
|
Result := ParseCellString_R1C1(Copy(AStr, p+1, MaxInt), ABaserow, ABaseCol, ACellRow, ACellCol, AFlags);
|
||||||
|
end else begin
|
||||||
|
ASheet := '';
|
||||||
|
Result := ParseCellString_R1C1(AStr, ABaseRow, ABaseCol, ACellRow, ACellCol, AFlags);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Parses a cell string in "R1C1" notation into zero-based column and row numbers
|
Parses a cell string in "R1C1" notation into zero-based column and row numbers
|
||||||
'AFlags' indicates relative addresses.
|
'AFlags' indicates relative addresses.
|
||||||
@@ -1078,6 +1097,17 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Calculates an Excel row name ('1', '2' etc) from the zero-based row index
|
||||||
|
|
||||||
|
@param ARowIndex Zero-based row index
|
||||||
|
@return Numerical, one-based row name string.
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
function GetRowString(ARowIndex: Integer): String;
|
||||||
|
begin
|
||||||
|
Result := IntToStr(ARowIndex+1);
|
||||||
|
end;
|
||||||
|
|
||||||
const
|
const
|
||||||
RELCHAR: Array[boolean] of String = ('$', '');
|
RELCHAR: Array[boolean] of String = ('$', '');
|
||||||
|
|
||||||
|
@@ -43,8 +43,10 @@ type
|
|||||||
procedure ReadCell(ANode: TDOMNode; AWorksheet: TsBasicWorksheet; ARow, ACol: Integer);
|
procedure ReadCell(ANode: TDOMNode; AWorksheet: TsBasicWorksheet; ARow, ACol: Integer);
|
||||||
procedure ReadCellProtection(ANode: TDOMNode; var AFormat: TsCellFormat);
|
procedure ReadCellProtection(ANode: TDOMNode; var AFormat: TsCellFormat);
|
||||||
procedure ReadComment(ANode: TDOMNode; AWorksheet: TsBasicWorksheet; ACell: PCell);
|
procedure ReadComment(ANode: TDOMNode; AWorksheet: TsBasicWorksheet; ACell: PCell);
|
||||||
|
procedure ReadExcelWorkbook(ANode: TDOMNode);
|
||||||
procedure ReadFont(ANode: TDOMNode; var AFormat: TsCellFormat);
|
procedure ReadFont(ANode: TDOMNode; var AFormat: TsCellFormat);
|
||||||
procedure ReadInterior(ANode: TDOMNode; var AFormat: TsCellFormat);
|
procedure ReadInterior(ANode: TDOMNode; var AFormat: TsCellFormat);
|
||||||
|
procedure ReadNames(ANode: TDOMNode; AWorksheet: TsBasicWorksheet);
|
||||||
procedure ReadNumberFormat(ANode: TDOMNode; var AFormat: TsCellFormat);
|
procedure ReadNumberFormat(ANode: TDOMNode; var AFormat: TsCellFormat);
|
||||||
procedure ReadRow(ANode: TDOMNode; AWorksheet: TsBasicWorksheet; ARow: Integer);
|
procedure ReadRow(ANode: TDOMNode; AWorksheet: TsBasicWorksheet; ARow: Integer);
|
||||||
procedure ReadStyle(ANode: TDOMNode);
|
procedure ReadStyle(ANode: TDOMNode);
|
||||||
@@ -193,6 +195,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{===============================================================================
|
||||||
|
TsSpreadExcelXMLReader
|
||||||
|
===============================================================================}
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Constructor of the ExcelXML reader
|
Constructor of the ExcelXML reader
|
||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
@@ -539,6 +546,41 @@ begin
|
|||||||
TsWorksheet(AWorksheet).WriteComment(ACell, txt);
|
TsWorksheet(AWorksheet).WriteComment(ACell, txt);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Reads the "ExcelWorkbook" node
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
procedure TsSpreadExcelXMLReader.ReadExcelWorkbook(ANode: TDOMNode);
|
||||||
|
var
|
||||||
|
s: String;
|
||||||
|
nodeName: String;
|
||||||
|
n: Integer;
|
||||||
|
begin
|
||||||
|
if ANode = nil then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
ANode := ANode.FirstChild;
|
||||||
|
while ANode <> nil do begin
|
||||||
|
nodeName := ANode.NodeName;
|
||||||
|
if nodeName = 'ActiveSheet' then begin
|
||||||
|
s := ANode.TextContent;
|
||||||
|
if (s <> '') and TryStrToInt(s, n) then
|
||||||
|
with TsWorkbook(FWorkbook) do
|
||||||
|
SelectWorksheet(GetWorksheetByIndex(n));
|
||||||
|
end else
|
||||||
|
if nodeName = 'ProtectStructure' then begin
|
||||||
|
s := ANode.TextContent;
|
||||||
|
if s = 'True' then
|
||||||
|
FWorkbook.Protection := FWorkbook.Protection + [bpLockStructure];
|
||||||
|
end else
|
||||||
|
if nodeName = 'ProtectWindows' then begin
|
||||||
|
s := ANode.TextContent;
|
||||||
|
if s = 'True' then
|
||||||
|
FWorkbook.Protection := FWorkbook.Protection + [bpLockWindows];
|
||||||
|
end;
|
||||||
|
ANode := ANode.NextSibling;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Reads the "Styles/Style/Font" node
|
Reads the "Styles/Style/Font" node
|
||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
@@ -629,6 +671,91 @@ begin
|
|||||||
Include(AFormat.UsedFormattingFields, uffBackground);
|
Include(AFormat.UsedFormattingFields, uffBackground);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Reads a "Worksheet/Names" node
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
procedure TsSpreadExcelXMLReader.ReadNames(ANode: TDOMNode;
|
||||||
|
AWorksheet: TsBasicWorksheet);
|
||||||
|
|
||||||
|
procedure DoProcess(AStr: String; var ARowIndex, AColIndex: Cardinal;
|
||||||
|
out IsRow: Boolean);
|
||||||
|
var
|
||||||
|
p: Integer;
|
||||||
|
begin
|
||||||
|
p := pos('!', AStr);
|
||||||
|
if p > 0 then AStr := Copy(AStr, p+1, MaxInt);
|
||||||
|
IsRow := AStr[1] in ['R', 'r'];
|
||||||
|
Delete(AStr, 1, 1);
|
||||||
|
if IsRow then
|
||||||
|
ARowIndex := StrToInt(AStr) - 1
|
||||||
|
else
|
||||||
|
AColIndex := StrToInt(AStr) - 1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure DoRepeatedRowsCols(AStr: String);
|
||||||
|
var
|
||||||
|
p: Integer;
|
||||||
|
isRow: Boolean;
|
||||||
|
r1: Cardinal = UNASSIGNED_ROW_COL_INDEX;
|
||||||
|
c1: Cardinal = UNASSIGNED_ROW_COL_INDEX;
|
||||||
|
r2: Cardinal = UNASSIGNED_ROW_COL_INDEX;
|
||||||
|
c2: Cardinal = UNASSIGNED_ROW_COL_INDEX;
|
||||||
|
begin
|
||||||
|
p := pos(':', AStr);
|
||||||
|
// No colon --> Single range, e.g. "=Sheet1!C1"
|
||||||
|
if p = 0 then
|
||||||
|
begin
|
||||||
|
DoProcess(AStr, r1, c1, isRow);
|
||||||
|
r2 := r1;
|
||||||
|
c2 := c1;
|
||||||
|
end else
|
||||||
|
// Colon --> Range block, e.g. "Sheet1!R1:R2"
|
||||||
|
begin
|
||||||
|
DoProcess(copy(AStr, 1, p-1), r1, c1, isRow);
|
||||||
|
DoProcess(copy(AStr, p+1, MaxInt), r2, c2, isRow);
|
||||||
|
end;
|
||||||
|
if isRow then
|
||||||
|
TsWorksheet(AWorksheet).PageLayout.SetRepeatedRows(r1, r2)
|
||||||
|
else
|
||||||
|
TsWorksheet(AWorksheet).PageLayout.SetRepeatedCols(c1, c2);
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
s, s1: String;
|
||||||
|
nodeName: String;
|
||||||
|
sheet1, sheet2: String;
|
||||||
|
r1, c1, r2, c2: Cardinal;
|
||||||
|
flags: TsRelFlags;
|
||||||
|
p, q: Integer;
|
||||||
|
begin
|
||||||
|
while ANode <> nil do begin
|
||||||
|
nodeName := ANode.NodeName;
|
||||||
|
if nodeName = 'NamedRange' then begin
|
||||||
|
s := GetAttrValue(ANode, 'ss:Name');
|
||||||
|
if s = 'Print_Area' then begin
|
||||||
|
// <NamedRange ss:Name="Print_Area" ss:RefersTo="=Tabelle2!R2C2:R5C7"/>
|
||||||
|
s := GetAttrValue(ANode, 'ss:RefersTo');
|
||||||
|
if (s <> '') and ParseCellRangeString_R1C1(s, 0, 0, sheet1, sheet2, r1, c1, r2, c2, flags) then
|
||||||
|
TsWorksheet(AWorksheet).PageLayout.AddPrintRange(r1, c1, r2, c2);
|
||||||
|
// to do: include sheet names here!
|
||||||
|
end else
|
||||||
|
if s = 'Print_Titles' then begin
|
||||||
|
// <NamedRange ss:Name="Print_Titles" ss:RefersTo="=Tabelle2!C1,Tabelle2!R1:R2"/>
|
||||||
|
s := GetAttrValue(ANode, 'ss:RefersTo');
|
||||||
|
if s <> '' then begin
|
||||||
|
p := pos(',', s);
|
||||||
|
if p > 0 then begin
|
||||||
|
DoRepeatedRowsCols(copy(s, 1, p-1));
|
||||||
|
DoRepeatedRowsCols(copy(s, p+1, MaxInt));
|
||||||
|
end else
|
||||||
|
DoRepeatedRowsCols(s);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
ANode := ANode.NextSibling;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Reads a "Styles/Style/NumberFormat" node
|
Reads a "Styles/Style/NumberFormat" node
|
||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
@@ -801,6 +928,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// Hidden
|
||||||
|
s := GetAttrValue(ANode, 'ss:Hidden');
|
||||||
|
if s = '1' then
|
||||||
|
sheet.HideCol(c);
|
||||||
|
|
||||||
inc(c);
|
inc(c);
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@@ -824,6 +956,11 @@ begin
|
|||||||
if (s <> '') and TryStrToFloat(s, x, FPointSeparatorSettings) then
|
if (s <> '') and TryStrToFloat(s, x, FPointSeparatorSettings) then
|
||||||
sheet.WriteRowHeight(r, x, suPoints);
|
sheet.WriteRowHeight(r, x, suPoints);
|
||||||
|
|
||||||
|
// Hidden
|
||||||
|
s := GetAttrValue(ANode, 'ss:Hidden');
|
||||||
|
if (s = '1') then
|
||||||
|
sheet.HideRow(r);
|
||||||
|
|
||||||
// Row format
|
// Row format
|
||||||
s := GetAttrValue(ANode, 'ss:StyleID');
|
s := GetAttrValue(ANode, 'ss:StyleID');
|
||||||
if s <> '' then begin
|
if s <> '' then begin
|
||||||
@@ -853,12 +990,22 @@ var
|
|||||||
nodeName: String;
|
nodeName: String;
|
||||||
s: String;
|
s: String;
|
||||||
begin
|
begin
|
||||||
|
if ANode = nil then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
s := GetAttrValue(ANode, 'ss:Protected');
|
||||||
|
if s ='1' then
|
||||||
|
AWorksheet.Options := AWorksheet.Options + [soProtected];
|
||||||
|
;
|
||||||
|
ANode := ANode.FirstChild;
|
||||||
while ANode <> nil do begin
|
while ANode <> nil do begin
|
||||||
nodeName := ANode.NodeName;
|
nodeName := ANode.NodeName;
|
||||||
if nodeName = 'Table' then
|
if nodeName = 'Table' then
|
||||||
ReadTable(ANode.FirstChild, AWorksheet)
|
ReadTable(ANode.FirstChild, AWorksheet)
|
||||||
else if nodeName = 'WorksheetOptions' then
|
else if nodeName = 'WorksheetOptions' then
|
||||||
ReadWorksheetOptions(ANode.FirstChild, AWorksheet);
|
ReadWorksheetOptions(ANode.FirstChild, AWorksheet)
|
||||||
|
else if nodeName = 'Names' then
|
||||||
|
ReadNames(ANode.FirstChild, AWorksheet);
|
||||||
ANode := ANode.NextSibling;
|
ANode := ANode.NextSibling;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@@ -870,12 +1017,15 @@ procedure TsSpreadExcelXMLReader.ReadWorksheetOptions(ANode: TDOMNode;
|
|||||||
AWorksheet: TsBasicWorksheet);
|
AWorksheet: TsBasicWorksheet);
|
||||||
var
|
var
|
||||||
sheet: TsWorksheet absolute AWorksheet;
|
sheet: TsWorksheet absolute AWorksheet;
|
||||||
node: TDOMNode;
|
node, childnode: TDOMNode;
|
||||||
nodeName: String;
|
nodeName: String;
|
||||||
s: String;
|
s: String;
|
||||||
x: Double;
|
x: Double;
|
||||||
n: Integer;
|
n: Integer;
|
||||||
hasFitToPage: Boolean = false;
|
hasFitToPage: Boolean = false;
|
||||||
|
c, r: Cardinal;
|
||||||
|
r1, c1, r2, c2: Cardinal;
|
||||||
|
flags: TsRelFlags;
|
||||||
begin
|
begin
|
||||||
if ANode = nil then
|
if ANode = nil then
|
||||||
exit;
|
exit;
|
||||||
@@ -984,7 +1134,110 @@ begin
|
|||||||
end;
|
end;
|
||||||
node := node.NextSibling;
|
node := node.NextSibling;
|
||||||
end;
|
end;
|
||||||
|
end else
|
||||||
|
if nodeName = 'Selected' then
|
||||||
|
TsWorkbook(FWorkbook).ActiveWorksheet := sheet
|
||||||
|
else
|
||||||
|
if nodeName = 'Panes' then begin
|
||||||
|
c := sheet.ActiveCellCol;
|
||||||
|
r := sheet.ActiveCellRow;
|
||||||
|
node := ANode.FirstChild;
|
||||||
|
while node <> nil do begin
|
||||||
|
nodeName := node.NodeName;
|
||||||
|
if nodeName = 'Pane' then begin
|
||||||
|
childnode := node.FirstChild;
|
||||||
|
while childnode <> nil do begin
|
||||||
|
nodeName := childNode.NodeName;
|
||||||
|
if nodeName = 'ActiveRow' then begin
|
||||||
|
s := childNode.TextContent;
|
||||||
|
if (s <> '') and TryStrToInt(s, n) then
|
||||||
|
r := n;
|
||||||
|
end else
|
||||||
|
if nodeName = 'ActiveCol' then begin
|
||||||
|
s := childNode.TextContent;
|
||||||
|
if (s <> '') and TryStrToInt(s, n) then
|
||||||
|
c := n;
|
||||||
|
end;
|
||||||
|
childnode := childNode.NextSibling;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
node := node.NextSibling;
|
||||||
|
end;
|
||||||
|
sheet.SelectCell(r, c);
|
||||||
|
end else
|
||||||
|
if nodeName = 'FreezePanes' then
|
||||||
|
sheet.Options := sheet.Options + [soHasFrozenPanes]
|
||||||
|
else
|
||||||
|
if (nodeName = 'TopRowBottomPane') then begin
|
||||||
|
s := ANode.TextContent;
|
||||||
|
if (s <> '') and TryStrToInt(s, n) then
|
||||||
|
sheet.TopPaneHeight := n;
|
||||||
|
end else
|
||||||
|
if (nodeName = 'LeftColumnRightPane') then begin
|
||||||
|
s := ANode.TextContent;
|
||||||
|
if (s <> '') and TryStrToInt(s, n) then
|
||||||
|
sheet.LeftPaneWidth := n;
|
||||||
|
end else
|
||||||
|
if nodeName = 'DoNotDisplayGridlines' then
|
||||||
|
sheet.Options := sheet.Options - [soShowGridLines]
|
||||||
|
else
|
||||||
|
if nodeName = 'DoNotDisplayHeadings' then
|
||||||
|
sheet.Options := sheet.Options - [soShowHeaders]
|
||||||
|
else
|
||||||
|
if nodeName = 'Zoom' then begin
|
||||||
|
s := ANode.TextContent;
|
||||||
|
if (s <> '') and TryStrToFloat(s, x) then
|
||||||
|
sheet.Zoomfactor := x * 0.01;
|
||||||
|
end else
|
||||||
|
if nodeName = 'Visible' then begin
|
||||||
|
s := ANode.TextContent;
|
||||||
|
if s = 'SheetHidden' then
|
||||||
|
sheet.Options := sheet.Options + [soHidden];
|
||||||
|
end else
|
||||||
|
if nodeName = 'AllowFormatCells' then
|
||||||
|
sheet.Protection := sheet.Protection - [spFormatCells]
|
||||||
|
else
|
||||||
|
if nodeName = 'AllowSizeCols' then
|
||||||
|
sheet.Protection := sheet.Protection - [spFormatColumns]
|
||||||
|
else
|
||||||
|
if nodeName = 'AllowSizeRows' then
|
||||||
|
sheet.Protection := sheet.Protection - [spFormatRows]
|
||||||
|
else
|
||||||
|
if nodeName = 'AllowInsertCols' then
|
||||||
|
sheet.Protection := sheet.Protection - [spInsertColumns]
|
||||||
|
else
|
||||||
|
if nodeName = 'AllowInsertRows' then
|
||||||
|
sheet.Protection := sheet.Protection - [spInsertRows]
|
||||||
|
else
|
||||||
|
if nodeName = 'AllowInsertHyperlinks' then
|
||||||
|
sheet.Protection := sheet.Protection - [spInsertHyperLinks]
|
||||||
|
else
|
||||||
|
if nodeName = 'AllowDeleteCols' then
|
||||||
|
sheet.Protection := sheet.Protection - [spDeleteColumns]
|
||||||
|
else
|
||||||
|
if nodeName = 'AllowDeleteRows' then
|
||||||
|
sheet.Protection := sheet.Protection - [spDeleteRows]
|
||||||
|
else
|
||||||
|
if nodeName = 'AllowSort' then
|
||||||
|
sheet.Protection := sheet.Protection - [spSort]
|
||||||
|
else
|
||||||
|
if nodeName = 'ProtectObjects' then
|
||||||
|
sheet.Protection := sheet.Protection + [spObjects]
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if nodeName = 'ProtectScenarios' then
|
||||||
|
sheet.Protection := sheet.Protection + [spScenarios];
|
||||||
|
else
|
||||||
|
}
|
||||||
|
if nodeName = 'EnableSelection' then begin
|
||||||
|
s := ANode.TextContent;
|
||||||
|
if s = 'NoSelection' then
|
||||||
|
sheet.Protection := sheet.Protection + [spSelectLockedCells, spSelectUnlockedCells]
|
||||||
|
else
|
||||||
|
if s = 'Unlocked' then
|
||||||
|
sheet.Protection := sheet.Protection + [spSelectLockedCells];
|
||||||
end;
|
end;
|
||||||
|
|
||||||
ANode := ANode.NextSibling;
|
ANode := ANode.NextSibling;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -1029,7 +1282,7 @@ begin
|
|||||||
s := GetAttrValue(ANode, 'ss:Name');
|
s := GetAttrValue(ANode, 'ss:Name');
|
||||||
if s <> '' then begin // the case of '' should not happen
|
if s <> '' then begin // the case of '' should not happen
|
||||||
FWorksheet := TsWorkbook(FWorkbook).AddWorksheet(s);
|
FWorksheet := TsWorkbook(FWorkbook).AddWorksheet(s);
|
||||||
ReadWorksheet(ANode.FirstChild, FWorksheet);
|
ReadWorksheet(ANode, FWorksheet);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
ANode := ANode.NextSibling;
|
ANode := ANode.NextSibling;
|
||||||
@@ -1047,14 +1300,26 @@ var
|
|||||||
begin
|
begin
|
||||||
try
|
try
|
||||||
ReadXMLStream(doc, AStream);
|
ReadXMLStream(doc, AStream);
|
||||||
|
|
||||||
|
// Read style list
|
||||||
ReadStyles(doc.DocumentElement.FindNode('Styles'));
|
ReadStyles(doc.DocumentElement.FindNode('Styles'));
|
||||||
|
|
||||||
|
// Read worksheets and their contents
|
||||||
ReadWorksheets(doc.DocumentElement.FindNode('Worksheet'));
|
ReadWorksheets(doc.DocumentElement.FindNode('Worksheet'));
|
||||||
|
|
||||||
|
// Read ExcelWorkbook node after worksheet nodes although before it is
|
||||||
|
// found before the worksheet nodes in the file, because is requires
|
||||||
|
// worksheets to be existing.
|
||||||
|
ReadExcelWorkbook(doc.DocumentElement.FindNode('ExcelWorkbook'));
|
||||||
finally
|
finally
|
||||||
doc.Free;
|
doc.Free;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{===============================================================================
|
||||||
|
TsSpreadExcelXMLWriter
|
||||||
|
===============================================================================}
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Constructor of the ExcelXML writer
|
Constructor of the ExcelXML writer
|
||||||
@@ -1815,6 +2080,8 @@ begin
|
|||||||
StrUtils.IfThen(AWorksheet.IsProtected {and [spScenarios in AWorksheet.Protection])}, 'True', 'False')
|
StrUtils.IfThen(AWorksheet.IsProtected {and [spScenarios in AWorksheet.Protection])}, 'True', 'False')
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// todo - Several protection options
|
||||||
|
|
||||||
// Put it all together...
|
// Put it all together...
|
||||||
AppendToStream(AStream, INDENT2 +
|
AppendToStream(AStream, INDENT2 +
|
||||||
'<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">' + LF + INDENT3 +
|
'<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">' + LF + INDENT3 +
|
||||||
|
@@ -4106,6 +4106,41 @@ begin
|
|||||||
else
|
else
|
||||||
AStrings.Add(' FooterImage, right=');
|
AStrings.Add(' FooterImage, right=');
|
||||||
|
|
||||||
|
if ASheet.PageLayout.NumPrintRanges = 0 then
|
||||||
|
AStrings.Add(' Print ranges=')
|
||||||
|
else
|
||||||
|
for i := 0 to ASheet.PageLayout.NumPrintRanges-1 do
|
||||||
|
with ASheet.PageLayout.PrintRange[i] do
|
||||||
|
AStrings.Add(Format(' Print range #%d=$%s$%s:$%s$%s', [ i,
|
||||||
|
GetColString(Col1), GetRowString(Row1), GetColString(Col2), GetRowString(Row2)
|
||||||
|
]));
|
||||||
|
|
||||||
|
if ASheet.PageLayout.RepeatedRows.FirstIndex = UNASSIGNED_ROW_COL_INDEX then
|
||||||
|
AStrings.Add(' Repeated rows=')
|
||||||
|
else
|
||||||
|
if ASheet.PageLayout.RepeatedRows.FirstIndex = ASheet.PageLayout.RepeatedRows.LastIndex then
|
||||||
|
AStrings.Add(Format(' Repeated rows=$%s', [
|
||||||
|
GetRowString(ASheet.PageLayout.RepeatedRows.FirstIndex)
|
||||||
|
]))
|
||||||
|
else
|
||||||
|
AStrings.Add(Format(' Repeated rows=$%s:$%s', [
|
||||||
|
GetRowString(ASheet.PageLayout.RepeatedRows.FirstIndex),
|
||||||
|
GetRowString(ASheet.PageLayout.RepeatedRows.lastIndex)
|
||||||
|
]));
|
||||||
|
|
||||||
|
if ASheet.PageLayout.RepeatedCols.FirstIndex = UNASSIGNED_ROW_COL_INDEX then
|
||||||
|
AStrings.Add(' Repeated columns=')
|
||||||
|
else
|
||||||
|
if ASheet.PageLayout.RepeatedCols.FirstIndex = ASheet.PageLayout.RepeatedCols.LastIndex then
|
||||||
|
AStrings.Add(Format(' Repeated columns=$%s', [
|
||||||
|
GetColString(ASheet.PageLayout.RepeatedCols.FirstIndex)
|
||||||
|
]))
|
||||||
|
else
|
||||||
|
AStrings.Add(Format(' Repeated columns=$%s:$%s', [
|
||||||
|
GetColString(ASheet.PageLayout.RepeatedCols.FirstIndex),
|
||||||
|
GetColString(ASheet.PageLayout.RepeatedCols.lastIndex)
|
||||||
|
]));
|
||||||
|
|
||||||
s := '';
|
s := '';
|
||||||
for po in TsPrintOption do
|
for po in TsPrintOption do
|
||||||
if po in ASheet.PageLayout.Options then s := s + '; ' + GetEnumName(typeInfo(TsPrintOption), ord(po));
|
if po in ASheet.PageLayout.Options then s := s + '; ' + GetEnumName(typeInfo(TsPrintOption), ord(po));
|
||||||
|
Reference in New Issue
Block a user