TAdvStringGrid

Example 28 : Using row, cell, cell ranges and column drag & drop

vcl grid drag and drop

Starting from v1.91, extensive support for automatic drag & drop is included in TAdvStringGrid. With this example application, the power of this is shown. Because drag & drop conforms to OLE based drag & drop, this makes drag & drop possible not only within your application but also between applications that conform to this standard such as Excel, Word or even other applications with TAdvStringGrid.

Making use of these capabilities is done through several properties and events:

Properties:
OleDropSource: make the grid act as a source for drag & drop
OleDropTarget : make the grid act as a target for drag & drop
OleEntireRows : make sure that entire row (including fixed row) is handled during drag & drop in RowSelect mode
OleInsertRows : perform automatic row insertion when rows are dropped on the grid
OleRemoveRows : perform automatic row removal if drag & drop move operation is done, otherwise the move will result in empty rows

Some other properties that might be overlooked but nevertheless play an important role in drag & drop are : In Navigation:
Navigation.AllowClipboardAlways : will allow drop on a grid where editing is disabled. Otherwise, only editable cells could change through the drop operation.
Navigation.AllowClipboardRowGrow : will allow automatic adding of rows if more rows are dropped on the grid than present
Navigation.AllowClipboardColGrow : will allow automatic adding of columns if more columns are dropped on the grid than present

Public property:
ExcelClipboardFormat:boolean : use clipboard format compatible with Excel

Events:
OnOleDrag : event triggered when drag starts. Through the Allow parameter, the drag can be enabled or not.
OnOleDragOver : event triggered during the drag operation when the mouse is over the grid. Through the Allow parameter, the place where data can be dropped can be set.
OnOleDragStart : event triggered when drag has started.
OnOleDragStop : event triggered when drag has stopped. Indicates whether it was a move, copy or cancelled drag & drop operation.
OnOleDrop : event triggered when succesfull drop of cells was performed on the grid.
OnOleDropCol : event triggered when succesfull drop of a column was performed on the grid.

Row drag & drop

Enabling row drag and drop is simple. OleDropSource and OleDropTarget properties are set true. In addition OleEntireRows, OleRemoveRows and OleInsertRows are set true to enable full row drag & drop. The only event used further is OnOleDrag where Allow is set true whenever the origin row of the drag operation is not a fixed row. This is necessary, as drag & drop from a fixed row starts a column drag & drop. Notice that drag & drop between grids as well as in the grid itself (to allow row rearranging is possible)

To allow only drag & drop between grids, use the OnOleDragStart event to set the source grid in a variable. In the OnOleDragOver event, set Allow to false if the Sender is equal to this source. Finally reset the source on the OnOleDragStop event.

Example :

ddsource:TObject;

procedure Form1.OnOleDragStart(Sender:TObject; Arow,Acol: integer);
begin
  ddsource := Sender;
end;

procedure Form1.OnOleDragOver(Sender:TObject; Arow,Acol: integer; var Allow: boolean);
begin
  Allow := ddsource <> Sender;
end;

procedure Form1.OnOleDragStop(Sender:TObject; Arow,Acol: integer; var Allow: boolean);
begin
  ddsource := nil;
end;

Cell drag & drop

Everything under row drag & drop applies to cell drag & drop, except that OleEntireRows, OleRemoveRows and OleInsertRows are set false here.

Column drag & drop

Column drag & drop is a little more involved. This is because the interface allows for more than just inter grid column drag & drop but allows the implementation for something like a field chooser (see example project 29 ) as well.

Where the previous examples disabled column drag & drop by setting Allow=false when the drag started from the fixed row, this example only enables drag & drop when the drag starts from the fixed row. (Nothing prevents enabling both in the same grid though)

The OnOleDragOver event is used to allow a drop of a column only when the mouse cursor is over a fixed row. Except when the grid has no columns, a drop on the fixed column is not allowed:

procedure TForm1.OnOleDragOver(Sender: TObject; Arow, Acol: integer; var Allow: boolean);
begin
  with Sender as TAdvStringGrid do
    Allow := (Sender<>ColSource) and (Arow=0) and ((Acol>0) or (ColCount=1));
end;

The event OnOleDropCol is triggered when a column is dropped. It indicates the index of the original column dropped as well as the index of the column where it is dropped. It is in this event that the column data of the source grid is inserted in the target grid:

procedure TForm1.AdvStringGrid5OleDropCol(Sender: TObject; Arow, Acol,
  DropCol: Integer);
var
  sl:TStringList;
begin
  coltarget := Sender as TAdvStringGrid;
  sl := TStringList.Create;
  sl.Assign(colsource.Cols[DropCol]);
 
  if (acol=0) then inc(acol);

  coltarget.InsertCols(acol,1);
  coltarget.Cols[acol].Assign(sl);
  sl.Free;
end;

Finally the OnOleDragStop event is used to remove the column from the source grid if the drag & drop was a move operation:

procedure TForm1.AdvStringGrid5OleDragStop(Sender: TObject;
  OLEEffect: Integer);
begin
  if OLEEffect=DROPEFFECT_MOVE then
  begin
    colsource.RemoveCols(colsourceidx,1);
  end;
end;

With this little additional coding, full drag & drop of columns between grids was achieved.

Delphi project & source files for downloading included in the main demos distribution for Delphi.