Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
401 views
in Technique[技术] by (71.8m points)

How do I know if spreadsheet cells are merged using google apps script

In a Google docs spreadsheet. If cells A1 & A2 are merged, is there a way to confirm they are merged, using google apps script?

There is a merge function in GAS https://developers.google.com/apps-script/class_range#merge

But there is no function or example that shows how to check if cells are merged.

getValues etc just returns an empty string for the cell. e.g. this does not work.

function testMerge() {

  var spreadsheet = SpreadsheetApp.openById('Z3ppTjxNUE........'); 
  var sheet = spreadsheet.getSheets()[0];
  var range = sheet.getRange("A3:A4");
  var values = range.getValues();
  var formulas = range.getFormulasR1C1();
  var formulasA1 = range.getFormulas();

  range = sheet.getRange("A4");
  range.setValue("a");

  range = sheet.getRange("A3:A4");
  var values2 = range.getValues();
  var formulas2 = range.getFormulasR1C1();
  var formulasA12 = range.getFormulas();


  var count = range.getHeight();


}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

range.isPartOfMerge()

It seems the .isPartOfMerge() method was implemented (11 sept 2016).

So you can check if a range is merged as such:

function testMerge() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName("Sheet1");
  var range = sheet.getRange(1,1,2); // example for cells A1 and A2
  Logger.log(range.isPartOfMerge());
}

Docs https://developers.google.com/apps-script/reference/spreadsheet/range#ispartofmerge


OLD APPROACH

Posting here another approach that I like more than the accepted answer.

If you try to use GAS to store a value in a cell of a merged range, except the first cell, it will not store it.

As such, we can exploit this and attempt to store the value and check if it was stored, using a function similar to this one:

  function isMerged(range){
  try {
    range.getDataSourceUrl()
  } catch (err) {
    throw "isMerged function only works with valid GAS Range objects"
  }
  var sheet = range.getSheet();
  var rangeData = range.getValues();

  var testValue = "testing merge";

  if (rangeData.length == 1 && rangeData[0].length == 1) return false; // we have a single cell. Can't possible be merged :)

  if (rangeData.length == 1) {
    // We have a single row. Which means we're testing a row with multiple columns
    var mainCell=range.getA1Notation().split(":")[0];
    var rowNumber= sheet.getRange(mainCell).getRow();
    var nextColNumber = sheet.getRange(mainCell).getColumn()+1;
    var row = rangeData[0];
    var oldValue = row[1]; // for testing purposes, we're chosing the next possible column

    sheet.getRange(rowNumber,nextColNumber).setValue(testValue);
    if (sheet.getRange(rowNumber,nextColNumber).getValue() !== testValue) {
      return true;
    } else {
      sheet.getRange(rowNumber,nextColNumber).setValue(oldValue);
      return false;
    };
  } else if (rangeData[0].length == 1) {
    // We have multiple rows and a single column.
    var mainCell=range.getA1Notation().split(":")[0];
    var nextRowNumber= sheet.getRange(mainCell).getRow()+1;
    var colNumber = sheet.getRange(mainCell).getColumn();
    var oldValue = rangeData[1][0]; // for testing purposes, we're chosing the next possible row

    sheet.getRange(nextRowNumber,colNumber).setValue(testValue);
    if (sheet.getRange(nextRowNumber,colNumber).getValue() !== testValue) {
      return true;
    } else {
      sheet.getRange(nextRowNumber,colNumber).setValue(oldValue);
      return false;
    };
  } else {
    // We have multiple rows and multiple columns
    var mainCell=range.getA1Notation().split(":")[0];
    var nextRowNumber= sheet.getRange(mainCell).getRow()+1;
    var nextColNumber = sheet.getRange(mainCell).getColumn()+1;
    var oldValue = rangeData[1][1]; // for testing purposes, we're chosing the next possible row and next possible column

    sheet.getRange(nextRowNumber,nextColNumber).setValue(testValue);
    if (sheet.getRange(nextRowNumber,nextColNumber).getValue() !== testValue) {
      return true;
    } else {
      sheet.getRange(nextRowNumber,nextColNumber).setValue(oldValue);
      return false;
    };
  }

  // if none of these checks worked, something's fishy. Either way, return false
  return false
}

I've ran a series of quick tests and it returned true/false accordingly, but there is a limitation that I didn't have time to cover: If you had a merged range like "A1:F1" and you checked the range "A1:G1" (so, one more column), it will return true, even if G1 is not part of the merged range - because it checks only the next column using as reference the first bound row/column.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...