fpspreadsheet: Improve copying of multiple cells in the WorksheetGrid. Fix worksheet not deleting formula if a blank cell is written.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4054 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2015-03-19 11:40:07 +00:00
parent 4093d31ddb
commit 2252e04cec
2 changed files with 76 additions and 19 deletions

View File

@ -1887,7 +1887,6 @@ begin
RemoveAndFreeCell(ACell^.Row, ACell^.Col);
end;
{@@ ----------------------------------------------------------------------------
Internal call-back procedure for looping through all cells when deleting
a specified column. Deletion happens in DeleteCol BEFORE this callback!
@ -3713,7 +3712,7 @@ end;
On formats that don't support unicode, the text will be converted
to ISO Latin 1.
@param ACell Poiner to the cell
@param ACell Pointer to the cell
@param AText The text to be written encoded in utf-8
-------------------------------------------------------------------------------}
procedure TsWorksheet.WriteUTF8Text(ACell: PCell; AText: ansistring);
@ -3938,6 +3937,7 @@ end;
procedure TsWorksheet.WriteBlank(ACell: PCell);
begin
if ACell <> nil then begin
ACell^.FormulaValue := '';
if HasHyperlink(ACell) then
WriteUTF8Text(ACell, '') // '' will be replaced by the hyperlink target.
else
@ -4001,7 +4001,7 @@ end;
string, the worksheet tries to guess whether it is a number, a date/time or
a text and calls the corresponding writing method.
@param ACell Poiner to the cell
@param ACell Pointer to the cell
@param AValue Value to be written into the cell given as a string. Depending
on the structure of the string, however, the value is written
as a number, a date/time or a text.

View File

@ -467,6 +467,7 @@ end;
type
TsCellList = class(TList)
private
FMultipleRanges: Boolean;
function GetCell(AIndex: Integer): PCell;
procedure SetCell(AIndex: Integer; ACell: PCell);
public
@ -478,6 +479,7 @@ type
procedure Delete(AIndex: Integer);
function IndexOf(ACell: PCell): Integer;
property CellByIndex[AIndex: Integer]: PCell read GetCell write SetCell;
property MultipleRanges: Boolean read FMultipleRanges write FMultipleRanges;
end;
var
@ -1086,6 +1088,7 @@ end;
procedure TsWorkbookSource.ClearCellClipboard;
begin
CellClipboard.Clear;
CellClipboard.MultipleRanges := false;
end;
{@@ ----------------------------------------------------------------------------
@ -1115,6 +1118,8 @@ begin
else
CellClipboard.AddCell(cell);
end;
CellClipboard.MultipleRanges := (Length(sel) > 1);
end;
{@@ ----------------------------------------------------------------------------
@ -1137,9 +1142,12 @@ end;
-------------------------------------------------------------------------------}
procedure TsWorkbookSource.PasteCellsFromClipboard(AItem: TsCopyOperation);
var
r, c, dr, dc: LongInt;
i: Integer;
r, c, dr, dc, destRow, destCol: LongInt;
i, j: Integer;
cell: PCell;
baserng, rng: TsCellRange;
nc, nr: Integer;
baseRow, baseCol: Cardinal;
begin
if CellClipboard.Count = 0 then
exit;
@ -1160,24 +1168,73 @@ begin
end;
cell := CellClipboard.CellByIndex[0];
dr := FWorksheet.ActiveCellRow - cell^.Row;
dc := FWorksheet.ActiveCellCol - cell^.Col;
baseRow := cell^.Row;
baseCol := cell^.Col;
for i:=0 to CellClipboard.Count-1 do
if CellClipboard.MultipleRanges then
begin
cell := CellClipboard.CellByIndex[i];
case AItem of
coCopyCell:
FWorksheet.CopyCell(cell^.Row, cell^.Col, LongInt(cell^.Row) + dr, LongInt(cell^.Col) + dc);
coCopyValue:
FWorksheet.CopyValue(cell, LongInt(cell^.Row) + dr, LongInt(cell^.Col) + dc);
coCopyFormat:
FWorksheet.CopyFormat(cell, LongInt(cell^.Row) + dr, LongInt(cell^.Col) + dc);
coCopyFormula:
FWorksheet.CopyFormula(cell, LongInt(cell^.Row) + dr, LongInt(cell^.Col) + dc);
dr := FWorksheet.ActiveCellRow - baseRow;
dc := FWorksheet.ActiveCellCol - baseCol;
for i:=0 to CellClipboard.Count-1 do
begin
cell := CellClipboard.CellByIndex[i];
case AItem of
coCopyCell:
FWorksheet.CopyCell(cell^.Row, cell^.Col, LongInt(cell^.Row) + dr, LongInt(cell^.Col) + dc);
coCopyValue:
FWorksheet.CopyValue(cell, LongInt(cell^.Row) + dr, LongInt(cell^.Col) + dc);
coCopyFormat:
FWorksheet.CopyFormat(cell, LongInt(cell^.Row) + dr, LongInt(cell^.Col) + dc);
coCopyFormula:
FWorksheet.CopyFormula(cell, LongInt(cell^.Row) + dr, LongInt(cell^.Col) + dc);
end;
end;
end else
begin
// Determine cell range enclosed by cells in clipboard
baserng.Row1 := MaxInt;
baserng.Col1 := MaxInt;
baserng.Row2 := 0;
baserng.Col2 := 0;
for i :=0 to CellClipboard.Count-1 do
begin
cell := CellClipboard.CellByIndex[i];
baserng.Row1 := Min(baserng.Row1, cell^.Row);
baserng.Row2 := Max(baserng.Row2, cell^.Row);
baserng.Col1 := Min(baserng.Col1, cell^.Col);
baserng.Col2 := Max(baserng.Col2, cell^.Col);
end;
// Each selected range of the worksheet gets tiled copies of the range of
// the cells in clipboard
for j:=0 to FWorksheet.GetSelectionCount-1 do
begin
rng := FWorksheet.GetSelection[j];
r := rng.Row1;
while (r <= rng.Row2) do begin
c := rng.Col1;
while (c <= rng.Col2) do begin
for i:=0 to CellClipboard.Count-1 do begin
cell := CellClipboard.CellByIndex[i];
destRow := r + LongInt(cell^.Row) - baserng.Row1;
destCol := c + LongInt(cell^.Col) - baserng.Col1;
case AItem of
coCopyCell:
FWorksheet.CopyCell(cell^.Row, cell^.Col, destRow, destCol);
coCopyValue:
FWorksheet.CopyValue(cell, destRow, destCol);
coCopyFormat:
FWorksheet.CopyFormat(cell, destRow, destCol);
coCopyFormula:
FWorksheet.CopyFormula(cell, destRow, destCol);
end;
end;
inc(c, baserng.Col2 - baserng.Col1 + 1);
end;
inc(r, baserng.Row2 - baserng.Row1 + 1);
end;
end;
end;
finally
EnableControls;
end;