选择下拉菜单中的名称时填写模板表

Posted

技术标签:

【中文标题】选择下拉菜单中的名称时填写模板表【英文标题】:fill out template sheet when a name in a dropdown menu is selected 【发布时间】:2019-10-15 14:55:05 【问题描述】:

我已经创建了一个成绩报告 Google 电子表格,但现在我正在寻找一种方法来用一个学生的成绩填写我的模板报告表。我怎样才能做到这一点?

在文件 1 中,我有学生的所有成绩。在文件 2 中,我有成绩报告的模板。如何在显示所有学生的模板成绩报告中创建一个下拉菜单,并且当我单击其中一个学生时会自动填写成绩报告中的所有字段? 我现在使用 importrange 函数将列中的数据导入模板,但现在我需要每个学生的成绩报告文件。 这确实比为每个学生创建一个成绩报告文件效率更高。

我希望你能帮助我。

文件 1: https://docs.google.com/spreadsheets/d/12M8W7fARJJZN90wM79U4x8RmcnZ08kFSDcZYnB26HB0/copy

文件 2: https://docs.google.com/spreadsheets/d/13-0qhCudC7EYRgOs2UpbJPRSq2nKoBiG2Md3-U8_U1Q/copy

【问题讨论】:

【参考方案1】:

您可以使用以下代码:

var LIST_WITH_GRADES_ID = 'YOUR_ID';
var LIST_WITH_GRADES_STUDENTS_A1 = 'Rapportoverzicht!B2:Y2';

function onOpenSpreadsheet(e) 
  var students = SpreadsheetApp.openById(LIST_WITH_GRADES_ID).getRange(LIST_WITH_GRADES_STUDENTS_A1).getValues()[0];
  var rangeRule = SpreadsheetApp.newDataValidation().requireValueInList(students).setAllowInvalid(false);
  SpreadsheetApp.getActive().getRange('Rapport!E1').setDataValidation(rangeRule);


function onEditSpreadsheet(e) 
  var rapportSheet = SpreadsheetApp.getActive().getSheetByName('Rapport');
  if (e.range.getA1Notation() == 'E1' && e.range.getSheet().getName() == 'Rapport') 
    var studentCol = findStudentCol(e.range.getValue());
    copyStudentGrades(studentCol);
  


/* Returns 1-indexed student column */
function findStudentCol(student) 
  var sheet = SpreadsheetApp.openById(LIST_WITH_GRADES_ID);
  var studentsRange = SpreadsheetApp.openById(LIST_WITH_GRADES_ID).getRange(LIST_WITH_GRADES_STUDENTS_A1);
  for (var col=1; col<=studentsRange.getWidth(); col++) 
    if (studentsRange.getCell(1, col).getValue() == student) 
      return col + studentsRange.getColumn() - 1;
  


function copyStudentGrades(studentCol) 
  var gradesSheet = SpreadsheetApp.openById(LIST_WITH_GRADES_ID).getSheetByName('Rapportoverzicht');
  var templateSheet = SpreadsheetApp.getActive().getSheetByName('Rapport');

  templateSheet.getRange(4, 4, 30, 1).setValues(
    gradesSheet.getRange(4, studentCol, 30, 1).getValues());

  templateSheet.getRange(4, 10, 25, 1).setValues(
    gradesSheet.getRange(36, studentCol, 25, 1).getValues());

您必须将成绩表的 ID 放在第一行,然后将此脚本添加到“模板”表的编辑器中。您还需要将onOpenSpreadsheetonEditSpreadsheet 设置为可安装的触发器以使其工作(请参阅managing triggers manually)。

编辑

为了同时使用两个不同的成绩文件并导入备注,您可以使用之前代码的以下编辑:

var LIST_WITH_GRADES_ID = 'YOUR_LIST_WITH_GRADES_1_ID';
var LIST_WITH_GRADES_2_ID = 'YOUR_LIST_WITH_GRADES_2_ID';
var LIST_WITH_GRADES_STUDENTS_A1 = 'Rapportoverzicht!B2:AG2';
var NSTUDENTS = 24; // Number of students

function onOpenSpreadsheet(e) 
  var students = SpreadsheetApp.openById(LIST_WITH_GRADES_ID).getRange(LIST_WITH_GRADES_STUDENTS_A1).getValues()[0];
  var rangeRule = SpreadsheetApp.newDataValidation().requireValueInList(students).setAllowInvalid(false);
  SpreadsheetApp.getActive().getRange('Rapport!E1').setDataValidation(rangeRule);


function onEditSpreadsheet(e) 
  var currentStudent = e.range.getValue();
  var rapportSheet = SpreadsheetApp.getActive().getSheetByName('Rapport');
  if (e.range.getA1Notation() == 'E1' && e.range.getSheet().getName() == 'Rapport') 
    var studentCol = findStudentCol(currentStudent);
    copyStudentGrades(studentCol);
    importRemarks(currentStudent);
  


/* Returns 1-indexed student column */
function findStudentCol(student) 
  var sheet = SpreadsheetApp.openById(LIST_WITH_GRADES_ID);
  var studentsRange = SpreadsheetApp.openById(LIST_WITH_GRADES_ID).getRange(LIST_WITH_GRADES_STUDENTS_A1);
  for (var col=1; col<=studentsRange.getWidth(); col++) 
    if (studentsRange.getCell(1, col).getValue() == student) 
      return col + studentsRange.getColumn() - 1;
  


function copyStudentGrades(studentCol) 
  var gradesSheet = SpreadsheetApp.openById(LIST_WITH_GRADES_ID).getSheetByName('Rapportoverzicht');
  var gradesSheet2 = SpreadsheetApp.openById(LIST_WITH_GRADES_2_ID).getSheetByName('Rapportoverzicht');
  var templateSheet = SpreadsheetApp.getActive().getSheetByName('Rapport');

  templateSheet.getRange(4, 4, 30, 1).setValues(
    gradesSheet.getRange(4, studentCol, 30, 1).getValues());

  templateSheet.getRange(4, 10, 25, 1).setValues(
    gradesSheet.getRange(36, studentCol, 25, 1).getValues());

  templateSheet.getRange(4, 6, 30, 1).setValues(
    gradesSheet2.getRange(4, studentCol, 30, 1).getValues());

  templateSheet.getRange(4, 12, 25, 1).setValues(
    gradesSheet2.getRange(36, studentCol, 25, 1).getValues());


function importRemarks(student) 
  var remarksSheet = SpreadsheetApp.openById(LIST_WITH_GRADES_ID).getSheetByName('opmerkingen rapport');
  var remarksSheet2 = SpreadsheetApp.openById(LIST_WITH_GRADES_2_ID).getSheetByName('opmerkingen rapport');
  var templateSheet = SpreadsheetApp.getActive().getSheetByName('Opmerkingen');
  var studentRow;

  for (var i=2; i<(2+NSTUDENTS); i++) 
    if (remarksSheet.getRange(i, 1).getValue() == student) 
      studentRow = i;
      break;
    
  

  templateSheet.getRange('B5').setValue(remarksSheet.getRange(studentRow, 2).getValue());
  templateSheet.getRange('B11').setValue(remarksSheet2.getRange(studentRow, 2).getValue());

【讨论】:

你好,我试着让它工作,但我仍然在努力解决一些问题。 - 你的_ID是docs.google.com/spreadsheets/d之后链接的最后一部分? @RikKnijnenburgDaltonschoolO 正确,在这种情况下,您的 ID 应为 12M8W7fARJJZN90wM79U4x8RmcnZ08kFSDcZYnB26HB0(摘自您的原始问题)。让我知道这是否适合你。干杯 - 我如何创建一个下拉菜单,我可以在其中选择学生来触发脚本? - 如何正确设置触发器?我没有太多使用这些功能的经验。所以我在这里有点迷路了。 docs.google.com/spreadsheets/d/…docs.google.com/spreadsheets/d/… 和脚本编辑器链接:script.google.com/d/… @RikKnijnenburgDaltonschoolO 脚本的第一行应如下所示:var LIST_WITH_GRADES_ID = '12M8W7fARJJZN90wM79U4x8RmcnZ08kFSDcZYnB26HB0'。此外,您必须设置一个 onOpen 触发器(请参阅我的答案)。设置后,将为您创建下拉列表。另外,请记得设置 onEdit 触发器。【参考方案2】:

我认为这不太可能在第一次就起作用。我无法复制您的工作表,所以我根本无法对此进行测试。我以前写过这样的东西,但通常需要一些调整才能使其正常工作。我也不相信 onEdit() 部分将始终在 30 秒内完成,但我愿意给它一个机会,但您可能必须转换为选择一个学期,然后选择一个学生,然后单击一个按钮。

阅读cmets:

//add this function to an installable onOpen Trigger
function onOpenFunc() 
  var ss=SpreadsheetApp.getActive();
  var sh=ss.getSheetByName('Rapport');
  var slss=SpreadsheetApp.openById("12M8W7fARJJZN90wM79U4x8RmcnZ08kFSDcZYnB26HB0");
  var slsh=slss.getSheetByName("Rapportoversicht");
  var namerg=slsh.getRange(2,1,1,slsh.getLastColumn());
  var cell=sh.getRange(1,2);
  cell.clearDataValidations();
  var rule1=SpreadsheetApp.newDataValidation()
  .setAllowInvalid(false)
  .requireValueInRange(namerg)
  .build();//gets student list into drop down
  cell.setDataValidation(rule1);
  var rule2=SpreadsheetApp.newDataValidation()
  .setAllowInvalid(false)
  .requireValueInList([1,2])
  .build();//Semester selection 1 or 2
  cell.offset(1,0).setDataValidation(rule2);


//This has to be an installable trigger
function onEditFunc(e) 
  var sh=e.range.getSheet();
  if(sh.getName()!='Rapport')return;
  if(e.range.getColumn==5 && e.range.getRow()==1 && e.value && e.value!=e.oldValue ) 
    fillInStudentInformation(e.value,e.range.offset(1,0).getValue());  
  


//I am not sure that this will always complete in 30 seconds so you may have to revert to clicking a button after selecting a semester and a student.
function fillinStudentInformation(student,semester) 
  var slss=SpreadsheetApp.openById("12M8W7fARJJZN90wM79U4x8RmcnZ08kFSDcZYnB26HB0");
  var slsh=slss.getSheetByName("Rapportoversicht");
  var hrg=slsh.getRange(2,2,1,slsh.getLastColumn()-1);
  var hA=nrg.getValues()[0];
  var hObj=;
  var lObj=;
  hA.forEach(function(name,i)hObj[name]=i+1;);//column number
  var grdRg=slsh.getRange(4,hObj[student],60,1);
  var lblRg=slsh.getRange(4,1,60,1);
  var grdA=grdRg.getValues();
  var lblA=lblRg.getValues();
  lblA.forEach(function(lbl,i)
    if(lbl && grdA[i]) 
      lObj[lbl]=grdA[i];//object converts from labels to grades
    
  );
  var ss=SpreadsheetApp.getActive();
  var sh=ss.getSheetByName('Rapport');
  var rg1=sh.getRange(4,2,sh.getLastRow()-3,5);
  var vA=rg1.getValues();
  var rg2=sh.getRange(4,8,sh.getLastRow()-3,5);
  var vB=rg2.getValues();
  //left half
  for(var i=0;i<vA.length;i++) 
    if(vA[i][0] && lObj.hasOwnProperty(vA[i][0])) 
      switch(semester) 
        case 1:
          sh.getRange(i+4,4).setValue(lObj[vA[i][0]]);
          break;
        case 2:
          sh.getRange(i+4,6).setValue(lObj[vA[i][0]]);
          break;
      

    
  
  //right half
  for(var i=0;i<vB.length;i++) 
    if(vB[i][0] && lObj.hasOwnProperty(vB[i][0])) 
      switch(semester) 
        case 1:
          sh.getRange(i+4,10).setValue(lObj[vB[i][0]]);
          break;
        case 2:
          sh.getRange(i+4,12).setValue(lObj[vB[i][0]]);
          break;
      

    
  

【讨论】:

感谢您的帮助。我已经编辑了链接。单击时,它会自动创建一个副本。我希望这对你更有效。 好的,谢谢,我会在我使用桌面时回复它。

以上是关于选择下拉菜单中的名称时填写模板表的主要内容,如果未能解决你的问题,请参考以下文章

将下拉菜单中的值传递给 Flask 模板

检索先前选择的下拉主题值

Excel 如何实现五级下拉菜单联动

从子表单的组合框中选择下拉菜单后,MS Access 在主表单中填写 ID

如何根据用户选择的下拉菜单更改 PHP 中的 SQL 查询

如何选择下拉菜单中的所有选项 - Selenium Webdriver?