-1

I've been attempting to find a way to run scripts across multiple worksheets in a specific order. Each worksheet has its own number of scripts that run just fine when I use them (by creating a "combined" script attached to a button and/or menu).

There are many scripts and going through each one manually to run scripts is not efficient.

I've been trying to utilize libraries, but have not found a way to make it work correctly.

I've seen the Google Apps Script section on libraries, and relevant stackoverflow threads like this one, but haven't been able to figure it out.

Here's the last attempt I put together (after trying many different methods...)

function mastercombine() {
    
    const west = SpreadsheetApp.openByUrl(`https://docs.google.com/spreadsheets/d/1NmN7h2wEGFlY1FatjEpJ9MRpZ_I_MtlyoApGG4F6rcw/edit#gid=589651642`);

    west.West.combine();
    
    
    freezeValues1();
    
}

I think maybe I'm not entirely understanding how to call each item within the library to run the function on its respective worksheet. I've tried calling it a few different ways, but I'm stumped because they all give null errors.

Textual error I receive:

TypeError: Cannot read property 'masterSheetInfo' of undefined mastercombine @ Copy of Combined Reset.gs:5

The section beginning with west.West is attempting to call library worksheets/functions. "west" being the const, "West" being the Library ID, "combine" being the function within West (which runs correctly on its own within its own worksheet).

The ending section (freezeValues1) is a function that should run on the current worksheet (and it works stand-alone without library section).

The closest I've come to getting things to run in a certain order is attaching installable triggers to each worksheet, but I can't have the "will run sometime within the hour" bit that seems to come with it. I'm looking to call them back-to-back with one trigger.

Script being called from within the library:

function combine() {

  sortSheets();

  SpreadsheetApp.flush();
  Utilities.sleep(500);

  sheetNames();

}

which calls the following function:

function sheetNames() {
    var ss, list, tar;
        ss = SpreadsheetApp.getActive()
        list = ss.getSheets().slice(4).map(function (s, ind) {
            return ['=HYPERLINK("https://docs.google.com/spreadsheets/d/1tfi_L668w7hpDqeGl84TEfVIm4zKMkyuwrKsG-uKx9A/edit#gid=' + s.getSheetId() + '", "' + s.getName() + '")'];
        })
        tar = ss.getSheets()[0]; //List will be written to FIRST sheet in the workbook.
        tar.getRange(2, 1, tar.getLastRow(), 1).clearContent();
    tar.getRange(2, 1, list.length, 1).setValues(list)
   
}
Marc Golas
  • 19
  • 5
  • Please read [mcve]. – Rubén Mar 14 '21 at 21:13
  • Is it more acceptable to add things without mention, making 1st few comments referencing things that are no longer true, as an ok thing? Looking to understand. – Marc Golas Mar 14 '21 at 21:40
  • Let's go back to the [mcve]. Please add the minimal code from the script **and** the minimal code from the library to reproduce the problem. – Rubén Mar 14 '21 at 21:45
  • If `sortSheets()` and `sheetNames()` are really needed to reproduce the problem the question should include their respective function declaration, otherwise remove them. – Rubén Mar 14 '21 at 22:09
  • The request made was to also include the library script - and that's what this is. I'm not sure what to do here because you're now asking me to remove what was added by your request? The library script works fine stand-alone, so none of it is really necessary (which is why I didn't include it in the original post). It was added because you asked for it...(?) – Marc Golas Mar 15 '21 at 13:42
  • Added the sheetNames function script per your request. – Marc Golas Mar 15 '21 at 13:52

2 Answers2

0

From the question

The section beginning with west.West is attempting to call library worksheets/functions. "west" being the const, "West" being the Library ID, "combine" being the function within West (which runs correctly on its own within its own worksheet).

  1. A Google Apps Script library hasn't worksheets.
  2. west.West is not working because west has assigned a Class Spreadsheet object and this class hasn't a West property/method. Because of this west.West returns undefined.

One option is to convert West.masterSheetInfo() into a parametized function i.e. West.masterSheetInfo(west)

NOTE: If the parametized function, has a line like

const west = SpreadsheetApp.getActiveSpreadsheet();

might be replaced by something like

var west = west || SpreadsheetApp.getActiveSpreadsheet();

Regarding the order of execution, in Google Apps Scripts function statements are executed in the order they are wrote.

Resources

Related

Rubén
  • 34,714
  • 9
  • 70
  • 166
  • Hmm, now I'm more confused. How would "getActiveSpreadsheet()" within your example point to running a script on another worksheet? – Marc Golas Mar 14 '21 at 21:44
  • ReferenceError: Cannot access 'west' before initialization mastercombine @ Copy of Combined Reset.gs:3 – Marc Golas Mar 14 '21 at 21:46
  • I made an slight change to the answer but it will be better that you add the *minimal* code from the library to the question. – Rubén Mar 14 '21 at 21:48
  • I understand the order of operations following the order they are written in. The issue is that I'm looking to call functions to happen on another worksheet before the functions on the current sheet. I've put together many "combined" functions that work great within their respective worksheet - the issue here is calling external sheets to run in a certain order before the internal functions run. – Marc Golas Mar 14 '21 at 21:54
  • To note: I originally tried the "combine" function, but thought since maybe it was calling multiple other functions from within the worksheet, it might not work well with what I'm trying to do. So I tried it out on a singular function that didn't call multiple other functions (and that's where the "masterSheetInfo" function came from). – Marc Golas Mar 14 '21 at 22:04
0

I'm afraid that is not possible

Not via Apps Script itself anyway. You can run functions remotely, but only via the Apps Script API.

https://developers.google.com/apps-script/api/how-tos/execute

Though that comes with its own complexity and limitations.

Even triggers will not fire from changes to the sheet made by other scripts. So you can't have a utility sheet where your external script can change something and have an onChange trigger on the sheet.

From:

https://developers.google.com/apps-script/guides/triggers/installable#restrictions

Script executions and API requests do not cause triggers to run.

Workaround

Why is it necessary for the scripts to live on the target spreadsheets? Can't you just have a master script that contains all the code and then operates on all the spreadsheets?

For example:

function main() {
  let ssIds = [
    "1b2RdsafasdfasdfE4GZy5y5465y54y54sMw",
    "1b2R40ierqwerqwerf9Mvkm6I-TqE4GZsyMw",
    "1b2R40iHFqqwerewqrwerkm6I-TqE4GZysMw",
    "1b2R40iHFqOV7-ytqwertywerkm6I-TqGZsMw",
    "1b2R40iHFqOVtryertyerf9Mvkm6I-T4GZsMw"
  ];

  ssIds.forEach(id => {
    let ss = SpreadsheetApp.openById(id);

    // Do stuff here.
    //...
    //...
  })
}
iansedano
  • 6,169
  • 2
  • 12
  • 24
  • o0o, that workaround looks interesting - I'll try it out and report back on how it goes (I have a number of scripts running on each external sheet, so it looks like I'll re-write each one with this workaround method, and then use a function to combine them). Thank you! – Marc Golas Mar 16 '21 at 18:25
  • I haven't been in the office to try it out until today, but thank you for the info! As for the answer - I tried a few different scripts to run within it, and keep receiving this error: *_Exception: Unexpected error while getting the method or property openById on object SpreadsheetApp. (anonymous) @ List Tabs All.gs:9 main @ List Tabs All.gs:8_* – Marc Golas Mar 19 '21 at 14:03
  • Usually that happens when the id is wrong. Are you sure you copied the ID of your spreadsheets correctly? Also, you would need to have access to those spreadsheets, so if one is not shared with you for instance it could throw an error. Finally, make sure you are not logged in to multiple accounts while using apps script! – iansedano Mar 19 '21 at 14:49
  • hmm, I clicked the "copy" button of the "Script ID" field within each script's Project Settings. Is that correct? Also noting, I'm only signed into 1 account, which has edit/owner access to all docs. – Marc Golas Mar 19 '21 at 15:20
  • That is pretty strange, that should be the right ID then. Is it in the array as a string? Hard to know whats wrong without seeing the code, but this is getting out of scope of the original question. Probably best to accept my answer and ask a new question at this point. I have tested this approach so I know it works if that's any assurance. – iansedano Mar 19 '21 at 15:31
  • Okie dokie. _________ – Marc Golas Mar 19 '21 at 15:43
  • Aha, I found the issue. I was using the script ID as mentioned above, but instead needed to use the 44-character ID within the URL. It's working now - thank you!!! – Marc Golas Mar 19 '21 at 21:13