Rename appsscript project on duplication of spreadsheet - google-apps-script

I'm duplicating spreadsheets based on a template file with attached appsscript project. Below you can see the basic code.
This works perfectly for the spreadsheets, but the name of the appsscript project remains the same as the template file. Which is a problem, as I can't distinguish them anymore. I will have hundreds of duplicates in the end.
Is there a way to set the appsscript project name on duplication?
Thank you in advance!
function copyTemplatev2(filename, sheetID) {
var ss = SpreadsheetApp.openById(sheetID);
//Make a copy of the template file
var copy = DriveApp.getFileById(sheetID).makeCopy()
var documentId = copy.getId();
// Set permissions
copy.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.EDIT)
//Rename the copied file
DriveApp.getFileById(documentId).setName(filename);
}

attached appsscript project of a template file with attached appsscript project is the container-bound script of Spreadsheet.
You want to rename the GAS project name of the container-bound script of Spreadsheet which was copied.
The Spreadsheet is used as the template, and the container-bound script is included in the Spreadsheet.
If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.
Issue and workaround:
The container-bound script of Google Docs cannot be retrieved by the methods of Files: list and Files: get in Drive API. This has already been reported to issue tracker.
The metadata of container-bound script of Google Docs can be updated by the method of Files: update in Drive API.
In your case, the GAS project ID (the script ID) is not changed because it is included in the template Spreadsheet. I think that this can be used for achieving your issue.
From above situation, I would like to propose the following flow.
Flow:
Set the variables of the container-bound script ID of the template Spreadsheet and the original project name of container-bound script ID of the template Spreadsheet.
Rename of the GAS project of the template Spreadsheet to the new project name.
Copy the template Spreadsheet. At this time, the GAS project is also copied as the new project name.
Rename of the GAS project of the template Spreadsheet to the original project name.
By above flow, the GAS project name of container-bound script in the copied Spreadsheet can be renamed.
When above workaround is reflected to your script, it becomes as follows.
Modified script:
Before you run the script, please enable Drive API at Advanced Google services. And please set the variables of GASProjectId, originalGASProjectName and newGASProjectName.
function copyTemplatev2(filename, sheetID) {
var GASProjectId = "###"; // Please set the container-bound script ID of the template Spreadsheet.
var originalGASProjectName = "originalName"; // Please set the original project name of container-bound script ID of the template Spreadsheet.
var newGASProjectName = "newName"; // Please set the new GAS project name.
// Rename to new project name.
Drive.Files.update({title: newGASProjectName}, GASProjectId);
var ss = SpreadsheetApp.openById(sheetID);
//Make a copy of the template file
var copy = DriveApp.getFileById(sheetID).makeCopy()
var documentId = copy.getId();
// Set permissions
copy.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.EDIT)
//Rename the copied file
DriveApp.getFileById(documentId).setName(filename);
// Rename to original project name.
Drive.Files.update({title: originalGASProjectName}, GASProjectId);
}
References:
Advanced Google services
Files: update
If I misunderstood your question and this was not the direction you want, I apologize.

Related

How to generate a Google Docs with an embedded AppScript, using Apps Script?

I'm interested in generating a Google Document with a particular Apps Script from my library.
The way I have been creating the Documents has been through basically, Jeff Everhart's code as seen here.
Is it possible that the code be changed as to have the new Google Docs have an embedded Apps Script right from the get go?
My reduced code:
function createNewGoogleDocs() {
const googleDocTemplate = DriveApp.getFileById('The template ID goes here');
const destinationFolder = DriveApp.getFolderById('The destination folder ID goes here');
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
const rows = sheet.getDataRange().getValues();
rows.forEach(function(row, index) {
if (index === 0 ) return;
if(row[rows[0].length - 1]) return;
const copy = googleDocTemplate.makeCopy(`First Column Name (${row[0]})`, destinationFolder);
const doc = DocumentApp.openById(copy.getId());
// Hopefully here we can have the addition of the the Apps Script on the new Docs
doc.saveAndClose();
const url = doc.getUrl();
sheet.getRange(index+1, rows[0].length).setValue(url);
})
}
If your goal is to create an Apps Script project bound to a Doc, you have to create it from that particular document. As it is said on the docs:
A script is bound to a Google Sheets, Docs, Slides, or Forms file if
it was created from that document rather than as a standalone script.
The file that a bound script is attached to is called a "container."
Bound scripts generally behave like standalone scripts except that
they do not appear in Google Drive, they cannot be detached from the
file they are bound to, and they gain a few special privileges over
the parent file.
If your end goal is to create a Doc with an embedded Apps Script from a different Apps Script project, you would have to first create that Doc/script as a template and then use makeCopy to create a copy of the Doc/script.
I am documenting this answer to help other people on this community, please feel free to leave a comment in your need further assistance.

Google Apps Script Save copy to read only

How do you save a copy of the current Sheets file to a read-only copy? We have scripts that set values that once confirmed save to a new Sheets file. This new file needs to be set as ReadOnly as a part of the script.
In your situation, how about using content protection?
Sample script:
Before you use this script, please enable Drive API at Advanced Google services.
const fileId = "###"; // Please set the file ID. In your situation, please set the Spreadsheet ID.
Drive.Files.patch({contentRestrictions: [{readOnly: true}]}, fileId);
When this script is run, the Spreadsheet can be only viewed and the Spreadsheet cannot be written.
If you want to unprotect it, please modify {readOnly: true} to {readOnly: false} in the above script.
References:
Protect file content from modification
Files: patch
A Google Sheets file will always be editable by the file onwer
It will not accesiable by other users it all unless it is explicitly shared with them
-The sharing can take place either through the UI or by script
To do it by script, you can use the method Spreadsheet.addViewer() or File.addViewer()
If a user who has is already an editor needs to be "downgraded" to a viewer, you can do remove him from the editors with removeEditor() before adding him as a viewer
You can also remove all editors (apart from the spreadsheet owner), sample:
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.getEditors().forEach(function(editor){
ss.removeEditor(editor):
})
You can use the DriveApp Permission enum, .setSharing, and related methods to do this.
Assuming you have a reference to the File object represented by the new Sheets file, this function will change all sharing so that the file is "View only" for anyone who previously had edit permission.
/**
* Change sharing permissions on a file or folder.
* #param {File or Folder object} asset
*/
function makeViewOnly(asset)
{
// General sharing permissions: change VIEW to NONE if you only want specific people to view the file
asset.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.VIEW);
asset.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
// These only apply if the file is on a Workspace domain.
asset.setSharing(DriveApp.Access.DOMAIN, DriveApp.Permission.VIEW);
asset.setSharing(DriveApp.Access.DOMAIN_WITH_LINK, DriveApp.Permission.VIEW);
// Change all edit permissions to view permissions
users = asset.getEditors();
user.forEach(function (user) {
asset.removeEditor(user)
asset.addViewer(user)
});
}
If you have a reference to the Spreadsheet object for the newly created Sheets file instead of the File object, you can get the File object via
var asset = DriveApp.getFileById(spreadsheet.getId())

Import and parse a HTML file from Drive to Sheets

I have a bunch of HTML files in the google drive, but I need to extract tables from them and put into Gsheets.
So far I saw ImportHTML function but it does not work with the drive link.
How can I import and parse HTML files from my Drive? Thank you
You want to put the values of the table from HTML data using Google Apps Script and/or the built-in functions of Spreadsheet.
The HTML files are put in your Google Drive.
If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.
Pattern 1:
In this pattern, IMPORTXML is used for the tables deployed with Web Apps.
Usage:
1. copy and paste the following script to the script editor.
function doGet(e) {
var fileId = e.parameter.id;
var html = DriveApp.getFileById(fileId).getBlob().getDataAsString();
var html = "<sample>" + html.match(/<table[\w\s\S]+?<\/table>/gi).join("") + "</sample>";
return ContentService.createTextOutput(html).setMimeType(ContentService.MimeType.XML);
}
2. Deploy Web Apps.
On the script editor, Open a dialog box by "Publish" -> "Deploy as web app".
Select "Me" for "Execute the app as:".
Select "Anyone, even anonymous" for "Who has access to the app:".
Click "Deploy" button as new "Project version".
Automatically open a dialog box of "Authorization required".
Click "Review Permissions".
Select own account.
Click "Advanced" at "This app isn't verified".
Click "Go to ### project name ###(unsafe)"
Click "Allow" button.
Click "OK".
Copy the URL of Web Apps. It's like https://script.google.com/macros/s/###/exec.
When you modified the Google Apps Script, please redeploy as new version. By this, the modified script is reflected to Web Apps. Please be careful this.
3. Put the formula.
Please put the following formula to a cell.
=IMPORTXML("https://script.google.com/macros/s/###/exec?id=###fileId###","//tr")
###fileId### is the file ID of HTML file on Google Drive.
Pattern 2:
In this pattern, the HTML tables are retrieved from the HTML data, and the tables are put to the Spreadsheet using Sheets API.
Usage:
1. copy and paste the following script to the script editor.
Please set the variables of fileId, spreadsheetId and sheetName.
function myFunction() {
var fileId = "###"; // Please set the file ID of HTML file.
var spreadsheetId = "###"; // Please set the Spreadsheet ID for putting the values.
var sheetName = "Sheet1"; // Please set the sheet name for putting the values.
// Retrieve tables from HTML data.
var html = DriveApp.getFileById(fileId).getBlob().getDataAsString();
var values = html.match(/<table[\w\s\S]+?<\/table>/gi);
// Put the HTML tables to the Spreadsheet.
var ss = SpreadsheetApp.openById(spreadsheetId);
var sheet = ss.getSheetByName(sheetName);
var sheetId = sheet.getSheetId();
var rowIndex = 0;
values.forEach(function(e) {
var resource = {requests: [{pasteData: {html: true, data: e, coordinate: {sheetId: sheetId, rowIndex: rowIndex}}}]};
Sheets.Spreadsheets.batchUpdate(resource, spreadsheetId);
rowIndex = sheet.getLastRow();
})
}
2. Enable Sheets API.
Please enable Sheets API at Advanced Google services.
3. Run the script.
When you run the function myFunction, the values are retrieved from HTML data and they are put to the Spreadsheet.
Note:
These are the simple sample scripts. So please modify them for your actual situation.
References:
Web Apps
Taking advantage of Web Apps with Google Apps Script
Advanced Google services
spreadsheets.batchUpdate
Unfortunately, from your question, I cannot understand about your actual HTML data. So if an error occurs and this was not the direction you want, I apologize.

Share a library by using google apps script

To share spreadsheets and documents it is easy to write a script:
var sheet = SpreadsheetApp.openById("xxxxxxxxxxxxxxxxxxxxxxxx");
sheet.addViewer("email#gmail.com");
A libray ia a stand alone Google Apps Script file. Is there a comparable script to share such a file?
You can achieve it using DriveApp as follows.
var file = DriveApp.getFileById("xxxxxxxxxxxxxxxxxxxxxxxx");
file.addViewer("email#gmail.com");
If you want to share files as ANYONE, you can use the following sample.
var file = DriveApp.getFileById("xxxxxxxxxxxxxxxxxxxxxxxx");
file.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.VIEW);
References :
Access
Permission

programmatically edit script in Google Drive document

I have a Google Drive document which writes values to a Google Drive spreadsheet using Google Apps Scripts.
The script associated with the document looks a lot like this:
// must change value to actual spreadsheet ID
RobProject.spreadsheetID = "spreadsheetID";
function onOpen()
{
// do stuff;
}
Each time I create a spreadsheet and its related documents, I manually change the value spreadsheetID to the spreadsheet's ID so the documents know to which spreadsheet they should write their values.
I would like a programmatic way to fill in the correct value for spreadsheetID into the Documents' scripts.
When I search for "edit scripts programmatically," I get tutorials for creating Google Apps Scripts, not editing scripts with scripts. Is there any way to edit Google Apps Scripts with a Google Apps Script?
If I understand correctly, you are working with a document and a spreadsheet. The document needs to know the Id of the spreadsheet.
There are some ways to access the Google Apps Script code through the API, but that is only for standalone projects, not for container-bound scripts (unfortunately).
You could consider using a naming convention for the document and spreadsheet so that you could use the Drive service to get from the document to the spreadsheet (DriveApp.getFilesByName()). Or possibly organize them by folder (DriveApp.getFoldersByName(), folder.getFiles()).
If you wanted to store the spreadsheet Id in a project property, you could build a UI in the document that let the user open up the list of files in Drive and pick the associated spreadsheet and then store the Id (ScriptProperties.setProperty('SpreadsheetId')).
Don't forget that onOpen has a parameter. You could use following code:
// Define global variable somewhere
RobProject = {};
function onOpen(e) {
RobProject.sSheet = e.source; // maybe the spreadsheet object is as useful as the ID
RobProject.spreadsheetID = e.source.getId();
// do stuff;
}
Please, for your own sake, don't try to write selfmodifying code.