【问题标题】:How do I know if spreadsheet cells are merged using google apps script我如何知道电子表格单元格是否使用谷歌应用脚​​本合并
【发布时间】:2012-06-17 00:57:57
【问题描述】:

在 Google 文档电子表格中。 如果单元格 A1 和 A2 合并,有没有办法 使用谷歌应用程序脚本确认它们已合并?

GAS中有合并功能https://developers.google.com/apps-script/class_range#merge

但是没有显示如何检查单元格是否合并的函数或示例。

getValues 等只为单元格返回一个空字符串。例如这 不工作。

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();


}

【问题讨论】:

    标签: google-apps-script google-sheets


    【解决方案1】:

    这是不可能知道的。已经为此打开了一个issue,但它已经很旧并且没有任何活动。您应该为它加注星标(以跟踪更新并为它投票)并发表评论,看看您是否能引起注意。

    但是当我需要确保合并的单元格符合我的要求时,我所做的就是将所有内容分开并再次合并,以确保确定。当然,这不是一个解决方案,只是一个可能也适合您的想法。

    【讨论】:

      【解决方案2】:

      对于像我这样不知道 .breakapart() 方法来取消合并单元格的人: https://developers.google.com/apps-script/class_range#breakApart

      感谢 Henrique 的提示!

      【讨论】:

        【解决方案3】:

        下载为 HTML:您可以将工作表下载为 HTML,这将包括合并的单元格信息。不是一个好的解决方案,但它有效。

        示例下载地址:

        docs.google.com/feeds/download/spreadsheets/Export?key=* spreadsheetkey *&exportFor‌​mat=html&gid=3

        其中 gid 是工作表 gid 编号。 - 需要通过 google drive api 登录(详见 google drive DrEdit 教程)

        【讨论】:

        • 您可以从 HTML 中验证哪些单元格被合并了?对此有任何见解(例如,他们设置了行跨度)?我问,因为那是你最初的问题。
        • 是的,HTML 包含合并单元格的 rowspan 和 colspan。易于测试,使用上面的 URL,更改密钥,如果您登录就会下载。(gid 是可选的,它选择工作表)。
        【解决方案4】:

        找到了这个解决方案,发布在这里:
        https://code.google.com/p/google-apps-script-issues/issues/detail?id=618

        但是只适用于有效范围

        // This is my function to test the active range is merged or not and return
        // true or false by passing active range to it
        function ismerge() {
          var spread = SpreadsheetApp.getActiveSpreadsheet();
          var sheet = spread.getActiveSheet();
          var last_row = sheet.getActiveRange().getLastRow();
          var last_col = sheet.getActiveRange().getLastColumn();
        
          Logger.log("Last row: %s", last_row);
          var active_row = sheet.getActiveRange().getRow();
          var active_col = sheet.getActiveRange().getColumn();
          Logger.log("Row: %s", active_row);
          if ( (last_row == active_row) && (last_col == active_col) ) {
            Logger.log("Cell not merged");
            return false;
          }
          else {
            Logger.log("Cell merged");
            return true;
          }
        }
        

        【讨论】:

          【解决方案5】:

          如果这里有人需要解决这个问题,我编写了一个小工具,可以省去从导出的 HTML 中创建所有合并单元格的键值文件的大部分工作。

          你可以在这里找到它:https://github.com/martinhbramwell/CellMergeWorkAround

          我写它是因为我有一个小项目,它依赖于能够将范围从一个电子表格完全克隆到另一个电子表格。显然,我已经投票赞成解决这个问题。

          (注意:我会将此作为注释添加到正确答案中,但缺少必要的要点。)

          【讨论】:

            【解决方案6】:

            似乎有一种解决方法可以利用合并单元格总是返回白色背景这一事实。下面的代码似乎对我有用;如果有人能确认,我将不胜感激。

            function testMerged() {
              var WHITE = '#ffffff';
              var NON_WHITE = '#fffffe';
              var range = SpreadsheetApp.getActiveSheet().getDataRange();
              range.setBackground(NON_WHITE);
              range.getBackgrounds().forEach(function (row, rowNum) {
                row.forEach(function (col, colNum) {
                  if (col === WHITE) { Logger.log('Cell merged at row ' + rowNum + ' col ' + colNum); }
                });
              });
              range.setBackground(WHITE);  
            }
            

            【讨论】:

              【解决方案7】:

              也许答案有点晚,因为我没有看到新版本的谷歌电子表格存在这个问题。但是,我仍然为我的项目使用旧的电子表格版本。所以我需要以某种方式弄清楚。

              我需要为新列复制上一列的格式。这是以下代码的一部分:

                    // trying to find first column with week day (white background)
                    var background = '';
                    for(var columnIndex = 3; columnIndex<=columnLetters.length; columnIndex++){
                      background = sheet.getRange(1, columnIndex).getBackground();
                      if(background == 'white' || background == ''){
                        tmpRange = columnLetters[columnIndex]+':'+columnLetters[columnIndex];
                        Logger.log('tmpRange: '+tmpRange);
                        // workaround to be able to copy format if there is some merged cells
                        try{
                          Logger.log('try');
                          // copy format of previous column
                          sheet.getRange(tmpRange).copyTo(
                            sheet.getRange('B1'), {formatOnly:true}
                          );
                        }catch(e) {
                          Logger.log('continue');
                          continue;
                        }
                        Logger.log('break');
                        break;
                      }
                    }
              

              所以,这里最重要的部分是:

              try{
                Logger.log('try');
                // copy format of previous column
                sheet.getRange(tmpRange).copyTo(
                  sheet.getRange('B1'), {formatOnly:true}
                );
              }catch(e) {
                Logger.log('continue');
                continue;
              }
              

              如果无法复制这些单元格,它会继续搜索其他单元格。

              【讨论】:

                【解决方案8】:

                range.isPartOfMerge()

                似乎.isPartOfMerge() 方法was implemented(2016 年 9 月 11 日)。

                所以你可以检查一个范围是否像这样合并:

                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());
                }
                

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


                旧方法

                在这里发布另一种我更喜欢的方法,而不是接受的答案。

                如果您尝试使用 GAS 将值存储在合并范围的单元格中,除了第一个单元格,它不会存储它。

                因此,我们可以利用这一点并尝试存储该值并检查它是否已存储,使用类似于此的函数:

                  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
                }
                

                我进行了一系列快速测试,并相应地返回了true/false,但有一个限制,我没有时间介绍: 如果您有一个像"A1:F1" 这样的合并范围,并且您检查了"A1:G1" 范围(因此,多一列),它将返回true,即使G1 不是合并范围的一部分 - 因为它只检查下一个使用第一个绑定行/列作为参考的列。

                【讨论】:

                • 很好的发现。 ...我猜这适用于新样式表而不是旧样式。由于问题中的代码已经检查了这个想法并显示它在旧样式表中失败,但我没有用新样式表测试它。
                【解决方案9】:

                是的,现在您可以使用isPartOfMerge 进行检查。

                对于任何想要获得合并单元格值的人:

                var value = (cell.isPartOfMerge() ? cell.getMergedRanges()[0].getCell(1,1) : cell).getValue();
                

                希望对您有所帮助。

                【讨论】:

                • 但什么是单元格?
                • 我的变量cell 这里是你想要获取它的值的合并单元格的范围。
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-12-30
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-06-15
                相关资源
                最近更新 更多