Is there a way to format a checkbox so that when it is "checked", The data in the column beside it will be moved to another column?
function onEdit(e) {
const sh = e.range.getSheet();
if (sh.getName() == 'Sheet1' && e.range.columnStart == 1 && e.value == 'TRUE') {
e.range.offset(0, 5).setValue(e.range.offset(0, 1).getValue());
e.range.offset(0, 1).setValue('');
e.range.setValue('FALSE');
}
}
As player0 mentioned, for this to work, you need Google Apps Script's Spreadsheet Service with the help of Event Objects.
The code below should work on the sample data below.
Sample data:
Code:
function onEdit(e) {
var sheet = e.source.getActiveSheet();
var range = e.range;
var column = range.getColumn();
// if edited data is in Sheet1 Column A and having value TRUE (checkbox ticked)
if (sheet.getName() == "Sheet1" && column == 1 && e.value == "TRUE") {
// get 1 column to the right of checkbox and assign to dataValue
var dataRange = range.offset(0, 1);
var dataValue = dataRange.getValue();
// get 3 columns to the right of dataValue and assign to transferToRange
var transferToRange = dataRange.offset(0, 3);
// set dataValue as value to transferToRange
transferToRange.setValue(dataValue);
// remove data from dataRange after
dataRange.setValue("");
}
}
Output:
Note:
Above code is just one of the many possible solutions you can create via Apps Script.
Read Apps Script for more information.
References:
Spreadsheet Service
Event Objects
Related
I am having 2 google sheet, having checkbox on 1st Sheet.
Requirement: When the checkbox is checked , Value from Cell C5 need to be stored in the Sheet2. When the checkbox is checked i.e value is 'True', the value in cell C5 of the Sheet1 needs to be submitted in the Sheet2 in the continuous manner.
I know this is the silly requirement, but I failed after several attempts as well.
Try
function onEdit(event) {
var sh1 = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if (sh1.getName() == 'Sheet1' && r.getA1Notation() == 'D5' && r.getValue() == true) {
var sh2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet2')
sh2.getRange('A' + (sh2.getLastRow() + 1)).setValue(r.offset(0, -1).getValue())
r.setValue(!r.getValue())
}
}
Store C5 in Sheet2 When Checkbox is checked
function onEdit(e) {
var sh1 = e.range.getSheet();
if (sh1.getName() == 'Sheet1' && e.range.columnStart == 4 && e.range.rowStart == 5 && e.value == "TRUE") {
var sh2 = e.source.getSheetByName('Sheet2');
sh2.getRange(sh2.getLastRow() + 1, 1).setValue(e.range.offset(0, -1).getValue());
e.range.setValue("FALSE");
}
}
I am quite bad at this stuff, I tried searching and have a somewhat workable script (apps script) but I just can't get it to work the way I want it to. I'm sure I added/edited things wrongly.
My Google sheet is a group work tracker and looks like the image below.
The primary need is to add an alert message when someone checks or unchecks any of the checkboxes in those columns (to prevent any misclicks - like so ). We are using custom cell values for checked and unchecked as "1" and "0" respectively. The columns with checkboxes are F,K,P,R,S.
In addition to that, I would like a timestamp (format dd/mm/yyyy) to be populated 2 columns away when any of the checkboxes in columns F&K are checked (and confirms the alert message). However, when an already ticked checkbox is unticked, the date should not be removed or updated.
The below script works to a certain extent, but I don't know how to amend it.
function onEdit(e) {
const sh=e.range.getSheet();
if(sh.getName()=='Video Projects' && e.range.columnStart==6,11,16,18 && e.value=='1') {
var resp=SpreadsheetApp.getUi().alert('Are you sure you want to tick this checkbox?', SpreadsheetApp.getUi().ButtonSet.YES_NO);
if(resp==SpreadsheetApp.getUi().Button.YES) {
var range = e.range;
var sheet = range.getSheet();
if(sheet.getSheetName() == "Video Projects") {
if(range.columnStart == 6) {
var nextCell = range.offset(0, 2);
nextCell.setValue(new Date());
} else if(range.columnStart == 11 && range.isChecked()) {
var nextCell = range.offset(0, 2);
nextCell.setValue(new Date());
}
}
};
}else{
e.range.setValue("0");
}
}
If anyone knows how to fix this, it would be really helpful! :)
I believe your goal is as follows.
You want to check the checkboxes of the columns F,K,P,R,S.
When the checkboxes of columns "F" and "K" are clicked, you want to put the date to the column "H" and "M", respectively.
Modification points:
When e.range.columnStart==6,11,16,18 is used as the if statement, all values of e.range.columnStart are true. I thought that this might be the reason of your issue.
When this point is reflected in your script, it becomes as follows.
Modified script:
function onEdit(e) {
const columns = [6, 11, 16, 18, 19]; // columns F,K,P,R,S
const { range, value } = e;
const sheet = range.getSheet();
if (sheet.getSheetName() != 'Video Projects' || !columns.includes(range.columnStart) || value == "0") return;
const ui = SpreadsheetApp.getUi();
const res = ui.alert('Are you sure you want to tick this checkbox?', SpreadsheetApp.getUi().ButtonSet.YES_NO);
if (res == ui.Button.YES) {
if (range.columnStart == 6 || (range.columnStart == 11 && value == "1")) {
range.offset(0, 2).setValue(new Date());
}
return;
}
range.uncheck();
}
References:
Simple Triggers
Event Objects
Added 1:
About your following 2 new requests,
Request 1: could we also add the alert message when unchecking a checkbox too?
Request 2: Is it possible for it to input only the date as dd/mm/yyyy?
The sample script is as follows.
Sample script:
function onEdit(e) {
const columns = [6, 11, 16, 18, 19]; // columns F,K,P,R,S
const { range, value } = e;
const sheet = range.getSheet();
if (sheet.getSheetName() != 'Video Projects' || !columns.includes(range.columnStart)) return;
const ui = SpreadsheetApp.getUi();
const res = ui.alert('Are you sure you want to tick this checkbox?', SpreadsheetApp.getUi().ButtonSet.YES_NO);
if (res == ui.Button.YES) {
if (range.columnStart == 6 || (range.columnStart == 11 && value == "1")) {
range.offset(0, 2).setValue(Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "dd/MM/yyyy"));
}
return;
}
range.uncheck();
}
Added 2:
About your following a new request,
Request 1: can be changed to "Are you sure you want to untick this checkbox?"
The sample script is as follows.
Sample script:
function onEdit(e) {
const columns = [6, 11, 16, 18, 19]; // columns F,K,P,R,S
const { range, value } = e;
const sheet = range.getSheet();
if (sheet.getSheetName() != 'Video Projects' || !columns.includes(range.columnStart)) return;
const ui = SpreadsheetApp.getUi();
if (value == "0") {
const res = ui.alert("Are you sure you want to untick this checkbox?", SpreadsheetApp.getUi().ButtonSet.YES_NO);
if (res == ui.Button.NO) range.check();
return;
}
const res = ui.alert('Are you sure you want to tick this checkbox?', SpreadsheetApp.getUi().ButtonSet.YES_NO);
if (res == ui.Button.YES) {
if (range.columnStart == 6 || (range.columnStart == 11 && value == "1")) {
range.offset(0, 2).setValue(Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "dd/MM/yyyy"));
}
return;
}
range.uncheck();
}
function onEdit() {
var now = new Date()
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet()
var row = ss.getActiveRange().getRow()
ss.getRange(row, 1).setValue("value for first Col")
ss.getRange(row, 2).setValue("value for second Col")
ss.getRange(row, 3).setValue(now) //third Col with the current date/Time
}
The code above fires every time you edit any cell in the doc.
To prevent this you can add a if/else statement to check the Column like so.
var col = ss.getActiveRange().getColumn()
if (col == 2){//replace the 2 with the checkbox Column.
//do this
}
Now the Code fires every time you edit a cell in the second col and adds values to the same row.
I've got the script below working except for the bottom portion starting at //3. The initial portion works on my first sheet listed and adds a timestamp if a checkbox is checked, clears it if it is unchecked. However, it only works on the first sheet, and I need it to work on the second sheet listed as well. The data is set up differently on each sheet so that's why I have these broken out. I'd appreciate any guidance, I'm very new to Apps Script and learning so I'm sure it's a novice and silly mistake:
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSheet();
var r = ss.getActiveCell();
//1.Change 'Sheet1' to match your sheet name
if (r.getColumn() == 1 && ss.getName()=='Sheet1') { // 2. If Edit is done in column 1 make change in column 4(D) then:
var celladdress ='D'+ r.getRowIndex();
if(r.getValue() !="" && r.getValue() !=" "){
ss.getRange(celladdress).setValue(new Date()).setNumberFormat("MM/DD/YYYY hh:mm:ss");
} else{
ss.getRange(celladdress).clearContent();
}
//3.Change 'Sheet2' to to match your sheet name
if (r.getColumn() == 1 && ss.getName()=='Sheet2') { // 4. If Edit is done in column (G) then:
var celladdress ='G'+ r.getRowIndex();
if(r.getValue() !="" && r.getValue() !=" "){
ss.getRange(celladdress).setValue(new Date()).setNumberFormat("MM/DD/YYYY hh:mm:ss");
} else{
ss.getRange(celladdress).clearContent();
}
}
}
}
Modification points:
In your script, I thought that an object for searching the sheet name might be able to be used.
In this modification var obj = {Sheet1: "D", Sheet2: "G"} is used.
For example, obj["Sheet1"] returns D. This is used for the modified script.
About the checkbox, you can also use isChecked() for checking whether the checkbox is checked.
When above points are reflected to your script, it becomes as follows.
Modified script:
function onEdit(e) {
var r = e.range;
var ss = r.getSheet();
// Prepare an object for searching sheet name.
var obj = {Sheet1: "D", Sheet2: "G"};
// Using the object, check the sheet and put or clear the range.
if (r.getColumn() == 1 && obj[ss.getSheetName()]) {
var celladdress = obj[ss.getName()] + r.getRowIndex();
if (r.isChecked()) {
ss.getRange(celladdress).setValue(new Date()).setNumberFormat("MM/DD/YYYY hh:mm:ss");
} else {
ss.getRange(celladdress).clearContent();
}
}
}
In this case, the event object is used. But if you want to directly run the function at the script editor, please modify as follows.
From
var r = e.range;
var ss = r.getSheet();
To
var ss = SpreadsheetApp.getActiveSheet();
var r = ss.getActiveCell();
References:
Event Objects
isChecked()
so I wrote a script that is working on edit and looking if the active cell in column A or column D. In column D I have a checkbox I want to fill the Column F with current time when the checkbox is true. You can see my script below. Currently it fills when column A is edited but It doesnt do anything if the checkbox is checked.
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
if( s.getName() == "Sheet1" ) { //checks that we're on Sheet1 or not
var r = s.getActiveCell();
if( r.getColumn() == 1 ) { //checks that the cell being edited is in column A
var nextCell = r.offset(0, 4);
nextCell.setValue(new Date());
}
else if( r.getColumn() == 4 ) { //checks that the cell being edited is in column A
if(r.getValue() == "TRUE") {
var nextCell = r.offset(0, 2);
nextCell.setValue(new Date());
}
}
}
}
You want to put the date object to the column "F" when the checkbox at the column "D" is checked.
You want to run the script with the OnEdit event trigger.
Modification points:
In your script, I think that the if statement of if(r.getValue() == "TRUE") {} is required to be modified. In this case, when r.getValue() is the boolean type, r.getValue() == "TRUE" is always false. By this, the script in the if statement is not run. I think that this is the reason of your issue.
Modified script 1:
When your script is modified, please modify as follows.
From:
if(r.getValue() == "TRUE") {
To:
if(r.getValue() === true) {
or
if(r.isChecked()) {
In this case, also you can use isChecked().
Modified script 2:
When the event object is used, the process cost of your script can be reduced a little. Ref The sample script using the event object is as follows.
Sample script:
function onEdit(e) {
var range = e.range;
var sheet = range.getSheet();
if(sheet.getSheetName() == "Sheet1") {
if(range.columnStart == 1) {
var nextCell = range.offset(0, 4);
nextCell.setValue(new Date());
} else if(range.columnStart == 4 && range.isChecked()) {
var nextCell = range.offset(0, 2);
nextCell.setValue(new Date());
}
}
}
References:
getValue()
isChecked()
Event Objects
I'm trying to build a glorified to-do list for posting to various job boards. I have a sheet with all website properties, including a unique ID for each property, as well as columns for when the most recent post was submitted (where the timestamp will land). The to-do list is a tab called Posting Tasks, and includes the same unique ID, as well as a checkbox to mark that post as complete.
Database tab
I'm using the onEdit trigger to produce a timestamp on the Database sheet (column K) when cells in Column A of Posting Tasks sheet are 'true'. However, the timestamps are fixed to the row of the corresponding trigger. I'd like them to be relative based on a matching (vlookup) of the unique ID (column C in the trigger sheet, and column B in the Database sheet), since the Posting Tasks sheet changes daily.
Posting tasks
I'm using the below script, but don't know how to change the e.range.rowStart to be relative and lookup corresponding values. Any ideas?
function onEdit(e) {
var sheetsToWatch= ['Posting Tasks', 'Database'
],
columnToWatch = 1,
columnToStamp = 11;
if (e.range.columnStart !== columnToWatch
|| sheetsToWatch.indexOf( e.source.getActiveSheet().getName() ) === -1
|| !e.value)
return;
e.source.getSheetByName('Database')
.getRange(e.range.rowStart, columnToStamp)
.setValue(new Date());
}
Try this:
function onEdit(e) {
e.source.toast('flag1');
var sh=e.range.getSheet();
var name=sh.getName();
if(name=='Posting Tasks' && e.range.columnStart==1 && e.value) {
e.source.toast('flag2');
var id=e.range.offset(0,2).getValue();
var tsh=e.source.getSheetByName('Database');
var idA=tsh.getRange(3,2,tsh.getLastRow()-2,1).getValues().map(function(r){return r[0]});
var row=idA.indexOf(id)+3;
var tsh=e.source.getSheetByName('Database').getRange(row,11).setValue(Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "dd/MM/yyyy HH:mm:ss"));
}
}
Andrew Karp Modification:
var sh = e.source.getActiveSheet();
if (sh.getName() !== 'Posting Tasks' || e.range.columnStart !== 1 || e.range.rowStart < 3 || e.value !== 'TRUE') return;
e.range.offset(0, 0).clearContent() } }