条件满足后,循环再次运行

时间:2020-04-06 02:33:45

标签: for-loop google-apps-script google-sheets

我正在创建一个函数,该函数可以从Google表格文档中的众多表格中添加数据。该功能创建具有名称和数据插槽的生产工作表,以及将粘贴到“打印”工作表中的数据的列标题。我遇到的一个问题是,即使据我所知,满足条件的for循环似乎又要运行一段时间。这是我到目前为止的代码,很丑陋,但我只是为自己构建。

function pasteToPrint(){

  var ui = SpreadsheetApp.getUi()

  var spreadsheet = SpreadsheetApp.getActive();

  var sheetName;

  var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();

  var lastCol;

  var lastRow;

  var a;

  var x;

  var y;

  var z;

  var array1 = [];

  var array2 = [];

  function getNextPage(){ // spreads subsequent data set to page break for printing 
    x = spreadsheet.getSheetByName("Print").getLastRow();
    y = x/32;
    y = Math.ceil(y);
    z = 32*y;
    return z;
  }

  for(var i = sheets.length-1; i > 4; i--){ // loops through the appropriate sheets and pushes to array1
    lastCol = spreadsheet.getSheetByName(sheets[i].getName()).getLastColumn()+1;
    lastRow = spreadsheet.getSheetByName(sheets[i].getName()).getLastRow()+1;
    array1.push(spreadsheet.getSheetByName(sheets[i].getName()).getRange(1, 1, lastRow, lastCol).getValues());
  }

  for(var i = 0; i < array1.length; i++){ 
    for(var j = 0; j < array1[i].length; j++){
      // Looking for data that has a value grater than 0 at .slice(2,3)
      if(array1[i][j].slice(2,3) > 0){ // Ref1
        for(var k = 0; k < array1[i].length; k++){ // here I push that data to array2
          if(array1[i][k].slice(2,3) > 0){ // ref 2
            array2.push(array1[i][k]);
          }
        }
        ui.alert(array2+" test 1"); // lets me know the content of array2
        ui.alert(array2.length); // tells me the length just to be sure
        for(var l = 0; l < array2.length; l++){ // decides where to paste the next data set
          if(spreadsheet.getSheetByName("Print").getLastRow()>1){ // ref 3
            a = getNextPage(); // returns the next 32nd line
          }
          else {
            a = 1; // starts at row 1
          } 
          // this next section is column formatting for the beginning of the production sheet
          // ref 4
          spreadsheet.getSheetByName("Print").getRange(a,1).setValue("Name:");    
          spreadsheet.getSheetByName("Print").getRange(a,3).setValue("Date:");
          a++; // moves to the next row
          spreadsheet.getSheetByName("Print").getRange(a,1).setValue("Product");
          spreadsheet.getSheetByName("Print").getRange(a,2).setValue("Work Order");
          spreadsheet.getSheetByName("Print").getRange(a,3).setValue("Planned Production");
          spreadsheet.getSheetByName("Print").getRange(a,4).setValue("Product Produced");
          spreadsheet.getSheetByName("Print").getRange(a,5).setValue("Steel Shortage");
          spreadsheet.getSheetByName("Print").getRange(a,6).setValue("Notes");
          a++ // moves to the next row
          // ref 5
          for(var m = 0; m < array2[l].length-1; m++){ // HERE IS THE PROBLEM LOOP
            ui.alert(array2[m]+" test 2"); // I see this run an additional time after m = length
            spreadsheet.getSheetByName("Print").getRange(a,1).setValue(array2[m][0]);
            spreadsheet.getSheetByName("Print").getRange(a,2).setValue(array2[m][4]);
            spreadsheet.getSheetByName("Print").getRange(a,3).setValue(array2[m][2]);
            a++; 
          }
        }
        array2 = []; // array2 is emptied 
        break; // First if statement checking .slice(2,3) now has the function go to the next sheet
      }
    }
  }

  ui.alert("Function ended"); // just letting me know

};

假设该文档中有许多工作表,其数据如下所示,不同之处在于列标题后可能有数百行,且零件号不同,依此类推

Material  Req Planned Quantity MTs Planned Order
AI UPC300 1   1                86  12744851

.slice(2,3)查找的是“计划数量”列。默认情况下,当我从库存系统将原始数据粘贴到工作表中时,“计划数量”的值将为0。经过文档并计划生产后,这意味着我为“计划数量”分配了一个大于0的值,将运行该功能以将数据粘贴到打印纸上。可能有数百个项目,但我只会计划其中的一部分,因此这很方便。我无法共享正在使用的完整文档,因为其中包含敏感数据。如果您使用一个名为print的工作表创建一个Google工作表,然后将第二个工作表命名为您想要的工作表,则可以将示例数据粘贴到第二个工作表的第1行和第2行,您会看到我得到的错误

TypeError:无法读取未定义的属性“ 0”(第138行,文件“ arrayTest”)

您还必须将for(var i = sheets.length-1; i > 4; i--)更改为for(var i = sheets.length-1; i > 1; i--),将4更改为1。我的文档中包含更多代码,但是它由与此功能分开的功能组成。

我在下面添加了一张图像,展示了在使用该功能之前它的外观以及该功能运行后的打印纸外观。不幸的是,我不得不截图,所以数据被压缩了。想象一下,您看到的每个数据部分(绿色,蓝色和白色)都在各自的工作表上。为了清楚起见,绿色的数据将包含在TestSheet1中,蓝色的数据将包含在TestSheet2中,并且在运行此函数之前,Print页将完全空白。在TestSheet 1和2的“计划数量”列中输入计划数量后,我将运行该功能。这将导致数据粘贴到打印页面上。我在代码中添加了“ ref”注释,以显示以下解释的每个步骤在何处发生。该功能按以下顺序运行:1)该功能将确定工作表中“计划数量”列“参考1”中的值是否大于零。 2)函数将使它们循环通过工作表并将符合此条件的任何行推送到array2,即“ ref 2”。 3)该函数将根据可能已经在页上第1行,第32行,第64行等等(参考3)的数据来确定将数据粘贴到打印页的位置。 4)该函数将在即将粘贴的数据上方粘贴标题。该标题包括名称,日期和列标题。 5)放置标题后,该函数将遍历array2并将其内容粘贴到“ ref 5”打印页上。 6)该函数将把array2设置为array2 = [],然后对下一张纸重复该过程,直到所有纸都过去了,并且没有更多数据可粘贴到“参考6”打印中。

Image of spreadsheets: "Print" only image of tab, "TestSheet1" cells in green, "TestSheet2" cells in blue, an example of the Print sheet after the function correctly runs

1 个答案:

答案 0 :(得分:1)

m循环是不必要的。它遍历当前行(l s)列。 mcve看起来像这样:

const array2d = [1, 2, 3].map(num => new Array(6).fill(num));//boilerplate to simulate array2
console.log({array2d});
for (var l = 0; l < array2d.length; l++) {
  for (var m = 0; m < array2d[l].length - 1; m++) {
    // HERE IS THE PROBLEM LOOP
    // alert(array2d[m] + ' test 2'); // I see this run an additional time after m = length
    console.log(array2d[m][0], array2d[m][2], array2d[m][4]);
  }
}

解决方案:

完全删除循环。

a++; // moves to the next row
//          for(var m = 0; m < array2[l].length-1; m++){ // HERE IS THE PROBLEM LOOP
//           ui.alert(array2[m]+" test 2"); // I see this run an additional time after m = length
spreadsheet
  .getSheetByName('Print')
  .getRange(a, 1)
  .setValue(array2[l][0]);
spreadsheet
  .getSheetByName('Print')
  .getRange(a, 2)
  .setValue(array2[l][4]);
spreadsheet
  .getSheetByName('Print')
  .getRange(a, 3)
  .setValue(array2[l][2]);
a++;
//          }

    }

最佳做法: