Now, I'm creating a mail sending application with Google Apps Script in my Google Spreadsheet.
This app do following actions.
Add a menu to call this application when the spreadsheet is opened.
Display UI to input mail subject when the menu is clicked.
Send mails to each addresses contained in the spreadsheet when submit button push by the spreadsheet opend user.
Problem
The app work fine when i use.
But the other users who can edit the spreadsheet can not send emails (display ui is ok).
From dubug logs, I've found that the doPost function is not called.
Please tell me what is the problem.
Program
/*
* #OnlyCurrentDoc
*
* create custome menu in active spreadsheet
*/
function onOpen(e) {
Logger.log("onOpen called");
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [
{name: "MailSendApp", functionName: "displayAppUi"}
];
sheet.addMenu("CustomAppMenu", menuEntries);
}
/*
* #OnlyCurrentDoc
*
* display ui
*/
function displayAppUi() {
Logger.log("displayAppUi called");
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var app = UiApp.createApplication();
var formPanel = app.createFormPanel().setId('form').setEncoding('multipart/form-data');
var scrollPanel = app.createScrollPanel();
var panel = app.createVerticalPanel();
var appLabel = app.createLabel("Sendmails SpreadSheet App");
var subjectLabel = app.createLabel("Subject");
var subjectTextBox = app.createTextBox().setName("subject");
var bodyLabel = app.createLabel("Body");
var bodyTextArea = app.createTextArea().setName("body");
var attachFile = app.createFileUpload().setName('attachFile');
var sendBtn = app.createSubmitButton().setText("Send ALL");
var sheetName = app.createHidden("sheetName", SpreadsheetApp.getActiveSheet().getName());
// set client handler
var submitClientHandler = app.createClientHandler()
.forEventSource().setEnabled(false)
.forEventSource().setText("Sending...");
sendBtn.addClickHandler(submitClientHandler)
// set sytles
app.setWidth(800);
app.setHeight(400);
panel.setStyleAttributes({width: "100%"});
appLabel.setStyleAttributes({color: "green", fontSize: "2em" });
subjectTextBox.setStyleAttributes({width: "100%"});
bodyTextArea.setHeight("240");
bodyTextArea.setWidth("780");
scrollPanel.setHeight("380");
scrollPanel.setWidth("800");
panel.add(appLabel)
.add(subjectLabel)
.add(subjectTextBox)
.add(bodyLabel)
.add(bodyTextArea)
.add(attachFile)
.add(sheetName)
.add(sendBtn);
scrollPanel.add(panel)
formPanel.add(scrollPanel);
app.add(formPanel);
sheet.show(app);
}
/*
* #OnlyCurrentDoc
*
* handler to send emails to addresses in active sheet with input subject & body.
*/
function doPost(e) {
Logger.log("doPost called");
var param = e.parameter;
var subject = param.subject;
var body = param.body;
var attachFile = param.attachFile;
var sheetName = param.sheetName;
var mailOptions = {};
var mailAttachments = []
// set attachment file if exists
if (attachFile != null) {
mailAttachments.push({
fileName: attachFile.getName(),
mimeType: attachFile.getContentType(),
content: attachFile.getBytes()
});
}
mailOptions["attachments"] = mailAttachments;
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
var emails = _collectEmailAddresses(sheet);
for(var i=0; i < emails.length; i++) {
var email = emails[i];
GmailApp.sendEmail(email, subject, body, mailOptions);
}
var app = UiApp.getActiveApplication();
app.close();
return app;
}
/*
* collect Email addresses from the argument sheet
*/
function _collectEmailAddresses(sheet) {
var emails = [];
var range = sheet.getDataRange();
var values = range.getValues();
// get skip row numbers(that is header row num) from property
var header_rownum = parseInt(PropertiesService.getScriptProperties().getProperty("header_rownum"));
for (var i = header_rownum; i < range.getLastRow(); i++) {
var email = values[i][1];
emails.push(email);
}
return emails;
}
Use openByID instead of .getActiveSpreadsheet().getSheetByName(sheetName) in your doPost trigger.
var ss = SpreadsheetApp.openById(_spreadsheetId);
var sheet = ss.getSheetByName(_sheetName);
Related
This question already has answers here:
onEdit() trigger is unable to create a new Spreadsheet
(1 answer)
Google Sheets OnEdit() - You do not have permission to call a service
(2 answers)
Closed 7 months ago.
I write a script and it works fine if you run them separately from app script (RUN bottom). If I run it combined with the "run" bottom in app script it is working, when a enable the checkbox in the sheet, it is not working at all, clearall() is always working, addrecord() is working if I put it before var checkexist = ... , the other 2 are not working (running).
What is wrong here?
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("KLANTinput");
var checkadd = sheet.getRange("AI3").getValue();
if (checkadd === 1) {
var checkexist = sheet.getRange("X2").getValue();
if (checkexist === 0) {
addContactPhoneAndCreateFolder();
Utilities.sleep(500);
createNewFolderInGoogleDrive();
Utilities.sleep(500);
}
addrecord();
Utilities.sleep(500);
clearall();
var checkstate = sheet.getRange("AH3");
checkstate.setValue("FALSE");
}
}
function addContactPhoneAndCreateFolder() {
var sheet = SpreadsheetApp.getActiveSheet();
//var sheet = ss.getSheetByName("KLANTinput");
var first_name = sheet.getRange("J5").getValue();
var last_name = sheet.getRange("AD5").getValue();
var email = sheet.getRange("J15").getValue();
var adres = sheet.getRange("J7").getValue().concat(" ").concat(sheet.getRange("Z7").getValue()).concat(" ").concat(sheet.getRange("J9").getValue()).concat(" ").concat(sheet.getRange("AD9").getValue());
var phone = sheet.getRange("J13").getValue();
Logger.log(adres);
var contact = ContactsApp.createContact(first_name, last_name, email);
var group = ContactsApp.getContactGroup("System Group: My Contacts");
group.addContact(ContactsApp.createContact(first_name, last_name, email));
var contact = ContactsApp.findByEmailAddress(email);
contact.setHomeAddress(adres);
contact.setPrimaryEmail(email);
//contact.setWorkAddress(adres);
contact.setHomePhone(phone);
}
function createNewFolderInGoogleDrive() {
var sheet = SpreadsheetApp.getActiveSheet();
//var sheet = ss.getSheetByName("KLANTinput");
var folderName = sheet.getRange("J5").getValue().concat(" ").concat(sheet.getRange("AD5").getValue()).concat(" ").concat(sheet.getRange("J9").getValue()).concat(" ").concat(sheet.getRange("AD9").getValue()).concat(" ").concat(sheet.getRange("AD19").getValue());
var folder = DriveApp.getFolderById("sheetID");
//Logger.log(folderName);
var nfolder = folder.createFolder(folderName);
}
function addrecord() {
var sss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = sss.getSheetByName("KLANTinput");
var datasheet = sss.getSheetByName("KLANTpredb");
var values = [[sheet.getRange("C2").getValue(), //DATE + TIME
sheet.getRange("J3").getValue(), //DATE
sheet.getRange("K2").getValue(), //DD
sheet.getRange("N2").getValue(), //MM
sheet.getRange("Q2").getValue(), //YY
....
Logger.log(values)
//var roow = datasheet.getLastRow()
//Logger.log(roow)
datasheet.getRange(datasheet.getLastRow() + 1, 1, 1, 45).setValues(values);
}
I wanted to create a bulk of folders in my google drive using scripts in google spreadsheet. Fortunately, I have found the script I have been looking for. However, upon executing the script, it gave a notice that (I forgot the exact message) I have reached the maximum number of folders to create. So it just stops. Here is the code. I hope someone could tell me how can I or what should I change for it to create folders as required.
function onOpen() { //This is the new standard script for the onOpen trigger that creates a menu item.
var ui = SpreadsheetApp.getUi();
// Or DocumentApp or FormApp.
ui.createMenu('GDrive')
.addItem('Create new Folders', 'crtGdriveFolder')
.addToUi();
}
function crtGdriveFolder() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var levelInput = Browser.inputBox('input Level', Browser.Buttons.OK_CANCEL);
var Level = levelInput * 2 + 1;
var numRows = sheet.getLastRow(); // Number of rows to process
var dataRange = sheet.getRange(3, Number(Level)-1, numRows, Number(Level)); //startRow, startCol, endRow, endCol
var data = dataRange.getValues();
var parentFolderID = new Array();
for(var i in data)
{
parentFolderID[i] = data [i][0];
if (data [i][0] == "")
{
parentFolderID[i] = parentFolderID[i-1];
}
}
for(var i in data){
if (data [i][1] !== "")
{
var theParentFolder = DriveApp.getFolderById(parentFolderID[i]);
var folderName = data[i][1];
var theChildFolder = theParentFolder.createFolder(folderName);
// Utilities.sleep(100);
var newFolderID = sheet.getRange(Number(i)+3,Number(Level)+1);
var folderIdValue = theChildFolder.getId();
newFolderID.setValue(folderIdValue);
var addLink = sheet.getRange(Number(i)+3,Number(Level));
var value = addLink.getDisplayValue();
addLink.setValue('=hyperlink("https://drive.google.com/corp/drive/folders/'+ folderIdValue +'","' + value + '")');
}
}
}```
[![enter image description here][1]][1]
[1]: https://i.stack.imgur.com/QKKLr.jpg
I'm on a project in which I get stuck just on the final step.
let me explain:
my project to filter data and move the filtered data to another spreadsheet. All work properly without issues but something happened and the issue is that I need to input dynamic data as filter and sheet name. I created 2 variables location which will determine the filter and sectionSelect which will determine the sheet name.
my goal is to send the data through the web with its tag to be filtered in the desired sheet.
FYI: the app script is bound to a gsheet.
Here is the code:
function doGet(e) {
var ss = SpreadsheetApp.openByUrl("sheetURL")
var sheet = ss.getSheetByName(Location);
return TagData(e,sheet);
}
function doPost(e) {
var ss = SpreadsheetApp.openByUrl("sheetURL")
var sheet = ss.getSheetByName(Location);
return TagData(e,sheet);
}
function TagData(e) {
var Location = e.parameter.Location; // send from app with respective tag
var sectiontSelect = e.parameter.sectiontSelect; // send from app with respective tag
sheet.append([Location, sectiontSelect])
}
function FilterOnText() {
var ss = SpreadsheetApp.getActive()
var range = ss.getDataRange();
var filter = range.getFilter() || range.createFilter()
var text = SpreadsheetApp.newFilterCriteria().whenTextContains(Location); // the location will be as per the location variable in the TagData function
filter.setColumnFilterCriteria(1, text);
}
function titleAsDate() {
const currentDate = Utilities.formatDate(new Date(), "GMT+4", "dd-MM-yyyy HH:mm:ss");
return SpreadsheetApp.create("Report of the " + currentDate);
}
function copyWithValues() {
const spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
const sourceSheet = spreadSheet.getSheetByName(sectionSelect); // fromApp variable will define which sheet the data will be copied (situated in the TagData function)
const temp_sheet = spreadSheet.insertSheet('temp_sheet');
const sourceRange = sourceSheet.getFilter().getRange();
sourceRange.copyTo(
temp_sheet.getRange('A1'),
SpreadsheetApp.CopyPasteType.PASTE_NORMAL,
false);
SpreadsheetApp.flush();
const sourceValues = temp_sheet.getDataRange().getValues();
const targetSpreadsheet = titleAsDate();
const rowCount = sourceValues.length;
const columnCount = sourceValues[0].length;
const targetSheet = targetSpreadsheet.getSheetByName('Sheet1').setName("Report"); // renamed sheet
const targetRange = targetSheet.getRange(1, 1, rowCount, columnCount);
targetRange.setValues(sourceValues);
spreadSheet.deleteSheet(temp_sheet);
}
function MoveFiles(){
var files = DriveApp.getRootFolder().getFiles();
var file = files.next();
var destination = DriveApp.getFolderById("1wan7PLhl4UFEoznmsN_BVa2y4AtFaCOr");
destination.addFile(file)
var pull = DriveApp.getRootFolder();
pull.removeFile(file);
}
function clearFilter() { // clearance of filters applied in first function
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("testo");
sheet.getFilter().remove();
}
Explanation:
Two issues:
TagData does not return anything (as Cooper pointed out)
TagData(e) has only one parameter e but you are passing two parameters TagData(e,sheet) when you call it from the doGet and doPost functions.
Not sure if this will solve all your issues, but it will solve the ones I mentioned above.
Solution:
Remove the return statements from doGet and doPost because of issue 1).
Add the sheet parameter in the TagData function.
Resulting code:
function doGet(e) {
var ss = SpreadsheetApp.openByUrl("sheetURL")
var sheet = ss.getSheetByName(Location);
TagData(e,sheet); // modified
}
function doPost(e) {
var ss = SpreadsheetApp.openByUrl("sheetURL")
var sheet = ss.getSheetByName(Location);
TagData(e,sheet); // modified
}
// added the sheet parameter
function TagData(e,sheet) {
var Location = e.parameter.Location; // send from app with respective tag
var sectiontSelect = e.parameter.sectiontSelect; // send from app with respective tag
sheet.append([Location, sectiontSelect]);
}
// rest of your code..
Or try this:
function doGet(e) {
var ss = SpreadsheetApp.openByUrl("sheetURL")
var sheet = ss.getSheetByName(Location);
var params = JSON.stringify(TagData(e,sheet)); // modified
return HtmlService.createHtmlOutput(params); // added
}
function doPost(e) {
var ss = SpreadsheetApp.openByUrl("sheetURL")
var sheet = ss.getSheetByName(Location);
ContentService.createTextOutput(JSON.stringify(e))
}
// added the sheet parameter
function TagData(e,sheet) {
var Location = e.parameter.Location; // send from app with respective tag
var sectiontSelect = e.parameter.sectiontSelect; // send from app with respective tag
sheet.append([Location, sectiontSelect]);
return { Location: Location, sectiontSelect: sectiontSelect }
}
I'm brand new to Google Apps Script, and I'm trying to create a simple spreadsheet that will allow me to share files by user email through a single spreadsheet.
I have written the following script, which will allow me to add editors and viewers, but not commenters.
I keep getting an error that states that the function addCommenter cannot be found in object spreadsheet.
function shareSheet () {
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.toast('Updating access level...');
var sheet = ss.getSheets()[0];
var lastRow = sheet.getLastRow();
var range1 = sheet.getRange (3,1, lastRow,9);
var data = range1.getValues();
for (var i= 0; i < data.length; i++) {
var row = data [i];
var accessLevel = row [5];
var values = row [8];
var ss2 = SpreadsheetApp.openById(values);
var values2 = row [4];
// Add new editor
if (accessLevel == 'Edit') {
var addEditors = ss2.addEditor(values2);
}
// Add new viewer
if (accessLevel == 'View'){
var addViewers = ss2.addViewer(values2);
}
// Add new commenter
if (accessLevel == 'Comment') {
var addCommenters = ss2.addCommenter(values2);
}
}
}
The Spreadsheet object does not support the addCommentor() method. You should use DriveApp service instead.
DriveApp.getFileById(id).addCommenter(emailAddress)
I am trying to copy a single worksheet to multiple workbooks within Google Drive. Just over a month ago, this code worked fine but now it doesn't because I'm thinking that the DocsList command within the code has been deprecated by Google (see https://developers.google.com/apps-script/sunset). I've heard that the new command is DriveApp but I'm not too sure. I'm a total newbie when it comes to writing code so I'm hoping someone can please fix this code?
function onOpen(){
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [];
menuEntries.push({name: "Copy Active Sheet to Other Spreadsheets", functionName: "doGet"});
spreadsheet.addMenu("Copy Sheet", menuEntries);
}
function doGet()
{
var app = UiApp.createApplication();
app.setTitle("Kishan - Copy Sheet in Multiple Spreadsheets");
var form = app.createFormPanel();
var flow = app.createFlowPanel();
var label = app.createLabel("Select Spreadsheet where you want to copy the current sheet:").setId('selectLabel');
flow.add(label);
var allfiles = DocsList.getAllFiles();
var verticalPanel = app.createVerticalPanel().setId('verticalPanel');
for(var i=0;i<allfiles.length;i++)
{
var temp = app.createCheckBox(allfiles[i].getName()).setName('cb'+i).setId('cb'+i);
var tempvalue = app.createHidden('cbvalue'+i, allfiles[i].getId());
verticalPanel.add(temp);
verticalPanel.add(tempvalue);
}
var scrollPanel = app.createScrollPanel().setId('scrollPanel');
scrollPanel.add(verticalPanel);
scrollPanel.setSize("400", "250")
flow.add(scrollPanel);
var buttonsubmit = app.createSubmitButton("Copy");
flow.add(buttonsubmit);
form.add(flow);
app.add(form);
SpreadsheetApp.getActiveSpreadsheet().show(app);
}
function doPost(eventInfo) {
var app = UiApp.getActiveApplication();
var allfiles = DocsList.getAllFiles();
var tempSsId = "";
for(var i=0;i<allfiles.length;i++)
{
var temp = eventInfo.parameter['cb'+i];
if(temp == 'on')
{
tempSsId = eventInfo.parameter['cbvalue'+i];
var activeSheet = SpreadsheetApp.getActiveSheet().copyTo(SpreadsheetApp.openById(tempSsId));
activeSheet.setName(SpreadsheetApp.getActiveSheet().getSheetName());
}
}
var label = app.createLabel('statusLabel');
label.setText("Copied Active sheet in all selected Spreadsheets...");
label.setVisible(true);
app.add(label);
return app;
}
This is the original code from [http://igoogledrive.blogspot.ca/2012/10/Google-Spreadsheet-Script-to-Copy-Sheet-to-multiple-Spreadsheets-at-a-time.html][1] that was working fine for me before but now isn't. Can anyone help?
Try this
function doGet()
{
var app = UiApp.createApplication();
app.setTitle("Kishan - Copy Sheet in Multiple Spreadsheets");
var form = app.createFormPanel();
var flow = app.createFlowPanel();
var label = app.createLabel("Select Spreadsheet where you want to copy the current sheet:").setId('selectLabel');
flow.add(label);
var allfiles = DriveApp.getFiles();
var verticalPanel = app.createVerticalPanel().setId('verticalPanel');
var i = 0;
while (allfiles.hasNext())
{
var file = allfiles.next();
var temp = app.createCheckBox(file.getName()).setName('cb'+i).setId('cb'+i);
var tempvalue = app.createHidden('cbvalue'+i, file.getId());
verticalPanel.add(temp);
verticalPanel.add(tempvalue);
i++;
}
var scrollPanel = app.createScrollPanel().setId('scrollPanel');
scrollPanel.add(verticalPanel);
scrollPanel.setSize("400", "250")
flow.add(scrollPanel);
var buttonsubmit = app.createSubmitButton("Copy");
flow.add(buttonsubmit);
form.add(flow);
app.add(form);
SpreadsheetApp.getActiveSpreadsheet().show(app);
}
function doPost(eventInfo) {
var app = UiApp.getActiveApplication();
var allfiles = DriveApp.getFiles();
var tempSsId = "";
var i = 0;
while (allfiles.hasNext())
{
var temp = eventInfo.parameter['cb'+i];
if(temp == 'on')
{
tempSsId = eventInfo.parameter['cbvalue'+i];
var activeSheet = SpreadsheetApp.getActiveSheet().copyTo(SpreadsheetApp.openById(tempSsId));
activeSheet.setName(SpreadsheetApp.getActiveSheet().getSheetName());
}
i++;
}
var label = app.createLabel('statusLabel');
label.setText("Copied Active sheet in all selected Spreadsheets...");
label.setVisible(true);
app.add(label);
return app;
}