【问题标题】:How to iterate through a range and build a "table" based on a criteria, using Google Apps Script?如何使用 Google Apps 脚本遍历范围并根据条件构建“表格”?
【发布时间】:2021-06-15 10:21:32
【问题描述】:

当我根据第 4 行中找到的日期条件在另一张表中搜索数据时,我得到了下表来填充(范围 D6:J15):

这是我要查找数据的地方,将 Col A 视为标准的基础:

我的困难是连接数据,因为它们符合标准。

这是我正在处理的代码:

/* @OnlyCurrentDoc */
function editarPrevProd() { 
  const lock = LockService.getScriptLock();
  lock.tryLock(3000);
  if (lock.hasLock()) {
    var sourceSheet = 'PrevProdDB2';
    var destinationSheet = 'Previsão Entreposto';
    var ss = SpreadsheetApp.getActiveSpreadsheet(); 
    var sheet = ss.getSheetByName(sourceSheet);
    var ActiveSheetName = ss.getActiveSheet().getName();
    var LastRowSource = sheet.getLastRow();
    var LastColumnSource = sheet.getLastColumn();
    var values = sheet.getRange(2,1,LastRowSource,9).getValues();
    var csh = ss.getSheetByName(destinationSheet);
    var itens = csh.getRange("I40:J57");
    var data = [];
    var weekNo = csh.getRange("B4").getValue();
    var weekDates = csh.getRange("D4:J4").getValues();
    
    if (weekNo == "") {
      Browser.msgBox("Escolher uma data e tente novamente!");
      return;
    }

    //var clearRng = ["K34:K35", "N34:N35", "I40:K"];
    //csh.getRangeList(clearRng).clearContent();

    for (var i = 0; i < values.length; i++) {
      if (values[i][7] == weekNo) {
        data.push(values[i]);
        //break;
      } 
    }
  var dias = 0;
  var prevData = [];
  for (var j = 0; j < weekDates.length; j++) {
    dias = dias + 1;
    Logger.log("Dias da Semana: " + dias);
      for (var a = 0; a < data.length; a++) {
        if (weekDates[j].valueOf() == data[a][0].valueOf()){         
          prevData.push(data[a][4]);
        }  
      }
    }
    
    //map columns whose data will be set in the header.
    var user = data.map(function(e){return e[5];});
    var lastUpdate = data.map(function(e){return e[6];});

    //Copy data array to destination sheet
    csh.getRange("I1").setValue(user);
    csh.getRange("I2").setValue(lastUpdate);
    
    //csh.getRange("E6").setValue(timeStamp);

    //If you wanted to set arrays in the form of 
    //a table, you'd use this below instead
    var seg = data.map(function(e) {return [e[3]];});
    var ter = data.map(function(e) {return [e[4]];});
    var qua = data.map(function(e) {return [e[5]];});
    var qui = data.map(function(e) {return [e[6]];});
    var sex = data.map(function(e) {return [e[7]];});
    var sab = data.map(function(e) {return [e[8]];});
    var dom = data.map(function(e) {return [e[9]];});

    //csh.getRange(6,4,data.length,1).setValues(seg);

    lock.releaseLock();
  }
}

这是文件的示例。请注意,我正在处理的 gs 文件名为 SalvaPrevProducao。

https://docs.google.com/spreadsheets/d/1NOWkzQIAPPdZdxeeTR7Id2v8LR00_u06uPhHs3tzLuU/edit?usp=sharing

【问题讨论】:

  • 在你的示例图片中,两张图片都是示例输入的情况?如果我的理解是正确的,你能提供示例输出情况吗?因为我不确定您要输入range D6:J15 的值。我为此道歉。而且,为了确认表格中的每个值,您能否提供样本电子表格?因为在你的情况下,我无法理解日期是否是日期对象。
  • 这是XY problem吗?考虑共享一个可公开编辑的sample spreadsheet,其中包含逼真的数据,并在那里显示您手动输入的预期结果。使用 Insert > Note 在电子表格中描述您想要的内容。
  • 是的,请分享一个样本表或其他包含样本数据的东西,我们可以用它来测试函数。
  • 嗨,@Tanaike,我已添加文件链接。谢谢!
  • 感谢您回复并提供示例电子表格。根据您的附加信息,我提出了一个答案。你能确认一下吗?如果这不是您期望的结果,我深表歉意。

标签: google-apps-script google-sheets


【解决方案1】:

我相信你的目标如下。

  • 您想使用 Google Apps 脚本将上面的图像转换为底部的图像。
  • 日期标题是单元格“D4:J4”。
  • 源值是单元格“A6:M”。
  • ID 的列“M”是目标工作表中的Semana

在这种情况下,我想提出以下流程。

  1. 从源工作表中检索值。
  2. 创建一个数组以放入目标工作表。
  3. 将数组放入目标工作表。

当这个流程反映到 Google Apps 脚本时,它变成如下。

示例脚本:

在使用此脚本之前,请先设置srcSheetNamedstSheetName的变量。

function editarPrevProd() {
  const srcSheetName = "Data Source"; // This is the source sheet name.
  const dstSheetName = "destSheet"; // Please set the destination sheet name.


  // This is from https://stackoverflow.com/a/44563639
  Object.prototype.get1stNonEmptyRowFromBottom = function (columnNumber, offsetRow = 1) {
    const search = this.getRange(offsetRow, columnNumber, this.getMaxRows()).createTextFinder(".").useRegularExpression(true).findPrevious();
    return search ? search.getRow() : offsetRow;
  };

  // 1. Retrieve values from the source sheet.
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const srcSheet = ss.getSheetByName(srcSheetName);
  const lastRow = srcSheet.get1stNonEmptyRowFromBottom(1);
  const [[, , , ...header1], header2, ...srcValues] = srcSheet.getRange("A4:M" + lastRow).getValues();

  // 2. Create an array for putting to the destination sheet.
  const values = header1.reduce((ar, h, i) => {
    srcValues.forEach(([a, b, c, ...dm]) => ar.push([h, a, b, c, dm[i] || 0, "", "", dm.pop(), h]));
    return ar;
  }, [["Data", "Tipo", "Cod", "Descrição", "Qtd", "Usuário", "TimeStamp", "Semana", "Data"]]);

  // 3. Put the array to the destination sheet.
  const dstSheet = ss.getSheetByName(dstSheetName);
  dstSheet.getRange(1, 1, values.length, values[0].length).setValues(values);
}
  • 运行上述脚本时,将从srcSheetName 检索值并将转换后的值放入dstSheetName

结果:

上面的脚本运行时,得到如下结果。

注意:

  • 不幸的是,从您的问题和示例电子表格中,我无法理解“F”和“G”列的UsuárioTimeStamp。在Turn the data from the left into the format on the right side的样本输出情况下,UsuárioTimeStamp没有值。

参考资料:

【讨论】:

  • 我会在一年后回来,在我了解这里显示的概念之后。脑洞大开!谢谢!
【解决方案2】:

目前还不清楚为什么您需要借助脚本来查找这些值,而 filter() 公式似乎也能做到这一点。在单元格D6 中试试这个公式:

=sum( iferror( filter(PrevProdDB2!$E$2:$E, PrevProdDB2!$B$2:$B = $A6, PrevProdDB2!$H$2:$H = $B$4, PrevProdDB2!$I$2:$I = D$4) ) )

【讨论】:

  • 我将以预期的格式将数据从一张表传输到另一张表,因此用户必须能够点击“保存”按钮,然后数据将被传输/附加。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-30
  • 1970-01-01
  • 2021-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多