0

In my spreadsheet, I have inserted 35 project in GAS to generate google doc from the same sheet with the placeholder present in the docs.
The script takes the fields from each row in the sheet the script is contained in and using a Google Doc template (identified by TEMPLATE_ID) creates a PDF doc. The fields replace the place-holders in the template. The place-holders are identified by having a % either side, e.g. %Name%. It is invoked by the “Create PDFs” menu.
Naturally I have created a project for each Google Doc template (because I need 35 different doc from 35 different templates) and so in my sheet i have about 35 custom voice in menu that activate each script. Sometimes some scripts not appears all together and so I must to reload the sheet to find the script I need.
Why? There is a way to avoid this?
The script is this:

var TEMPLATE_ID = 'xxxxxxxx';

var PDF_FILE_NAME = '';

var RESULTS_FOLDER_ID = 'xxxxxxx';

var SENT_COLUMN_NAME = 'Date Sent';

var FILE_NAME_COLUMN_NAME = 'File Name';

var EMAIL_COLUMN_NAME = 'Email';

var DATE_FORMAT = 'yyyy/MM/dd';

var DATE_TIME_FORMAT = 'yyyy/MM/dd HH:mm:ss';

function sendMultiplePdfs() {

  var ui = SpreadsheetApp.getUi();

  if (TEMPLATE_ID === '') {    
    throw new Error('TEMPLATE_ID needs to be defined in Code.gs');
    return;
  }

  var templateFile = DriveApp.getFileById(TEMPLATE_ID); 
  var activeSheet = SpreadsheetApp.getActiveSheet();
  var ranges = activeSheet.getActiveRangeList().getRanges();
  var activeRows = [];

  ranges.forEach(function(range) {
    activeRows.push(range.getValues());
  })

Update:
Solved by replacing the Template ID taking the value dynamically from a cell:

var ss = SpreadsheetApp.openById("ID_OF_THE_SS").getSheetByName("SHEET_NAME");
var TEMPLATE_ID = ss.getRange("RANGE_OF_THE_ID").getValue();
  • 3
    My first thought is that you don't need 35 projects. You might need thirty five scripts in a project. Share the contents of one of your projects and perhaps an image of your sheet. I personally, do not follow links to spreadsheets. – Cooper Jun 03 '20 at 18:15
  • This is one of many projects I have. They are the same, change only the template ID and the folder ID. https://imgur.com/HtUW8w6 –  Jun 03 '20 at 18:29
  • 2
    Please post code into you question. First impression is that you can probably do all of that in one project. And you better hurry because your question is one vote away from closing. – Cooper Jun 03 '20 at 18:51
  • I have updated the question with the code. –  Jun 03 '20 at 18:53
  • 1
    It's probably beyond the scope of a single question here. I would recommend that you go to [Top Users](https://stackoverflow.com/tags/google-apps-script/topusers) and select one of the users on that list and try to get one of them to do it for you by contacting them through their profiles. Many of them provide the ability for other users to contact them. I do as well. – Cooper Jun 03 '20 at 19:11
  • You can end up with one project and one menu and maybe a few more scripts. – Cooper Jun 03 '20 at 19:14
  • Ok, how I can parameterize this project? –  Jun 03 '20 at 19:20
  • Ok. Give me the link of the form –  Jun 03 '20 at 19:31

1 Answers1

1

AFAIK there isn't a max number of projects that can be bounded to a G Suite editor document but having simple triggers on them could cause problems due to a "race - condition"

Rhetoric question

If there are multiple onOpen each of them creating a custom menu, will all of them be displayed correctly always on the same order?

One approach is to "parameterize" your project, i.e. create 35 functions to call a parameterized function receiving the template id and other parameters

Those 35 functions could be called from a menu, from images, among other ways to call them.


In Google Apps Script / JavaScript a function looks like this:

function doSomething(){
  console.info('Hello world!');
}

the parameterized version could be

function saySomething(message){
   console.info(message);
}

Then you call saySomething by passing a value for the parameter

function greetTheWorld(){
  var message = 'Hello world!';
  saySomethin(message);
}

In the case of this project you might put all the global variables in an array of object, having one object for each template.

var settings = [

  { /* First template */

    TEMPLATE_ID:'xxxxxxxx',

    PDF_FILE_NAME:'',

    RESULTS_FOLDER_ID:'xxxxxxx',

    SENT_COLUMN_NAME:'Date Sent',

    FILE_NAME_COLUMN_NAME:'File Name',

    EMAIL_COLUMN_NAME:'Email',

    DATE_FORMAT:'yyyy/MM/dd',

    DATE_TIME_FORMAT:'yyyy/MM/dd HH:mm:ss'

  },
  { /* Second template */

    TEMPLATE_ID:'xxxxxxxx',

    PDF_FILE_NAME:'',

    RESULTS_FOLDER_ID:'xxxxxxx',

    SENT_COLUMN_NAME:'Date Sent',

    FILE_NAME_COLUMN_NAME:'File Name',

    EMAIL_COLUMN_NAME:'Email',

    DATE_FORMAT:'yyyy/MM/dd',

    DATE_TIME_FORMAT:'yyyy/MM/dd HH:mm:ss'

  }
]

The pass the corresponding object of the parameterized function which previously was prepared to receive the corresponding values as an object.

Reference

Rubén
  • 34,714
  • 9
  • 70
  • 166
  • I have not any trigger on the project. In any case, how I can parameterize this project? –  Jun 03 '20 at 19:10
  • The code included in the question includes a onOpen function, it's a reserved name for a simple trigger – Rubén Jun 03 '20 at 19:44
  • @Tomas added some basic explanation about what I mean by "parametize" a project. – Rubén Jun 03 '20 at 20:02
  • It seems good, but I don't know how to substitute with the script.. –  Jun 03 '20 at 20:19
  • @Tomas I added more details but still is not complete. You should try to do it by yourself, and if you get stuck you can post a follow up question. – Rubén Jun 03 '20 at 20:21
  • Good! The only thing now, is how to link each template to the voice of menu that can activate them. –  Jun 03 '20 at 20:26
  • 1
    I think I found the solution. If the string " var TEMPLATE_ID = 'xxxxxxxx'; " can be updated from a cell ( with the ID value desired that replace the 'xxxxxxxx' in the script ), it could works! –  Jun 05 '20 at 06:24