使用应用脚本在Google电子表格中拆分(拆分)合并的表格单元格

时间:2013-03-15 20:33:35

标签: javascript google-apps-script google-sheets

当操作(复制/移动)包含合并单元格的范围时,我总是会收到错误“您的粘贴与合并单元格重叠”。请取消合并细胞并再试一次“。但是当尝试使用Range#breakApart取消合并范围内的单元格时,我得到另一个错误:“所选单元格无法合并。”,这更令人困惑,因为我没有尝试合并任何东西,我是只是试图将细胞分开。

4 个答案:

答案 0 :(得分:5)

结果breakApart仅在调用它的范围包含所有合并单元格时才有效,而不仅仅是合并区域的一部分。

这不会太糟糕。一旦您意识到API中无法获得合并单元格的范围,问题就会开始。因此,解决此问题的最佳方法(我迄今为止发现)只是轻轻扩展您的范围,直到没有错误发生:

var breakRange = myRange;
for(;;) {
  try {
    breakRange.breakApart();
    break;
  } catch(e) {
    breakRange = mySheet.getRange(
      breakRange.getRowIndex(),
      breakRange.getColumnIndex(),
      Math.min(
        breakRange.getHeight()+5,
        mySheet.getMaxRows()-breakRange.getRowIndex()+1
      ),
      Math.min(
        breakRange.getWidth()+5,
        mySheet.getMaxColumns()-breakRange.getColumnIndex()+1
      )
    );
  }
}

(我添加了五行/列而不是一行,因为获取范围似乎是一个相当昂贵的过程)。只要在展开搜索区域时没有添加其他合并单元格,这种方法就可以正常工作。

对于电子表格中的合并单元格,Google Apps Scripts API至少在以下方面受到打破:

  1. 无法在工作表/范围内获取合并单元格范围的数组。
  2. 应该有办法查看哪些单元格已被拆分(breakApart仅返回原始范围“以进行链接”)。这使得无法拆分合并,然后让每个单元格包含原始合并单元格的内容。
  3. 尝试在仅包含合并单元格的一部分的范围内使用breakApart仍然应该拆分整个合并而不是抛出异常。
  4. 总而言之,目前的API仅适用于电子表格,其脚本作者自己可以完全控制其布局和用法。

答案 1 :(得分:1)

此功能可分解与所提供的单元格或范围部分相交的合并单元格的范围。 如@clssrmtechtools中的Adam Morris(thread)所建议的那样,它使用Sheets高级服务来识别给定表单中的所有合并范围。

演示电子表格here

/** 
* Breaks apart merged cells in range
* @param {sheet} sheet Sheet of range
* @param {range} rangeToSplit Cell or cells that intersect with whole merged range
*/
function breakApartAux(sheet, rangeToSplit) {

  // Current spreadsheet & sheet
  let ss = SpreadsheetApp.getActiveSpreadsheet();
  let activeSSId = ss.getId();
  let activeSId = sheet.getSheetId();

  // Get sheet's merges using advanced sheets service
  let merges = Sheets.Spreadsheets.get(activeSSId).sheets.find(s => s.properties.sheetId == activeSId).merges;

  if (merges == undefined) SpreadsheetApp.getUi().alert('No merged cells found in sheet.');
  else {

    // Logger.log(merges);

    // Cells to merge R/C
    let rowS = rangeToSplit.getRow();
    let rowE = rowS + rangeToSplit.getNumRows() - 1;
    let colS = rangeToSplit.getColumn();
    let colE = colS + rangeToSplit.getNumColumns() - 1;

    // Find overlapping merged range
    // Advanced service merged ranges start in 0 and are right-open [..)
    let merge = merges.find(m => {
                            let mRowS = m.startRowIndex + 1;
                            let mRowE = m.endRowIndex;
                            let mColS = m.startColumnIndex + 1;
                            let mColE = m.endColumnIndex;

                            // Check for overlapping
                            return ((rowS >= mRowS && rowS <= mRowE)  || 
                                    (rowE <= mRowE && rowE >= mRowS)  ||
                                    (rowS < mRowS && rowE > mRowE)) &&
                                   ((colS >= mColS && colS <= mColE)  ||
                                    (colE <= mColE && colE >= mColS)  ||
                                    (colS < mColS && colE > mColE));
    })

    // Overlapping range?
    if (merge == undefined) SpreadsheetApp.getUi().alert('No merged cells found in specified range.');
    else {
      // Break apart whole range
      ss.getActiveSheet().getRange(merge.startRowIndex + 1,
                                   merge.startColumnIndex + 1,
                                   merge.endRowIndex - merge.startRowIndex,
                                   merge.endColumnIndex - merge.startColumnIndex).breakApart();
    }
  }

}

答案 2 :(得分:0)

受拉斐尔(Raphael)的回答启发,这是如何取消合并工作表中所有单元格的方法。这是我用于合并具有相邻空值的单元格的数据导入所使用的数据,即我正在将单元格a1与单元格b1合并,其中a1具有值而b1没有:

palette = sns.color_palette("mako_r", 6)
sns.lineplot(..., palette=palette, data=data)

答案 3 :(得分:0)

这是我找到的最简单的方法:

function unmerge() {
  var sheetName = 'Sheet1';   // Change!
  var a1Notation = 'A1:B15';  // Change!  
  var range = SpreadsheetApp.getActive().getSheetByName(sheetName).getRange(a1Notation);  
  var mergedRanges = range.getMergedRanges();
  for (var i = 0; i < mergedRanges.length; i++)
  {
    mergedRanges[i].breakApart();
  }
}