Google Sheets – Custom Shortcuts to Move Selected Rows

google sheetskeyboard shortcuts

As the title says, I do move rows a lot and the lack of default shortcut complicates things for me…

The drag option isn't practical when I need to move some rows to the bottom of a huge sheet!

I tried to us AutoHotKey, but it's a pain since it move one row at a time and takes ages to reach the bottom.

So I'm looking maybe for a JavaScript solution, maybe if someone could put me on the right path with a base example code/references that I could edit/extend later to suit my needs…

Also, any alternative solution I'm not thinking of is welcome.

Edit:
From the title:

  • Up: move row(s) one row up
  • Down: move row(s) one row down
  • Top: move row(s) to the top of the sheet (all the way up)
  • End: move row(s) to the bottom of the sheet (all the way down, at the end of non-empty rows)

Best Answer

The following script moves selected consecutive rows in one of four ways described in the question. It is triggered by custom menu items (Custom > Move rows...) which is created by onOpen function whenever the spreadsheet is opened. Unfortunately, there is no way to assign keyboard shortcuts to script functions.

The structure of functions is simple: insert rows, copy the range (including formulas and formatting), delete old copy of the range. The helper function getData eliminates the need to repeat the same data-gathering in each of four functions.

function onOpen() {
  var menu = [{name: "Move rows up", functionName: "moveUp"}, {name: "Move rows down", functionName: "moveDown"}, {name: "Move rows to top", functionName: "moveTop"}, {name: "Move rows to bottom", functionName: "moveBottom"}];
  SpreadsheetApp.getActiveSpreadsheet().addMenu("Custom", menu);
}

function moveDown(){
  var d = getData(); 
  d.sheet.insertRowsAfter(d.row+d.height, d.height);
  d.selection.copyTo(d.sheet.getRange(d.row+d.height+1, 1, d.height, d.width));
  d.sheet.deleteRows(d.row, d.height);
}

function moveBottom(){
  var d = getData(); 
  d.sheet.insertRowsAfter(d.last, d.height);
  d.selection.copyTo(d.sheet.getRange(d.last+1, 1, d.height, d.width));
  d.sheet.deleteRows(d.row, d.height);
}

function moveUp(){
  var d = getData();
  d.sheet.insertRowsBefore(d.row-1, d.height);
  d.sheet.getRange(d.row+d.height, 1, d.height, d.width).copyTo(d.sheet.getRange(d.row-1, 1, d.height, d.width));
  d.sheet.deleteRows(d.row+d.height, d.height);
}

function moveTop(){
  var d = getData(); 
  d.sheet.insertRowsBefore(1, d.height);
  d.sheet.getRange(d.row+d.height, 1, d.height, d.width).copyTo(d.sheet.getRange(1, 1, d.height, d.width));
  d.sheet.deleteRows(d.row+d.height, d.height);
}              

function getData() {              
  var d = {};
  d.sheet = SpreadsheetApp.getActiveSheet();
  d.selection = d.sheet.getActiveRange();
  d.row = d.selection.getRowIndex();
  d.height = d.selection.getHeight();
  d.width = d.selection.getWidth();
  d.last = d.sheet.getLastRow();
  return d;
}