diff --git a/components/fpspreadsheet/fpsopendocument.pas b/components/fpspreadsheet/fpsopendocument.pas index 2bd0e4df9..37e648bc9 100755 --- a/components/fpspreadsheet/fpsopendocument.pas +++ b/components/fpspreadsheet/fpsopendocument.pas @@ -142,7 +142,7 @@ type destructor Destroy; override; { General reading methods } -(* procedure ReadFromFile(AFileName: string); override;*) + procedure ReadFromClipboardStream(AStream: TStream); override; procedure ReadFromStream(AStream: TStream); override; end; @@ -229,8 +229,11 @@ type { General writing methods } procedure WriteStringToFile(AString, AFileName: string); + procedure WriteToClipboardStream(AStream: TStream); override; + { procedure WriteToFile(const AFileName: string; const AOverwriteExisting: Boolean = False); override; + } procedure WriteToStream(AStream: TStream); override; end; @@ -2035,131 +2038,12 @@ begin if FIsVirtualMode then Workbook.OnReadCellData(Workbook, ARow, ACol, cell); end; - (* -{ In principle, this method could be simplified by calling ReadFromStream which - is essentially a duplication of ReadFromFile. But ReadFromStream leads to - worse memory usage. --> KEEP READFROMFILE INTACT - See fpspeedtest, ods 20k x 100 cells --> out of mem in Win7-32 bit, 4 GB} -procedure TsSpreadOpenDocReader.ReadFromFile(AFileName: string); -var - Doc : TXMLDocument; - FilePath : string; - UnZip : TUnZipper; - FileList : TStringList; - BodyNode, SpreadSheetNode, TableNode: TDOMNode; - StylesNode: TDOMNode; - OfficeSettingsNode: TDOMNode; - nodename: String; - pageLayout: PsPageLayout; - sheet: TsWorksheet; + +procedure TsSpreadOpenDocReader.ReadFromClipboardStream(AStream: TStream); begin - //unzip files into AFileName path - FilePath := GetUniqueTempDir(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 - ReadXMLFile(Doc, FilePath+'styles.xml'); - DeleteFile(FilePath+'styles.xml'); - - ReadFontFaces(Doc.DocumentElement.FindNode('office:font-face-decls')); - - StylesNode := Doc.DocumentElement.FindNode('office:styles'); - ReadNumFormats(StylesNode); - ReadStyles(StylesNode); - - StylesNode := Doc.DocumentElement.FindNode('office:automatic-styles'); - ReadAutomaticStyles(StylesNode); - - StylesNode := Doc.DocumentElement.FindNode('office:master-styles'); - ReadMasterStyles(StylesNode); - - Doc.Free; - - //process the content.xml file - ReadXMLFile(Doc, FilePath+'content.xml'); - DeleteFile(FilePath+'content.xml'); - - ReadFontFaces(Doc.DocumentElement.FindNode('office:font-face-decls')); - StylesNode := Doc.DocumentElement.FindNode('office:automatic-styles'); - ReadNumFormats(StylesNode); - ReadStyles(StylesNode); - - BodyNode := Doc.DocumentElement.FindNode('office:body'); - if not Assigned(BodyNode) then Exit; - - SpreadSheetNode := BodyNode.FindNode('office:spreadsheet'); - if not Assigned(SpreadSheetNode) then Exit; - - ReadDateMode(SpreadSheetNode); - - //process each table (sheet) - TableNode := SpreadSheetNode.FindNode('table:table'); - while Assigned(TableNode) do - begin - nodename := TableNode.Nodename; - // These nodes occur due to leading spaces which are not skipped - // automatically any more due to PreserveWhiteSpace option applied - // to ReadXMLFile - if nodeName <> 'table:table' then - begin - TableNode := TableNode.NextSibling; - continue; - end; - FWorkSheet := FWorkbook.AddWorksheet(GetAttrValue(TableNode, 'table:name'), true); - // Collect column styles used - ReadColumns(TableNode); - // Process each row inside the sheet and process each cell of the row - ReadRowsAndCells(TableNode); - // Read page layout - pageLayout := ReadPageLayout(StylesNode, GetAttrValue(TableNode, 'table:style-name')); - if pageLayout <> nil then - FWorksheet.PageLayout := pagelayout^; - // Handle columns and rows - ApplyColWidths; - // Page layout - FixCols(FWorksheet); - FixRows(FWorksheet); - // Continue with next table - TableNode := TableNode.NextSibling; - end; //while Assigned(TableNode) - - Doc.Free; - - // process the settings.xml file (Note: it does not always exist!) - if FileExists(FilePath + 'settings.xml') then - begin - ReadXMLFile(Doc, FilePath+'settings.xml'); - DeleteFile(FilePath+'settings.xml'); - - OfficeSettingsNode := Doc.DocumentElement.FindNode('office:settings'); - ReadSettings(OfficeSettingsNode); - end; - - // Active sheet - if FActiveSheet <> '' then - sheet := FWorkbook.GetWorksheetByName(FActiveSheet) else - sheet := FWorkbook.GetWorksheetByIndex(0); - FWorkbook.SelectWorksheet(sheet); - - finally - RemoveDir(FilePath); - if Assigned(Doc) then Doc.Free; - end; + ReadFromStream(AStream); end; - *) + procedure TsSpreadOpenDocReader.ReadFromStream(AStream: TStream); var Doc : TXMLDocument; @@ -4850,7 +4734,7 @@ begin TheStream.WriteBuffer(Pointer(S)^,Length(S)); TheStream.Free; end; - + (* {@@ ---------------------------------------------------------------------------- Writes an OOXML document to a file. -------------------------------------------------------------------------------} @@ -4874,6 +4758,11 @@ begin finally FreeAndNil(lStream); end; +end; *) + +procedure TsSpreadOpenDocWriter.WriteToClipboardStream(AStream: TStream); +begin + WriteToStream(AStream); end; procedure TsSpreadOpenDocWriter.WriteToStream(AStream: TStream); @@ -6233,7 +6122,7 @@ initialization {@@ ---------------------------------------------------------------------------- Registers this reader / writer on fpSpreadsheet -------------------------------------------------------------------------------} - RegisterSpreadFormat(TsSpreadOpenDocReader, TsSpreadOpenDocWriter, sfOpenDocument); + RegisterSpreadFormat(TsSpreadOpenDocReader, TsSpreadOpenDocWriter, sfOpenDocument, true, true); end. diff --git a/components/fpspreadsheet/fpspreadsheetctrls.pas b/components/fpspreadsheet/fpspreadsheetctrls.pas index a4f766f8f..14e9a81e4 100644 --- a/components/fpspreadsheet/fpspreadsheetctrls.pas +++ b/components/fpspreadsheet/fpspreadsheetctrls.pas @@ -465,7 +465,8 @@ procedure Register; implementation uses - Types, Math, StrUtils, TypInfo, LCLType, LCLProc, Dialogs, Forms, Clipbrd, + Types, Math, StrUtils, TypInfo, LCLType, LCLIntf, LCLProc, + Dialogs, Forms, Clipbrd, fpsStrings, fpsUtils, fpsNumFormat, fpsHTMLUtils, fpsCSV; var @@ -474,6 +475,7 @@ var cfHTMLFormat: Integer = 0; cfTextHTMLFormat: Integer = 0; cfCSVFormat: Integer = 0; + cfOpenDocumentFormat: Integer = 0; {@@ ---------------------------------------------------------------------------- Registers the spreadsheet components in the Lazarus component palette, @@ -1140,11 +1142,9 @@ end; -------------------------------------------------------------------------------} procedure TsWorkbookSource.CopyCellsToClipboard; var - r,c,i: Integer; sel: TsCellRangeArray; - cell: PCell; stream: TStream; - csv: TsCSVParams; + savedCSVParams: TsCSVParams; begin sel := FWorksheet.GetSelection; if Length(sel) = 0 then @@ -1156,7 +1156,13 @@ begin stream := TMemoryStream.Create; try - // At first write BIFF8 format + // Write OpenDocument format + FWorkbook.CopyToClipboardStream(stream, sfOpenDocument); + if cfOpenDocumentFormat <> 0 then + Clipboard.AddFormat(cfOpenDocumentFormat, stream); + (stream as TMemoryStream).Clear; + + // Write BIFF8 format FWorkbook.CopyToClipboardStream(stream, sfExcel8); if cfBiff8Format <> 0 then Clipboard.AddFormat(cfBiff8Format, stream); @@ -1177,7 +1183,7 @@ begin (stream as TMemoryStream).Clear; // Then write CSV format - csv := CSVParams; + savedCSVParams := CSVParams; CsvParams.Delimiter := ';'; CsvParams.AutoDetectNumberFormat := false; CsvParams.SheetIndex := FWorkbook.GetWorksheetIndex(FWorkbook.ActiveWorksheet); @@ -1190,7 +1196,7 @@ begin CsvParams.Delimiter := #9; FWorkbook.CopyToClipboardStream(stream, sfCSV); Clipboard.AddFormat(CF_TEXT, stream); - CSVParams := csv; + CSVParams := savedCSVParams; (stream as TMemoryStream).Clear; // To do: XML format @@ -1258,13 +1264,17 @@ begin stream := TMemoryStream.Create; try // Check whether the clipboard content is suitable for fpspreadsheet - if Clipboard.GetFormat(cfBiff8Format, stream) then + if Clipboard.GetFormat(cfOpenDocumentFormat, stream) then + fmt := sfOpenDocument + else if Clipboard.GetFormat(cfBiff8Format, stream) then fmt := sfExcel8 else if Clipboard.GetFormat(cfBiff5Format, stream) then fmt := sfExcel5 else if Clipboard.GetFormat(cfHTMLFormat, stream) or Clipboard.GetFormat(cfTextHTMLFormat, stream) then fmt := sfHTML - else if Clipboard.GetFormat(cfCSVFormat, stream) or Clipboard.GetFormat(CF_TEXT, stream) then + else if Clipboard.GetFormat(cfCSVFormat, stream) then //or Clipboard.GetFormat(CF_TEXT, stream) then + fmt := sfCSV + else if Clipboard.GetFormat(PredefinedClipboardFormat(pcfText), stream) then fmt := sfCSV else begin // Exit if there are no spreadsheet data in clipboard @@ -3183,13 +3193,28 @@ initialization RegisterPropertyToSkip(TsSpreadsheetInspector, 'RowHeights', 'For compatibility with older Laz versions.', ''); RegisterPropertyToSkip(TsSpreadsheetInspector, 'ColWidths', 'For compatibility with older Laz versions.', ''); - - cfBiff8Format := RegisterClipboardFormat('Biff8'); + (* + {$IFDEF MSWINDOWS} + cfOpenDocumentFormat := RegisterClipboardFormat('Star Embed Source (XML)'); + {$ELSE} + cfOpenDocumentFormat := RegisterClipboardFormat('application/x-openoffice-embed-source-xml;windows_formatname="Star Embed Source (XML)'); + {$ENDIF} + *) + cfOpenDocumentFormat := RegisterClipboardFormat('application/x-openoffice-embed-source-xml;windows_formatname="Star Embed Source (XML)"'); +// cfOpenDocumentFormat := RegisterClipboardFormat('application/x-openoffice;windows_formatname="Star Embed Source (XML)"'); + //cfOpenDocumentFormat := RegisterClipboardFormat('Star Embed Source (XML)'); +// cfBiff8Format := RegisterClipboardFormat('application/vnd.ms-excel'); //Biff8'); + cfBiff8Format := RegisterclipboardFormat('Biff8'); cfBiff5Format := RegisterClipboardFormat('Biff5'); cfHTMLFormat := RegisterClipboardFormat('HTML Format'); cfTextHTMLFormat := RegisterClipboardFormat('text/html'); cfCSVFormat := RegisterClipboardFormat('CSV'); + // xls: application/vnd.ms-excel + // xlsx: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet + + // ods: application/x-openoffice-embed-source-xml;windows_formatname="Star Embed Source (XML)" -- Linux -- tested + // ods: Star Embed Source (XML) -- Windows finalization // CellClipboard.Free;