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();
Related
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 have the below spreadsheet that I would like to AutoFill the persons name. the issue is that there are blank rows between the names. Each name is in line with a sku2 and needs to be inline with all locations. there can be up to 10 blank rows (due to how many locations).
if I could loop this maybe
function LoopTillLr() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('A2').activate();
spreadsheet.getActiveRange().autoFillToNeighbor(SpreadsheetApp.AutoFillSeries.DEFAULT_SERIES);
spreadsheet.getCurrentCell().getNextDataCell(SpreadsheetApp.Direction.DOWN).activate();
};
Appreciate any help
If you only want to replicate the NAME values against variable LOCATION values then use this script:
function myFunction() {
var ss = SpreadsheetApp.getActiveSheet();
var lastRow = ss.getDataRange().getLastRow();
for (var i = 1; i < lastRow+1; i++) {
if (ss.getRange(i,1).getValue() == "") {
var value = ss.getRange(i-1,1).getValue();
ss.getRange(i,1).setValue(value);
}
}
}
Ensure that A2 is not empty else the script will fail.
If it is a lot of records, you can create a function and run it. The following does this until the end of the sheet, so make sure to delete all the rows towards the end which you do not need or adjust the range in the 2nd row.
function autoFillDown(){
const range = SpreadsheetApp.getActiveSheet().getRange("A:A");
const rows = range.getValues();
let outputArray = [];
rows.forEach( row => {
// if it contains a name, leave it
if( row[0].length > 1){
outputArray.push( [row[0]] )
// otherwise replace it with the value above it
} else {
outputArray.push( [outputArray[outputArray.length-1]] );
}
});
range.setValues( outputArray );
}
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");
}
})
I’m writing a custom function in Google Apps Script that, if a certain other cell contains a number, uses the value of that cell and several other cells to calculate a result. Otherwise, if that certain other cell does not contain a number, the function should just return an empty string so that the active cell appears blank.
I was able to come up with a working function to do this, but in order to protect sensitive information, I’m not going to copy it here. Instead, here’s an example function that accomplishes the same thing:
function myFunction() {
var sheet = SpreadsheetApp.getActiveSheet();
var rowNum = sheet.getActiveCell().getRow();
var rowVals = sheet.getRange(rowNum, 1, 1, 15).getValues();
var fVal = rowVals[0][5];
if (fVal == "" || isNaN(fVal)) {
return ""; //leave cell blank if column F doesn't contain a number
}
var aVal = rowVals[0][0];
var bVal = rowVals[0][1];
var cVal = rowVals[0][2];
var gVal = rowVals[0][6];
return ((gVal * fVal) + aVal + bVal + cVal);
}
However, in an effort to speed it up (and also some other reasons that would be complicated to try to explain here, so you'll have to just trust me), I want to have the custom function set the value of the cell to be a formula instead of doing the calculating itself. It doesn’t work to just put the formula in the cell in the first place because then it still calculates/shows a result even if column F doesn’t contain a number.
Here’s what I’ve tried so far:
function myFunction2() {
var sheet = SpreadsheetApp.getActiveSheet();
var rowNum = sheet.getActiveCell().getRow();
var fVal = sheet.getRange(rowNum, 6).getValue();
if (fVal == "" || isNaN(fVal)) {
return ""; //leave cell blank if column F doesn't contain a number
}
var formula = '=SUM((G2*F2)+A2+B2+C2)';
return formula;
}
^This just makes the cell display the string “=SUM((G2*F2)+A2+B2+C2)”.
So I then tried using setFormula on the active cell:
function myFunction3() {
var sheet = SpreadsheetApp.getActiveSheet();
var cell = sheet.getActiveCell();
var rowNum = cell.getRow();
var fVal = sheet.getRange(rowNum, 6).getValue();
if (fVal == "" || isNaN(fVal)) {
return ""; //leave cell blank if column F doesn't contain a number
}
cell.setFormula('=SUM((G2*F2)+A2+B2+C2)');
}
^which, when I called the function in a cell, returned an error saying “You do not have permission to call setFormula”. The same thing happened when I tried getting the a1 notation of the active cell and then using getRange(a1Notation).setFormula('=SUM((G2*F2)+A2+B2+C2)') instead of calling setFormula directly on the active cell.
Anybody know if there's a way around that permission error? or have any other ideas for how to accomplish this?
The permission error is because of restrictions on what user defined functions can do. You can, however, do this with onEdit like this:
function onEdit(e) {
var ss=SpreadsheetApp.getActiveSpreadsheet()
var s=ss.getActiveSheet();
var col = e.range.getColumn();
var rowNum = e.range.getRow();
if(col==6){
var fVal = s.getRange(rowNum,col,1, 1).getValue()
}
if (fVal == "" || isNaN(fVal)) {
return
}
else{
s.getRange(rowNum,col,1, 1).setFormula('=SUM((G2*F2)+A2+B2+C2)');
}}
I actually ended up figuring out a way to accomplish what I wanted using the built-in IF function, so that's what I did.
I have a spreadsheet with the following script that adjusts the view rows according to a variable:
function ConditionalHideRow() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Form responses 1");
var maxrows = sheet.getMaxRows()
for (var i = 0; i < maxrows; ++i) {
if (sheet.getRange(maxrows-i,4).getValue() == "var1" ) {
sheet.hideRows(maxrows-i,1)
}
else
{
sheet.showRows(maxrows-i,1)
}
}
}
I want to pass a variable in the page that adjusts the view:
for example
if I pass var1 in the URL for example, the rows containing var1 are
shown, all the others are not
if I pass var2 in the URL for example,
the rows containing var2 are shown, all the others are not
etc
I have tried function doGet(e) var viewmode = e.parameter.view but doesn't seem to work when I am passing ....?view = "a"
To pass "a" to the doGet() in the URL query it like this ...?view=a; no need in the apostrophes.
Sample
function doGet(e){
var parameter = e.parameter;
if(parameter.view){ //check off the view type was passed
ConditionalHideRow(parater.view);
};
}
function ConditionalHideRow(condition){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Form responses 1");
var maxrows = sheet.getDataRange().getHeight();
for (var i = 0; i < maxrows; ++i) {
if (sheet.getRange(maxrows-i,4).getValue() == condition ) {
sheet.hideRows(maxrows-i,1);
}
else
{
sheet.showRows(maxrows-i,1);
};
}
}
This is off topic, but getDataRange().getHeight() i my experience is better to use, since getMaxRows() will return you a total number of rows, even if they are empty.
By default there is a 1000 empty rows, and even though you don't have any data there, you will still loop through it. getDataRange().getHeight() will give you a number of the last row where any piece of data appears.
Also, I am just curious, why are you looping backwards through the rows?