Using an imported module inside Google App Script
Asked Answered
P

6

21

I am trying to use string similarity inside Google App Script, however it is not entirely clear to me how to get it working inside App Script, I get multiple errors, such as "require" is not defined, as another note, the module itself appears to have a dependency.

My final goal is to use this script to match string score between one array with strings full of typos to one with correct strings all within App Script. This is my failed code.

function matchEmails() {   var doc =
 SpreadsheetApp.openById(("ID"));

   var ts = doc.getSheetByName("dir");   var source =
 doc.getSheetByName("data");   var names =
 source.getDataRange().getValues();   var data =
 ts.getDataRange().getValues();   var arr = [];   var arr2 = [];   var
 arr3 = [];   var arr4 = [];
      for (i=0; i<names.length; i++) {

     for (j=0; j<data.length; j++) {

           stringSimilarity.compareTwoStrings(names[i][0], data[j][0]);   Logger.log(stringSimilarity);




       /*
       var n = data[j][0].split();
       for (N=0; N<n.length; N++) {
       arr2.push(n[N].charAt(0));
       }
       var string2 = arr2.join("");
       var arr2 = [];

       if (names[i][0] === data[j][0]) {

       arr.push([data[j][1]]);

       }      */ //I want to replace this blanked out code with String >similarity.      

       if (string === string2) {

         arr.push([data[j][1]]);
         arr3.push([i+1]);
         arr4.push([data[j][0]]);


       }
     }   }   for (i = 0; i<arr.length; i++) {
     source.getRange(arr3[i],6).setValue(arr[i]);
     source.getRange(arr3[i],7).setValue(arr4[i]);   }    }
Phenazine answered 10/3, 2018 at 1:49 Comment(0)
C
38

Your GAS project is not a Node.js app, so the above will not work. While both Google Apps Script and Node use JavaScript, they provide different runtime environments for executing JS code. In GAS, the environment is a closed ecosystem on Google Servers that end users don't know anything about.

In Node, the runtime consists of V8 (JS engine) and C++ add-ons that expose low-level APIs (access to the file system, etc.). The library you referenced is an NPM package created for Node.js. Installing the package via NPM will make it available for Node projects, but don't think it will magically appear on Google servers as well.

You must either use GAS-specific versions of these dependencies, or, if they don't exist, refactor the source code to make it compatible with GAS (Node and GAS use different ECMAScript versions, so the very latest features may break your GAS code).

For example, here's lodash for GAS https://github.com/contributorpw/lodashgs

Using libraries in GAS https://developers.google.com/apps-script/guides/libraries

P.S. In GAS, all ".gs" files share the same namespace, so calling 'require' function is redundant. If you want to mimic this behavior, you'll still need to write your own require function.

Campania answered 10/3, 2018 at 14:5 Comment(1)
Thank you Anton, it is clearer to me now. I have given up on attempting to refactor the code, it's time to move on.Phenazine
C
13

I wrote up some guidance on packaging up an npm module for usage in Apps Script in this article.

tl;dr is to create an index.js with the following in a new directory:

import {compareTwoStrings, findBestMatch} from 'string-similarity';
export {compareTwoStrings, findBestMatch};

and then run the following in that directory:

npm init -y
npm install --save-dev string-similarity
npx esbuild index.js --bundle --global-name=stringSimilarity --outfile=StringSimilarity.js

You can then copy the contents of StringSimiliarity.js into a new .gs file in the Apps Script editor. The exported functions will be usable from your own Code.gs as stringSimilarity. compareTwoStrings() and stringSimilarity.findBestMatch().

(In case you'd rather not bundle it yourself, the output of the esbuild process for string-similarity can be found in this gist. But the general steps should apply to most npm modules that don't require a Node or browser-specific runtime environment.)

Cuttlebone answered 14/7, 2021 at 14:11 Comment(0)
V
4

Google Apps Script files by default have access to Google APIs, such as the Spreadsheet Service in the G Suite Services: https://developers.google.com/apps-script/reference/spreadsheet/

A GAS project (so scripts in that project) doesn't by default have access to Node.js or any other frameworks. However, a GAS project can include another GAS project by reference as a library. In the GAS Script Editor, use menu Resources > Libraries... to add an external GAS project as a library by setting the source project's project key (and some other source project properties).

So if you have a Javascript that depends on external resources (like Node.js) by require then if you can find an external GAS project that provides the same services with the same API you can provide it as a library to the script. You omit the require statements from the original script as they're replaced by the GAS library dependency configuration I mentioned.

If your original script and its dependencies are all open source you could create GAS projects for each level of dependencies in the originals. You can already find some popular JS frameworks scripts available as GAS libraries.

GAS also allows packaging external resources as Web apps and other package formats. They can be used with corresponding techniques, and some of them found already available from other developers.

Victuals answered 1/3, 2019 at 20:50 Comment(0)
S
3

An easy workaround is to use JavaScript's Eval function to call an external library hosted online

i. e. eval(UrlFetchApp.fetch('http://path.to/external/javascript.js').getContentText());

This won't work if the library itself depends on other modules which aren't available in the GAS runtime, but for certain libraries it can be a simple solution.

Sural answered 24/5, 2022 at 13:16 Comment(1)
Might be worth caching the script to avoid downloading it on every run.Lucillalucille
S
2

Building upon the answer of Jeff Posnick, note we can use https://esbuild.github.io in the same simple way to bring a complete library into Google Apps Script. For example with Ramda :

npm init -y
npm install --save-dev ramda
cp ./node_modules/ramda/dist/ramda.js .
npx esbuild ramda.js --minify --bundle --global-name=R --outfile=R.js

Then copy the contents of R.js into a new .gs file in the Apps Script editor.

Now you can use ramda in your code, for example:

const seventeen = R.add(7)(10);
Seismography answered 7/12, 2021 at 14:37 Comment(0)
L
-2

In GAS, all ".gs" are share automatic. it´s no necessary make a export

Longlived answered 28/2, 2023 at 11:5 Comment(1)
This is a comment rather than an answer.Goldina

© 2022 - 2024 — McMap. All rights reserved.