fpspreadsheet: Improved cooperation of visual controls with clipboard.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4363 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2015-09-28 20:23:28 +00:00
parent 295db4cdda
commit 95704110ce
7 changed files with 157 additions and 98 deletions

View File

@ -348,6 +348,7 @@ type
procedure AcShowGridLinesExecute(Sender: TObject);
procedure AcShowGridLinesUpdate(Sender: TObject);
procedure AcViewInspectorExecute(Sender: TObject);
procedure EditCut1Execute(Sender: TObject);
procedure HyperlinkHandler(Sender: TObject; ACaption: String;
var AHyperlink: TsHyperlink);
procedure InspectorTabControlChange(Sender: TObject);
@ -581,6 +582,11 @@ begin
InspectorSplitter.Left := 0; // Make sure that the splitter is always at the left of the inspector
end;
procedure TMainForm.EditCut1Execute(Sender: TObject);
begin
//
end;
{ Event handler for hyperlinks: it only has to provide the hyperlink data
which are applied to the active cell by the TsCellHyperlinkAction.
Is called by the "new hyperlink" and "edit hyperlink" actions.

View File

@ -118,6 +118,7 @@ type
FCopyMode: TsCopyMode;
public
procedure ExecuteTarget(Target: TObject); override;
function HandlesTarget(Target: TObject): Boolean; override;
procedure UpdateTarget(Target: TObject); override;
published
property Caption;
@ -525,7 +526,7 @@ implementation
uses
StdCtrls, ExtCtrls, Buttons, Forms,
fpsUtils, fpsNumFormat, fpsVisualUtils;
fpsUtils, fpsNumFormat, fpsVisualUtils, fpSpreadsheetGrid;
procedure Register;
begin
@ -767,28 +768,47 @@ const
coCopyFormat, coCopyValue, coCopyFormula, coCopyCell
);
begin
Unused(Target);
if Target is TsCustomWorksheetGrid then
case FCopyMode of
cmBrush:
begin
Checked := true;
WorkbookSource.SetPendingOperation(OPERATIONS[FCopyItem], Worksheet.GetSelection);
end;
cmCopy:
begin
Checked := false;
WorkbookSource.CopyCellsToClipboard;
end;
cmCut:
begin
Checked := false;
WorkbookSource.CutCellsToClipboard;
end;
cmPaste:
begin
Checked := false;
WorkbookSource.PasteCellsFromClipboard(OPERATIONS[FCopyItem]);
end;
end
else
if Target is TCustomEdit then
case FCopyMode of
cmBrush : ;
cmCopy : (Target as TCustomEdit).CopyToClipboard;
cmCut : (Target as TCustomEdit).CutToClipboard;
cmPaste : (Target as TCustomEdit).PasteFromClipboard;
end;
end;
function TsCopyAction.HandlesTarget(Target: TObject): Boolean;
begin
case FCopyMode of
cmBrush:
begin
Checked := true;
WorkbookSource.SetPendingOperation(OPERATIONS[FCopyItem], Worksheet.GetSelection);
end;
cmCopy:
begin
Checked := false;
WorkbookSource.CopyCellsToClipboard;
end;
cmCut:
begin
Checked := false;
WorkbookSource.CutCellsToClipboard;
end;
cmPaste:
begin
Checked := false;
WorkbookSource.PasteCellsFromClipboard(OPERATIONS[FCopyItem]);
end;
cmBrush: Result := inherited HandlesTarget(Target);
cmCopy,
cmCut,
cmPaste: Result := (Target <> nil) and
( (Target is TsCustomWorksheetGrid) or (Target is TCustomEdit) );
end;
end;

View File

@ -22,6 +22,7 @@ type
procedure ReadNumber(AStream: TStream); override;
public
constructor Create(AWorkbook: TsWorkbook); override;
procedure ReadFromClipboardStream(AStream: TStream); override;
procedure ReadFromFile(AFileName: String); override;
procedure ReadFromStream(AStream: TStream); override;
procedure ReadFromStrings(AStrings: TStrings); override;
@ -200,6 +201,11 @@ begin
Unused(AStream);
end;
procedure TsCSVReader.ReadFromClipboardStream(AStream: TStream);
begin
ReadFromStream(AStream);
end;
procedure TsCSVReader.ReadFromFile(AFileName: String);
begin
FWorksheetName := ChangeFileExt(ExtractFileName(AFileName), '');
@ -372,9 +378,10 @@ end;
procedure TsCSVWriter.WriteSheet(AStream: TStream; AWorksheet: TsWorksheet);
var
r: Cardinal;
FirstRow: Cardinal;
LastRow: Cardinal;
firstRow: Cardinal;
lastRow: Cardinal;
cell: PCell;
n: Integer;
begin
FWorksheet := AWorksheet;
@ -385,15 +392,23 @@ begin
FCSVBuilder.QuoteChar := CSVParams.QuoteChar;
FCSVBuilder.SetOutput(AStream);
if FClipboardMode then
FirstRow := FWorksheet.GetFirstRowIndex else
FirstRow := 0;
LastRow := FWorksheet.GetLastOccupiedRowIndex;
for r := FirstRow to LastRow do
n := FWorksheet.GetCellCount;
if FClipboardMode and (n = 1) then
begin
for cell in FWorksheet.Cells.GetRowEnumerator(r) do
WriteCellToStream(AStream, cell);
FCSVBuilder.AppendRow;
cell := FWorksheet.Cells.GetFirstCell;
WriteCellToStream(AStream, cell);
end else
begin
if FClipboardMode then
firstRow := FWorksheet.GetFirstRowIndex else
firstRow := 0;
lastRow := FWorksheet.GetLastOccupiedRowIndex;
for r := firstRow to lastRow do
begin
for cell in FWorksheet.Cells.GetRowEnumerator(r) do
WriteCellToStream(AStream, cell);
FCSVBuilder.AppendRow;
end;
end;
finally
FreeAndNil(FCSVBuilder);
@ -433,7 +448,7 @@ end;
initialization
InitFormatSettings(CSVParams.FormatSettings);
RegisterSpreadFormat(TsCSVReader, TsCSVWriter, sfCSV, false, true);
RegisterSpreadFormat(TsCSVReader, TsCSVWriter, sfCSV, true, true);
end.

View File

@ -1601,6 +1601,10 @@ begin
toRow := AToCell^.Row;
toCol := AToCell^.Col;
// Avoid misplaced notifications during the copy operations when things could
// not yet be in place.
FWorkbook.DisableNotifications;
// Copy cell values
AToCell^ := AFromCell^;
@ -1648,6 +1652,11 @@ begin
end;
end;
FWorkbook.EnableNotifications;
// Notify visual controls of changes
ChangedCell(AToCell^.Row, AToCell^.Col);
// Notify visual controls of possibly changed row heights.
ChangedFont(AToCell^.Row, AToCell^.Col);
end;
@ -7876,27 +7885,30 @@ begin
end;
// Select the same cells as in the clipboard
n := clipsheet.GetSelectionCount;
SetLength(selArray, n);
for i := 0 to n-1 do
begin
sel := clipsheet.GetSelection[i];
selArray[i].Row1 := sel.Row1 + dr;
selArray[i].Col1 := sel.Col1 + dc;
selArray[i].Row2 := sel.Row2 + dr;
selArray[i].Col2 := sel.Col2 + dc;
if n > 0 then
begin
SetLength(selArray, n);
for i := 0 to n-1 do
begin
sel := clipsheet.GetSelection[i];
selArray[i].Row1 := sel.Row1 + dr;
selArray[i].Col1 := sel.Col1 + dc;
selArray[i].Row2 := sel.Row2 + dr;
selArray[i].Col2 := sel.Col2 + dc;
end;
ActiveWorksheet.SetSelection(selArray);
// Select active cell. If not found in the file, let's use the last cell of the selections
if (clipsheet.ActiveCellRow <> 0) and (clipsheet.ActiveCellCol <> 0) then
begin
r := clipsheet.ActiveCellRow;
c := clipsheet.ActiveCellCol;
end else
begin
r := sel.Row2;
c := sel.Col2;
end;
ActiveWorksheet.SelectCell(r + dr, c + dc);
end;
ActiveWorksheet.SetSelection(selArray);
// Select active cell. If not found in the file, let's use the last cell of the selections
if (clipsheet.ActiveCellRow <> 0) and (clipsheet.ActiveCellCol <> 0) then
begin
r := clipsheet.ActiveCellRow;
c := clipsheet.ActiveCellCol;
end else
begin
r := sel.Row2;
c := sel.Col2;
end;
ActiveWorksheet.SelectCell(r + dr, c + dc);
finally
clipbook.Free;
end;

View File

@ -237,7 +237,7 @@ begin
end else
if cell^.ContentType = cctUTF8String then begin
FCurItem.X := AIndex;
FCurItem.Text := FDataWorksheet.ReadAsUTF8Text(cell);
FCurItem.Text := FDataWorksheet.ReadAsText(cell);
end else
begin
FCurItem.X := FDataWorksheet.ReadAsNumber(cell);
@ -473,7 +473,7 @@ begin
end else
if cell^.ContentType = cctUTF8String then begin
ANumber := APointIndex;
AText := FWorksheets[rngX].ReadAsUTF8Text(cell);
AText := FWorksheets[rngX].ReadAsText(cell);
end else
begin
ANumber := FWorksheets[rngX].ReadAsNumber(cell);

View File

@ -270,6 +270,7 @@ type
{ TsCellFormatItem }
TsCellFormatItem = (cfiFontName, cfiFontSize, cfiFontColor, cfiBackgroundColor,
cfiBorderColor);
@ -498,6 +499,7 @@ function SpreadsheetFormatInClipboard: Boolean;
begin
Result := Clipboard.HasFormat(cfBiff8Format) or
Clipboard.HasFormat(cfBiff5Format) or
Clipboard.HasFormat(cfOpenDocumentFormat) or
Clipboard.HasFormat(cfHTMLFormat) or
Clipboard.HasFormat(cfTextHTMLFormat) or
Clipboard.HasFormat(cfCSVFormat) or
@ -955,23 +957,12 @@ 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
I.ListenerNotification(AChangedItems, AData)
else
raise Exception.CreateFmt('Class %s is not prepared to be a spreadsheet listener.',
raise Exception.CreateFmt('[TsWorkbookSource.NotifyListeners] Class %s is not prepared to be a spreadsheet listener.',
[C.ClassName]);
end;
end;
@ -1258,40 +1249,37 @@ var
cf: Integer;
fmt: TsSpreadsheetFormat;
stream: TStream;
s: String;
begin
Clipboard.Open;
stream := TMemoryStream.Create;
try
stream := TMemoryStream.Create;
try
// Check whether the clipboard content is suitable for fpspreadsheet
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) 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
MessageDlg('No appropriate spreadsheet data in clipboard', mtError, [mbOk], 0);
exit;
end;
// Paste stream into workbook
FWorkbook.PasteFromClipboardStream(stream, fmt, AItem);
// To do: XML format
// I don't know which format is written by xlsx and ods natively.
finally
stream.Free;
// Check whether the clipboard content is suitable for fpspreadsheet
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) then
fmt := sfCSV
else if Clipboard.GetFormat(CF_TEXT, stream) then
fmt := sfCSV
else begin
// Exit if there are no spreadsheet data in clipboard
MessageDlg('No appropriate spreadsheet data in clipboard', mtError, [mbOk], 0);
exit;
end;
// Paste stream into workbook
stream.Position := 0;
FWorkbook.PasteFromClipboardStream(stream, fmt, AItem);
// To do: XML format
// I don't know which format is written by xlsx and ods natively.
finally
Clipboard.Close;
stream.Free;
end;
(*

View File

@ -151,6 +151,9 @@ type
procedure CreateNewWorkbook;
procedure DblClick; override;
procedure DefineProperties(Filer: TFiler); override;
procedure DoCopyToClipboard; override;
procedure DoCutToClipboard; override;
procedure DoPasteFromClipboard; override;
procedure DoOnResize; override;
procedure DoPrepareCanvas(ACol, ARow: Integer; AState: TGridDrawState); override;
procedure DrawAllRows; override;
@ -1329,6 +1332,21 @@ begin
Unused(Filer);
end;
procedure TsCustomWorksheetGrid.DoCopyToClipboard;
begin
WorkbookSource.CopyCellsToClipboard;
end;
procedure TsCustomWorksheetGrid.DoCutToClipboard;
begin
WorkbookSource.CutCellsToClipboard;
end;
procedure TsCustomWorksheetGrid.DoPasteFromClipboard;
begin
WorkbookSource.PasteCellsFromClipboard(coCopyCell);
end;
procedure TsCustomWorksheetGrid.DoOnResize;
begin
if (csDesigning in ComponentState) and (Worksheet = nil) then
@ -3989,7 +4007,7 @@ var
nfs: String;
isGeneralFmt: Boolean;
begin
Result := Worksheet.ReadAsUTF8Text(ACell);
Result := Worksheet.ReadAsText(ACell);
if (Result = '') or ((ACell <> nil) and (ACell^.ContentType = cctUTF8String))
then
exit;