You've already forked lazarus-ccr
fpspreadsheet: Experiments with ods to/from clipboard
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4362 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -142,7 +142,7 @@ type
|
|||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
|
||||||
{ General reading methods }
|
{ General reading methods }
|
||||||
(* procedure ReadFromFile(AFileName: string); override;*)
|
procedure ReadFromClipboardStream(AStream: TStream); override;
|
||||||
procedure ReadFromStream(AStream: TStream); override;
|
procedure ReadFromStream(AStream: TStream); override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -229,8 +229,11 @@ type
|
|||||||
|
|
||||||
{ General writing methods }
|
{ General writing methods }
|
||||||
procedure WriteStringToFile(AString, AFileName: string);
|
procedure WriteStringToFile(AString, AFileName: string);
|
||||||
|
procedure WriteToClipboardStream(AStream: TStream); override;
|
||||||
|
{
|
||||||
procedure WriteToFile(const AFileName: string;
|
procedure WriteToFile(const AFileName: string;
|
||||||
const AOverwriteExisting: Boolean = False); override;
|
const AOverwriteExisting: Boolean = False); override;
|
||||||
|
}
|
||||||
procedure WriteToStream(AStream: TStream); override;
|
procedure WriteToStream(AStream: TStream); override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -2035,131 +2038,12 @@ begin
|
|||||||
if FIsVirtualMode then
|
if FIsVirtualMode then
|
||||||
Workbook.OnReadCellData(Workbook, ARow, ACol, cell);
|
Workbook.OnReadCellData(Workbook, ARow, ACol, cell);
|
||||||
end;
|
end;
|
||||||
(*
|
|
||||||
{ In principle, this method could be simplified by calling ReadFromStream which
|
procedure TsSpreadOpenDocReader.ReadFromClipboardStream(AStream: TStream);
|
||||||
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;
|
|
||||||
begin
|
begin
|
||||||
//unzip files into AFileName path
|
ReadFromStream(AStream);
|
||||||
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;
|
|
||||||
end;
|
end;
|
||||||
*)
|
|
||||||
procedure TsSpreadOpenDocReader.ReadFromStream(AStream: TStream);
|
procedure TsSpreadOpenDocReader.ReadFromStream(AStream: TStream);
|
||||||
var
|
var
|
||||||
Doc : TXMLDocument;
|
Doc : TXMLDocument;
|
||||||
@ -4850,7 +4734,7 @@ begin
|
|||||||
TheStream.WriteBuffer(Pointer(S)^,Length(S));
|
TheStream.WriteBuffer(Pointer(S)^,Length(S));
|
||||||
TheStream.Free;
|
TheStream.Free;
|
||||||
end;
|
end;
|
||||||
|
(*
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Writes an OOXML document to a file.
|
Writes an OOXML document to a file.
|
||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
@ -4874,6 +4758,11 @@ begin
|
|||||||
finally
|
finally
|
||||||
FreeAndNil(lStream);
|
FreeAndNil(lStream);
|
||||||
end;
|
end;
|
||||||
|
end; *)
|
||||||
|
|
||||||
|
procedure TsSpreadOpenDocWriter.WriteToClipboardStream(AStream: TStream);
|
||||||
|
begin
|
||||||
|
WriteToStream(AStream);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TsSpreadOpenDocWriter.WriteToStream(AStream: TStream);
|
procedure TsSpreadOpenDocWriter.WriteToStream(AStream: TStream);
|
||||||
@ -6233,7 +6122,7 @@ initialization
|
|||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Registers this reader / writer on fpSpreadsheet
|
Registers this reader / writer on fpSpreadsheet
|
||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
RegisterSpreadFormat(TsSpreadOpenDocReader, TsSpreadOpenDocWriter, sfOpenDocument);
|
RegisterSpreadFormat(TsSpreadOpenDocReader, TsSpreadOpenDocWriter, sfOpenDocument, true, true);
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -465,7 +465,8 @@ procedure Register;
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
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;
|
fpsStrings, fpsUtils, fpsNumFormat, fpsHTMLUtils, fpsCSV;
|
||||||
|
|
||||||
var
|
var
|
||||||
@ -474,6 +475,7 @@ var
|
|||||||
cfHTMLFormat: Integer = 0;
|
cfHTMLFormat: Integer = 0;
|
||||||
cfTextHTMLFormat: Integer = 0;
|
cfTextHTMLFormat: Integer = 0;
|
||||||
cfCSVFormat: Integer = 0;
|
cfCSVFormat: Integer = 0;
|
||||||
|
cfOpenDocumentFormat: Integer = 0;
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Registers the spreadsheet components in the Lazarus component palette,
|
Registers the spreadsheet components in the Lazarus component palette,
|
||||||
@ -1140,11 +1142,9 @@ end;
|
|||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
procedure TsWorkbookSource.CopyCellsToClipboard;
|
procedure TsWorkbookSource.CopyCellsToClipboard;
|
||||||
var
|
var
|
||||||
r,c,i: Integer;
|
|
||||||
sel: TsCellRangeArray;
|
sel: TsCellRangeArray;
|
||||||
cell: PCell;
|
|
||||||
stream: TStream;
|
stream: TStream;
|
||||||
csv: TsCSVParams;
|
savedCSVParams: TsCSVParams;
|
||||||
begin
|
begin
|
||||||
sel := FWorksheet.GetSelection;
|
sel := FWorksheet.GetSelection;
|
||||||
if Length(sel) = 0 then
|
if Length(sel) = 0 then
|
||||||
@ -1156,7 +1156,13 @@ begin
|
|||||||
|
|
||||||
stream := TMemoryStream.Create;
|
stream := TMemoryStream.Create;
|
||||||
try
|
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);
|
FWorkbook.CopyToClipboardStream(stream, sfExcel8);
|
||||||
if cfBiff8Format <> 0 then
|
if cfBiff8Format <> 0 then
|
||||||
Clipboard.AddFormat(cfBiff8Format, stream);
|
Clipboard.AddFormat(cfBiff8Format, stream);
|
||||||
@ -1177,7 +1183,7 @@ begin
|
|||||||
(stream as TMemoryStream).Clear;
|
(stream as TMemoryStream).Clear;
|
||||||
|
|
||||||
// Then write CSV format
|
// Then write CSV format
|
||||||
csv := CSVParams;
|
savedCSVParams := CSVParams;
|
||||||
CsvParams.Delimiter := ';';
|
CsvParams.Delimiter := ';';
|
||||||
CsvParams.AutoDetectNumberFormat := false;
|
CsvParams.AutoDetectNumberFormat := false;
|
||||||
CsvParams.SheetIndex := FWorkbook.GetWorksheetIndex(FWorkbook.ActiveWorksheet);
|
CsvParams.SheetIndex := FWorkbook.GetWorksheetIndex(FWorkbook.ActiveWorksheet);
|
||||||
@ -1190,7 +1196,7 @@ begin
|
|||||||
CsvParams.Delimiter := #9;
|
CsvParams.Delimiter := #9;
|
||||||
FWorkbook.CopyToClipboardStream(stream, sfCSV);
|
FWorkbook.CopyToClipboardStream(stream, sfCSV);
|
||||||
Clipboard.AddFormat(CF_TEXT, stream);
|
Clipboard.AddFormat(CF_TEXT, stream);
|
||||||
CSVParams := csv;
|
CSVParams := savedCSVParams;
|
||||||
(stream as TMemoryStream).Clear;
|
(stream as TMemoryStream).Clear;
|
||||||
|
|
||||||
// To do: XML format
|
// To do: XML format
|
||||||
@ -1258,13 +1264,17 @@ begin
|
|||||||
stream := TMemoryStream.Create;
|
stream := TMemoryStream.Create;
|
||||||
try
|
try
|
||||||
// Check whether the clipboard content is suitable for fpspreadsheet
|
// 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
|
fmt := sfExcel8
|
||||||
else if Clipboard.GetFormat(cfBiff5Format, stream) then
|
else if Clipboard.GetFormat(cfBiff5Format, stream) then
|
||||||
fmt := sfExcel5
|
fmt := sfExcel5
|
||||||
else if Clipboard.GetFormat(cfHTMLFormat, stream) or Clipboard.GetFormat(cfTextHTMLFormat, stream) then
|
else if Clipboard.GetFormat(cfHTMLFormat, stream) or Clipboard.GetFormat(cfTextHTMLFormat, stream) then
|
||||||
fmt := sfHTML
|
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
|
fmt := sfCSV
|
||||||
else begin
|
else begin
|
||||||
// Exit if there are no spreadsheet data in clipboard
|
// 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, 'RowHeights', 'For compatibility with older Laz versions.', '');
|
||||||
RegisterPropertyToSkip(TsSpreadsheetInspector, 'ColWidths', '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');
|
cfBiff5Format := RegisterClipboardFormat('Biff5');
|
||||||
cfHTMLFormat := RegisterClipboardFormat('HTML Format');
|
cfHTMLFormat := RegisterClipboardFormat('HTML Format');
|
||||||
cfTextHTMLFormat := RegisterClipboardFormat('text/html');
|
cfTextHTMLFormat := RegisterClipboardFormat('text/html');
|
||||||
cfCSVFormat := RegisterClipboardFormat('CSV');
|
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
|
finalization
|
||||||
// CellClipboard.Free;
|
// CellClipboard.Free;
|
||||||
|
Reference in New Issue
Block a user