Create Google Apps Script file with DriveApp - google-apps-script

Code to create an appscript file using appscript editor.
for example you type this:
function msWordExt() {
var ss = SpreadsheetApp.openById('1MUwH0Cm1cwHcTWSCGPp2SePbzs_4QQmtjwOEWOrOkMw');
var sheetName = ss.getSheetByName("Sheet2");
var get = sheetName.getRange(2,3).getValue();
var folder = DriveApp.getFolderById("1rsicZccurujGp5Ye5HUecBIAPf3_h5Pc");
folder.createFile("PLAIN TEXT",get,MimeType.MICROSOFT_WORD);}
So the above code creates a MS Word extension file inside a persons Google Drive.
Now I want to try creating a google appscript file extension using code as well, for example the below code doesn't work but it will help give the gist of what I wish to accomplish:
function appScript() {
var ss = SpreadsheetApp.openById('1MUwH0Cm1cwHcTWSCGPp2SePbzs_4QQmtjwOEWOrOkMw');
var sheetName = ss.getSheetByName("Sheet2");
var get = sheetName.getRange(2,3).getValue();
var folder = DriveApp.getFolderById("1rsicZccurujGp5Ye5HUecBIAPf3_h5Pc");
folder.createFile("This is an appscript file",get,MimeType.GOOGLE_APPS_SCRIPTS);
}

Considerations
You can't use the Drive API to create a Google Apps Scripts Project. Here you can see it's already been reported to Google.
Proposed workaround
You can use the Apps Script API to manage your Apps Script projects. Here is a link to the guide: https://developers.google.com/apps-script/api/samples/manage
Reference
Managing Apps Script Projects

Related

Access Spreadsheet Cell values from library script

Is there a way I can access data, stored within a spreadsheet-file from the library script?
I want to use 1 Google Apps Script from multiple Google Spreadsheet files within my Google Drive.
I followed this answer: "you could use Libraries. The idea is that you create one script that you use as a library" and could successfully import the library to my project.
In order to work, the scripts within the library need some of the cell-values stored in the google sheet files. I know how to access the script via a helper function in my sheet-bound script file. For example:
function loc_my_credits()
{
SISTRIXAbfrageFreigabe.my_credits();
}
Whilst "SISTRIXAbfrageFreigabe" is the library name, and my_credits a function within the library.
When I call loc_my_credits from sheets, nothing happens. My best guess: the script cant read data from the spreadsheet file it needs to execute.
The my_credits script from the library file looks like this:
function my_credits(){
// Base URL to access customsearch
var urlTemplate = "https://api.sistrix.com/credits?api_key=%KEY%";
// initialize sheets: 1. Get the spreadsheet, 2. Get the first and the second sheets in this spreadsheet
var spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
var inputSheet = spreadSheet.getSheets()[0];
// Script-specific credentials & search engine
var sistrix_Apikey = inputSheet.getRange('A2').getValue();
var url = urlTemplate.replace("%KEY%", encodeURIComponent(sistrix_Apikey));
var params = {
muteHttpExceptions: true
};
var xml = UrlFetchApp.fetch(url).getContentText();
var document = XmlService.parse(xml);
var root = document.getRootElement();
var items = document.getRootElement().getChildren();
for (var i = 0; i < items.length; i++) {
if(items[i].getName() == 'answer'){
var answer = items[i].getChildren();
return answer[0].getAttribute('value').getValue();
}
}
return 0;
}
Is there a way I can access the data stored in the spreadsheet file from the library script?
I'm writing this answer as a community wiki, since the issue was resolved from the comments section, in order to provide a proper response to the question.
The problem was related to the usage of methods that need scopes that require authorization, therefore it would be expected that simple triggers would show the error:
You do not have permission to call SpreadsheetApp.openById
Google's documentation states that installable triggers would solve the problem:
Installable triggers, however, offer more flexibility than simple triggers: they can call services that require authorization
According to s.Panse, the usage of installable triggers has resolved the issue in this case.
References:
google script openById : You do not have permission to perform that action
Installable Triggers

Why doesn't my Google Apps Script work anymore?

I don't believe I changed my code, yet it doesn't work anymore. Did Apps Script change something? I enabled the Drive API and tried both the legacy editor and the new editor.
I'm trying to replace links in multiple Google Docs within a folder. Below is a snippet of the code but I have 50+ links.
function myFunction() {
var oldLinkText = "Casarett and Doull’s Essentials of Toxicology, 3e";
var newLinkText = "Casarett & Doull’s Essentials of Toxicology, 4e";
var oldLinkURL = "accesspharmacy.mhmedical.com/book.aspx?bookID=1540";
var newLinkURL = "accesspharmacy.mhmedical.com/Book.aspx?bookid=3000";
var oldLinkText2="Harrison's Principles of Internal Medicine, 19e";
var newLinkText2="Harrison's Principles of Internal Medicine, 20e";
var oldLinkURL2="accessmedicine.mhmedical.com/book.aspx?bookid=1130";
var newLinkURL2="accessmedicine.mhmedical.com/book.aspx?bookid=2129";
var oldLinkText3="Behavioral Medicine: A Guide for Clinical Practice, 4e";
var newLinkText3="Behavioral Medicine: A Guide for Clinical Practice, 5e";
var oldLinkURL3="accessmedicine.mhmedical.com/book.aspx?bookID=1116";
var newLinkURL3="accessmedicine.mhmedical.com/book.aspx?bookid=2747";
var files = DriveApp.getFolderById("folderID").getFilesByType(MimeType.GOOGLE_DOCS);
while (files.hasNext()) {
var file = files.next();
if(file){
var doc = DocumentApp.openById(file.getId());
var link=doc.getBody().findText(oldLinkText);
var link2=doc.getBody().findText(oldLinkText2);
var link3=doc.getBody().findText(oldLinkText3);
}
}
if(link){
link=link.getElement().asText();
link.setLinkUrl(newLinkURL);
doc.replaceText(oldLinkText, newLinkText);
}
if(link2){
link2=link2.getElement().asText();
link2.setLinkUrl(newLinkURL2);
doc.replaceText(oldLinkText2, newLinkText2);
}
if(link3){
link3=link3.getElement().asText();
link3.setLinkUrl(newLinkURL3);
doc.replaceText(oldLinkText3, newLinkText3);
}
Logger.log("Done")
}
I used the code on one file and it worked, but I was trying to get it to work on multiple Google Docs files within a Google Drive folder. It kept stopping at one. In other words, it would look at the first file in the folder, and would stop looking if it didn't find the text in that file. It ignored the other files in the Google Drive folder.
I changed two things in the code and now it worked. I removed the two curly brackets before "if(link){" and put them at the very end of the code. I also changed ".getFilesByType(MimeType.GOOGLE_DOCS);" to just ".getFiles();"

Can I use DocumentApp.openById() with read only permission?

I am creating a Google Apps Script add-on that is for a Google Spreadsheet, but it needs to be able to access the content of a separate Google Doc, which I am doing using DocumentApp.openById(). I have given the script these scopes:
"oauthScopes": [
"https://www.googleapis.com/auth/documents.readonly",
"https://www.googleapis.com/auth/script.container.ui",
"https://www.googleapis.com/auth/spreadsheets.currentonly"
]
But apparently, that's not enough. The script is telling me it needs the https://www.googleapis.com/auth/documents permission to work properly. However, it seems excessive to give the add-on permission to edit ALL Google Docs files when it just needs to be able to view the content of one. Am I missing something? Is there a way to give it read-only access to a separate Google Docs file?
Here is the function I am using for testing, with most of the document ID censored out:
function getDoc() {
var id = '1NLH----------------------------------------'
var templateFile = DocumentApp.openById(id)
var templateText = templateFile.getBody().getText()
Logger.log(templateText)
}
Thanks!
I believe your goal as follows.
You want to retrieve the text data from Google Document using the following script.
function getDoc() {
var id = '1NLH----------------------------------------'
var templateFile = DocumentApp.openById(id)
var templateText = templateFile.getBody().getText()
Logger.log(templateText)
}
You want to achieve this using the scope of https://www.googleapis.com/auth/documents.readonly and Google Apps Script.
Issue and workaround:
In the current stage, DocumentApp.openById of Document service is used, it is required to use the scope of https://www.googleapis.com/auth/documents. It seems that this is the current specification. So, in this answer, as a workaround, I would like to propose to use Google Docs API instead of Document service. When Google Docs API is used, your script can be achieved using the scope of https://www.googleapis.com/auth/documents.readonly.
When your above script is modified using Google Docs API, it becomes as follows.
Sample script:
Before you use this script, please enable Google Docs API at Advanced Google services. This script can work with only the scope of https://www.googleapis.com/auth/documents.readonly.
function myFunction() {
const documentId = "###"; // Please set the Document ID.
const obj = Docs.Documents.get(documentId);
const text = obj.body.content.reduce((s, c) => {
if (c.paragraph && c.paragraph.elements) {
s += c.paragraph.elements.map(e => e.textRun.content).join("");
}
return s;
}, "");
console.log(text)
}
Reference:
Method: documents.get

Google Apps script to navigate to given row of google sheet

I'm developing a Chrome extension that has access to Google Sheets using a standalone Google Apps Script.
I need help to be able to navigate and highlight given variable row from my extension. either using Apps Script or some other way.
I've tried this code in google apps script.
function navigateToRow(parameters) {
var ss = SpreadsheetApp.openByUrl(parameters.url)
var sheet = ss.getSheets()[0]
var range = sheet.getRange('A1:D10'); // will get range from parameters in future
range.activate();
}
There is another solution that could solve the problem, but it refreshes the page: using url parameters, e.g.
https://docs.google.com/spreadsheets/d/<spreadsheet id>/edit#gid=<sheet id>&range=<a1 notation>.
Try something like :
var range = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange(1, 1);
SpreadsheetApp.setActiveRange(range);
Reference : https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet-app#setactiverangerange
Solved using these lines of code inside the content-script.
hash = window.location.hash.split('&range=')[0]
hash += `&range=${currentRowInput.value}:${currentRowInput.value}#`;
window.location.hash = hash

Insert Image into Spreadsheet Cell from Drive using Google Apps Script

I would like to be able to add an image file into my spreadsheet from Google Drive. I see there is a built-in image function available =image, but this requires a URL and that image files should be shared publicly on the internet. However, I am working with digital assets and can not share them publicly.
I have the following code, this works but does not add to the required cell. Is this at all possible?
function insertImageFromDrive(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var fileId = '0B5UAkV0avfiKNGYtd1VzUzlsTVk';
var img = DriveApp.getFileById(fileId).getBlob();
sheet.insertImage(img, 4, 3)
}
Try using the guide Insert image in a spreadsheet from App Script:
function insertImageOnSpreadsheet() {
var SPREADSHEET_URL = 'INSERT_SPREADSHEET_URL_HERE';
// Name of the specific sheet in the spreadsheet.
var SHEET_NAME = 'INSERT_SHEET_NAME_HERE';
var ss = SpreadsheetApp.openByUrl(SPREADSHEET_URL);
var sheet = ss.getSheetByName(SHEET_NAME);
var response = UrlFetchApp.fetch(
'https://developers.google.com/adwords/scripts/images/reports.png');
var binaryData = response.getContent();
// Insert the image in cell A1.
var blob = Utilities.newBlob(binaryData, 'image/png', 'MyImageName');
sheet.insertImage(blob, 1, 1);
}
Just replace the necessary values. The part where you indicate which cell you insert the image is in:
sheet.insertImage(blob, 1, 1);
There is a google spreadsheet add-on ImageKit to help insert multiple images from difference sources including Google Drive, check it out > https://chrome.google.com/webstore/detail/imagekit/cnhkaohfhpcdeomadgjonnahkkfoojoc
Here you find a screenshot of tool's interface.
It is not possible if the drive image file is not public on your google drive, Having said that there is a trick to overcome i.
First make sure the image file is temporary public on your drive. you can do that also via app script by changing the file permissions to DriveApp.Access.ANYONE, DriveApp.Permission.EDIT. Then the drive file is like a file as if it was from the internet. You can then add the blob.
After that you can decide two things.
Change the permissions back or remove the image file from your drive (if you only want to use it embedded in your blob (also via app script code if you want)
good luck
I don't think it is currently possible, see here: https://code.google.com/p/google-apps-script-issues/issues/detail?id=3303
Here's another alternative:
var fileId = "..."; // your image's google drive id
sheet.insertImage("https://docs.google.com/uc?id=" + fileId, column, row);
Just make sure your file has link sharing turned on (anyone with the link can view) otherwise this method won't work.
Documentation