Search code examples
google-apps-scriptgoogle-sheetsswap

Swap the contents of two selected cells in google sheets


I am an elementary music teacher and trying to create a seating chart in google sheets. I have 29 sections to manage! I often want to change the seating chart and looking for a streamline way of doing this. I have a cell that has a student's ID number which is referenced to populate the students name and related info from another spread sheet into nearby cells. I would like to write a script that allows me to swap two student numbers. Once swapped the student information will re-populate with the corresponding student information. I am a relatively new to coding and am getting stuck since I know there are more steps to the sequence than I realize when trying to work my way through the code.

I found this bit of code that gets references for two selected cell but don't know how to take it from here. I know I need to get the cell contents then exchange them somehow. Ideas? Thanks, Peter

function getSelectedRange_NonContiguous() {
  const sheet = SpreadsheetApp.getActive().getActiveSheet();
  const selected = sheet.getActiveRangeList().getRanges();
  // an array of selected ranges
  const notations = selected.map(rng=>rng.getA1Notation()); 
  // log them:
  notations.forEach(nt=>console.log(nt));
  return notations;
 
}

Update 8/20/23 I tried the code posted below and it works perfectly. Thank you @Cooper!!

The only problem is that it is sheet specific. I will have many sheet tabs that I would want the Swap function to work on. Can it grab the active sheet instead of getting a specific sheet by name?

For more context here are links to a test data file and the seating chart file. The student names in the data file have a student number as column A. The seating chart file has two cells that use a formula with index and match functions to check the student number in the small box just above them and gathers the proper student first and last names from the data sheet. By using the swap function (thanks again for sharing @Cooper!) I can simply swap the student numbers in the reference boxes on the seating chart and poof, the names "switch places". Data file: https://docs.google.com/spreadsheets/d/1qQV8xtv-ViR8v7NxsqFRxLDxCKEPsjUmmVnBTGcvaLA/edit?usp=sharing Seating Chart File: https://docs.google.com/spreadsheets/d/1MxcYxWdQuGQUYtH_eRvzHUj_wNuahRJzCz6-ccLqNMc/edit?usp=sharing

Update: Solution found for non sheet specific reference. in line 3 I swapped getSheetByName("sheet0") with getActiveSheet() giving the following code:

function swap() {
  const ss = SpreadsheetApp.getActive();
  const sh = ss.getActiveSheet();
  const list = sh.getActiveRangeList();
  const rgl = breakUpRangeList(ss, sh, list);
  if (rgl.getRanges().length == 2) {
    let v = rgl.getRanges().flatMap(r => r.getValue()).reverse();
    rgl.getRanges().forEach((r, i) => r.setValue(v[i]));
  } else {
    SpreadsheetApp.getUi().alert("Only works with two cells");
  }
}

Solution

  • function swap() {
      const ss = SpreadsheetApp.getActive();
      const sh = ss.getSheetByName("Sheet0");
      const list = sh.getActiveRangeList();
      const rgl = breakUpRangeList(ss, sh, list);
      if (rgl.getRanges().length == 2) {
        let v = rgl.getRanges().flatMap(r => r.getValue()).reverse();
        rgl.getRanges().forEach((r, i) => r.setValue(v[i]));
      } else {
        SpreadsheetApp.getUi().alert("Only works with two cells");
      }
    }
    

    This breaks up any range list into separate cells

    function breakUpRangeList(ss = SpreadsheetApp.getActive(), sh = ss.getSheetByName("Sheet0"), rgl) {
      let b = [];
      rgl.getRanges().forEach(rg => {
        rg.getValues().forEach((r, i) => {
          let row = rg.getRow() + i;
          r.forEach((c, j) => {
            let col = rg.getColumn() + j;
            b.push(sh.getRange(row, col).getA1Notation())
          })
        })
      })
      b = [...new Set(b)];
      Logger.log(JSON.stringify(b));
      return sh.getRangeList(b);
    }
    

    enter image description here