Google Sheet Script to convert values to Lowercase - javascript

New to scripting, trying to use the OnEdit() to force lowercase on values in column E
started with a few iteration of the following with no succes...
function onEdit(e) {
var range = e.range;
var value = range.getValue();
if (range.getColumn() = 5 ) {
e.range.setValue(e.value.toLowerCase());
} else {
return;
}
}
Any easy tweak you can think of to force lowercase on edits in cloumn E?
Thank you,
JF

function onEdit(e) {
if (e.range.columnStart == 5) {
e.range.setValue(e.value.toLowerCase());
}
}
Generally scripts limit there activity to a specific set of pages and rows. I suppose you are aware that this trigger will be running for all of your tab/sheets.

Related

Running an onEdit Script on selected sheets only

I am new to coding Scripts but have managed to copy and edit (bodge...) a script that will onEdit, put a custom timestamp into the cell next to the cell where the edit took place. The script targets x2 onEdit columns (3,6), timestamping the cell offset(-1).
The workbook has developed to include multiple sheets now, most of which this script is not appropriate to run on, but I cannot figure out how to specify which sheets it should run on.
The below is the script I have cobbled together which works across all sheets, which I would now like to restrict to specific sheets only.
function onEdit(e) {
var colsToWatch = [3,6],
offset = [-1,-1],
ind = colsToWatch.indexOf(e.range.columnStart);
if (ind === -1 || e.range.rowStart === 1) return;
e.range.offset(0, offset[ind])
.setValue(!e.value ? null : Utilities.formatDate(new Date(), "GMT+1", "dd MMM yyyy HH:mm.ss"))
}
Please can someone help me by providing the code to run the scripts on specific sheets only. I would also be grateful for any suggestions of a simpler script to achieve the same aim, especially if it eliminates the timestamp being overwritten if the onEdit cell is subsequently edited after the initial edit.
Many thanks!!
function onEdit(e) {
const sh = e.range.getSheet();
const shts = ['Sheet1','Sheet2'];
const idx = shts.indexOf(sh.getName());
if(~idx ) {
//Whatever code you put here will only run on Sheet1 or Sheet2
}
}
This works for me (on on Sheet1 and Sheet2):
function onEdit(e) {
//e.source.toast('entry');
const sh = e.range.getSheet();
const shts = ['Sheet1','Sheet2'];
const idx = shts.indexOf(sh.getName());
if(~idx ) {
let rg = sh.getRange(e.range.rowStart,9);
if(rg.isBlank()) {
rg.setValue(new Date());
}
}
}
JavaScript Reference

Check if a column header title matches a string and if so then return the column index

I am trying to write a script for google sheets which returns the date in the next cell when the user enters 'y' in the current cell. I have a script which does this already, but the problem with my script is that the columns which it is evaluating is based on the column index, which means if our data set ever grows then these columns always have to stay in the same index which is creating a lot of organizational issues.
My question is..
Is it possible to look for the column header title rather than the column index in my code, and if so, what changes would I need to make?
function onEdit(e) {
if ([19].indexOf(e.range.columnStart) == -1 || ['y', 'Y'].indexOf(e.value) == -1) return;
e.range.offset(0, 1)
.setValue(Utilities.formatDate(new Date(), "GMT-5", "MM-dd-yyyy"))
}
This code currently looks at column index 19 and when either 'y' or 'Y' is entered into a cell in column index 19 it then outputs the date in the next cell in column 20.
How can I change the code to look for where the column header = 'Replied?' rather than index?
Goal:
If the following criteria is met:
Value is written into column 19 (S).
Header of column 19 (S) is 'Replied?'.
Value written is either 'Y' or 'y'.
Then write a date into the adjacent cell.
Code:
function onEdit(e) {
var sh = e.source.getActiveSheet();
var row = e.range.getRow();
var col = e.range.getColumn();
var value = e.value.toUpperCase();
var header = sh.getRange(1, col).getValue();
if (col === 19 && value === 'Y' && header === 'Replied?') {
sh.getRange(row, 20).setValue(Utilities.formatDate(new Date(), "GMT-5", "MM-dd-yyyy"))
}
}
Explanation:
I've based everything on the event objects passed to your onEdit trigger. For var value I have used toUpperCase() so that we don't have to check for either 'Y' OR 'y', only 'Y' alone. Also, instead of using range.offset I have just specified column 20 specifically in the getRange().setValue().
References:
Event Objects
String.toUpperCase()
One possible way to do this is to name the column/ cell in google sheets. See this website on how to.
Basically:
Open a spreadsheet in Google Sheets.
Select the cells you want to name.
Click Data and then Named ranges. A menu will open on the right.
Type the range name you want.
To change the range, click Spreadsheet Grid.
Select a range in the spreadsheet or type the new range into the text box, then - click Ok.
Click Done.
You can then refer to that named cell in google scripts by creating a custom function
function myGetRangeByName(n) { // just a wrapper
return SpreadsheetApp.getActiveSpreadsheet().getRangeByName(n).getA1Notation();
}
Then, in a cell on the spreadsheet:
myGetRangeByName("Names")
I'd do this.
function onEdit(e) {
var editedColumn = e.range.columnStart;
var sh = SpreadsheetApp.getActiveSpreadsheet();
var ss = sh.getSheetByName("This");//you only want onedits to the specific page
var data = ss.getDataRange().getValues();
var header = data[0][editedColumn];
if (header != "Replied") return;
if(e.value.toLowerCase() == "y"){
e.range.offset(0, 1)
.setValue(Utilities.formatDate(new Date(), "GMT-5", "MM-dd-yyyy"));}
}
You could also consider using a checkbox, that might be faster for your users.

Edit script to apply across all sheets

This is the script that I am using currently. I want it to apply to all sheets in my document automatically. Please help. The following is the code.
/**
* Creates a Date Stamp if a column is edited.
*/
//CORE VARIABLES
// The column you want to check if something is entered.
var COLUMNTOCHECK = 1;
// Where you want the date time stamp offset from the input location. [row, column]
var DATETIMELOCATION = [0,1];
// Sheet you are working on
var SHEETNAME = '46'
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
//checks that we're on the correct sheet.
if( sheet.getSheetName() == SHEETNAME ) {
var selectedCell = ss.getActiveCell();
//checks the column to ensure it is on the one we want to cause the date to appear.
if( selectedCell.getColumn() == COLUMNTOCHECK) {
var dateTimeCell = selectedCell.offset(DATETIMELOCATION[0],DATETIMELOCATION[1]);
dateTimeCell.setValue(new Date());
}
}
}
I want the script to execute on every sheet so that whenever I add a new sheet the script runs automatically and helps me add a time stamp to column two when I add a value to column 1.
Please help.
I am a complete noob here and as such some detailed explanation will help me immensely.
Basically, just remove the if statement and the code will apply to EVERY sheet.
In the answer given below, I've also used some of the objects returned by the onEdit trigger.
/**
* Creates a Date Stamp if a column is edited.
*/
//CORE VARIABLE
// The column you want to check if something is entered.
var COLUMNTOCHECK = 1;
function onEdit(e) {
var sh = e.range.getSheet();
if (e.range.columnStart == COLUMNTOCHECK){
// edited the right column do something
var targetcell = sh.getRange(e.range.rowStart,2);
targetcell.setValue(new Date());
}
else {
// do nothing
}
}

Automatic sort multiple columns once entire row of data is entered

I have designed a google spreadsheet to help improve efficiency of material flow. I want to automatically sort the data by 2 different columns to prioritize critical parts that need to be received first once the entire row of data is entered. The problem I am having is that the data is sorting as soon as you enter one of the columns I am calling to sort but the columns I want to sort are not the last column of that row of data that needs to be entered. I am trying to use an if statement to not execute the sort until the last column has been entered else throw an error statement that says you must enter data in this column to proceed. Logically, the code makes sense to me but I have only an adequate understanding of computer language. I keep receiving an error in line 10 that the range is not found. I believe my error is the syntax in trying to call the last column. Any help would be greatly appreciated
**function autosort(){
// Variable Declaration
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var NewsheetName = SpreadsheetApp.getActiveSheet().getName();
var sheetName = sheet.getSheetByName(NewsheetName);
var lastCol = sheetName.getLastColumn();
var lastColBlank = SpreadsheetApp.getActiveSheet().getRange(lastCol).isBlank()
// Find range to sort
var range = sheetName.getRange("A2:G");
// Sorting algorithm
if (lastColBlank == false ){
range.sort([6,5]);
}
else {
throw ("error: If trailer # is unavailable, please enter N/A");
}
}**
Try this code:
function onEdit() {
var sh = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var editedCell = sh.getActiveRange().getColumnIndex();
if(editedCell == 2) {
var range = sh.getRange("A2:B10");
var blank = range.isBlank()
var values = range.getValues();
Logger.log(values)
for (var i = 0; i<values.length; i++) {
//values.length returns 11 for eleven items
// values[10][0] would be the 11th row 1st column
Logger.log(values[i][1])
if (values[i][0] == "" || values[i][1] == "") {
//throw new Error("error: If trailer # is unavailable, please enter N/A");
var ui = SpreadsheetApp.getUi();
var response = ui.alert('If trailer # is unavailable, please enter N/A');
}else{
range.sort({column: 2});
}
}
}
}
If you'll look into the code, the sort depends on the second column to be edited. Then, will check the range if the is still a blanked cell.
Just apply your additional code to meet your goal and I think that will work.
Hope this helps.

Google Sheets Wildcards in if statements

I have a Google Sheet that has form responses. The e-mail address was not required, however it should have been. Either way, I am trying to back-fill the e-mail addresses (in order to make them ready to import as Spiceworks tickets, but I digress). I am going through and typing in usernames, but I want Sheets to auto-fill the domain. I was thinking I could do this by having it detect that the string ended in #, and then just adding the domain to it. Currently I have:
// assumes source data in sheet named Done 14-15
// test column with done is col 9 or I
if(s.getName() == "Done 14-15" && r.getColumn() == 9 && r.getValue() == "?#" ) {
var row = r.getRow();
var value = r.getValue();
r.setValue(value + "example.org");
var numColumns = s.getLastColumn();
s.getRange(row, 1, 1, numColumns).copyTo(target);
}
As you can see, I have a question mark for a wildcard. I have tried using an asterisk or a percentage sign as well, and not gotten anywhere. It will replace if I have literally ?# in there, but I want it to take anything# and append our domain.
RegEx should solve your problem.
Replace the r.getValue() == "?#" with
var regEx = new RegExp('.*#$')
if (regEx.test(r.getValue())) {
// your code
}
Instead of r.getValue() == "?#" you can write r.getValue().endsWith("#")
The email addresses can be easily updated like this:
var newValue = event.value.replace(/#$/,'#example.org');
Where the match is not found, the replacement will not happen... and newValue will equal the original value. Instead of checking for the match before deciding to do something, I'm suggesting doing it then checking the result.
Since you are entering the email addresses by hand, this is a good application of the onEdit() simple trigger and its event object.
function onEdit(event) {
var r = event.range;
var s = r.getSheet();
if (s.getName() == "Done 14-15" && r.getColumn() == 9 && r.getRow() > 1) {
// Replace an # at the end of the string with domain
var newValue = event.value.replace(/#$/,'#example.org');
// If value changed, write it back to spreadsheet
if (event.value !== newValue) {
event.range.setValue(newValue);
}
}
}
If you have rows that have already been edited and need to be checked, this function will take care of them. It uses the technique from How can I test a trigger function in GAS? to create a fake event, then passes it to the onEdit() trigger function.
// Call onEdit for each row in conversion sheet
function convertAllEmails() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName( "Done 14-15" );
var lastRow = sheet.getLastRow();
for (var row=1; row<lastRow; row++) {
var fakeEvent = {
range: sheet.getRange(row,9);
value: range.getValue();
};
onEdit( fakeEvent );
}
}

Categories