diff --git a/components/fpspreadsheet/fpshtml.pas b/components/fpspreadsheet/fpshtml.pas index 8fcde3e87..670277199 100644 --- a/components/fpspreadsheet/fpshtml.pas +++ b/components/fpspreadsheet/fpshtml.pas @@ -1310,7 +1310,7 @@ begin begin w := FWorksheet.DefaultColWidth; col := FWorksheet.FindCol(AColIndex); - if col <> nil then + if (col <> nil) and (col^.Width > 0) then w := col^.Width; end; w := w * FWorkbook.GetDefaultFont.Size; diff --git a/components/fpspreadsheet/fpsopendocument.pas b/components/fpspreadsheet/fpsopendocument.pas index 52c634396..2a00a3af4 100755 --- a/components/fpspreadsheet/fpsopendocument.pas +++ b/components/fpspreadsheet/fpsopendocument.pas @@ -192,6 +192,7 @@ type procedure AddBuiltinNumFormats; override; procedure CreateStreams; procedure DestroyStreams; + procedure InternalWriteToStream(AStream: TStream); procedure ListAllColumnStyles; procedure ListAllHeaderFooterFonts; procedure ListAllNumFormats; override; @@ -233,6 +234,9 @@ type procedure WriteToStream(AStream: TStream; AParam: Integer = 0); override; end; +procedure WriteStarObjectDescriptorToStream(AStream: TStream); + + implementation uses @@ -354,6 +358,27 @@ type end; *) + +{******************************************************************************} +{ Clipboard utility } +{******************************************************************************} + +{@@ ---------------------------------------------------------------------------- + Writes the "Star Object Descriptor". This is written to the clipboard by + Open/LibreOffice. No idea about the meaning of this... +-------------------------------------------------------------------------------} +procedure WriteStarObjectDescriptorToStream(AStream: TStream); +const + BYTES: packed array[0..$38] of byte = ( + $39,$00,$00,$00,$CB,$B4,$BB,$47,$4C,$CE,$80,$4E,$A5,$91,$42,$D9, + $AE,$74,$95,$0F,$01,$00,$00,$00,$D2,$08,$00,$00,$C4,$01,$00,$00, + $00,$00,$00,$00,$00,$00,$00,$00,$05,$00,$63,$61,$6C,$63,$38,$00, + $00,$67,$45,$23,$01,$EF,$CD,$AB,$89); +begin + AStream.Write(BYTES, SizeOf(BYTES)); +end; + + {******************************************************************************} { TXMLHeaderFooterFont } {******************************************************************************} @@ -3657,6 +3682,49 @@ begin DestroyStream(FSMetaInfManifest); end; +procedure TsSpreadOpenDocWriter.InternalWriteToStream(AStream: TStream); +var + FZip: TZipper; +begin + { Analyze the workbook and collect all information needed } + ListAllNumFormats; + ListAllColumnStyles; + ListAllRowStyles; + ListAllHeaderFooterFonts; + + { Create the streams that will hold the file contents } + CreateStreams; + + { Fill the strings with the contents of the files } + WriteMimetype(); + WriteMetaInfManifest(); + WriteMeta(); + WriteSettings(); + WriteStyles(); + WriteContent; + + { Now compress the files } + FZip := TZipper.Create; + try + FZip.FileName := '__temp__.tmp'; + + FZip.Entries.AddFileEntry(FSMeta, OPENDOC_PATH_META); + FZip.Entries.AddFileEntry(FSSettings, OPENDOC_PATH_SETTINGS); + FZip.Entries.AddFileEntry(FSStyles, OPENDOC_PATH_STYLES); + FZip.Entries.AddFileEntry(FSContent, OPENDOC_PATH_CONTENT); + FZip.Entries.AddFileEntry(FSMimetype, OPENDOC_PATH_MIMETYPE); + FZip.Entries.AddFileEntry(FSMetaInfManifest, OPENDOC_PATH_METAINF_MANIFEST); + + ResetStreams; + + FZip.SaveToStream(AStream); + + finally + DestroyStreams; + FZip.Free; + end; +end; + procedure TsSpreadOpenDocWriter.ListAllColumnStyles; var i, j, c: Integer; @@ -4764,48 +4832,9 @@ end; procedure TsSpreadOpenDocWriter.WriteToStream(AStream: TStream; AParam: Integer = 0); -var - FZip: TZipper; begin Unused(AParam); - - { Analyze the workbook and collect all information needed } - ListAllNumFormats; - ListAllColumnStyles; - ListAllRowStyles; - ListAllHeaderFooterFonts; - - { Create the streams that will hold the file contents } - CreateStreams; - - { Fill the strings with the contents of the files } - WriteMimetype(); - WriteMetaInfManifest(); - WriteMeta(); - WriteSettings(); - WriteStyles(); - WriteContent; - - { Now compress the files } - FZip := TZipper.Create; - try - FZip.FileName := '__temp__.tmp'; - - FZip.Entries.AddFileEntry(FSMeta, OPENDOC_PATH_META); - FZip.Entries.AddFileEntry(FSSettings, OPENDOC_PATH_SETTINGS); - FZip.Entries.AddFileEntry(FSStyles, OPENDOC_PATH_STYLES); - FZip.Entries.AddFileEntry(FSContent, OPENDOC_PATH_CONTENT); - FZip.Entries.AddFileEntry(FSMimetype, OPENDOC_PATH_MIMETYPE); - FZip.Entries.AddFileEntry(FSMetaInfManifest, OPENDOC_PATH_METAINF_MANIFEST); - - ResetStreams; - - FZip.SaveToStream(AStream); - - finally - DestroyStreams; - FZip.Free; - end; + InternalWriteToStream(AStream); end; { Writes an empty cell to the stream } @@ -6117,6 +6146,7 @@ begin end; end; + initialization {@@ ---------------------------------------------------------------------------- diff --git a/components/fpspreadsheet/fpspreadsheetctrls.pas b/components/fpspreadsheet/fpspreadsheetctrls.pas index d30d9f4e4..a808f8328 100644 --- a/components/fpspreadsheet/fpspreadsheetctrls.pas +++ b/components/fpspreadsheet/fpspreadsheetctrls.pas @@ -468,7 +468,7 @@ implementation uses Types, Math, StrUtils, TypInfo, LCLType, LCLIntf, LCLProc, Dialogs, Forms, Clipbrd, - fpsStrings, fpsUtils, fpsNumFormat, fpsHTMLUtils, fpsCSV; + fpsStrings, fpsUtils, fpsNumFormat, fpsHTMLUtils, fpsCSV, fpsOpenDocument; var cfBiff8Format: Integer = 0; @@ -477,6 +477,7 @@ var cfTextHTMLFormat: Integer = 0; cfCSVFormat: Integer = 0; cfOpenDocumentFormat: Integer = 0; + cfStarObjectDescriptor: Integer = 0; {@@ ---------------------------------------------------------------------------- Registers the spreadsheet components in the Lazarus component palette, @@ -1136,7 +1137,17 @@ var sel: TsCellRangeArray; stream: TStream; savedCSVParams: TsCSVParams; - param: Integer; + + procedure CopyToClipboard(AStream: TStream; AFileFormat: TsSpreadsheetFormat; + AClipboardFormat: Integer; AParam: Integer = 0); + begin + if AClipboardFormat = 0 then + exit; + FWorkbook.CopyToClipboardStream(AStream, AFileFormat, AParam); + Clipboard.AddFormat(AClipboardFormat, AStream); + (AStream as TMemoryStream).Clear; + end; + begin sel := FWorksheet.GetSelection; if Length(sel) = 0 then @@ -1149,82 +1160,47 @@ begin stream := TMemoryStream.Create; try // Write OpenDocument format - FWorkbook.CopyToClipboardStream(stream, sfOpenDocument); - if cfOpenDocumentFormat <> 0 then - Clipboard.AddFormat(cfOpenDocumentFormat, stream); + CopyToClipboard(stream, sfOpenDocument, cfOpenDocumentFormat); + + // Write OpenDocument's "Star Object Descriptor" + WriteStarObjectDescriptorToStream(stream); + if cfStarObjectDescriptor <> 0 then + Clipboard.AddFormat(cfStarObjectDescriptor, stream); (stream as TMemoryStream).Clear; // Write BIFF8 format - FWorkbook.CopyToClipboardStream(stream, sfExcel8); - if cfBiff8Format <> 0 then - Clipboard.AddFormat(cfBiff8Format, stream); - (stream as TMemoryStream).Clear; + CopyToClipboard(stream, sfExcel8, cfBiff8Format); // Then write BIFF5 format - FWorkbook.CopyToClipboardStream(stream, sfExcel5); - if cfBiff5Format <> 0 then - Clipboard.AddFormat(cfBiff5Format, stream); - (stream as TMemoryStream).Clear; + CopyToClipboard(stream, sfExcel5, cfBiff5Format); // Then write Windows HTML format {$IFDEF MSWINDOWS} - param := PARAM_WINDOWS_CLIPBOARD_HTML; - FWorkbook.CopyToClipboardStream(stream, sfHTML, param); - if cfHtmlFormat <> 0 then - Clipboard.AddFormat(cfHTMLFormat, stream); - (stream as TMemoryStream).Clear; + CopyToClipboard(stream, sfHTML, cfHtmlFormat, PARAM_WINDOWS_CLIPBOARD_HTML); {$ENDIF} // Write standard html format (MIME-type "text/html") - FWorkbook.CopyToClipboardStream(stream, sfHTML); - if cfTextHtmlFormat <> 0 then - Clipboard.AddFormat(cfTextHTMLFormat, stream); - (stream as TMemoryStream).Clear; + CopyToClipboard(stream, sfHTML, cfTextHTMLFormat); // Then write CSV format savedCSVParams := CSVParams; CsvParams.Delimiter := ';'; CsvParams.AutoDetectNumberFormat := false; CsvParams.SheetIndex := FWorkbook.GetWorksheetIndex(FWorkbook.ActiveWorksheet); - FWorkbook.CopyToClipboardStream(stream, sfCSV); - if cfCSVFormat <> 0 then - Clipboard.AddFormat(cfCSVFormat, stream); - (stream as TMemoryStream).Clear; + CopyToClipboard(stream, sfCSV, cfCSVFormat); // Finally write TEXT format CsvParams.Delimiter := #9; - FWorkbook.CopyToClipboardStream(stream, sfCSV); - Clipboard.AddFormat(CF_TEXT, stream); + CopyToClipboard(stream, sfCSV, CF_TEXT); CSVParams := savedCSVParams; - (stream as TMemoryStream).Clear; // To do: XML format - // I don't know which format is written by xlsx and ods natively. finally stream.Free; end; finally Clipboard.Close; end; - (* - exit; - - - ClearCellClipboard; - - for i:=0 to High(sel) do - for r := sel[i].Row1 to sel[i].Row2 do - for c := sel[i].Col1 to sel[i].Col2 do - begin - cell := FWorksheet.FindCell(r, c); - if cell = nil then - CellClipboard.AddEmptyCell(r, c) - else - CellClipboard.AddCell(cell); - end; - - CellClipboard.MultipleRanges := (Length(sel) > 1); - *) end; {@@ ---------------------------------------------------------------------------- @@ -3200,6 +3176,7 @@ initialization {$ENDIF} *) cfOpenDocumentFormat := RegisterClipboardFormat('application/x-openoffice-embed-source-xml;windows_formatname="Star Embed Source (XML)"'); + cfStarObjectDescriptor := RegisterClipboardFormat('application/x-openoffice-objectdescriptor-xml;windows_formatname="Star Object Descriptor (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');