下拉列表所有值的循环脚本

Loop script for all values of dropdown

我想制作一个脚本,循环显示下拉列表并为每个列表创建一个 pdf。

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

首先我想检查B2是否不为空,如果是则创建pdf并将A2更改为下一个选项,直到全部完成。我有一个基本的脚本,但请随意忽略!

function loopScript() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const interface = ss.getSheetByName("Interface");
  
  var folderID = "###GOOGLE DRIVE FOLDER ID###";
  var folder = DriveApp.getFolderById(folderID);
  
  const exportOptions =  'exportFormat=pdf&format=pdf' 
    + '&size=A4'                      
    + '&portrait=true'               
    + '&scale=4'            
    + '&fith=true&source=labnol'         
    + '&top_margin=0.05'
    + '&bottom_margin=0.05'
    + '&left_margin=1.00'
    + '&right_margin=0.25'
    + '&sheetnames=false&printtitle=false'
    + '&pagenumbers=false&gridlines=false'
    + '&fzr=false'                       
    + '&gid=125740569';                        
  
  var params = {method:"GET",headers:{"authorization":"Bearer "+ ScriptApp.getOAuthToken()}};
 
  var response = UrlFetchApp.fetch(url+exportOptions, params).getBlob();

  const nameFile =  "NAME OF FILE" + ".pdf" ;
  folder.createFile(response.setName(nameFile));
  DriveApp.createFile(response.setName(nameFile));
  
}

我相信你的目标如下。

  • 您要检查单元格“B2”。当“B2”单元格不为空时,您想将“A2”单元格下拉列表的值设置为列表的下一个值。
  • 例如,当下拉列表为Joe, Barry, Jane, Fred,单元格“A2”为Barry时,您想将单元格设置为Jane

在这种情况下,下面的修改脚本怎么样?

修改后的脚本:

发件人:

const ss = SpreadsheetApp.getActiveSpreadsheet();
const interface = ss.getSheetByName("Interface");

收件人:

const ss = SpreadsheetApp.getActiveSpreadsheet();
const interface = ss.getSheetByName("Interface");
if (interface.getRange("B2").isBlank()) return;
const range = interface.getRange("A2");
const values = [...new Set(range.getDataValidation().getCriteriaValues()[0].getValues().flat())];
const nextValue = values[values.indexOf(range.getValue()) + 1] || values[0];
range.setValue(nextValue);
  • 在此修改后的脚本中,当单元格“B2”为空时,脚本完成。当单元格“B2”不为空时,脚本为 运行 并且单元格“A2”已更新,用于创建 PDF 文件的脚本为 运行.

注:

  • 在上述修改后的脚本中,当下拉列表为Joe, Barry, Jane, Fred且单元格“A2”为Fred时,设置Joe的值。如果你想改变这个,请修改上面的脚本。
  • 在您当前的脚本中,url 未定义。请注意这一点。

参考文献:

问题:

如果我没有理解错的话,你想做以下事情:

  • 对于 A2 中的每个下拉列表,检查 B2 中的公式是否填充了任何值(基于来自 sheet Data 的数据)。
  • 如果由于公式而在 B 中填充了任何值,请使用 A2 的值作为文件名创建一个 PDF 文件(您已经做到了这一点)。

方法一:

在这种情况下,我建议采用以下工作流程:

  • A2 下拉列表中检索具有接受的 values 的数组(您可以使用 中使用的方法)。
  • 遍历这些 values,并为每个设置 A2 值,使用 Range.setValue.
  • 调用flush根据A2中的当前值更新B2中的数据。
  • 检查 B2 是否为空(例如,使用 Range.isBlank)。
  • 如果 B2 不为空,则创建驱动文件。
function loopScript() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const interface = ss.getSheetByName("Interface");
  const range = interface.getRange("A2");
  const values = [...new Set(range.getDataValidation().getCriteriaValues()[0].getValues().flat())].filter(String);
  values.forEach(name => {
    range.setValue(name);
    SpreadsheetApp.flush();
    if (!interface.getRange("B2").isBlank()) {
      // CODE FOR CREATING FILE
    }
  });
}

方法二:

在前面的方法中,setValueflushgetRangeisBlank是迭代使用的,大大增加了spread的调用量sheet.这不是最佳做法,因为它会减慢脚本速度(参见 Minimize calls to other services),如果下拉菜单有更多有效选项,情况会变得更糟。

因此,由于此公式使用的数据可以在 sheet Data 中找到,我建议使用该源数据而不是公式,以尽量减少对传播sheet.

在这种情况下,您可以遵循以下工作流程:

  • 使用Range.getValues一次获取Data中的所有数据。
  • A2 获取数据验证中的所有有效选项,如方法 1。
  • 对于每个选项,检查 Data 中是否有任何行在 A 列中有此选项,并且在 B.
  • 中是否有非空单元格
  • 如果该选项有一些数据,请创建文件。
function loopScript() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const interface = ss.getSheetByName("Interface");
  const data = ss.getSheetByName("Data");
  const DATA_FIRST_ROW = 2;
  const dataValues = data.getRange(DATA_FIRST_ROW,1,data.getLastRow()-DATA_FIRST_ROW+1,2).getValues();
  const range = interface.getRange("A2");
  const values = [...new Set(range.getDataValidation().getCriteriaValues()[0].getValues().flat())].filter(String);
  values.forEach(name => {
    const optionValues = dataValues.filter(dataRow => dataRow[0] === name);
    const nonEmpty = optionValues.some(optionValue => optionValue[1] !== "");
    if (nonEmpty) {
      // CODE FOR CREATING FILE
    }
  });
}

感谢大家的帮助,我最终采纳了 Tanaike 的建议并继续想出这个:

function sendAll() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var interface = ss.getSheetByName("Interface");
var range = interface.getRange("A2");                                                               
// Cell of validation
const values = [...new Set(range.getDataValidation().getCriteriaValues() 
[0].getValues().flat())];   // Gets array of validation
var first = values[0];                                                                              
// 1st cell of validation
var number = values.length - 1;                                                                     
// Length of validation
range.setValue(first);                                                                              
// Sets value to first one

for(i = 0;i < number;i++) {                                                                           
// Loop number of names
if (interface.getRange("B2").getValue().length > 0) {                                             
// Sheet isn't empty
var person = interface.getRange("A2").getValue();
const url = 'MY SHEET URL';

var folderID = "MY FOLDER ID";
var folder = DriveApp.getFolderById(folderID);

const exportOptions =  'exportFormat=pdf&format=pdf' 
+ '&size=A4'                      
+ '&portrait=true'               
+ '&scale=4'            
+ '&fith=true&source=labnol'         
+ '&top_margin=0.05'
+ '&bottom_margin=0.05'
+ '&left_margin=1.00'
+ '&right_margin=0.25'
+ '&sheetnames=false&printtitle=false'
+ '&pagenumbers=false&gridlines=false'
+ '&fzr=false'                       
+ '&gid=0';    

var params = {method:"GET",headers:{"authorization":"Bearer "+ 
ScriptApp.getOAuthToken()}};

var response = UrlFetchApp.fetch(url+exportOptions, params).getBlob();

const nameFile =  person + ".pdf" ;
folder.createFile(response.setName(nameFile));
DriveApp.createFile(response.setName(nameFile));   

const nextValue = values[values.indexOf(range.getValue()) + 1] || values[0];
range.setValue(nextValue);
}
else {const nextValue = values[values.indexOf(range.getValue()) + 1] || 
values[0];
range.setValue(nextValue);}
}

}