Google Spreadsheets and sheets - javascript

It seems like in the documentation that Google Spreadsheets and Google Sheets both have methods such as getActiveCell() which leads to confusion what the difference between the "Spreadsheet" object and the "Sheet" object. I assume that a spreadsheet is a collection of sheets. Suppose that I want to open a file with the following code where my Spreadsheet only has 1 sheet (see question in commented lines and assume I want to then do operations on the first sheet of both files):
function OpenFile(FileName) {
var FileToGetIterator = DriveApp.getFilesByName(FileName);
var FileToGet = FileToGetIterator.next();
var SpreadSheets = SpreadsheetApp.open(FileToGet);
var SpreadSheet1 = SpreadSheets.getSheets()[0]; // is this line necessary??
}
Similarly for creating a file
function CreateFile(SpreadSheetName) {
var NewSpreadSheets = SpreadsheetApp.Create(SpreadSheetName);
var NewSpreadSheet = NewSpreadSheets.getSheets()[0]; // is this line necessary?
}

when you create a spreadsheet or you open a spreadsheet it automatically open the first sheet of the spreadsheet,so no it's not necessary. nevertheless the opened sheet is opened as the "activesheet" and you've got less methods than if you specifically open a particular sheet with your method

Related

Extra double quotes in csv coming in Google Sheets Apps Script Web App

In my google sheet I have some data in it. Later I published my sheet as .csv format.
Pls find my sheet here, below are the Cell Values
C1 = tdsyltt = 'ఈరోజు ( బుధవారం ) క్విజ్ సిలబస్' ;
C2 = tdsyl = 'హబక్కూకు 1 & యాకోబు 2, 3' ;
C4 = document.getElementById("tdsyltt).innerHTML = tdsyltt ;
C5 = document.getElementById("tdsyl").innerHTML = tdsyl ;
And using my published URL I have developed a web app
code.gs
const doGet = _ => ContentService.createTextOutput(UrlFetchApp.fetch("https://docs.google.com/spreadsheets/d/e/2PACX-1vReY-tDEwKYjTiSjsfAN42qjFUwMv_OD3_64bFdGrgL-2p3otc13elLcCq3pkb5xqhTA-bW3QXobpqh/pub?gid=1861615717&single=true&range=c1:c5&output=csv").getContentText()).setMimeType(ContentService.MimeType.JAVASCRIPT);
In the web app output 1st line is ok,
but for 2nd, 3rd and 4th line there are Extra 2 Apostrophes coming at the starting and ending of the lines.
Here is My Web App
How to fix this ..?
Modification points:
In this case, how about directly retrieving the values from Spreadsheet using Spreadsheet service instead of UrlFetchApp.fetch("https://docs.google.com/spreadsheets/d/e/2PACX-1vReY-tDEwKYjTiSjsfAN42qjFUwMv_OD3_64bFdGrgL-2p3otc13elLcCq3pkb5xqhTA-bW3QXobpqh/pub?gid=1861615717&single=true&range=c1:c5&output=csv").getContentText()? I thought that the reason of your current issue might be due to exporting the Spreadsheet as CSV data. When the Spreadsheet service is used, the values can be retrieved.
In your previous question, I said "In this answer, your Spreadsheet is used. Of course, you can directly set the script in Web Apps.". Ref In your this question, I thought that this can be used.
In your sample Spreadsheet, document.getElementById("tdsyltt).innerHTML = tdsyltt ; is required to be document.getElementById("tdsyltt").innerHTML = tdsyltt ;. Please be careful about this.
When these points are reflected in your script, how about the following modification?
Modified script:
const doGet = _ => {
const spreadsheetId = "###"; // Please set your Spreadsheet ID.
const ss = SpreadsheetApp.openById(spreadsheetId);
const sheet = ss.getSheetByName("SYLLABUSC");
const html = sheet.getRange("C1:C6").getDisplayValues().filter(([c]) => c).join("\n");
// console.log(html); // When you directly run this function with the script editor, you can see the created value in the log.
return ContentService.createTextOutput(html).setMimeType(ContentService.MimeType.JAVASCRIPT);
}
From your Spreadsheet, in this sample script, I used "C1:C6" of "SYLLABUSC" sheet. So, please modify this for your actual situation.
Note:
When you modified the Google Apps Script of Web Apps, please modify the deployment as a new version. By this, the modified script is reflected in Web Apps. Please be careful about this.
You can see the detail of this in my report "Redeploying Web Apps without Changing URL of Web Apps for new IDE (Author: me)".
Try a way to solve this by changing the spreadsheet Publishing Format from csv to tsv then it will work.
Code.gs
const doGet = _ => ContentService.createTextOutput(UrlFetchApp.fetch("https://docs.google.com/spreadsheets/d/e/2PACX-1vReY-tDEwKYjTiSjsfAN42qjFUwMv_OD3_64bFdGrgL-2p3otc13elLcCq3pkb5xqhTA-bW3QXobpqh/pub?gid=1861615717&single=true&range=c1:c5&output=tsv").getContentText()).setMimeType(ContentService.MimeType.JAVASCRIPT);

Disable Spreadsheet Copy

Can someone help me fix the following code?
I using this script to disable editor to copy my Google spreadsheet
function onOpen () {
const ss = SpreadsheetApp.getActive();
const id = ss.getId();
if (id !== '1ld8aPE5zVBYoT39WPzZjWxU1uHJ8lVVV5vkBiv5USzI') ss.getSheets().forEach((s) => ss.deleteSheet(s)); }
Reference.
Disable Spreadsheet copy - Google Sheets
I tried copying to another worksheet but code wont work
Example
https://drive.google.com/drive/folders/11Jqh_xaw0CdI1cBUL_hZwCjOJNnRKSU6?usp=sharing
Tl;Dr There is no way to prevent that spreadsheet editors copy the spreadsheet, because of this, in order to prevent that editors copy the spreadsheet you should use another approach to whatever you are doing with your spreadsheet.
Regarding the code in the question, it doesn't disable spreadsheet copy, what it does is, if the spreadsheet id is not equal to certain value, iterates over all the sheets but as it's not possible to delete all the sheets as each spreadsheet should include at least one sheet, the script throws an error. You might change the script i.e. inserting a new sheet and delete the other sheets, but the editor of the original spreadsheet, as there are the owner of the copy, they will be able to delete the script and restore the deleted data from the version history of the new spreadsheet.
Related
Disable Spreadsheet copy - Google Sheets
At least, you can add a sheet with an alert and delete all other sheets
var id = '1ld8aPE5zVBYoT39WPzZjWxU1uHJ8lVVV5vkBiv5USzI'
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
if (ss.getId() != id) {
var gid = ss.insertSheet().getSheetId()
ss.getSheets().forEach(function (sh) {
if (sh.getSheetId() != gid) { ss.deleteSheet(sh) }
})
}
}
I am not sure that there is no bypass! See Rubén's advice.

Making a checkbox Ui with Google Apps Script

This is my first time posting on Stack Overflow, so I apologize in advance if I made any "posting" mistakes.
I am using Google Apps Script for the project I am doing, because I am interacting with Google Docs and Google sheets. Google Script has a deprecated Ui Service, which is very frustrating to me.
So far, I have written a JavaScript program that parses through the "table of contents" part of a Google Doc, and retrieves the items I wanted. (If the table of content is changed, then the items retrieved might be different too.) Now, my intention is to make a checkbox that uses all the items that I retrieved from the table of contents as its options, and after users choosing and clicking "submit" button, a new Google Sheet would be generated. Of course I will operate on that new Google Sheet, but I want to stick with this problem first.
I did look up HTML Service, a Ui recommended by Google Script, but I don't know too much about HTML. What is most difficult is that if I use HTML to make the checkbox, how am I supposed to get all the items I parsed from the JavaScript passed into the HTML file, check which options are checked, and then get checked options passed back to the JavaScript so that I can do further operation? Is it even possible? Or am I having a misconception?
What I have so far:
//custom menu
function onOpen()
{
var ui = DocumentApp.getUi();
ui.createMenu('Custom Menu')
.addItem('Export Checksheets', 'customMenu')
.addToUi();
}
//parse the table of contents
function readFile()
{
var options = [];
var testDoc = DocumentApp.getActiveDocument();
var file = testDoc.getBody();
var tableOfCon = DocumentApp.ElementType.TABLE_OF_CONTENTS;
var searchRes = file.findElement(tableOfCon);
//If the element exists
if (searchRes)
{
var TC = searchRes.getElement().asTableOfContents();
var numChild = TC.getNumChildren();
for (var i=0; i < numChild; i++)
{
var info = {};
var TCItem = TC.getChild(i).asParagraph();
var TCItemText = TCItem.getChild(0).asText();
var TCItemAttrs = TCItemText.getAttributes(); //for future usage
//get all the options
if (!TCItemText.isBold())
{
options.push(TCItem.getText());
}
}
}
Logger.log(options); //which successfully displays the items retrieved
}
//linked to the HTML file
function customMenu()
{
var html = HtmlService.createHtmlOutputFromFile('Index');
html.setHeight(350).setWidth(280);
var ui = DocumentApp.getUi().showModalDialog(html, 'Hello!');
}
My HTML file only has a little code that displays some message when the custom menu is chosen.
Any help would be appreciated!

Google App Script emailing entire workbook as opposed to a single sheet

this pseudo scrip that I've pieced together sort of works.
Essentially, what I want to do is to email one tab, that holds formulas on a daily basis to directors within my company.
This, for the moment, is working, but it's emailing the entire sheet as opposed to one sheet. I embedded a function near the bottom to hide the sheets but I'm quite sure it's not being executed. I've just got my head around coding in Python so JS has been quite difficult for me.. apologies for this.
additionally, would anyone happen to know how to embed a password into the PDF? (this is a nice to have not essential).
// Simple function to send Weekly Status Sheets to contacts listed on the "Contacts" sheet in the MPD.
// Load a menu item called "Project Admin" with a submenu item called "Send Status"
// Running this, sends the currently open sheet, as a PDF attachment
function onOpen() {
var submenu = [{name:"Send Status", functionName:"exportSomeSheets"}];
SpreadsheetApp.getActiveSpreadsheet().addMenu('Project Admin', submenu);
}
function exportSomeSheets() {
// Set the Active Spreadsheet so we don't forget
var originalSpreadsheet = SpreadsheetApp.getActive();
// Set the message to attach to the email.
var message = "Daily Sales Snapshot"; // Could make it a pop-up perhaps, but out of wine today
// Get Project Name from Cell A1
var projectname = originalSpreadsheet.getRange("H1:H1").getValues();
// Get Reporting Period from Cell B3
var period = originalSpreadsheet.getRange("B3:B3").getValues();
// Construct the Subject Line
var subject = projectname + " - Daily Status Sheet - " + period;
// Get contact details from "Contacts" sheet and construct To: Header
// Would be nice to include "Name" as well, to make contacts look prettier, one day.
var contacts = originalSpreadsheet.getSheetByName("Contacts");
var numRows = contacts.getLastRow();
var emailTo = contacts.getRange(2, 2, numRows, 1).getValues();
// Google scripts can't export just one Sheet from a Spreadsheet
// So we have this disgusting hack
var newSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheets = newSpreadsheet.getSheets;
for (var i = 5; i < sheets.length; i++) {
if (sheets[i].getSheetName() != sheetName) {
sheet[i].hideSheet();
}
}
// Make zee PDF, currently called "Weekly status.pdf"
// When I'm smart, filename will include a date and project name
var pdf = DriveApp.getFileById(newSpreadsheet.getId()).getAs('application/pdf').getBytes();
var attach = {fileName:'Daily Status.pdf',content:pdf, mimeType:'application/pdf'};
// Send the freshly constructed email
MailApp.sendEmail(emailTo, subject, message, {attachments:[attach]});
}
Can't export just a single sheet but a quick search shows this gist, with a function for "Simple Google Apps Script to export a single sheet to PDF and email it to a contact list". You can adapt that for your needs.
Essentially, that script creates a new spreadsheet, copies the single sheet that you need into that new spreadsheet, deletes the automatically generated "Sheet 1", sends an email with the new Spreadsheet as pdf, and then deletes the new spreadsheet.
Pasting that code here for your reference (in case it gets deleted):
function exportSomeSheets() {
// Set the Active Spreadsheet so we don't forget
var originalSpreadsheet = SpreadsheetApp.getActive();
// Set the message to attach to the email.
var message = "Please see attached"; // Could make it a pop-up perhaps, but out of wine today
// Get Project Name from Cell A1
var projectname = originalSpreadsheet.getRange("A1:A1").getValues();
// Get Reporting Period from Cell B3
var period = originalSpreadsheet.getRange("B3:B3").getValues();
// Construct the Subject Line
var subject = projectname + " - Weekly Status Sheet - " + period;
// Get contact details from "Contacts" sheet and construct To: Header
// Would be nice to include "Name" as well, to make contacts look prettier, one day.
var contacts = originalSpreadsheet.getSheetByName("Contacts");
var numRows = contacts.getLastRow();
var emailTo = contacts.getRange(2, 2, numRows, 1).getValues();
// Google scripts can't export just one Sheet from a Spreadsheet
// So we have this disgusting hack
// Create a new Spreadsheet and copy the current sheet into it.
var newSpreadsheet = SpreadsheetApp.create("Spreadsheet to export");
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var projectname = SpreadsheetApp.getActiveSpreadsheet();
sheet = originalSpreadsheet.getActiveSheet();
sheet.copyTo(newSpreadsheet);
// Find and delete the default "Sheet 1", after the copy to avoid triggering an apocalypse
newSpreadsheet.getSheetByName('Sheet1').activate();
newSpreadsheet.deleteActiveSheet();
// Make zee PDF, currently called "Weekly status.pdf"
// When I'm smart, filename will include a date and project name
var pdf = DocsList.getFileById(newSpreadsheet.getId()).getAs('application/pdf').getBytes();
var attach = {fileName:'Weekly Status.pdf',content:pdf, mimeType:'application/pdf'};
// Send the freshly constructed email
MailApp.sendEmail(emailTo, subject, message, {attachments:[attach]});
// Delete the wasted sheet we created, so our Drive stays tidy.
DocsList.getFileById(newSpreadsheet.getId()).setTrashed(true);
}
Don't know the creator of the script but like his style.

Google Scripts external spreadsheet data validation

I was interested in automating data validation of a Google Spreadsheet against another Google Spreadsheet using Google Scripts. I can't seem to find a way to reference the range of another spreadsheet using the openById method. Any thoughts?
function externalSheetDataValidation() {
var cell = SpreadsheetApp.getActiveRange();
//var dataValidationSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("dataValidationRules");
//var dataValidationSheet = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/10Z2s1bSRIhZzBBrMfPmhEphnPx-kJdV3LLlbv0L59g8/edit#gid=0");
var dataValidationSheet = SpreadsheetApp.openById("10Z2s1bSRIhZzBBrMfPmhEphnPx-kJdV3LLlbv0L59g8");
var sheet = dataValidationSheet.getSheets()[0];
var range = SpreadsheetApp.getActiveSheet().getRange("A3:A4");
var rule = SpreadsheetApp.newDataValidation()
.requireValueInRange(range, true)
.setAllowInvalid(false)
.build();
cell.setDataValidation(rule);
Logger.log(dataValidationSheet.getName());
}
If I am understanding correctly, the issue you are having is selecting a data range from an external spreadsheet?
Im assuming dataValidationSheet is supposed to be the external sheet. It looks like you were on the right track. It looks like the issue is that you are expecting the sheet to be active once you grab it.
Try this change:
var range = sheet.getRange("A3:A4");
Currently you are grabbing the external sheet, but then getting the range from the sheet that was already active. Hopefully this helps!

Categories