I find this code but it doesn't work like expected.
function onOpen() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange("'Feuille 1'!1:1137");//This line is most likely the culprit
var to_replace = ".";
var replace_with = ",";
replaceInSheet(sheet,range, to_replace, replace_with);
}
function replaceInSheet(sheet, range, to_replace, replace_with) {
//Confirm
var ui = SpreadsheetApp.getUi();
var spread = SpreadsheetApp.getActiveSpreadsheet();
var result = ui.alert(
"Will update " + to_replace + " to " + replace_with + " ",
'Are you sure you want to continue?',
ui.ButtonSet.YES_NO);
// Process the user's response.
if (result == ui.Button.YES) {
// User clicked "Yes".
spread.toast("Will update " + to_replace + " to " + replace_with + " ", "ALERT");
var data = range.getValues();//I think error is occurring here
var oldValue="";
var newValue="";
var cellsChanged = 0;
for (var row=0; row<data.length; row++) {
for (var item=0; item<data[row].length; item++) {
oldValue = data[row][item];
newValue = data[row][item].replace(to_replace, replace_with);
if (oldValue!=newValue)
{
cellsChanged++;
data[row][item] = newValue;
}
}
}
range.setValues(data);
spread.toast(cellsChanged + " cells changed", "STATUS");
}
else {
// User clicked "No" or X in the title bar.
spread.toast("No action taken", "ABANDONED");
}
}
I got this error :
TypeError: Impossible d'appeler la méthode "getValues" de undefined. (ligne 25, fichier "Code")
Could you help me I'm a noob
Regards
So apparently this line has a problem:
var range = sheet.getRange("'Feuille 1'!1:1137");
The range is the problem it should be something like 'Sheet1!A1:A1137'.
So may be this will work: var range = sheet.getRange("'Feuille 1'!A1:A1137");
Since I can't see your sheet you will have to determine the appropriate range.
Related
I have a google sheet with a dropdown menu. When the cell the drop down is in is equal to a certain string a pop up shows up on screen. You answer yes or no.
When you answer yes it sends the email. If you answer no it does not send the email and resets the cell to its previous state.
The issue I am having is that if you select no it does reset to the previous data, but it still sends the email regardless. Please help. I am fairly new and still learning.
UPDATE:
Please see the update below. The only var I had to fix was for rData, other than that the script works as intended now. Thank you so much for your time and input. This was a headache for some time.
function sendMailEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ui = SpreadsheetApp.getUi();
if (ss.getSheetName() == 'Project List' &
ss.getActiveCell().getColumn() == 3 &
ss.getActiveCell().getValue() == "_Complete") {
var alertPromptText = 'Are you sure you want to select Complete? ' +
'This action will notify all parties in the next process that this job is ready for fabrication.';
var promptResponse = ui.alert(alertPromptText, ui.ButtonSet.YES_NO);
if (promptResponse == ui.Button.YES) {
// CHECK START
// variable email needs to be fixed. It gets the column of values.
// it needs to be converted to a comma separated list of recepients
var email = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Email").getRange(1, 1, 100).getValues();
// CHECK END
var rData = e.source.getActiveSheet().getRange(e.range.rowStart,1,1,12).getValues();
sendEmail(email,rData);
} else { // For both 'No' and cancel response to pop-up
fix(e);
}
}
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
function sendEmail(email,rData) {
var first = 0;
var email = 1;
var emailTemp = HtmlService.createTemplateFromFile("send");
var ws = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Email");
var data = ws.getRange("A1:B" + ws.getLastRow()).getValues();
var lj = rData[0][1];
var j = rData[0][5];
var d = rData[0][3];
var p = rData[0][4];
var m = rData[0][7];
var desc = rData[0][11];
var now = new Date().toLocaleString("en-US");
var msg1 = "Laser Job Number: " + lj + " (" + now + ")" +
"\nProject Job Number: " + j +
"\nDesigner: " + d +
"\nDate Project was Submitted to Programming: " + p +
"\nMaterial used: " + m +
"\nDescription: " + desc;
var subject = "Project Ready for Fab";
Logger.log(msg1);
data.forEach(function(row){
emailTemp.fn = row[first];
emailTemp.msg = msg1;
emailTemp.j = j;
emailTemp.d = d;
emailTemp.lj = lj;
emailTemp.p = p;
emailTemp.m = m;
emailTemp.desc = desc;
//emailTemp.cart = cart;
const htmlMessage = emailTemp.evaluate().getContent();
GmailApp.sendEmail(row[email], subject, "Please open with an email client that supports HTML",
{htmlBody: htmlMessage});
return;
});
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
function fix(e) {
e.range.setNote(e.oldValue);
e.range.setValue(e.range.getNote());
e.range.clearNote();
}
You need to set a variable to capture the response to the pop-up.
And then compare the value of the variable for the go-no-go part of the script.
For example:
var response = ui.prompt('Alert', 'Are you sure you want to select Complete?', ui.ButtonSet.YES_NO);
And then
if (response.getSelectedButton() == ui.Button.YES) { ... }
More here in the documentation.
Update
Try the following script. You'll need to set the onEdit trigger to run the function SendMailEdit
Also, check the code for getting the list of email recepients. Not sure if it will work.
function sendMailEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ui = SpreadsheetApp.getUi();
if (ss.getSheetName() == 'Project List' &
ss.getActiveCell().getColumn() == 3 &
ss.getActiveCell().getValue() == "_Compvare") {
var alertPromptText = 'Are you sure you want to select Compvare? ' +
'This action will notify all parties in the next process that this job is ready for fabrication.';
var promptResponse = ui.alert(alertPromptText, ui.ButtonSet.YES_NO);
if (promptResponse.getSelectedButton() == ui.Button.YES) {
// CHECK START
// variable email needs to be fixed. It gets the column of values.
// it needs to be converted to a comma separated list of recepients
var email = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Email").getRange(1, 1, 100).getValues();
// CHECK END
var rData = ss.getRange(ss.getActiveCell().getRow(), 1, 1, 12).getValues();
sendEmail(email, rData);
} else { // For both 'No' and cancel response to pop-up
fix(e);
}
}
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
function sendEmail(email, rData) {
var lj = rData[0][1];
var j = rData[0][5];
var d = rData[0][3];
var p = rData[0][4];
var m = rData[0][7];
var desc = rData[0][11];
var now = new Date().toLocaleString("en-US");
var msg = "Laser Job Number: " + lj + " (" + now + ")" +
"\nProject Job Number: " + j +
"\nDesigner: " + d +
"\nDate Project was Submitted to Programming: " + p +
"\nMaterial used: " + m +
"\nDescription: " + desc;
Logger.log(msg);
GmailApp.sendEmail(email, "Project Ready for Fab", msg);
return;
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
function fix(e) {
e.range.setNote(e.oldValue);
e.range.setValue(e.range.getNote());
e.range.clearNote();
}
How I record an action for this function?
Basically I have to do this and others actions everyday and always is the same.
searching and replacing does not record in google sheets
That is right, the find and replace function is not accessible via Google App Scripts and is not therefore able to be recorded. You need to create your own code to accomplish a behavior similar to the behavior you want manually.
Here is one of many example ways of doing it: https://webapps.stackexchange.com/questions/104157/auto-find-and-replace-in-google-sheets-with-scripts
Thanks i used that code and i edited a litle bit.
function Herramienta() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('A1:A69').activate();
spreadsheet.getRange('A1:A69').splitTextToColumns();
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange("a2:a69");
var to_replace = "HH-";
var replace_with = "";
replaceInSheet(sheet,range, to_replace, replace_with);
function replaceInSheet(sheet, range, to_replace, replace_with) {
//Confirm
var ui = SpreadsheetApp.getUi();
var spread = SpreadsheetApp.getActiveSpreadsheet();
var result = ui.alert(
"Will update " + to_replace + " to " + replace_with + " ",
'Are you sure you want to continue?',
ui.ButtonSet.YES_NO);
// Process the user's response.
if (result == ui.Button.YES) {
// User clicked "Yes".
spread.toast("Will update " + to_replace + " to " + replace_with + " ", "ALERT");
var data = range.getValues();
var oldValue="";
var newValue="";
var cellsChanged = 0;
for (var row=0; row<data.length; row++) {
for (var item=0; item<data[row].length; item++) {
oldValue = data[row][item];
newValue = data[row][item].replace(to_replace, replace_with);
if (oldValue!=newValue)
{
cellsChanged++;
data[row][item] = newValue;
}
}
}
range.setValues(data);
spread.toast(cellsChanged + " cells changed", "STATUS");
}
else {
// User clicked "No" or X in the title bar.
spread.toast("No action taken", "ABANDONED");
}
}
}
I work with surveymonkey and when someone doesn't answer my question, my cell is filled with "Not Answered".
The goal is to merge multiple rows into one.
Possible solutions are:
I need a script to automatically find and replace. Which will replace (more precisely delete "Not Answered") with an empty cell. So my TEXTJOIN will work. I've tried some code but it doesn't work for the whole sheet.
The problem with the TEXTJOIN function (delimiter, ignore_empty, text1, [text2, ...]) is that the second parameter igrone_empty is boolean and only works with TRUE or FALSE and cannot write "Not Answered" there. So with this I have to find another solution to ignore or delete the word "Not Answered".
Alternative to TEXTJOIN where the word "Not Answered" is ignored.
Or if it is possible to delete this option in SurveyMonkey?
I have tried this solution but doesn't work for entire sheet/table.
var result = ui.alert(
"Will update " + to_replace + " to " + replace_with + " ",
'Are you sure you want to continue?',
ui.ButtonSet.YES_NO);
// Process the user's response.
if (result == ui.Button.YES) {
// User clicked "Yes".
spread.toast("Will update " + to_replace + " to " + replace_with + " ", "ALERT");
var data = range.getValues();
var oldValue="";
var newValue="";
var cellsChanged = 0;
for (var row=0; row<data.length; row++) {
for (var item=0; item<data[row].length; item++) {
oldValue = data[row][item];
newValue = data[row][item].replace(to_replace, replace_with);
if (oldValue!=newValue)
{
cellsChanged++;
data[row][item] = newValue;
}
}
}
range.setValues(data);
spread.toast(cellsChanged + " cells changed", "STATUS");
}
else {
// User clicked "No" or X in the title bar.
spread.toast("No action taken", "ABANDONED");
}
}
Try this:
function replaceNotAnswerWithBlank(e) {
var ss=e.source;
var sh=ss.getActiveSheet();
var rg=sh.getDataRange();
var tf=sh.createTextFinder('Not Answered').findAll();
for(var i=0;i<tf.length;i++) {
sh.getRange(tf[i].getRow(),tf[i].getColumn()).setValue('');
}
}
How about this:
function onOpen(e) {
replaceNotAnswerWithBlank(e);
}
I needed a trigger so this is how I solved the problem. If there is a simpler functional solution write it down. Thank you Cooper.
function onOpen() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
var rg=sh.getDataRange();
var tf=sh.createTextFinder('Not Answered').findAll();
replaceNotAnswerWithBlank(ss, sh, rg, tf);
}
function replaceNotAnswerWithBlank(ss, sh, rg, tf) {
for(var i=0;i<tf.length;i++) {
sh.getRange(tf[i].getRow(),tf[i].getColumn()).setValue('');
}
}
I have the following Google Script. It runs through a spreadsheet and imports information into a Google Calendar. However, I also want it to populate an array with the uploaded data and send it in a Google email. Is this possible? Here is what I have so far.
var MAINTENANCE_EXPORTED = "MAINTENANCE_EXPORTED";
var MAINTENANCE_ERROR = "MAINTENANCE_ERROR";
var ss = SpreadsheetApp.getActiveSpreadsheet();
function onOpen() {
var menuEntries = [{name: "Upload CS Maintenance Schedule", functionName: "importCalendarCS"}, {name: "Upload EP Maintenance Schedule", functionName: "importCalendarEP"}];
ss.addMenu("Maintenance Scripts", menuEntries);
}
//
//Coral Street Import Function
//
function importCalendarCS() {
var sheet = ss.getSheetByName('CS');
var startcolumn = 1; // First column of data to process
var numcolumns = sheet.getLastRow(); // Number of columns to process
var dataRange = sheet.getRange(startcolumn, 1, numcolumns, 13) // Fetch values for each column in the Range.
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) { // this is a "for loop" that asks the script to run through all rows.
var column = data[i];
var building = column[0]; // 1st column in spreadsheet "BLDG"
var cart = column[1]; // 2nd column in spreadsheet "CART OR LAB"
var room = column[2]; // 3rd column in spreadsheet "LOCATION OF CART OR ROOM"
var deviceType = column[3]; // 4th column in spreadsheet "TYPE OF DEVICES"
var deviceQuantity = column[4]; // 5th column in spreadsheet "# of Devices"
var maintenancePerson = column[5]; // 7th column in spreadsheet "Maintenance Person"
var maintenanceDate = column[6]; // 6th column in spreadsheet "Maint Date"
var maintenanceImported = column[13];
var title = building + " - " + room;
var description = "Building: " + building
+ "\n" + "Room: " + room
+ "\n" + "Cart: " + cart
+ "\n" + "Device Type: " + deviceType
+ "\n" + "Device Quantity: " + deviceQuantity;
var calendarName = "Cart Maint Schedule";
if (maintenancePerson == "Bobby Obvious") {
var email = "example#example.com"
}
else {
var email = "example#example.com"
}
if ((maintenanceImported != MAINTENANCE_EXPORTED) && (maintenanceImported != MAINTENANCE_ERROR) && (building != "BLDG") && (cart != "Cycle 1 Checklist") && (cart != "Cycle 2 Checklist")) { // Prevents importing duplicates
var cal = CalendarApp.openByName(calendarName);
var advancedArgs = {description: description, location: ("Cart: " + cart)};
var itsEmail = "example#example.com";
if
if (maintenanceDate != "") {
cal.createAllDayEvent(title, new Date(maintenanceDate), advancedArgs);
var sheet2 = ss.getSheetByName('CS');
sheet.getRange(startcolumn + i, 14).setValue(MAINTENANCE_EXPORTED);
SpreadsheetApp.flush();
}
else {
var sheet2 = ss.getSheetByName('CS');
sheet.getRange(startcolumn + i, 14).setValue(MAINTENANCE_ERROR);
SpreadsheetApp.flush();
}
}
}
}
Yes it's possible. Use the MailApp class.
https://developers.google.com/apps-script/reference/mail/mail-app
or the GmailApp Class:
https://developers.google.com/apps-script/reference/gmail/gmail-app
Try to use the MailApp.sendEmail method. It accepts an address.
Please anyone can help my? this is my code and throws We're sorry, a server error occurred. Please wait a bit and try again always.
The idea is take a sheet generic and another sheet and copy all data from a sheet to generic sheet.
function importData(id){
try{
var sheet = SpreadsheetApp.openById(id);
Logger.log("name of sheet: " + sheet.getName())
var sheetToImport = sheet.getSheetByName("planilla para carga de datos");
var sheetGeneric = DocsList.getFileById('0ArvYhlthIEV-dGxLOTI1MG5OSkI2SzRGRDhlendwcnc');
var newSheet = sheetGeneric.makeCopy(sheet.getName()+" V2");
var row = sheetToImport.getRange('A:Z');
var range = row.getA1Notation();
var values = row.getValues();
var ss = SpreadsheetApp.openById(newSheet.getId()).getSheetByName("planilla para carga de datos");
Logger.log("Valores a insertar: " + values)
var valuesNewSheet = ss.getRange(range).getValues();
Logger.log("Rango: " + range + "valores del sheet antes: " + valuesNewSheet);
ss.getRange(range).setValues(values);
Logger.log("valores del sheet dsp: " + ss.getRange(range).getValues());
Logger.log("new id: " + ss.getId());
}catch(e){
Logger.log("error: " + e )
return;
}
return ss.getId();
}
Changing the code to the following works with a plain new spreadsheet containing Sheet1, but sometimes I also get that server-error during the makeCopy-call. Added a retry for that and changed the lines containing ss.getId() to newSheet.getId() and added the stack-trace to the exception-logging.
function importData(id){
if (id==undefined) {
id="0AowkhKY0KeQAdDZCMXZPb2VOc1NoN2pFZk9Qd0xHNGc";
}
try{
var sheet = SpreadsheetApp.openById(id);
Logger.log("name of sheet: " + sheet.getName())
var sheetToImport = sheet.getSheetByName("Sheet1");
var sheetGeneric = DocsList.getFileById('0AowkhKY0KeQAdEZ0NFBkXzdMY05VVWFRa0J2bVJvelE');
var newSheet;
retried (5,"Permanent error while trying to copy sheet", function () {
newSheet = sheetGeneric.makeCopy(sheet.getName()+" V2");
});
var row = sheetToImport.getRange('A:Z');
var range = row.getA1Notation();
var values = row.getValues();
var ss = SpreadsheetApp.openById(newSheet.getId()).getSheetByName("Sheet1");
Logger.log("Valores a insertar: " + values)
var valuesNewSheet = ss.getRange(range).getValues();
Logger.log("Rango: " + range + "valores del sheet antes: " + valuesNewSheet);
ss.getRange(range).setValues(values);
Logger.log("valores del sheet dsp: " + ss.getRange(range).getValues());
Logger.log("new id: " + newSheet.getId());
}catch(e){
Logger.log("error: " + e +"\n"+e.stack)
return;
}
return newSheet.getId();
}
This server-errors sometimes happen and often it works when retrying after a short while. To easily repeat such a call, the following function is handy:
function retried (maxRetries, msg, f) {
var retries=0;
do {
try {
f ();
if (retries>0) {
Logger.log ("succeeded after "+retries+" retries for "+f);
}
return; // success;
}
catch(err) {
Logger.log ("catched "+err.toString()+"\n"+err.stack);
retries++;
Utilities.sleep (5000);
}
} while (retries<maxRetries);
Logger.log (msg);
throw msg;
}
which is used in the above code to retry the makeCopy-call