I'm making a script that copies the contents of a Google Doc into a text file and stores it on Google Drive. The user then edits the document and when they are finished it copies a new version to drive in a separate file. I have this part done, but now I need to know how to make the script automagically compare the differences in the text and then change the color of these differences in the doc. Any ideas?
The only thing I've tried is asking my friend who knows a lot more than me when it comes to programming, haha. He couldn't help me.
function copyQuestions() {
var body = DocumentApp.getActiveDocument().getBody();
var getquestions = body.getText()
DriveApp.createFile('tempquestions.txt', getquestions);
DocumentApp.getUi()
.alert('Questions have been copied to a new file on Google Drive. Get to work, and be sure not to delete the file!')
}
function copyAnswers() {
var body = DocumentApp.getActiveDocument().getBody();
var getanswers = body.getText()
DriveApp.createFile('tempanswers', getanswers);
DocumentApp.getUi()
.alert('Coloring answers...')
}
The script creates files with copies of the document's contents. I need to know how to compare the differences between the two of those now. Thank you!
Sounds like you need a Diff engine. You can attempt to write your own by leveraging well-known algorithms such as Levenshtein Distance or Dice's Coefficient but if you're not so inclined you can try looking for an existing javascript library that's compatible with Apps Script.
Did a quick search and found a few open-source repos. I can't vouch for their compatibility with Apps Script, but at least one of them seems viable (JSDiff supports EcmaScript 3 where Apps Script supports up to EcmaScript 5):
JSDIFF
Source (web-packed) : http://incaseofstairs.com/jsdiff/diff.js
Github : https://github.com/kpdecker/jsdiff
NODE-DELTA
Github : https://github.com/znerol/node-delta
Related
Ok. this is simple but I had no success searching in internet.
I want to allow people to use the functions I make in Drive Scripts Editor, so that whoever that wants to use them in their own scripts can.
I want to be clear as I am not a programmer, so here is an example:
I have this script:
function myFunction(a, b) {
return a + b;
}
Then I want other people to just type:
function anothersFunction() {
var x = Titleofproject.myFunction(1, 2);
}
In order to get a 3 for his x (obviously Titleofproject would be much larger).
The idea is to give them the possibility of using it, but not to see the project source code, at least for now.
Thank you!
You can create a Shared Library but note that this is against best practices and the page starts with this:
Warning: A script that uses a library will not run as quickly as it would if all the code were contained within a single script project. Although libraries can make development and maintenance more convenient, you should avoid them in projects where speed is critical. Because of this issue, libraries should not be used in add-ons.
I have some code from gitHub I'd like to run in GAS, but it uses a library (chance.js) I don't know how to install.
I have looked at the documentation here, and tried to follow the steps but I don't have a project key (because nobody's used it in GAS?).
I see that I might be able to call it from my script (?), but I don't even know how to start with that - I am a novice at this.
Is there a simple way to add this library? Can you point me to any resources?
Download the development version of chance.js. Open it and copy the whole text. Then go to your Apps Script editor, create a new script (File/New/Script File) and paste the text into there. Then at the bottom of the chance.js code (but before the closing parenthesis) you need to add chance = new Chance();
btw. In Apps Script every single time you start a function manually or through a trigger, all the js code in all js files belonging to the project is being executed and only afterwards is the selected function run. Of course that doesn't mean that the code inside of all the functions is being run.
edit:
Here is a better approach.
Change the start of chance.js from (function () { to Chance = (function () {. And then change the end from })(); to
return Chance;
})();
chance = new Chance();
I have so many documents that I need to manage due to the amount of people that have access to them, and when someone needs to be added or removed, it can become a real pain and time consumer.
I'm curious, is there a script that you can set across multiple documents that give edit or view access.
I'm aware that there is this, "addEditor(emailAddress)", but from what I have gathered, you have to do a script for each document which defeats the purpose of productivity.
Basically, I need one script that gives access to a particular set of documents, and when I need someone removed, i just delete their name and run the script and removes edit/view access from those documents.
Ax example of a script, or rather what I'm trying to achieve. (Not actually a script):
//Human Resources//
addEditor(emailAddress) to BBM1 - Membership Tracker, "https://docs.google.com/spreadsheets/d/1gb8T1K74cRR_6qSyByqrtiphujrchceLP_QsMunoras/edit#gid=0"
//Administrator//
addEditor(emailAddress) to BBM1 - Membership Tracker, "https://docs.google.com/spreadsheets/d/1gb8T1K74cRR_6qSyByqrtiphujrchceLP_QsMunoras/edit#gid=0"
//Moderator//
addViewer(emailAddress) to BBM1 - Membership Tracker, "docs.google.com/spreadsheets/d/1gb8T1K74cRR_6qSyByqrtiphujrchceLP_QsMunoras/edit#gid=0"
So basically, I can just add emails to that, run the script, and it gives them edit access. But, I just don't know how to create a script that actually works for that and also to have a script across multiple documents.
Many Thanks,
Shaun.
Take a look on folder api. You can put all those files into a folder, and then everytime you run the script you can loop through all files in the folder and set correct permissions.
Example (untested):
var folderName = "My auto-managed documents";
var folderIterator = DriveApp.getFoldersByName(folderName);
while (folderIterator.hasNext()) {
var folder = folderIterator.next();
var fileIterator = folder.getFiles();
while (fileIterator.hasNext()) {
var file = fileIterator.next();
// Do things with the file:
// file.addEditor('my-email#example.com');
}
}
I'm creating a Google Apps Script that's kind of a quiz marker / email merger in one. I've got everything working but my code is pretty long because I find myself having to use procedural coding. This is mostly because I don't know how to use the editor to include a class / library.
I've viewed the Crash Course Video by Kalyan on using the Script Editor, but it didn't answer my question. I've also scoured the internet with no luck.
If you look in the top left of this screenshot, you'll see I have Code.gs and test.gs:
I have all my code in the Code.gs file, but I want to include test.gs in Code.gs. Once I figure out how to do that, I'd like to create a couple of simple classes to organize my functions a bit better (and possibly re-use my classes later).
Thanks in advance!
To clarify Zig Mandel's answer and add to it:
All .gs files that are located in the same Script Project have global access to each other. That is to say that a function that you define in test.gs is accessible by Code.gs if they are in the same Script Project
You can create your own library of code. To do this you would simply create another Script Project, then go to Resources -> Manage libraries..., and add the project key of your original project (that contains the Code.gs and test.gs files). The project key is located in File -> Project properties.
The second bullet point is a good way to organize your code. If you have the same code that you are reusing throughout many Script Projects, then you want to put those functions into one Script Project and create a library out of them, as I explained above.
You already included the code. Should work as is. You can also look at the apps script docummentation and learn to use libraries for code reuse:
https://developers.google.com/apps-script/guide_libraries.
This makes development easier but for best performance you should include them all in your project before publishing like you did this time.
Part of the problem may be the order of execution. The .gs files are executed in order of creation. Copying Code.gs, deleting the original, then running functions from the new copy may fix your problem.
<?!= include('JavaScript.html'); ?>
function include(filename) {
return HtmlService.createHtmlOutputFromFile(filename)
.getContent();
}
I am trying to organize my code for a Spreadsheet in several script files. Within the script editor I can create as many *.gs files as I want, but I can't figure out how to access code that would be defined in another script.
Simple Example of what I'd like do achieve:
Code.gs:
function onEdit(){
myFunctionFromLibrary_gs();
}
Library.gs:
function myFunctionFromLibrary_gs(){
Browser.msgBox("hi there");
}
The onEdit() is obviously called by a Trigger.
Without modification this will result in a Runtime-Error, stating that
myFunctionFromLibrary_gs TypeError: is not a function, it is undefined.
So how can I make this work, or is this currently not supported?
Thx in advance for your help.
Yes, it's possible.
You are not limited to a single server Code.gs file. You can spread server code across multiple files for ease of development. All of the server files are loaded into the same global namespace, so use JavaScript classes when you want to provide safe encapsulation.
Reference: Google Documentation - features and limitations
I don't know what the _gs suffix means for Google, but without it (see code bellow), the code works.
file1.gs:
function onEdit(){
myFunctionFromLibrary();
}
file2.gs
function myFunctionFromLibrary(){
Browser.msgBox("hi there");
}
I know this is an old question but I found it looking for a similar task and happened to find the answer during my same search.
From the docs at https://developers.google.com/apps-script/guide_libraries#writingLibrary:
If you want one or more methods of your script to not be visible (nor usable) to your library users, you can end the name of the method with an underscore. For example, myPrivateMethod_().
While your function does not END in an underscore, it may have special meaning in other places than just this, or the _gs suffix may also have special meaning (particularly given the same filename suffix).