如何根据单元格内容扩展或缩小公式

时间:2019-06-13 19:54:04

标签: google-apps-script google-sheets

我有一张由几张纸组成的桌子。该表应由多个用户每天同时处理。主要编辑工作在Sheet1中完成。 Sheet2仅包含查询和公式。

示例表1:

  • 第1页包含2500行和17列。

从第12行开始(第11行是标题行。上面的行包含公式引用),用户将填写A,B列。 C-H列包含各种公式(例如GoogleFinance查询)。用户必须再次填写G-M列。最后,在N-Q列中又有一个公式。

目标:根据是否已在A和B列中添加/删除内容,在CH和NQ列中自动扩展/删除公式。删除过程应逐行执行,以删除列中的其余用户内容总经理。

工作表应该也可以排序。

示例表2:

  • 第2页包含1500行和11列。

从第9行开始(第9行也是标题行。上面的行包含公式引用),第A-I列填充了查询结果(位于单元格A9中)。该查询从工作表1获得某些内容,并且是动态的。 J-K列包含公式。

目标:根据是否在A-I列中(通过查询)添加/删除内容,自动扩展/删除J-K列中的公式。

对于扩展,删除和排序,我使用了以下代码示例。

不幸的是,所示代码不符合星座中描述的要求。因此,我非常感谢您提供更好的解决方案。

function fillDownFormulaTD(){

  Sheet = "sheet1";

  var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(Sheet);
  var lr = ss.getLastRow();
  var Rng1 = ss.getRange(1, 2, lr-1);

  ss.getRange("").setFormula('');
  ss.getRange("").copyTo(Rng1);         
}

function removeEmptyRows(){    
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Ticker-Datenbank');
  var maxRows = sheet.getMaxRows(); 
  var lastRow = sheet.getLastRow();

  sheet.deleteRows(lastRow+1, maxRows-lastRow-20);            
}

function Sortieren(){

  var spreadsheet = SpreadsheetApp.getActive();
  spreadsheet.getRange('A11:Q11')
  var currentCell = spreadsheet.getCurrentCell();
  spreadsheet.getSelection().getNextDataRange(SpreadsheetApp.Direction.DOWN).activate();
  currentCell.activateAsCurrentCell();
  spreadsheet.getActiveRange().sort({column: 3, ascending: true});
  spreadsheet.getRange('A11').activate();
 }

1 个答案:

答案 0 :(得分:1)

这是Sheet2的快速解决方案(Sheet#1的答案正在酝酿中)。

对于Sheet2,与其使用公式手动填充J和I列的每一行,不如使用一个可根据数据行“自动”扩展/收缩的arrayformula。

  1. 删除J列和I列中每行> 9的所有公式(空白和非空白单元格)。
  2. 在单元格J10中,插入此公式
    =arrayformula(IF($C10:$C="";"";HYPERLINK($J$1&$A10:$A&$J$2&$B10:$B;$J$3)))
  3. 在I10单元格中,插入此公式
    =arrayformula(IFERROR(VLOOKUP($C10:$C;'Geprüfte Ticker'!$C:$P;14;FALSE);""))

此代码解决了 Sheet1 场景。

该代码在技术上是准确的,可以正常工作,但OP可能还需要考虑另外两个问题。

  1. 电子表格“每天由多个用户同时处理”。存在在A列或B列中检测到的空白单元格(可能是删除while行的指示符)只是暂时的风险-用户可能打算更正拼写或输入新数据。删除行的“理想”基础是在A **列和** B列中都检测到空白单元格,但这并不总是可能的。

  2. 即使只有测试数据,电子表格的重新计算时间也很长-@大约10+秒-实时电子表格的时间未知。尚不清楚此代码将对重新计算产生什么影响。


    function onEdit(e) {
      // setup spreadsheet and sheet
      var ss = SpreadsheetApp.getActiveSpreadsheet();
      var tsName = "onedittest";
      var targetsheet = ss.getSheetByName(tsName);

      // list event data
      // Logger.log(JSON.stringify(e)); //DEBUG

      //get the formukla ranges and formulas
      // set 1 = Column C-H
      // set 2 = Column N-P
      // Column Q = arrayformula - leave as is
      var rR1 = targetsheet.getRange("C12:H12");
      var fR1 = rR1.getFormulasR1C1();
      var rR2 = targetsheet.getRange("N12:P12");
      var fR2 = rR2.getFormulasR1C1();

      // collect event data
      var editR = e.range.getRow();
      var editRS = e.range.rowStart;
      var editRE = e.range.rowEnd;
      var editC = e.range.getColumn();
      var editCS = e.range.columnStart;
      var editCE = e.range.columnEnd;
      //Logger.log("DEBUG: edited rowstart = "+editRS+", rowend = "+editRE+", columnstart = "+editCS+", columnend = "+editCE);
      //Logger.log("DEBUG: edited row = "+editR+", edited column = "+editC);

      var editedsheet = e.range.getSheet().getSheetName();
      // Logger.log("DEBUG: sheet name = "+editedsheet);

      if (editedsheet === tsName  && editC>= 1 && editC<= 2 && editR>12) {

        // this range/cell is a trigger
        // Logger.log("DEBUG: match");
        var editCell = targetsheet.getRange(editRS, editCS);
        // Logger.log("DEBUG: the edited cell is "+editCell.getA1Notation());
        //Logger.log("DEBUG: the old value = "+e.oldValue+", and the new value = "+e.value);

        //now split Logic#1 and Logic#2
        // Logic#1 = AND there is data in the edited cell (that is, the edit did not make the cell blank), 
        // then copy (or recopy) the formulas from row 12 Columns C-H and N-Q onto the edited row.
        if (editCell.length !=0){
          // copy formulas
          // Logger.log("DEBUG: copy the formulas");
          var formulaset1 = targetsheet.getRange(editRS,3,1,6);
          formulaset1.setFormulasR1C1(fR1);  
          // Logger.log("DEBUG: set formulas for range 1")
          var formulaset2 = targetsheet.getRange(editRS,14,1,3);
          formulaset2.setFormulasR1C1(fR2);  
          // Logger.log("DEBUG: set formulas for range 2")

// Sort the data
      // get the number of rows of data
      var lastheaderRow = 11;
      var Avals = ss.getRange("A12:A").getValues();
      var Alast = Avals.filter(String).length;
      //Logger.log("DEBUG: Number of rows of data = "+Alast+", so last row = "+(Alast+lastheaderRow));

      // define the sort range
      var sortRange = targetsheet.getRange(lastheaderRow, 1, Alast+1, 17);
      // Logger.log("DEBUG: the range = "+range.getA1Notation());

      // sort by Column C, ascending
      sortRange.sort({column: 3, ascending: true});

          }
          else{
            // Logic#2 - delete the row
            // Logger.log("DEBUG: delete the row");
            targetsheet.deleteRow(editRS);
          }      
      }
      else
      {
        //not the right sheet, not the column, not the right row
        // Logger.log("DEBUG: do nothing - not matched");    
      }
    }