【问题标题】:How to insert the email address by querying corresponding ID using Google App Scripts?如何使用 Google App Scripts 通过查询对应 ID 来插入电子邮件地址?
【发布时间】:2020-10-27 07:30:49
【问题描述】:

如果我当前的代码用于手动输入,当我选择一个主题、一个日期并一次最多输入 4 个学生 ID(例如 1802001、1802002、1802004)然后选择一个选项时,它只是连接使用电子邮件模式(例如@icte.bdu.ac.bd)并将其插入到之前选择的目标主题表中。

我不想再使用电子邮件模式 (@icte.bdu.ac.bd)。鉴于一批学生的所有电子邮件地址都相似(例如 1902001@ubd.ac.bd、1902002@ubd.ac.bd),我当前的代码工作正常。然而,在许多机构不提供基于学生 ID 号的电子邮件地址,通常是像 tom@ubd.ac.bd 或 james@ubd.ac.bd。

请注意,当输入到仪表板(见附图)和 StudentList 表时,学生 ID 相同,但在目标表 (HUM4105) 中不同,例如 1802001、1802003、“Roll No.:18.02. 004 Reg No.:2018.11.000027"。但是,学生的电子邮件地址在所有地方都是相同的,应该作为一个基础。实际上它是一个学生考勤系统,输入通常来自一个android应用程序。如果很少有学生错过报告出勤,然后我们进行手动输入。

我想要做的是,当我输入学生 ID 时,最多 4 个(例如 1802001, 1802003) 它实际上会插入它们对应的电子邮件 从 Google 工作表 (StudentList) 到之前选择的主题工作表 (HUM4105) 的地址。学生名单 sheet contains SID in COLUMN D and Email in Column F. Please note that Edit trigger is already there and when a certain option is selected, the following code is executed.

代码是:

function manualEntry(e){ 
    var spreadsheet = SpreadsheetApp.getActive();
      var dashboard = spreadsheet.getSheetByName("Dashboard");
      var sheetName = dashboard.getRange("F5").getValue(); 
      var mDate = dashboard.getRange("G5").getDisplayValue();
      var sheetw = dashboard.getRange("A8");
      var sheetw2 = dashboard.getRange("G8");
           
        if (e.range.getA1Notation() === 'K6' && e.range.getValue() === "Report 1P") {
          sheetw2.setValue('Manual entry process is up and running. Please Wait!').setFontColor('Red');
          onePeriodm();       
          sheetw.setValue('You may take class attendance now. Thank You!').setFontColor('Green');
          sheetw2.setValue('You may do manual entry now. Thank You!').setFontColor('Green');
        }
   }          
    
    function onePeriodm(){
    //for one period manual entry
      const srcSheetName = "Dashboard";
    
      // 1. Retrieve values from the source sheet.
      const ss = SpreadsheetApp.getActiveSpreadsheet();
      const srcSheet = ss.getSheetByName(srcSheetName);
      const [
        [, , , , , emailPattern],
        ,
        [courseCatalogId, dateString, ...studentIds],
      ] = srcSheet.getRange("F3:K5").getDisplayValues();
    
      // 2. Retrieve current values
      const dstSheet = ss.getSheetByName(courseCatalogId);
      const dstCurrentValues = dstSheet
        .getRange(`A2:C${dstSheet.getLastRow()}`) // expanded to include email column
        .getDisplayValues(); // not flattening since we have multiple columns now
    
      // 3. Convert the values for putting to the destination sheet.
      //    Do not include if there is already an email for this date in current values
      const dstValues = studentIds.reduce((array, studentId) => {
        const existingEntry = dstCurrentValues.find(
          (row) => row[0] === dateString && row[2] === studentId + emailPattern
        );
        if (studentId != "" && !existingEntry)
          array.push([
            dateString,
            Number(studentId),
            studentId + emailPattern,
            ,
            ,
            courseCatalogId,
          ]);
        return array;
      }, []);
    
      // 4. Put the converted values to the destination sheet.
      const index = dstCurrentValues.map((row) => row[0]).lastIndexOf(dateString);
      const row = index + 2;
      if (dstValues.length > 0){
         dstSheet.insertRowsAfter(row, dstValues.length);
         dstSheet.getRange(row + 1, 1, dstValues.length, dstValues[0].length).setValues(dstValues);
      }

【问题讨论】:

    标签: google-apps-script google-sheets


    【解决方案1】:

    现在您的代码正在将 id 与电子邮件模式结合起来。因此,要使代码在这两种情况下都能正常工作,您需要进行检查以确定何时将 ID 与电子邮件模式连接,以及何时将 ID 替换为整个电子邮件地址。 (我假设整个电子邮件地址都在 F 列的 StudentList 表中。)

    如果始终列出整个电子邮件,即使它基于学生 ID,我也会完全取消 ID 和电子邮件模式的连接,而只使用 ID 替换整个电子邮件地址。

    以下是需要在您的代码中实现的步骤:

    1. 获取 StudentList 列 D 到 F 的范围。这将是一个 数组(比如 studentListArray)。
    2. 获取学生 ID 数组。 (如果您以不同的方式构建仪表板,您可以简单地在一行中列出任意数量的 ID,而不是一次只列出 4 个。)
    3. 检查您的 ID 数组是否有重复项。
    4. 遍历 ID 数组并在 studentListArray[0] 上按 ID 过滤 studentListArray,返回 studentListArray[2]。
    5. 检查过滤结果是否未定义。
    6. 如果过滤结果未定义,则将结果设置为学生电子邮件。

    编辑


    这是对代码进行更改的示例表:

    https://docs.google.com/spreadsheets/d/146vRZ1QDGpnzhxnAuQ03qX4jTORZdj_piueW7ORfYDY/edit?usp=sharing

    这是onePeriodm()的代码:

    function onePeriodm(){
      //For protecting dashboard while scripts running
      var spreadsheet = SpreadsheetApp.getActive(); 
      
      //### new code ##########################################
      var studentListSheet = spreadsheet.getSheetByName("StudentList");
      var studentList = studentListSheet.getDataRange().getValues();
      var studentEmail = null;
      var tempEmail = null;
      //### end new code ######################################
      
      var dashboard = spreadsheet.getSheetByName("Dashboard");  
      var sheetw = dashboard.getRange("A8");
      var sheetw2 = dashboard.getRange("G8");  
      sheetw.setValue('Class Attendance is restricted now. Try Again Later!').setFontColor('Red');
       
      var rangem = dashboard.getRange("A4:K6");
      
      var timeZone = Session.getScriptTimeZone();
      var stringDate = Utilities.formatDate(new Date(), timeZone, 'dd/MM/yy HH:mm');
      //var me2 = Session.getEffectiveUser();
      var me2 = Session.getActiveUser().getEmail();
      var description = 'Scripts running on ' + stringDate + ' by ' + me2;
      
      //var me = Session.getEffectiveUser();
      //var description = 'Scripts are running by ' + me;
      var protectionm = rangem.protect().setDescription(description);  
      protectionm.removeEditors(protectionm.getEditors());
      protectionm.addEditor(me2);
      if (protectionm.canDomainEdit()) {
          protectionm.setDomainEdit(false);
      }  
      
      //Refreshing sheet with removing unprotectd data
      var spreadsheet = SpreadsheetApp.getActive();  
      var dashboard = spreadsheet.getSheetByName("Dashboard");  
      var sheetName = dashboard.getRange("F5").getValue(); 
      var sheet = spreadsheet.getSheetByName(sheetName);
      
      //For removing unprotected rows of data from a particular sheet  
      // 1. Retrieve data range.
        const dataRange = sheet.getDataRange();
    
        // 2. Create an object from the protected range. This is used for removing from the cleared rows.
        const protectedRanges = sheet.getProtections(SpreadsheetApp.ProtectionType.RANGE).map(e => {
          const r = e.getRange();
          const start = r.getRow();
          return {start: start, end: r.getNumRows() + start - 1};
        });
    
        // 3. Create range list for clearing rows using the object.
        let rangeList = [];
        for (let r = 2; r <= dataRange.getNumRows(); r++) {
          let bk = false;
          for (let e = 0; e < protectedRanges.length; e++) {
            if (protectedRanges[e].start == r) {
              r = protectedRanges[e].end;
              bk = true;
              break;
            }
          }
          if (!bk) rangeList.push(`A${r}:${r}`);
        }
    
        // 4. Delete the rows without the rows of the protected ranges.
        if (rangeList.length > 0) sheet.getRangeList(rangeList).getRanges().reverse().forEach(r => sheet.deleteRow(r.getRow()));
        //sheet.getRangeList(rangeList).getRanges().reverse().forEach(r => sheet.deleteRow(r.getRow()));
      
    
      //for one period manual entry
      const srcSheetName = "Dashboard";
    
      // 1. Retrieve values from the source sheet.
      const ss = SpreadsheetApp.getActiveSpreadsheet();
      const srcSheet = ss.getSheetByName(srcSheetName);
      const [
        [, , , , , emailPattern],
        ,
        [courseCatalogId, dateString, ...studentIds],
      ] = srcSheet.getRange("F3:K5").getDisplayValues();
    
      // 2. Retrieve current values
      const dstSheet = ss.getSheetByName(courseCatalogId);
      const dstCurrentValues = dstSheet
        .getRange(`A2:C${dstSheet.getLastRow()}`) // expanded to include email column
        .getDisplayValues(); // not flattening since we have multiple columns now
    
      // 3. Convert the values for putting to the destination sheet.
      //    Do not include if there is already an email for this date in current values
      const dstValues = studentIds.reduce((array, studentId) => {
        const existingEntry = dstCurrentValues.find(
          (row) => row[0] === dateString && +row[1] === +studentId //(row) => row[0] === dateString && row[2] === studentId + emailPattern //############# code change
      );
    //### new code ##########################################
    tempEmail = studentList.filter(function(a){return (+a[3]) == (+studentId);})[0];
    if (tempEmail != undefined && tempEmail != null &&tempEmail != ""){
      studentEmail = tempEmail[5];
    }else{
      studentEmail = studentId + emailPattern;
    }
    //### end new code ######################################
    
        if (studentId != "" && !existingEntry)
          array.push([
            dateString,
            Number(studentId),
            studentEmail,//studentId + emailPattern //############# code change
            ,
            ,
            courseCatalogId,
          ]);
        return array;
      }, []);
    
      // 4. Put the converted values to the destination sheet.
      const index = dstCurrentValues.map((row) => row[0]).lastIndexOf(dateString);
      const row = index + 2;
      if (dstValues.length > 0){
         dstSheet.insertRowsAfter(row, dstValues.length);
         dstSheet.getRange(row + 1, 1, dstValues.length, dstValues[0].length).setValues(dstValues);
      }
    
      //dstSheet.insertRowsAfter(row, dstValues.length);
      //dstSheet.getRange(row + 1, 1, dstValues.length, dstValues[0].length).setValues(dstValues); 
      protectionm.remove();  
      SpreadsheetApp.flush();
      
      srcSheet.getRange("F5").setValue("All"); 
      srcSheet.getRange("K6").setValue("Please Select"); 
      srcSheet.getRange("G5:K5").clearContent();
      srcSheet.getRange('G5').clearDataValidations();
      //srcSheet.getRange('G5').setValue(new Date()).setNumberFormat("yyyy-mm-dd");    
    } 
    

    【讨论】:

    • 请查看附件图片。
    • 您能分享一份包含虚假数据的电子表格副本吗?仍然有太多未知数无法有效地提供任何帮助。 StudentList 表中是否列出了完整的电子邮件地址?
    • 请查看此表格链接:docs.google.com/spreadsheets/d/…
    • 检查带有主题 HUM4105 的手动输入部分,并检查底部的工作表 HUM4105 和 StudentList 选项卡。请注意,此处的主题和工作表名称相同。
    • 您可以通过工具 --> 脚本编辑器查看代码
    【解决方案2】:

    您的任务可以通过使用onEdit 触发器来完成。

    代码

    // Copyright 2020 Google LLC.
    // SPDX-License-Identifier: Apache-2.0
    
    function onEdit(e) {
        let currentSheet = e.range.getSheet().getName();
        let valsToSearchIn = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('SHEET_WHERE_THE_IDS_ARE').getRange(ROW, COL, NO_ROWS, NO_COLS).getValues();
    
        if (currentSheet == 'SHEET_WHERE_YOU_INPUT_THE_IDS') {
            let inputValue = e.value;
            for (let i = 0; i < valsToSearchIn.length; i++)
                if (valsToSearchIn[i][0] == inputValue) 
                    e.range.setValue(SpreadsheetApp.getActiveSpreadsheet().getSheetByName('SHEET_WHERE_YOU_INPUT_THE_IDS').getRange(i + ROW, COL).getValue());
                else
                    SpreadsheetApp.getUi().alert('Please input a valid student id!');
        }
    }
    

    说明

    上述代码通过使用e 事件对象来识别编辑所在的工作表。如果此表的名称与SHEET_WHERE_YOU_INPUT_THE_IDS 相同,则将输入的值存储在inputValue 变量中。之后,它会在valsToSearchIn 数组中搜索inputValue,它是存储学生ID 的数组,如果搜索成功,则会在编辑的范围内设置相应的电子邮件地址。如果找不到 id,则会向用户显示警报。

    注意

    请记住,您必须调整上面的代码(尤其是工作表的范围和名称)以符合您的要求。

    演示

    1. onEdit(e) 触发器之前

    SHEET_WHERE_THE_IDS_ARE

    SHEET_WHERE_YOU_INPUT_THE_IDS

    1. onEdit(e) 触发器之后

    SHEET_WHERE_YOU_INPUT_THE_IDS

    参考

    【讨论】:

    • 我的情况有点不同。输入谷歌表格页面附加到上面的帖子。编辑触发器已经存在。我只需要做一个或多个输入(每个输入页面图像最多四个)并搜索相应的 ID,然后将相应的电子邮件插入目标工作表。
    • 你到底在说什么输入?您是否介意更精确并提供更多关于您想要实现的目标的详细信息?上面的脚本是onEdit 触发器吗?
    • 请在帖子中查看我的完整代码。我在 Student ID 01 (1802003)、Student ID 02 (1802007)、Student ID 03 (1802011) 等处进行输入。同时检查附件图像。然后,这些输入将搜索 StudentList 表的 SID(第 4 列)。如果匹配,那么它将获取相应的电子邮件地址并将其插入到目标工作表中。就是这样。
    • 那么在执行了manualEntry触发的onePeriodm函数后,为什么不能再添加一个条件并使用上面提供的代码呢?
    • 我需要在现有触发器中创建另一个触发器吗?一次可以插入多少个ID?当前代码允许我一次最多插入 4 个 ID。请注意,目标表与我输入 ID 的位置不同,请在帖子中查看我的代码的最后一部分。
    猜你喜欢
    • 2021-05-31
    • 1970-01-01
    • 1970-01-01
    • 2016-09-16
    • 2021-12-13
    • 1970-01-01
    • 1970-01-01
    • 2016-05-06
    • 1970-01-01
    相关资源
    最近更新 更多