fpspreadsheet: Read/write name of active worksheet (biff5, biff8, xlsx, ods, visual controls)

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4240 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2015-08-03 19:04:40 +00:00
parent acaacf81d4
commit 6a6f290fda
8 changed files with 125 additions and 46 deletions

View File

@ -89,6 +89,7 @@ type
FPageLayoutList: TFPList;
FMasterPageList: TFPList;
FHeaderFooterFontList: TObjectList;
FActiveSheet: String;
FDateMode: TDateMode;
// Applies internally stored column widths to current worksheet
procedure ApplyColWidths;
@ -1865,6 +1866,7 @@ var
OfficeSettingsNode: TDOMNode;
nodename: String;
pageLayout: PsPageLayout;
sheet: TsWorksheet;
begin
//unzip files into AFileName path
FilePath := GetTempDir(false);
@ -1958,6 +1960,12 @@ begin
ReadSettings(OfficeSettingsNode);
end;
// Active sheet
if FActiveSheet <> '' then
sheet := FWorkbook.GetWorksheetByName(FActiveSheet) else
sheet := FWorkbook.GetWorksheetByIndex(0);
FWorkbook.SelectWorksheet(sheet);
finally
if Assigned(Doc) then Doc.Free;
end;
@ -1966,32 +1974,14 @@ end;
procedure TsSpreadOpenDocReader.ReadFromStream(AStream: TStream);
var
Doc : TXMLDocument;
// FilePath : string;
// UnZip : TUnZipper;
// FileList : TStringList;
BodyNode, SpreadSheetNode, TableNode: TDOMNode;
StylesNode: TDOMNode;
OfficeSettingsNode: TDOMNode;
nodename: String;
pageLayout: PsPageLayout;
XMLStream: TStream;
sheet: TsWorksheet;
begin
{
//unzip files into AFileName path
FilePath := GetTempDir(false);
UnZip := TUnZipper.Create;
FileList := TStringList.Create;
try
FileList.Add('styles.xml');
FileList.Add('content.xml');
FileList.Add('settings.xml');
UnZip.OutputPath := FilePath;
Unzip.UnZipFiles(AFileName,FileList);
finally
FreeAndNil(FileList);
FreeAndNil(UnZip);
end; //try
}
Doc := nil;
try
// process the styles.xml file
@ -2079,17 +2069,17 @@ begin
XMLStream.Free;
end;
// Active sheet
if FActiveSheet <> '' then
sheet := FWorkbook.GetWorksheetByName(FActiveSheet) else
sheet := FWorkbook.GetWorksheetByIndex(0);
FWorkbook.SelectWorksheet(sheet);
finally
FreeAndNil(Doc);
end;
end;
{
begin
Unused(AStream);
raise Exception.Create('[TsSpreadOpenDocReader.ReadFromStream] '+
'Method not implemented. Use "ReadFromFile" instead.');
end;
}
procedure TsSpreadOpenDocReader.ReadHeaderFooterFont(ANode: TDOMNode;
var AFontName: String; var AFontSize: Double;
var AFontStyle: TsHeaderFooterFontStyles; var AFontColor: TsColor);
@ -2997,6 +2987,11 @@ begin
if (nodeName = 'config:config-item') then
begin
cfgName := lowercase(GetAttrValue(cfgEntryItemNode, 'config:name'));
if cfgName = 'activetable' then
begin
cfgValue := GetNodeValue(cfgEntryItemNode);
FActiveSheet := cfgValue;
end else
if cfgName = 'showgrid' then
begin
cfgValue := GetNodeValue(cfgEntryItemNode);
@ -3734,15 +3729,18 @@ var
i: Integer;
showGrid, showHeaders: Boolean;
sheet: TsWorksheet;
actSheet: String;
begin
// Open/LibreOffice allow to change showGrid and showHeaders only globally.
// As a compromise, we check whether there is at least one page with these
// settings off. Then we assume it to be valid also for the other sheets.
showGrid := true;
showHeaders := true;
actSheet := 'Table1';
for i:=0 to Workbook.GetWorksheetCount-1 do
begin
sheet := Workbook.GetWorksheetByIndex(i);
if sheet = Workbook.ActiveWorksheet then actSheet := sheet.Name;
if not (soShowGridLines in sheet.Options) then showGrid := false;
if not (soShowHeaders in sheet.Options) then showHeaders := false;
end;
@ -3758,7 +3756,7 @@ begin
'<config:config-item-set config:name="ooo:view-settings">' +
'<config:config-item-map-indexed config:name="Views">' +
'<config:config-item-map-entry>' +
'<config:config-item config:name="ActiveTable" config:type="string">Tabelle1</config:config-item>' +
'<config:config-item config:name="ActiveTable" config:type="string">'+actSheet+'</config:config-item>' +
'<config:config-item config:name="ZoomValue" config:type="int">100</config:config-item>' +
'<config:config-item config:name="PageViewZoomValue" config:type="int">100</config:config-item>' +
'<config:config-item config:name="ShowPageBreakPreview" config:type="boolean">false</config:config-item>' +

View File

@ -735,7 +735,7 @@ type
procedure ClearErrorList;
{@@ Identifies the "active" worksheet (only for visual controls)}
property ActiveWorksheet: TsWorksheet read FActiveWorksheet;
property ActiveWorksheet: TsWorksheet read FActiveWorksheet write SelectWorksheet;
{@@ Retrieves error messages collected during reading/writing }
property ErrorMsg: String read GetErrorMsg;
{@@ Filename of the saved workbook }
@ -7110,7 +7110,10 @@ begin
if (AWorksheet <> nil) and (FWorksheets.IndexOf(AWorksheet) = -1) then
raise Exception.Create('[TsWorkbook.SelectSheet] Worksheet does not belong to the workbook');
FActiveWorksheet := AWorksheet;
if Assigned(FOnSelectWorksheet) then FOnSelectWorksheet(self, AWorksheet);
if FReadWriteFlag = rwfRead then
exit;
if Assigned(FOnSelectWorksheet) then
FOnSelectWorksheet(self, AWorksheet);
end;
{@@ ----------------------------------------------------------------------------

View File

@ -76,7 +76,7 @@ type
procedure CellSelectedHandler(Sender: TObject; ARow, ACol: Cardinal);
procedure InternalCreateNewWorkbook;
procedure InternalLoadFromFile(AFileName: string; AAutoDetect: Boolean;
AFormat: TsSpreadsheetFormat; AWorksheetIndex: Integer = 0);
AFormat: TsSpreadsheetFormat; AWorksheetIndex: Integer = -1);
procedure SetFileName(const AFileName: TFileName);
procedure SetOptions(AValue: TsWorkbookOptions);
// procedure WorkbookChangedPaletteHandler(Sender: TObject);
@ -105,9 +105,9 @@ type
procedure CreateNewWorkbook;
procedure LoadFromSpreadsheetFile(AFileName: string;
AFormat: TsSpreadsheetFormat; AWorksheetIndex: Integer = 0); overload;
AFormat: TsSpreadsheetFormat; AWorksheetIndex: Integer = -1); overload;
procedure LoadFromSpreadsheetFile(AFileName: string;
AWorksheetIndex: Integer = 0); overload;
AWorksheetIndex: Integer = -1); overload;
procedure SaveToSpreadsheetFile(AFileName: string;
AOverwriteExisting: Boolean = true); overload;
@ -835,7 +835,7 @@ end;
@param AWorksheetIndex Index of the worksheet to be selected after loading.
-------------------------------------------------------------------------------}
procedure TsWorkbookSource.InternalLoadFromFile(AFileName: string;
AAutoDetect: Boolean; AFormat: TsSpreadsheetFormat; AWorksheetIndex: Integer = 0);
AAutoDetect: Boolean; AFormat: TsSpreadsheetFormat; AWorksheetIndex: Integer = -1);
begin
// Create a new empty workbook
InternalCreateNewWorkbook;
@ -851,6 +851,12 @@ begin
EnableControls;
end;
if AWorksheetIndex = -1 then
begin
if FWorkbook.ActiveWorksheet <> nil then
AWorksheetIndex := FWorkbook.GetWorksheetIndex(FWorkbook.ActiveWorksheet) else
AWorksheetIndex := 0;
end;
SelectWorksheet(FWorkbook.GetWorkSheetByIndex(AWorksheetIndex));
// If required, display loading error message
@ -879,9 +885,10 @@ end;
@param AFilename Name of the spreadsheet file to be loaded
@param AFormat Spreadsheet file format assumed for the file
@param AWorksheetIndex Index of the worksheet to be selected after loading.
(If empty then the active worksheet is loaded)
-------------------------------------------------------------------------------}
procedure TsWorkbookSource.LoadFromSpreadsheetFile(AFileName: string;
AFormat: TsSpreadsheetFormat; AWorksheetIndex: Integer = 0);
AFormat: TsSpreadsheetFormat; AWorksheetIndex: Integer = -1);
begin
InternalLoadFromFile(AFileName, false, AFormat, AWorksheetIndex);
end;
@ -895,9 +902,10 @@ end;
@param AFilename Name of the spreadsheet file to be loaded
@param AWorksheetIndex Index of the worksheet to be selected after loading.
(If empty then the active worksheet is loaded)
-------------------------------------------------------------------------------}
procedure TsWorkbookSource.LoadFromSpreadsheetFile(AFileName: string;
AWorksheetIndex: Integer = 0);
AWorksheetIndex: Integer = -1);
const
sfNotNeeded = sfExcel8;
// The parameter AFormat if InternalLoadFromFile is not needed here,
@ -924,6 +932,17 @@ var
I: IsSpreadsheetControl;
C: TComponent;
begin
{
// Select worksheet in tab control first
if lniWorksheet in AChangedItems then
for j:=0 to FListeners.Count-1 do begin
C := TComponent(FListeners[j]);
if C is TsWorkbookTabControl then begin
C.GetInterface(GUID_SpreadsheetControl, I);
I.ListenerNotification(AChangedItems, AData);
end;
end;
}
for j:=0 to FListeners.Count-1 do begin
C := TComponent(FListeners[j]);
if C.GetInterface(GUID_SpreadsheetControl, I) then
@ -1275,7 +1294,9 @@ procedure TsWorkbookSource.WorkbookOpenedHandler(Sender: TObject);
begin
Unused(Sender);
NotifyListeners([lniWorkbook]);
SelectWorksheet(FWorkbook.GetFirstWorksheet);
if FWorkbook.ActiveWorksheet = nil then
SelectWorksheet(FWorkbook.GetFirstWorksheet) else
SelectWorksheet(FWorkbook.ActiveWorksheet);
end;
{@@ ----------------------------------------------------------------------------
@ -1478,9 +1499,16 @@ begin
begin
inc(FLockCount); // avoid WorkbookSelect message when adding each tab
GetSheetList(Tabs);
{
if (lniWorkbook in AChangedItems) then
TabIndex := 0
else
}
if (lniWorkbook in AChangedItems) and (Workbook <> nil) then
begin
i := Workbook.GetWorksheetIndex(Workbook.ActiveWorksheet);
if i > -1 then TabIndex := i else TabIndex := 0
end else
if (lniWorksheetAdd in AChangedItems) then
TabIndex := Tabs.Count-1
else

View File

@ -237,9 +237,9 @@ type
procedure InsertCol(AGridCol: Integer);
procedure InsertRow(AGridRow: Integer);
procedure LoadFromSpreadsheetFile(AFileName: string;
AFormat: TsSpreadsheetFormat; AWorksheetIndex: Integer = 0); overload;
AFormat: TsSpreadsheetFormat; AWorksheetIndex: Integer = -1); overload;
procedure LoadFromSpreadsheetFile(AFileName: string;
AWorksheetIndex: Integer = 0); overload;
AWorksheetIndex: Integer = -1); overload;
procedure NewWorkbook(AColCount, ARowCount: Integer);
procedure SaveToSpreadsheetFile(AFileName: string;
AOverwriteExisting: Boolean = true); overload;
@ -3433,6 +3433,7 @@ end;
@param AFileName Name of the file to be loaded
@param AFormat Spreadsheet file format assumed for the file
@param AWorksheetIndex Index of the worksheet to be displayed in the grid
(If empty then the active worksheet is loaded)
-------------------------------------------------------------------------------}
procedure TsCustomWorksheetGrid.LoadFromSpreadsheetFile(AFileName: string;
AFormat: TsSpreadsheetFormat; AWorksheetIndex: Integer);
@ -3461,6 +3462,7 @@ end;
@param AFileName Name of the file to be loaded
@param AWorksheetIndex Index of the worksheet to be shown in the grid
(If empty then the active worksheet is loaded)
-------------------------------------------------------------------------------}
procedure TsCustomWorksheetGrid.LoadFromSpreadsheetFile(AFileName: string;
AWorksheetIndex: Integer);

View File

@ -1605,6 +1605,7 @@ procedure TsSpreadBIFF5Writer.WriteWindow2(AStream: TStream;
ASheet: TsWorksheet);
var
Options: Word;
actSheet: TsWorksheet;
begin
{ BIFF Record header }
WriteBiffHeader(AStream, INT_EXCEL_ID_WINDOW2, 10);
@ -1613,10 +1614,11 @@ begin
Options :=
MASK_WINDOW2_OPTION_SHOW_ZERO_VALUES or
MASK_WINDOW2_OPTION_AUTO_GRIDLINE_COLOR or
MASK_WINDOW2_OPTION_SHOW_OUTLINE_SYMBOLS or
MASK_WINDOW2_OPTION_SHOW_OUTLINE_SYMBOLS; { or
MASK_WINDOW2_OPTION_SHEET_SELECTED or
MASK_WINDOW2_OPTION_SHEET_ACTIVE;
{ Bug 0026386 -> every sheet must be selected/active, otherwise Excel cannot print }
MASK_WINDOW2_OPTION_SHEET_ACTIVE; }
{ Bug 0026386 -> every sheet must be selected/active, otherwise Excel cannot print
---> wp: after changes for issue 0028452: this is not necessary any more. }
if (soShowGridLines in ASheet.Options) then
Options := Options or MASK_WINDOW2_OPTION_SHOW_GRID_LINES;
@ -1624,6 +1626,11 @@ begin
Options := Options or MASK_WINDOW2_OPTION_SHOW_SHEET_HEADERS;
if (soHasFrozenPanes in ASheet.Options) and ((ASheet.LeftPaneWidth > 0) or (ASheet.TopPaneHeight > 0)) then
Options := Options or MASK_WINDOW2_OPTION_PANES_ARE_FROZEN;
if FWorkbook.ActiveWorksheet <> nil then
actSheet := FWorkbook.ActiveWorksheet else
actSheet := Fworkbook.GetWorksheetByIndex(0);
if (ASheet = actSheet) then
Options := Options or MASK_WINDOW2_OPTION_SHEET_ACTIVE or MASK_WINDOW2_OPTION_SHEET_SELECTED;
AStream.WriteWord(WordToLE(Options));

View File

@ -3147,6 +3147,7 @@ procedure TsSpreadBIFF8Writer.WriteWINDOW2(AStream: TStream;
ASheet: TsWorksheet);
var
Options: Word;
actSheet: TsWorksheet;
begin
{ BIFF Record header }
WriteBiffHeader(AStream, INT_EXCEL_ID_WINDOW2, 18);
@ -3155,10 +3156,12 @@ begin
Options :=
MASK_WINDOW2_OPTION_SHOW_ZERO_VALUES or
MASK_WINDOW2_OPTION_AUTO_GRIDLINE_COLOR or
MASK_WINDOW2_OPTION_SHOW_OUTLINE_SYMBOLS or
MASK_WINDOW2_OPTION_SHOW_OUTLINE_SYMBOLS;
{or
MASK_WINDOW2_OPTION_SHEET_SELECTED or
MASK_WINDOW2_OPTION_SHEET_ACTIVE;
{ Bug 0026386 -> every sheet must be selected/active, otherwise Excel cannot print }
MASK_WINDOW2_OPTION_SHEET_ACTIVE;}
{ Bug 0026386 -> every sheet must be selected/active, otherwise Excel cannot print
---> wp: after changes for issue 0028452: this is not necessary any more. }
if (soShowGridLines in ASheet.Options) then
Options := Options or MASK_WINDOW2_OPTION_SHOW_GRID_LINES;
@ -3166,6 +3169,11 @@ begin
Options := Options or MASK_WINDOW2_OPTION_SHOW_SHEET_HEADERS;
if (soHasFrozenPanes in ASheet.Options) and ((ASheet.LeftPaneWidth > 0) or (ASheet.TopPaneHeight > 0)) then
Options := Options or MASK_WINDOW2_OPTION_PANES_ARE_FROZEN;
if FWorkbook.ActiveWorksheet <> nil then
actSheet := FWorkbook.ActiveWorksheet else
actSheet := Fworkbook.GetWorksheetByIndex(0);
if (ASheet = actSheet) then
Options := Options or MASK_WINDOW2_OPTION_SHEET_ACTIVE or MASK_WINDOW2_OPTION_SHEET_SELECTED;
AStream.WriteWord(WordToLE(Options));
{ Index to first visible row }

View File

@ -2280,6 +2280,9 @@ begin
FWorksheet.Options := FWorksheet.Options + [soHasFrozenPanes]
else
FWorksheet.Options := FWorksheet.Options - [soHasFrozenPanes];
if (flags and MASK_WINDOW2_OPTION_SHEET_ACTIVE <> 0) then
FWorkbook.SelectWorksheet(FWorksheet);
end;
{ Reads the workbook globals. }

View File

@ -65,6 +65,7 @@ type
procedure ApplyCellFormatting(ACell: PCell; XfIndex: Integer);
procedure ApplyHyperlinks(AWorksheet: TsWorksheet);
function FindCommentsFileName(ANode: TDOMNode): String;
procedure ReadActiveSheet(ANode: TDOMNode; out ActiveSheetIndex: Integer);
procedure ReadBorders(ANode: TDOMNode);
procedure ReadCell(ANode: TDOMNode; AWorksheet: TsWorksheet);
procedure ReadCellXfs(ANode: TDOMNode);
@ -421,6 +422,20 @@ begin
Result := '';
end;
procedure TsSpreadOOXMLReader.ReadActiveSheet(ANode: TDOMNode;
out ActiveSheetIndex: Integer);
var
S: string;
i: Integer;
begin
ActiveSheetIndex := -1;
if ANode = nil then
Exit;
S := GetAttrValue(ANode.FindNode('workbookView'), 'activeTab');
if TryStrToInt(S, i) then
ActiveSheetIndex := i;
end;
procedure TsSpreadOOXMLReader.ReadBorders(ANode: TDOMNode);
function ReadBorderStyle(ANode: TDOMNode;
@ -1883,7 +1898,7 @@ var
i: Integer;
fn: String;
fn_comments: String;
XMLStream: TStream;
actSheetIndex: Integer;
begin
//unzip "content.xml" of "AFileName" to folder "FilePath"
FilePath := GetTempDir(false);
@ -1920,6 +1935,7 @@ begin
ReadFileVersion(Doc.DocumentElement.FindNode('fileVersion'));
ReadDateMode(Doc.DocumentElement.FindNode('workbookPr'));
ReadSheetList(Doc.DocumentElement.FindNode('sheets'), SheetList);
ReadActiveSheet(Doc.DocumentElement.FindNode('bookViews'), actSheetIndex);
FreeAndNil(Doc);
// process the styles.xml file
@ -2004,6 +2020,10 @@ begin
end;
// Add hyperlinks to cells
ApplyHyperlinks(FWorksheet);
// Active worksheet
if i = actSheetIndex then
FWorkbook.SelectWorksheet(FWorksheet);
end; // for
finally
@ -2021,6 +2041,7 @@ var
fn: String;
fn_comments: String;
XMLStream: TStream;
actSheetIndex: Integer;
begin
Doc := nil;
SheetList := TStringList.Create;
@ -2047,6 +2068,7 @@ begin
ReadFileVersion(Doc.DocumentElement.FindNode('fileVersion'));
ReadDateMode(Doc.DocumentElement.FindNode('workbookPr'));
ReadSheetList(Doc.DocumentElement.FindNode('sheets'), SheetList);
ReadActiveSheet(Doc.DocumentElement.FindNode('bookViews'), actSheetIndex);
FreeAndNil(Doc);
finally
XMLStream.Free;
@ -2163,6 +2185,10 @@ begin
// Add hyperlinks to cells
ApplyHyperlinks(FWorksheet);
// Active worksheet
if i = actSheetIndex then
FWorkbook.SelectWorksheet(FWorksheet);
end; // for
finally
@ -3371,6 +3397,7 @@ end;
procedure TsSpreadOOXMLWriter.WriteContent;
var
i, counter: Integer;
actTab: String;
begin
{ --- WorkbookRels --- }
{ Workbook relations - Mark relation to all sheets }
@ -3396,6 +3423,9 @@ begin
{ --- Workbook --- }
{ Global workbook data - Mark all sheets }
actTab := IfThen(FWorkbook.ActiveWorksheet = nil, '',
'activeTab="' + IntToStr(FWorkbook.GetWorksheetIndex(FWOrkbook.ActiveWorksheet)) + '"');
AppendToStream(FSWorkbook,
XML_HEADER);
AppendToStream(FSWorkbook, Format(
@ -3406,7 +3436,7 @@ begin
'<workbookPr defaultThemeVersion="124226" />');
AppendToStream(FSWorkbook,
'<bookViews>' +
'<workbookView xWindow="480" yWindow="90" windowWidth="15195" windowHeight="12525" />' +
'<workbookView xWindow="480" yWindow="90" windowWidth="15195" windowHeight="12525" ' + actTab + '/>' +
'</bookViews>');
AppendToStream(FSWorkbook,
'<sheets>');