来自另一个电子表格的多个下拉列表,每个电子表格中有超过 500 个项目

Multiple Dropdownlist from another spreadsheet with more than 500 items in each

您好,在此先感谢您的帮助,

我找到了很多关于此的其他主题,但我没有找到问题的答案,所以我来了。

我的目标是根据另一列中的单词自动在板中创建下拉列表(50-100 之间的下拉列表)。数据应该在另一个 spreadsheet 中,并且大多数下拉列表可以包含 600-700 个项目。 请查看下图以获取更多说明:

board picture 如果在 F 列“名称”的第一个单词中找到 sheet 名称,则在 G 列和 H 列中创建下拉列表 1 和 2。如果您选择 G 列“Libellés”中的项目,它会在指定的 sheet 中对“MP”列和价格进行 Vlookup。同样,如果您在“MP”列中选择一个项目,它会在“Libellés”和“price”中进行 Vlookup 以匹配。

当所有 sheet 都在同一个传播sheet 时,这工作正常,但是当所有数据 sheet 都是在另一个传播sheet。带有代码的spreadsheet会被复制很多次(每年200+),所以我想把数据库sheets(15000+lignes x 5列)放在一个spread[=43中=] 当我们打开它们时,它会喂养所有其他“小”传播sheets。

我尝试了很多选择:

有没有办法绕过 requireValueInRange 的限制?这是我第一次使用google应用程序脚本,所以请不要太苛刻地判断。

这是代码,当所有数据 sheet 与下拉列表的目标 sheet 处于相同的 sspreadsheet 时,它工作正常:

 function onOpen(e) {
     
  // sss for source spreadsheet where I have all datas, and tss for target spreadsheet where I want my lists to be created
  var sss1 = spreadsheetApp.openById('blahblah');
  var ssh1 = sss1.getSheetByName('Emballages');
 
  var tss = SpreadsheetApp.getActiveSpreadsheet();
  var tsh = tss.getActiveSheet();
  var tsh1 = tss.getSheetByName('Fiche_eclate_CS');

     
// The below part is to update 2 lists, using datas from the sheet "emballages" in the source spreadsheet, all working fine except data validation rule, won't accept arguments
   
  var sheet = tss.getSheets()[0]; 
  var column = sheet.getRange("F:F").getValues();
  var prow;
   for (var i = 0; i < column.length; i++){
    if (column[i][0] === "Packaging :") {
      prow = i+1;
      break;     
     }
    }
      
   var emblrow = ssh1.getRange('B:B').getLastRow();
  
       var cel1D = tsh1.getRange(prow,7);
// This is where I have problems. The call ('B2:B'+ emblrow) is not accepted. I can't use this as data validation on another spreadsheet.
       var cel2D = ssh1.getRange('B2:B'+ emblrow); 
       var ruleD = SpreadsheetApp.newDataValidation().requireValueInRange(cel2D).build();
       cel1D.setDataValidation(ruleD);
   
   var cel1M = tsh1.getRange(prow,8);
// Same problem here. The call ('A2:A'+ emblrow) is not accepted.  
   var cel2M = ssh1.getRange('A2:A'+ emblrow ); 
   var ruleM = SpreadsheetApp.newDataValidation().requireValueInRange(cel2M).build();
   cel1M.setDataValidation(ruleM);
     

 // The below part is to update many lists, using datas from one sheet in the source spreadsheet. To find the good sheet in the other spreadsheet, I use the split function. This part is working fine. I only have problems with data validation rules, same as above.
   
   var ui = SpreadsheetApp.getUi();     
   var button = ui.alert("Voulez vous mettre à jour toutes les listes de la feuille ?",ui.ButtonSet.YES_NO);
   
   if (button == ui.Button.YES) {
   
   
  var anchhrow;
  var anchbrow;
  var column1 = tsh1.getRange("B:B").getValues();

   for (var i = 0; i < column1.length; i++){
    if (column1[i][0] === "Anchor-haut") {
      anchhrow = i+3;
      break;     
     }
    } 
    
   for (var i = 0; i < column1.length; i++){
    if (column1[i][0] === "Anchor-bas") {
      anchbrow = i;
      break;     
     }
    }
   
   var rangeH1 = tsh.getRange('H'+anchhrow +':H'+anchbrow).getValues();
   var range = tsh.getRange('H'+anchhrow +':H'+anchbrow);
   var lrowH = rangeH1.length; 

   for (var k=0; k<lrowH; k++){
   
     var rown = anchhrow + k;
     var testrng = sheet.getRange("F" + rown);     
     
     if ( testrng == "" ) {
     }
     else {
       
       var name = nom(tsh,rown);                       
       var ssh3 = sss1.getSheetByName(name);
       
       if (ssh3 == null){
       }
         else {
           
           var flrow = ssh3.getRange('B2:B').getLastRow();
     


            var rng1D = tsh1.getRange(k+anchhrow,7);
// same issu, can't use ('B2:B'+ flrow)for data validation 
            var rng2D = ssh3.getRange('B2:B'+ flrow); 
            var ruleD = 

SpreadsheetApp.newDataValidation().requireValueInRange(rng2D).build();
               rng1D.setDataValidation(ruleD);
       
   
               var rng1M = tsh1.getRange(k+anchhrow,8);
// same here, can't use ('A2:A'+ flrow)for data validation 
               var rng2M = ssh3.getRange('A2:A'+ flrow ); 
               var ruleM = SpreadsheetApp.newDataValidation().requireValueInRange(rng2M).build();
               rng1M.setDataValidation(ruleM);  
                 
           }
      }

  }

     function nom(sheet,row){
       var word = [{}]; 
       var rng = sheet.getRange("F" + row);
       var word = rng.getValue().split(" ");
       Logger.log(word);
       return word[0];       
     }   
   }
  else {
  }   
   
// This part is where I control prices once all lists are updated, this is working fine.   
   
   var ui = SpreadsheetApp.getUi();     
   var button = ui.alert("Les listes ont été mises à jour. Voulez vous mettre à jour les prix ?",ui.ButtonSet.YES_NO);
   
   if (button == ui.Button.YES) {
     
     for(var j=0;j<lrowH; j++){     
   
       var cellI1 = tsh.getRange(j+anchhrow,8).getValue(); 
  
       if (cellI1 == "") {
        }
       else {
         var cellI2 = vlookup(ssh2,1,3,cellI1);   
         tsh.getRange(j+anchhrow,9).setValue(cellI2);

    
    function vlookup(sheet, column, index, value) {

      var lastRow=sheet.getLastRow();
      var data=sheet.getRange(1,column,lastRow,column+index).getValues();
    
      for(i=0;i<data.length;++i){
        if (data[i][0]==value){
          return data[i][index];             
        }
      }
    }
   }
  } 
 }
  else {
  }
  Browser.msgBox ("MAJ feuille terminée");
}

如果您有不明白的地方或需要更多详细信息,请随时提出问题。

提前致谢,

我建议

function betweenSpreadsheets() {
  let localSs = SpreadsheetApp.getActiveSpreadsheet();
  
  let distSsUrl = 'https://docs.google.com/spreadsheets/d/1H-Zh blah blah KHP7x8/edit?usp=sharing'; 
  let distSsId = '1H-Zh blah blah KHP7x8';
  let distSs1 = SpreadsheetApp.openById(distSsId)
  let distSs2 = SpreadsheetApp.openByUrl(distSsUrl)
  
}

然后继续,就好像工作表在同一个电子表格中一样。

您遇到的主要问题是由于您调用的是 getActiveSpreadsheet 方法而不是 openById(id)

但是,假设您的工作表名称相同,但它们只是在不同的电子表格中,并且您想继续使用 requireValueInRange 方法,我建议您在代码中添加以下行:

代码

function createDataValidation() {
  let spreadsheetIds = ['SS_1_ID', 'SS_2_ID', ...];
  for (let i=0; i<spreadsheetIds.length; i++) {
    var tss = SpreadsheetApp.openById(spreadsheetIds[i]);
    var tsh = tss.getActiveSheet();
    var tsh1 = tss.getSheetByName('Fiche_eclate_CS');
    // the rest of your code
  }
}

上面的代码循环遍历所有电子表格 - 这是通过将要使用的电子表格的所有 ID 存储在 spreadsheetIds 变量中,然后使用 for 循环来完成的, 正在访问它们中的每一个并使用您已有的代码。

参考