【问题标题】:Google apps script - using for loop to pull data from range based on conditionGoogle 应用程序脚本 - 使用 for 循环根据条件从范围中提取数据
【发布时间】:2017-05-19 10:26:05
【问题描述】:

我在从 Google 表格的 for 循环中提取正确值时遇到问题。 这是我的代码: 注意:这是一个更大函数的 sn-p

function sendEmails() {
var trackOriginSheet = SpreadsheetApp.getActiveSpreadsheet().getName();
var getMirSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Miranda");

//Set a new object to hold conditional data
var holdingData = new Object();

//Create function to get values from origin sheet
var returnedValues = function (trackOriginSheet) {

//Load dynamic variables into an object via returnedValues()
    if (trackOriginSheet === getMirSheet) {

        var startMirRow = 2; // First row of data to process
        var numRowsMir = 506; // Number of rows to process

        // Fetch the range of cells A2:Z506
        var dataRangeMir = getMirSheet.getRange(startMirRow, 1, numRowsMir, 26);

        // Fetch values for each cell in the Range.
        var dataMir = dataRangeMir.getValues();

        for (var k in dataMir) {
            var secondRowMir = dataMir[k];
            var intRefDescMir = secondRowMir[3];
            var intAdminActionsMir = secondRowMir[4];

            //Push returned data to holdingData Object
            holdingData.selectedData = secondRowMir;
            holdingData.refDesc = intRefDescMir;
            holdingData.adminActions = intAdminActionsMir;
        }
    }
}

Here's a copy of the sheet I'm working on

我首先需要在这里做的是跟踪原始表,然后创建一个对象来保存从 returnedValues() 函数返回的数据。稍后,我会将此对象的属性调用到发送电子邮件函数中。

问题是我需要能够动态地从选定的工作表中提取数据(在这种情况下为“米兰达”工作表。)换句话说,当用户在米兰达的第一列中选​​择“是”选项时工作表,该脚本需要做的第一件事是在用户选择“是”的同一行中提取 for 循环顶部的变量值。 然后,我正在推动数据到稍后调用的自定义对象。

对我来说很明显,我做错了。至少,我的循环有问题。我做了什么? :)

编辑: 在查看了 VyTautas 的建议后,这是我对工作循环的尝试:

for (var k = 0; k < dataMir.length; k++) {
            var mirColI = dataMir[k][8];
            var mirRefDesc = dataMir[k][2];
            var mirAdminActions = dataMir[k][3];
            var mirDates = dataMir[k][4];
            if (mirColI === "Yes") {
              var activeRowMir = mirColI.getActiveSelection.getRowIndex();
              //Pull selected values from the active row when Yes is selected
              var mirRefDescRange = getMirSheet.getRange(activeRowMir, mirRefDesc);
              var mirRefDescValues = mirRefDescRange.getValues();
              var mirAdminActionsRange = getMirSheet.getRange(activeRowMir, mirAdminActions);
              var mirAdminActionsValues = mirAdminActionsRange.getValues();
              var mirDatesRange = getMirSheet.getRange(activeRowMir, mirDates);
              var mirDatesValues = mirAdminActionsRange.getValues();
              var mirHoldingArray = [mirRefDescValues, mirAdminActionsValues, mirDatesValues];
              //Push mirHoldingArray values to holdingData
              holdingData.refDesc = mirHoldingArray[0];
              holdingData.adminActions = mirHoldingArray[1];
              holdingData.dates = mirHoldingArray[2];
            }
        }

【问题讨论】:

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


    【解决方案1】:

    所有这些空白在实际的脚本编辑器中都去了哪里? :D

    您已经正确使用.getValues() 将整个表拉入一个数组。您现在需要做的是让 for 循环通过 dataMir[k][8] 并简单地获取数据 if dataMir[k][8] === 'Yes'。我也觉得使用for (var k in dataMir) 不是很必要,因为for (var k = 0; k &lt; dataMir.length; k++) 更干净,而且你有一个保证控制的for 循环(尽管这可能更偏爱)。

    您还可以通过使用来减少使用的变量数量

    holdingData.selectedData = mirData[k]
    holdingData.refDesc = mirData[k][2] //I assume you want the 3rd column for this variable, not the 4th
    holdingData.adminActions = mirData[k][3] //same as above
    

    记住,数组从 0 开始,所以如果你 mirData[k][0] 是 A 列,mirData[k][1] 是 B 列等等。

    编辑:您在编辑中写的内容似乎加倍了代码。您已经拥有数据,但您正试图再次提取它,并且您使用的一些变量应该会给您一个错误。我将从 if 中删除代码,尽管我真的不明白为什么您需要同时按名称获取活动工作表和工作表。如果您知道名称是不变的,那么只需始终按名称(或索引)获取正确的工作表,从而消除使用错误工作表的可能性。

       var titleMirRows = 1; // First row of data to process
       var numRowsMir = getMirSheet.getLastRow(); // Number of rows to process
    
    // Fetch the range of cells A2:Z506
       var dataRangeMir = getMirSheet.getRange(titleMirRows + 1, 1, numRowsMir - titleMirRows, 26); // might need adjusting but now it will only get as many rows as there is data, you can do the same for columns too
    
    // Fetch values for each cell in the Range.
       var dataMir = dataRangeMir.getValues();
    
       for (var k = 0; k < dataMir.length; k++) {
         if (dataMir[k][7] === 'Yes') {    //I assume you meant column i
           holdingData.refDesc = dataMir[k] //this will store the entire row
           holdingData.adminActions = dataMir[k][3] //this stores column D
           holdingData.dates = dataMir[k][4] //stores column E
         }
       }
    

    仔细检查我添加到这些变量中的列是否是您想要的。据我了解,该对象存储整个行数组,名为 Administrative Actions 的列中的值和列中的值 Dates/Periods if Applicable。如果不是,请进行相应调整,但如您所见,我们通过简单地操作整个数据数组来最小化我们对工作表本身所做的工作。始终尽可能少地调用 Google 服务。

    【讨论】:

    • 因为 mirData[k] 正在获取第 8 行中的每个单元格,作为数组中的行对象,并且在其中运行 for 循环以查找字符串会拉出实际的单元格。现在这很有意义:) 谢谢!今天早上我会试试这个,然后报告
    • 我想我明白如何实现你在这里所说的(就循环而言)我是否与上面编辑中的代码保持一致?
    • 编辑与我的一天结束:) 我相信这会奏效,但请随时纠正我。另外,我想减少一些变量,但现在没时间了
    • @Jensen010 请查看我对答案的编辑。查看您的 for 循环,如果没有其他任何变化,那么您正在做同样的事情两次。您已经拥有dataMir,这应该是您想要的所有数据,并且您想要对该表执行的唯一其他调用是如果您更改其中的任何内容。我还更改了numRowsMir,以便您只获得所需的数据
    • ooooook,这对我来说很有意义。我不知道为什么我没有想到通过将列推送到对象来选择单元格值,因为该行已经处于活动状态。我知道它可以更简单,但没有时间工作:) 感谢您的所有帮助!可能感觉不像,但你帮助我对自己的能力有了一些信心(你激励我重写和简化了一堆我没有发布的代码:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-07-04
    • 2020-06-05
    • 1970-01-01
    • 2016-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多