Google AppsScript and Drive API v2 - Change google platform project programmatically - google-apps-script

What I want to do
Copy a google sheet programmatically via API.
Change the copied sheet's cloud platform project to the original sheets project, when copied Google creates a new google platform project, that's not what I want.
Get the script id of the copied sheet.
All of the above only programmatically, I already know how to do these things manually by clicking menu's.
What I have already tried:
This google documentation article tells me how to change a platform project manually, I want to do the same thing via some API that Google may be providing.
You can copy a sheet programmatically via this API, however you can't get the associated script id or the project and it doesn't let me set the cloud platform project.
I know how to get the script id from within the sheet, I want to do this from outside the sheet.
Note that the API's I need have to be accessible via outside the sheet, via a program that I host myself.

I realized what I was really looking for were Add on's. Via that I can keep the apps script project as one which solves all my requirements.
Read more about App Script addons from this google doc page: https://developers.google.com/apps-script/add-ons/

Related

How can I set an app script on a Google Sheet via the API?

Is there a way to set an App Script on a new Google Sheet via the Google Sheets API? We use pygsheets as our Python API Client for Google Sheets. Since we are using the onSelectionChange trigger to populate certain cells with a date, we would like to setup the app script after we have populated rows in the spreadsheet.
The Google Sheets API doesn't have a method to do this. You can use the Apps Script API instead, but there are a few caveats which may or may not work with your use case:
You can use projects.create to create a new Apps Script project and attach it to a Sheets file by specifying the parentId field, which is the Sheet's ID. However, there are no methods to attach a preexisting script to a Sheet. You can still use projects.updateContent to add the required script files, though.
You cannot unbind the script once it has been attached.
This API does not work with service accounts, and the user running it needs to explicitly allow it in their settings page. This is for security reasons, since allowing a malicious app to freely write scripts on your account could be catastrophic, but it adds more steps that your users would need to take in order to run your app.

Updating multiple appscript projects from one appscript

I have scenario where I have more than 60 sheet, and all have appscript project behind them running and managing those sheet.
I want to updat/control those appscript projects all at once, from one different project. So that I don't have to manually go and update them.
I know this solution where we can update it by manually getting OAuth Token from single appscript project but, Is there any way we can just mention sheetID and it updates project behind all those sheet all at once?
From the question
Is there any way we can just mention sheetID and it updates project behind all those sheet all at once?
There is no direct way to do this. Related issue Retrieving Project ID of Container-Bound script (created in 2018, as of the end of 2021 it still has the "New" status).
Assuming that by "SheetID" you mean the spreadsheet id, it's possible to use the Spreadsheet Service and the Drive Service to get a Class Spreadsheet or Class File object, respectively. Unfortunately those classes hasn't any method to retrieve the bounded Google Apps Script project.
The same for the Sheets API, Drive API and the Apps Script API.
The indirect way is to build a list of spreadsheets and their respective bounded scripts but it's clear that this is not what you are looking for. Anyway, build the list of spreadsheet/script projects pairs and store it somewhere (it might be an spreadsheet if the list is not humongous. CLAPS has a command to retrieve the list of the recent projects, and it's possible to get the container id from the script project metadata (see https://developers.google.com/apps-script/api/reference/rest/v1/projects/get)
Considering the above, the advice to make it easier to maintain your scripts "for the next time" is to either use a library or to create and add-on.
Resources
https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet
https://developers.google.com/apps-script/reference/drive/file
https://developers.google.com/apps-script/api/reference/rest/v1/projects#Project
Related
How to programmatically create a list of Google Apps Script projects owned by me?
List Google app script projects
Google Apps Script: Get the ID of script bound to a spreadsheet
How to make Google Apps Script library always serve the latest version
If you're asking can you reference different codes from the same document but not the same sheet in a new code, the answer is yes. But, there is no way to manipulate this code other than editing the original code. I would recommend manually getting an OAuth Token from a single Apps Script Rroject.
A different way to control those Spreadsheets can be with a NodeJS project locally, using Clasp and Multi-clasp2 (https://www.npmjs.com/package/multi-clasp2).

Unable to open Google xlsx spreadsheet / Also Google Drive permission Blocked

I have a Google Apps Script that I am currently using to successfully open a Google Sheets spreadsheet (read-only shared with my account) and perform some reading functions.
I received another spreadsheet that I would like to run similar processes on.
If I try:
SpreadsheetApp.openById("_______") (which works on the other sheet), I get Exception: Service Spreadsheets failed while accessing document with id _____" with this sheet. This spreadsheet is actually an xlsx on Google Drive (but appears it can still open in Google sheets) rather than a native Google sheet so I figured maybe that was the issue...?
So now I'm trying to instead access it as a Google Drive file using DriveApp.getFileById("____"). However now I get an authorization request to allow my script to access Google Drive. When I authorize it, I get:
This app is blocked
This app tried to access sensitive info in your Google Account. To keep your account safe, Google blocked this access.
I haven't found a way to fix this. I'm on a private Google account, not using a company's Apps.
Any ideas?
Found a solution to the permission issue.
To work with Apps Script, I've modified this from #alper's solution which sources #tellowkrinkle's comment.
Do the following:
Go to https://console.developers.google.com and create a new project for yourself
Search for the Google Drive API in the search box at the top, and turn it on
Click OAuth consent screen on the left and set it up.
Assuming your account isn't part of an organization, you'll have to say your app is for external users and in testing
In the required scopes section, add .../auth/docs and .../auth/drive (I'm not sure which needed, it's probably only one of those). This will probably not be available if you didn't complete (2)
Add the accounts you want to use with your copy of gdrive as testers of your app. Only these accounts will be able to use your copy of gdrive, so everyone will have to compile their own (unless someone goes and gets theirs reviewed by Google). I only added my own account because I am the only one using my App Script which uses my Drive.
Click the 3 dots on the top right and select "Project settings". Make note of the "Project number".
Go to your Apps Script. Go to Resources > Cloud Platform project. Insert the project number from (4).
Next time you try to run your Apps Script, you'll be asked to Authorize but this time you'll have the chance to actually do it successfully.

Maintaining enabled APIs in Container-bound Script for a Google Sheet Template

I have a Google sheet with a Container-bound Script that makes Google Classroom API calls. I have added the spreadsheet now as a template for all teachers in my organization to copy the sheet and use it for themselves.
However, when teachers copy from the template, a new project is created in Google Console with no enabled APIs for that new project. They would have to go into the developer console and enable Classroom API for it to work....
No! This is way too much of a hassle for my fellow teachers! There has to be a better way. What am I doing wrong? How can my script keep the API calls enabled for all copies of the spreadsheet? Do I need to publish my script in a particular way or set up my project in a particular way? Whats the right approach here, guys?
This error when using the script in a copied spreadsheet. But of course, works fine in the original template file.
Google Classroom API has not been used in project project-id-xxxxxxxxxxxxxxx before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/classroom.googleapis.com/overview?project=project-id-xxxxxxxxxxxxxxxx then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.
You should publish your script as Sheets Add-on: https://developers.google.com/apps-script/add-ons/
This gives you next benefits:
when spreadsheet (with enabled add-on) is copied, there's no need to manually enable APIs, they are stay enabled;
when you update code of your add-on, it is automatically updated for all spreadsheets where it was enabled, so you don't have to copy your changes manually.

How can I create spreadsheet with included gs script by API?

I'd like to manage spreadsheets (uploaded by a client via API) over google engine. I created test spreadsheet extended by functions in .gs script (which works great if I add them via online editor) but I do not know how to apply such a .gs script to every uploaded spreadsheet automatically (possibly via API).
Moreover, I do not want to share this .gs file by publishing it as an extension (because of security policies).
Updated: I also tried copying existing spreadsheet with working gs script and overwriting its spreadsheet data via API (instead of uploading new one) - it's overwritten data successfully but unfortunately lost gs script. Details are described in separate (bounty) question: Custom google app script doesn't work after copying spreadsheet with google java client
So I've even tried copying using plain HTTP methods since I thought it might be a problem with Java SDK but it still didn't work which means that there is some problem at google side (or something is really unclear) with service accounts.
After all I solved the problem with another approach.
First I copy spreadsheet with script attached to it to my service account (as I described in this Custom google app script doesn't work after copying spreadsheet with google java client topic). The file is copied with broken script.
Then I make user authorize using google's oauth (this tutorial shows how https://developers.google.com/identity/protocols/OAuth2WebServer#overview)
And then on his behalf I perform copying.
Finally the file is on his private drive which is the biggest downside of this solution but at least the script works which was my main goal.
Hope it helps ;)
You can publish a google script without it going on the Marketplace. If you make a Google group you can publish in such a way that only members of your google group can see it. If your google group only has you, only you can see it. Then it will be on all of your spread sheets.
The downside being that google will never let you remove it from their server, only unpublish it.
You can create a stand-alone script that is independent of any spreadsheet. This script would contain any methods/functions needed to create and manipulate spreadsheets according to your use case. Furthermore you could deploy the script as a web-app and implement a doGet() or doPost() method. Whenever a user uploads spreadsheet data via API you can call the web app with the information and have it create spreadsheets as needed.