复制互连(通过 IMPORTRANGE)电子表格并通过 Google Apps 脚本更改 IMPORTRANGE 公式

DUPLICATING interconnected (via IMPORTRANGE) spreadsheets and CHANGING the IMPORTRANGE formulas both via Google Apps Script

如果你不关心背景,想马上看coding题,请跳过这一段。 我对编码还很陌生,这是我 post 在这里提出的第一个问题,但我希望我能说得通。我彻底搜索了网络,但找不到我可能不那么特殊的问题的答案。 一些背景:我是一名教练,并且 google 传播 sheet 我给客户的培训计划。由于我喜欢编码和 google spreadsheets,我编写的统计数据和功能开发得很快,所以我不得不将 spreadsheet 和最多 7 个训练日 tabs/sheets 在不同的 spreadsheet 中,所以我为我的客户或者他们的智能手机保存了一些工作内存。到目前为止一切顺利。

我编写了一个应用程序脚本来复制 master/setup sheet 以及培训日传播 sheets(#1 到 #7)并自定义保存它们的文件夹以及带有客户 nickname/first 名称的副本名称。

今天我还成功地替换了日历 sheet 中的导入范围(背景:所以我可以看到我的客户在哪一天训练)我的 master/setup 传播sheet,这样我刚刚复制的 master spreadsheet 的副本就不会 link 训练日 #1, #2, ... 模板,而是 copy 训练日 #1,#2 ... 模板。我不知道这是多么容易理解(英语也不是我的第一语言)所以我试着改写它:当然,将所有模板 spreadsheet 相互连接的 IMPORTRANGE 公式在复制时不会更新,但仍参考模板spreadsheets.

但是,我问自己为什么要对所有内容(实际的单元格范围和内容)进行硬编码,并且是否不可能总是用 id 替换所有 importrange 函数(例如模板 #1 的)的 id 部分sheet 的(我已经将其存储在数组中)。 你明白我的意思吗,你能帮我解决这个问题吗? 这是我到目前为止已经编写的代码。

感谢阅读此问题并试图提供帮助的任何人! PS:如果有人想更正或简化我当前的代码,我也很高兴,但我很高兴它到目前为止能正常工作,如果有人能推动我朝着正确的方向前进,我会不知所措。 PPS:我倾向于 GAS 版本的 find and replace all importrange 函数的原因是,我会在我的 spreadsheet 模板架构中保持一些灵活性,我会能够在将来编辑模板而无需考虑 GAS 代码中的硬编码范围,我可能会破坏它。

Tl;Dr:有没有一种简单的方法可以在复制 spreadsheets 后通过 GAS 使用查找和替换来仅更改导入范围公式的 id 部分?

//function that creates a new menu in the spreadsheet just right of the "help" tab
function onOpen() {

SpreadsheetApp.getUi()
              .createMenu('Scripts')
              .addItem('Create Duplicates', 'createDuplicates')
              .addItem('Create Links in Master Spreadsheet', 'createLinksInMasterSheet')
              .addToUi();
  
}
const parentFolder = DriveApp.getFolderById("ID OF PARENT FOLDER");
const nameOfMasterSheet = "TrnngPln";
const currentVersion = "4.0";

//function that creates duplicates of master sheet, all training days in a new folder that is named after the clients nickname
function createDuplicates() {
  const clientNickname = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SETUP").getRange('AB2').getValue();
  const currentmonth = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("InfoForAppsScript").getRange('F2').getValue();
  const currentyear = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("InfoForAppsScript").getRange('G2').getValue();
  const folderNewClient = parentFolder.createFolder('TP.'+clientNickname+'.['+currentmonth+'/'+currentyear+']');
  
  const newMasterSpreadSheetName = ''+clientNickname+'.'+nameOfMasterSheet+'['+currentmonth+'/'+currentyear+'.]'+currentVersion+'';
  const setup = DriveApp.getFileById("ID OF SETUP TEMPLATE");
  var newMasterID = setup.makeCopy(newMasterSpreadSheetName,folderNewClient).getId();
  
  const nameOfCopyOfDay1 = '#1.'+clientNickname+'['+currentmonth+'/'+currentyear+']'+currentVersion+'';
  const day1 = DriveApp.getFileById("ID OF TEMPLATE DAY 1");
  var newDay1id = day1.makeCopy(nameOfCopyOfDay1,folderNewClient).getId();
  
  const nameOfCopyOfDay2 = '#2.'+clientNickname+'['+currentmonth+'/'+currentyear+']'+currentVersion+'';
  const day2 = DriveApp.getFileById("ID OF TEMPLATE DAY 2");
  var newDay2id = day2.makeCopy(nameOfCopyOfDay2,folderNewClient).getId();
  
  const nameOfCopyOfDay3 = '#3.'+clientNickname+'['+currentmonth+'/'+currentyear+']'+currentVersion+'';
  const day3 = DriveApp.getFileById("ID OF TEMPLATE DAY 3");
  var newDay3id = day3.makeCopy(nameOfCopyOfDay3,folderNewClient).getId();
  
  const nameOfCopyOfDay4 = '#4.'+clientNickname+'['+currentmonth+'/'+currentyear+']'+currentVersion+'';
  const day4 = DriveApp.getFileById("ID OF TEMPLATE DAY 4");
  var newDay4id = day4.makeCopy(nameOfCopyOfDay4,folderNewClient).getId();
  
  const nameOfCopyOfDay5 = '#5.'+clientNickname+'['+currentmonth+'/'+currentyear+']'+currentVersion+'';
  const day5 = DriveApp.getFileById("ID OF TEMPLATE DAY 5");
  var newDay5id = day5.makeCopy(nameOfCopyOfDay5,folderNewClient).getId();
  
  const nameOfCopyOfDay6 = '#6.'+clientNickname+'['+currentmonth+'/'+currentyear+']'+currentVersion+'';
  const day6 = DriveApp.getFileById("ID OF TEMPLATE DAY 6");
  var newDay6id = day6.makeCopy(nameOfCopyOfDay6,folderNewClient).getId();
  
  const nameOfCopyOfDay7 = '#7.'+clientNickname+'['+currentmonth+'/'+currentyear+']'+currentVersion+'';
  const day7 = DriveApp.getFileById("ID OF TEMPLATE DAY 7");
  var newDay7id = day7.makeCopy(nameOfCopyOfDay7,folderNewClient).getId();
}


//function that sets Links in Calendar tab of master trainingplan spreadsheet
function createLinksInMasterSheet() {
  var searchFor = ['title contains ".TrnngPln"','title contains "#1."','title contains "#2."','title contains "#3."','title contains "#4."','title contains "#5."','title contains "#6."','title contains "#7."'];
  var ss = SpreadsheetApp.getActive();                               //current spreadsheet
  var directParents = DriveApp.getFileById(ss.getId()).getParents(); // folderIterator "targets" parent folder
  var folder = directParents.next();                                 //accesses parent folder
  var names =[];                                                     //array that stores names of the spreadsheets found in folder in the order of the array variable searchFor
  var fileIds=[];                                                    //array that stores the IDs of the spreadsheets found in folder in the order of the array variable searchFor
  for (var i=0; i<searchFor.length; i++) {                           //forLoop that goes through the searchFor array
    var files = folder.searchFiles(searchFor[i]);                    //creates file iterator t
    while (files.hasNext()) {                                        //while loop goes through all the files that match searchFor variable
      var file = files.next();                                       //
      var fileId = file.getId();                                     // To get FileId of the file
      fileIds.push(fileId);                                          //
      var name = file.getName();                                     //To get name of the file
      names.push(name);                                              //
    }                                                                
  }
  for (var i=1; i<fileIds.length;i++) {
    const formula = 'IMPORTRANGE("'+fileIds[i]+'";"#'+i+'!JJ188:JX188")'; //tak
    var rownumber = 265+i;
    Logger.log(rownumber);
    ss.getSheetByName('Cal').getRange('C'+rownumber+'').setFormula(formula);
    Logger.log(formula);
  } 
}

PS:其中大部分不是我的代码,而是我在本版块、youtube 或其他任何地方找到的经过编辑的代码,并根据我的目的进行了编辑。

来自问题

Tl;Dr: Is there an easy way to use find and replace via GAS to just change the id part of the importrange formulas after duplicating spreadsheets?

有多种方法可以使用 Google Apps 脚本替换 IMPORTRANGE 函数的第一个参数 (id / key / url)。也许使用 Class TextFinder 更容易,因为它有几种可能有用的方法,例如:

  • 匹配公式文本(匹配公式文本)
  • replaceAllWith(replaceText)
  • 使用正则表达式(使用正则表达式)