Skip to content

Move cells

Move or copy a selected range of cells by dragging its border, the same way you would in a spreadsheet application.

Overview

When you set moveCells to true, hovering the border of a selected cell range shows a grab cursor. Dragging that border moves the block’s data — cell values and formatting — to the new location. Hold Ctrl (Windows) or (Mac) during the drag to copy instead of move. Press Escape to cancel a drag before releasing.

The moveCells option was introduced in Handsontable 18.1.0. To move whole rows or columns instead of a cell range, see the Row moving and Column moving guides.

Enable cell moving

To enable drag-to-move, set the moveCells option to true:

moveCells: true,

This option applies at the grid level and defaults to false.

Select a range of cells in the demo below, then drag its border to a new location. Hold Ctrl or to copy the range instead of moving it.

JavaScript
import { useEffect, useRef } from 'react';
import { HotTable } from '@handsontable/react-wrapper';
import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modules
registerAllModules();
const data = [
['Ana García', 'Engineering', 'Senior Engineer', 95000, 'Madrid', 12],
['James Okafor', 'Marketing', 'Product Manager', 88000, 'Lagos', 8],
['Li Wei', 'Engineering', 'Frontend Dev', 82000, 'Shanghai', 5],
['Maria Santos', 'HR', 'HR Specialist', 71000, 'Lisbon', 3],
['David Kim', 'Engineering', 'Backend Dev', 85000, 'Seoul', 7],
['Emma Wilson', 'Marketing', 'SEO Analyst', 68000, 'London', 2],
['Ahmed Hassan', 'Finance', 'Controller', 92000, 'Cairo', 10],
['Sara Johansson', 'Engineering', 'QA Engineer', 78000, 'Stockholm', 6],
];
const ExampleComponent = () => {
const hotRef = useRef(null);
// Pre-select an interior range so the move border is immediately discoverable.
useEffect(() => {
hotRef.current?.hotInstance?.selectCell(1, 1, 3, 3);
}, []);
return (<HotTable ref={hotRef} data={data} colHeaders={['Name', 'Department', 'Role', 'Salary', 'City', 'Tenure']} rowHeaders={true} width="auto" height="auto" moveCells={true} autoWrapRow={true} autoWrapCol={true} licenseKey="non-commercial-and-evaluation"/>);
};
export default ExampleComponent;
TypeScript
import { useEffect, useRef } from 'react';
import { HotTable, HotTableRef } from '@handsontable/react-wrapper';
import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modules
registerAllModules();
const data = [
['Ana García', 'Engineering', 'Senior Engineer', 95000, 'Madrid', 12],
['James Okafor', 'Marketing', 'Product Manager', 88000, 'Lagos', 8],
['Li Wei', 'Engineering', 'Frontend Dev', 82000, 'Shanghai', 5],
['Maria Santos', 'HR', 'HR Specialist', 71000, 'Lisbon', 3],
['David Kim', 'Engineering', 'Backend Dev', 85000, 'Seoul', 7],
['Emma Wilson', 'Marketing', 'SEO Analyst', 68000, 'London', 2],
['Ahmed Hassan', 'Finance', 'Controller', 92000, 'Cairo', 10],
['Sara Johansson', 'Engineering', 'QA Engineer', 78000, 'Stockholm', 6],
];
const ExampleComponent = () => {
const hotRef = useRef<HotTableRef>(null);
// Pre-select an interior range so the move border is immediately discoverable.
useEffect(() => {
hotRef.current?.hotInstance?.selectCell(1, 1, 3, 3);
}, []);
return (
<HotTable
ref={hotRef}
data={data}
colHeaders={['Name', 'Department', 'Role', 'Salary', 'City', 'Tenure']}
rowHeaders={true}
width="auto"
height="auto"
moveCells={true}
autoWrapRow={true}
autoWrapCol={true}
licenseKey="non-commercial-and-evaluation"
/>
);
};
export default ExampleComponent;

Moving cells with formulas

When the formulas plugin is active, formula references adjust automatically on move — the same way they do in Excel.

Limitations

  • Drag-to-move works on a single contiguous cell range only. It has no effect on full-row, full-column, select-all, or multiple selections.
  • The target must stay within the grid. Neither the target nor the source may overlap read-only cells, because a move has to clear the source. Copying with Ctrl or leaves the source in place, so a read-only source cell blocks a move but not a copy.
  • Drag-to-move is hidden when disableVisualSelection is set.
  • A move that would split a merged cell is blocked.

Hooks

  • beforeMoveCells fires before the data relocates. Return false from the handler to cancel the move.
  • afterMoveCells fires after the data has been relocated.

Move cells programmatically

To move or copy a range from code, call the plugin’s moveCellRange() method:

hot.getPlugin('moveCells').moveCellRange(sourceRange, targetTopLeft, isCopy);

Related guides

Configuration options

Hooks

Plugins

Microsoft and Excel are registered trademarks of Microsoft Corporation.