I've got a script that saves data from cells to a seperate sheet then clears the cells.
I'd like to add in a message box/error pop up or something that let's the user know there is a blank cell and to fill it out.
This would ideally stop the script from saving the data to prevent duplicate entry.
My current script is this
function submitData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formSS = ss.getSheetByName("Form");
var datasheet = ss.getSheetByName("Data");
var values = [[formSS.getRange("C3").getValue(),
formSS.getRange("C5").getValue(),
formSS.getRange("C7").getValue(),
formSS.getRange("C9").getValue(),
formSS.getRange("C11").getValue(),
formSS.getRange("C13").getValue()]];
datasheet.getRange(datasheet.getLastRow()+1, 1, 1, 6).setValues(values);
Browser.msgBox('Entry Captured - Thank you come again!')
var sheet = SpreadsheetApp.getActive().getSheetByName('Form');
sheet.getRange('C3:C9').clearContent();
}
You can add this blank value check for the values array.
values[0].forEach(function(val) {
if (val === "") {
Browser.msgBox("Required Cell is empty");
return;
}
})
This is a typical use case for array.some:
//if some values are empty strings
if(values[0].some(val => val === '')) throw new Error("All fields are compulsory");
//Create a seperate list of values that you want required and name it required.
//This will loop in the required fields and send an error message if one is missing.
var REQUIRED = [[formSS.getRange("C3").getValue(),
formSS.getRange("C5").getValue(),
formSS.getRange("C7").getValue(),
formSS.getRange("C9").getValue()]];
REQUIRED[0].forEach(function(val) {
if (val === "") {
throw new Error("Please fill in all the required fields");
}
})
Related
The script, that I will post below, allows me to use a check box to move an entire row from one sheet to another in the same workbook. Everything works (I was following a YouTube tutorial), but it moves the entire row of data. Instead, I need it to move only data from specific columns, i.e. move the info from column A to C or move the info from column A and column K. I know this might be a simple question, but I just don't know which line to modify and how to modify it so that the script only pulls the info from specific columns within the row to move to the other sheet.
function sendMail() {
var client = 3;
var date = 0;
var email = 19;
var dnr = 18;
var emailTemp = HtmlService.createTemplateFromFile("email");
var ws = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Promos");
var data = ws.getRange("A3:T" + ws.getLastRow()).getValues();
data = data.filter(function(r){return r[1] == true })
data.forEach(function(row){
emailTemp.client = row[client];
emailTemp.date = row[date];
emailTemp.dnr = row[dnr];
var htmlMessage = emailTemp.evaluate().getContent();
GmailApp.sendEmail(row[email],
"Promo Reminder",
"Your email does not support html",
{name: "JV Ops", htmlBody: htmlMessage}
);
});
}
I tried to modify the line "var row = range.getRow()" by putting column letters in the parenthesis but it didn't do anything, not only did it not move the info from those specific columns but it no longer moved the entire row. It just no longer did anything.
You have a spreadsheet in which a "checked" checkbox identified the row(s) that are to be sent an email. However you can't identify the actual row number of the checked checkbox.
There are two issues in your script:
data = data.filter(function(r){return r[1] == true }) replaces the array that contains ALL the data on the sheet with just those rows that contain checked checkboxes.
you need to compare the new filtered array with the original array in order to get the row numbers. I adapted the method described in StackOverflow compare rows on google spreadsheets
the array equalRows contains the row numbers/indexes that contain checked checkboxes.
the OP can use the row number together with the mailData array to copy data on the relevant row.
function myFunction() {
var ws = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Promos")
var data = ws.getRange("A3:T" + ws.getLastRow()).getValues();
// Logger.log(data) // DEBUG
var mailData = data.filter(function(r){return r[1] == true })
// Logger.log(mailData) // DEBUG
// compare rows on google spreadsheets
// https://stackoverflow.com/a/34960630/1330560
var equalRows = [];
for(var i in data){
var anEqualRow = false;
for(var j in mailData){
if(data[i].join() == mailData[j].join()){
anEqualRow = true;
}
}
if(anEqualRow){
var row = +i+3
equalRows.push(row);
}
}
// Logger.log(equalRows) // DEBUG
}
I have cell range. First column have content. Second column have check box. See first picture.
I try to clear content Infront of unchecked boxes.
function clearCon() {
var ss = SpreadsheetApp;
var sheet =ss.getActiveSpreadsheet().getSheetByName("AddData");
var chkVal = sheet.getRange("A29:B33").getValues();
Logger.log(chkVal);
Logger.log(chkVal.length);
for(var i=0; i<=chkVal.length; i++){
if(chkVal[i][1] == false){
Logger.log(i);
sheet.getRange(28,1,i+1,1).clearContent();
return;
}
}
}
See this picture
it's not correctly work. How to do this?
Description
First your script and picture of script don't match, so I'm not sure which one you are currently using.
Second, your for loop should be i<chkval.length.
Third, there should not be a return in your for loop.
Fourth, your sheet.getRange(29+i, 1).clearContent()
And lastly, if there are no formulas in the range you specified I would use setValues() as shown below.
Script
function clearCon() {
try {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName ("AddData");
var chkval = sheet.getRange("A29:B33").getValues();
// test for true or false
chkval.forEach( row => row[0] = row[1] ? row[0] : '' );
// extract column A
chkval = chkval.map( row => row.slice(0,1) );
console.log(chkval);
sheet.getRange(29,1,chkval.length,1).setValues(chkval);
}
catch(err) {
console.log(err);
}
}
References
https://www.w3schools.com/jsref/jsref_foreach.asp
https://www.w3schools.com/jsref/jsref_map.asp
https://developers.google.com/apps-script/guides/support/best-practices
You are only clearing the row 28 with your current code because you of sheet.getRange(28, 1, …). So in your forward loop, you are not moving down the rows. To fix this issue, just do sheet.getRange(29+i,1).clearContent().
Hello I am currently working on a time tracking system. With the following code I track the time how long a value was in a cell. This time is recorded in another worksheet and this is done continuously by appendRow ().
function onEdit(e) {
addTimestamp(e);
}
function addTimestamp(e) {
var ui = SpreadsheetApp.getUi();
var ws = "Tabellenblatt2";
var ss = e.source;
var targetSheet = ss.getSheetByName("Tabellenblatt1");
var range = targetSheet.getRange(3, 2, 1000, 1);
var currentDate = new Date();
if (e.source.getActiveSheet().getName() === ws && range != "") {
var val = e.range.getValue();
if (val != "") {
let rowToAdd = [val, "", currentDate, ""]
ss.getSheetByName("Tabellenblatt1").appendRow(rowToAdd);
ui.alert("Test2");
} else {
var sheet = ss.getSheetByName("Tabellenblatt1");
var dataFinder = sheet.createTextFinder(e.oldValue);
var nameRow = dataFinder.findAll()[0].getRow();
sheet.getRange(nameRow, 4).setValue(currentDate);
ui.alert("Test3");
}
}
}
Currently I cannot delete the content of the cell with the delete key, otherwise e.oldValue is undfined and I cannot get the date in the first worksheet. Now I always have to go to the formula area, mark the text in the cell and delete it. Is there a way to use the whole thing with the delete key anyway?
Unfortunately you cannot have the property oldValues if you use del or backspace button. According to Tanaike's comment here, there are certain scenarios where values and oldValues would appear in the event object.
In the case for editing a value to empty cell
e.value is included in e.
e.oldValue is NOT included in e.
In the case for overwriting a cell with a value by other value
Both e.value and e.oldValue are included in e.
In the case for deleting a value from a cell with a value
Both e.value and e.oldValue are NOT included in e.
Values of event object in multiple scenarios:
Adding value to an empty cell:
Overwriting a cell:
Deleting a value from a cell with a value:
A workaround would be creating a macro or button that will save and delete the value of the cell.
Example:
Code:
// this function will delete and display value of the active cell
function deleteCell(){
var sh = SpreadsheetApp.getActiveRange();
var oldValue = sh.getValue();
sh.clear();
Browser.msgBox(oldValue);
}
Button:
References:
Creating macros in Apps Script
Add A Google Sheets Button To Run Scripts
I'm working on the script below (keep in mind that it's far from done):
function Import() {
var dealCells = getRange('Deals');
var blank = new Array ("");
if (blank.indexOf(dealCells.getValue()) != -1) {
if (Browser.msgBox('You have not entered all the Deal IDs, do you want to continue anyway?', Browser.Buttons.YES_NO) == 'no') {
Browser.msgBox('Please fill in all the Deal IDs')
if (blank.indexOf(dealCells.getValue()) == -1) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Worksheet");
var cell = sheet.getRange(2,12);
cell.setValue("IMPORT");
}
}
}
}
I'm trying to determine whether or not there is an empty cell in the range A4:A23 in the worksheet 'Newsletter'.
If there is an empty cell: prompt the yes/no message box
If yes: continue with setting the cell value to 'IMPORT' and finish the script without further actions
If no: prompt the second message box and finish the script without any further action
Assuming that dealCells is A4:A23:
function Import() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName('Newsletter');
// Get range values
var dealCells = sh.getRange("A4:A23").getValues()
// Flatten array for `indexOf()`
var blank = dealCells.join().split(',');
if (blank.indexOf("") != -1) { // Check if there is a blank cell
// If a blank cell exist
var response = Browser.msgBox('You have not entered all the Deal IDs, do you want to continue anyway?', Browser.Buttons.YES_NO)
// Handle the msgBox response
if (response == "yes") {
var value = Browser.msgBox('Please fill in all the Deal IDs')
} else { //response == no
...
}
} else { // no blank cell
...
}
...
}
edit you can also getRangeByName():
var ss = SpreadsheetApp.getActiveSpreadsheet();
var dealCells = ss.getRangeByName('Deals').getValues();
I just wanted to know if there was a way to pull multiple (only 2 at the most) results with the code provided below. All the code is doing is searching for a user's name in a spread sheet and then displaying the value in the cell next to that user's name. The slight issue I'm running into now is that their name might appear twice in a given column and I would like for both results to be displayed. Any help would be appreciated. The full explanation of what this code is used for can be found here if needed: VLOOKUP style app script using UiApp and textBox form to reference a spreadsheet
// function called when submit button is clicked
function submit(e) {
var app = UiApp.getActiveApplication();
Logger.log(Utilities.jsonStringify(e)); // Log the input parameter (temporary)
// Write the data in the text boxes back to the Spreadsheet
var cell = e.parameter.userName;
var doc = SpreadsheetApp.openById('SPREADSHEET-ID');
var ss = doc.getSheets()[0];
var lastRow = doc.getLastRow();
var data = ss.getRange(2, 1, 2, 4).getValues();
var result = "User not found";
for (nn = 0; nn < data.length; ++nn) {
if (data[nn][1] == cell) {
result = data[nn][1];
break
}; // if a match in column B is found, break the loop
}
// Make the status line visible and tell the user the possible actions
app.getElementById('status').setVisible(true).setText(result);
return app;
}
All you need to do is modify the behavior of the search loop. Perform the search, adding finds to an array, and get rid of the break that was terminating a search after finding one item. At the end of the search, join the array of finds into a string, and you're done.
// function called when submit button is clicked
function submit(e) {
var app = UiApp.getActiveApplication();
Logger.log(Utilities.jsonStringify(e)); // Log the input parameter (temporary)
// Write the data in the text boxes back to the Spreadsheet
var cell = e.parameter.userName;
var doc = SpreadsheetApp.openById('SPREADSHEET-ID');
var ss = doc.getSheets()[0];
var lastRow = doc.getLastRow();
var data = ss.getRange(2, 1, 2, 4).getValues();
var result = "User not found";
var result_array = [];
for (nn = 0; nn < data.length; ++nn) {
if (data[nn][1] == cell) {
result_array.push( data[nn][1] );
}; // if a match in column B is found, keep going, there may be more!
}
if (result_array.length > 0)
result = result_array.join(", "); // concatenate multiple results
// Make the status line visible and tell the user the possible actions
app.getElementById('status').setVisible(true).setText(result);
return app;
}