Set Value of checkbox - google-apps-script

I want to uncheck a checkbox if an adjacent cell has a value input in it.
function onEdit(event) {
var eventRange = event.range;
if (eventRange.getColumn() == 3) { // 3 == column C
var columnFRange = SpreadsheetApp.getActiveSheet().getRange(eventRange.getRow(), 6, eventRange.getNumRows(), 6);
var values = columnFRange.getValues();
for (var i = 0; i < values.length; i++) {
values[i][0] = 'FALSE';
}
columnFRange.setValues(values);
}
}

This looks at a sheet called "Testing" and if there is a value in column A it will put "TRUE" in the adjacent cell to the right. I believe this is what you're going for?
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Testing");
var hasValue = sheet.getRange("A:A").getValues();
var value = '';
for(var i = 0; i < hasValue.length; i++){
if(hasValue[i][0].length > 0) {
sheet.getRange("B" + (i + 1)).setValue("TRUE");
}
else {
sheet.getRange("B" + (i + 1)).setValue("");
}
}
}

Related

Google Sheet : The result could not be auto-expanded. Please insert new columns (1)

This script import opportunities that we get. It populates rows which then calculates some numbers such as interest and stuff. However, I now have errors when populating my cells (#REF error, see pictures below). Nothing has changed so my first guess is it has do with the processing of the sheet which has become too heavy.
`
function onInstall(e) {
onOpen(e);
}
function onOpen(e) {
var menu = SpreadsheetApp.getUi().createAddonMenu();
menu.addItem('Créer étude', 'init');
menu.addToUi();
}
function init() {
ss = SpreadsheetApp.getActiveSpreadsheet();
identifyJe();
sheetMaker = ss.getActiveSheet();
currentRow = ss.getActiveCell().getRowIndex();
ssEtudes = SpreadsheetApp.openById(getSheetEtudesId());
var ui = SpreadsheetApp.getUi();
var respon se = ui.alert(
'Ligne sélectionnée : ' + currentRow + '. Exécuter ?',
ui.ButtonSet.OK_CANCEL
);
if (response !== ui.Button.OK) return;
doEtude();
doContrat();
doPhases();
}
function doEtude(nomEtude) {
var etudeData = [];
for (var i = 0; i < etudeNamedRanges.length; i++) {
var column = ss.getRangeByName(etudeNamedRanges[i]).getColumn();
etudeData.push(sheetMaker.getRange(currentRow, column).getValue());
}
var destSheet = ssEtudes.getSheetByName('etudes');
var rowToAppend = getFirstEmptyRow(destSheet, 0);
for (var i = 0; i < etudeData.length; i++) {
var column = ssEtudes.getRangeByName(etudeNamedRanges[i]).getColumn();
destSheet.getRange(rowToAppend, column).setValue(etudeData[i]);
}
}
function doContrat() {
var contratData = [];
for (var i = 0; i < contratNamedRanges.length; i++) {
var column = ss.getRangeByName(contratNamedRanges[i]).getColumn();
contratData.push(sheetMaker.getRange(currentRow, column).getValue());
}
var destSheet = ssEtudes.getSheetByName('contrats');
var rowToAppend = getFirstEmptyRow(destSheet, 11);
for (var i = 0; i < contratData.length; i++) {
destSheet.getRange(rowToAppend, i + 4).setValue(contratData[i]);
}
}
function doPhases() {
var phasesCoords = getPhasesCoords();
var phasesData = [];
for (var i = 0; i < phasesCoords.length; i++) {
var phaseData = getPhaseData(phasesCoords[i]);
phaseData.unshift(i + 1);
phasesData.push(phaseData);
}
var destSheet = ssEtudes.getSheetByName('phases');
var rowToAppend = getFirstEmptyRow(destSheet, 9);
var columns = [];
for (var nPhase = 0; nPhase < phasesData.length; nPhase++) {
var phaseData = phasesData[nPhase];
for (var i = 0; i < phaseData.length; i++) {
if (columns[i] === undefined)
columns[i] = ssEtudes.getRangeByName(phasesNamedRanges[i]).getColumn();
destSheet
.getRange(rowToAppend + nPhase, columns[i])
.setValue(phaseData[i]);
}
}
}
`
Type of formula
The results
The error, which translates into The result could not be auto-expanded. Please insert new columns (1).
The results actually appear for some time and disappear after a few seconds, constantly. Does it have something to do with the size of the spreadsheet ?

Is it possible to copy range with formating using apps scripts?

dears
I need your support to edit this function as I need to copy data with formatting
This is the equation I working on
function copyRows()
{
var copySheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('sheet1');
var dataSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('sheet2');
var dataRange = dataSheet.getDataRange();
var dataValues = dataRange.getValues();
for(var i = 1; i < dataValues.length; i++)
{
if(dataValues[i][29] === 'done')
{
copySheet.appendRow([dataValues[i][0],
dataValues[i][1],
dataValues[i][2],
dataValues[i][3],
dataValues[i][4]]);
}
}
for(var i = 1; i < dataValues.length; i++)
{
if(dataValues[i][29] === 'done')
{
var clearRow = i+1;
dataSheet.getRange('A' + clearRow + ':AC' + clearRow).clear();
}

Lock/Protect cells in a whole Google spreadsheet containing a specific text value

I have the following script (from this answer) which inserts a specific text value to a range of cells based on the date on the second column (B) in the same row.....
function onEdit(e) {
if (e.range.getColumn() == 2) {
//User edited the date column
if (typeof e.range.getValue() === typeof new Date()) {
//Value of edit was a date
endColumns(e.range.getRow(), e.range.getValue());
} else if (e.range.getValue() === "" || e.range.getValue() === null) {
var sheets = SpreadsheetApp.getActiveSheet();
// Delete all "ENDED" values:
var resetRange = sheets.getRange(e.range.getRow(), e.range.getColumn() + 1, 1, sheets.getMaxColumns() - e.range.getColumn());
var resetValues = resetRange.getValues()[0];
for(var i = 0; i < resetValues.length; i++) {
if(resetValues[i] == "ENDED") {
var resetCell = sheets.getRange(e.range.getRow(), e.range.getColumn() + 1 + i);
resetCell.clearContent();
}
}
}
}
}
function endColumns(rowNum, limitDate) {
var sheets = SpreadsheetApp.getActiveSheet();
var colOffset = 3; //Offset to account for your row Headers
var dateHeader = sheets.getRange(1, colOffset, 1, sheets.getMaxColumns() - colOffset);
var availableDates = dateHeader.getValues()[0];
var foundCol = 0;
for (var i = 0; i < availableDates.length; i++) {
if (availableDates[i] >= limitDate) {
break;
}
foundCol++;
}
var rewriteCells = sheets.getRange(rowNum, foundCol + colOffset, 1, sheets.getMaxColumns() - (foundCol + colOffset - 1));
//Add your formatting and text below:
rewriteCells.setValue("ENDED");
// Clear past dates if new date is later:
var beforeDate = sheets.getRange(rowNum, colOffset, 1, foundCol);
var beforeValues = beforeDate.getValues()[0];
for(var i = 0; i < beforeValues.length; i++) {
if(beforeValues[i] == "ENDED") {
sheets.getRange(rowNum, colOffset + i).clearContent();
}
}
// Clear all cells that are "white" (no header)
for (var i = 0; i < availableDates.length; i++) {
if (availableDates[i] === "" || availableDates[i] === null) {
sheets.getRange(rowNum, colOffset+i).clear();
}
}
}
I want these cells, containing that specific text value, to be lock/protect from edit/delete by any other user except me (which i am the owner of the file). If the date in second column (B) is deleted then the above script clears the text values and the cells should be available for editing from all users.
I've try many codes snippets to do this with no luck and the closest approach that i found is the bellow script, but it locks only one column and all the cells in that column. Not only those with a specific value...
function onEdit(event)
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSheet();
var CellRow = SpreadsheetApp.getActiveRange().getRow();
var CellColumn = SpreadsheetApp.getActiveRange().getColumn();
if (CellColumn == 7){
sheet.getRange(CellRow, CellColumn).setValue("ENDED");
Browser.msgBox("YOU CANNOT ADD DATA HERE!");
}
}
Any idea how can i lock only the cells containing that specific text value ("ENDED") and unlock/un-protect them when that value it's cleared?.
The workflow would be as following:
Incorporate a function that when run, protects all cells of your range with the content "ENDED"
Modify your existing onEdit() function by adding additional code that will check if the content of a cell in column B has been deleted
Below is a sample:
function myStartFunction(){
var sheets = SpreadsheetApp.getActive().getActiveSheet();
//adapt according to your datarange
var myRange=sheets.getRange(1,3,sheets.getLastRow(),sheets.getLastColumn());
var values=myRange.getValues();
for(var i=0;i<values.length;i++){
for(var j=0;j<values[0].length;j++){
if(values[i][j]=="ENDED"){
var cell=myRange.getCell(i+1,j+1);
var protection = cell.protect();
protection.removeEditors(protection.getEditors());
}
}
}
}
function onEdit(e){
//YOUR EXISTING CODE
if (e.range.getColumn() == 2) {
//User edited the date column
if (typeof e.range.getValue() === typeof new Date()) {
//Value of edit was a date
endColumns(e.range.getRow(), e.range.getValue());
} else if (e.range.getValue() === "" || e.range.getValue() === null) {
var sheets = SpreadsheetApp.getActiveSheet();
// Delete all "ENDED" values:
var resetRange = sheets.getRange(e.range.getRow(), e.range.getColumn() + 1, 1, sheets.getMaxColumns() - e.range.getColumn());
var resetValues = resetRange.getValues()[0];
for(var i = 0; i < resetValues.length; i++) {
if(resetValues[i] == "ENDED") {
var resetCell = sheets.getRange(e.range.getRow(), e.range.getColumn() + 1 + i);
resetCell.clearContent();
}
}
}
}
//HERE COMES THE ADDITIONAL PART
if(e.range.getColumn() == 2 && e.oldValue != "" && e.range.getValue() == "") {
var row=e.range.getRow();
var sheets = SpreadsheetApp.getActiveSheet();
var protections=sheets.getProtections(SpreadsheetApp.ProtectionType.RANGE);
for (var i = 0; i < protections.length; i++) {
var protection = protections[i];
if (protection.getRange().getRow()==row) {
protection.remove();
}
}
}
}
UPDATE
To implement protection changes on each edit, you can modify the code as following:
var sheets = SpreadsheetApp.getActiveSheet();
function Open(){
var sheets = SpreadsheetApp.getActive().getActiveSheet();
//adapt according to your datarange
var myRange=sheets.getRange(3,3,sheets.getLastRow(),sheets.getLastColumn());
var values=myRange.getValues();
for(var i=0;i<values.length;i++){
for(var j=0;j<values[0].length;j++){
if(values[i][j]=="ENDED"){
var cell=myRange.getCell(i+1,j+1);
var protection = cell.protect();
protection.removeEditors(protection.getEditors());
}
}
}
}
function onEdit(e) {
if (e.range.getColumn() == 2) {
//User edited the date column
if (typeof e.range.getValue() === typeof new Date()) {
//Value of edit was a date
endColumns(e.range.getRow(), e.range.getValue());
// wait until the function endColumns() finished
SpreadsheetApp.flush();
var myRange=sheets.getRange(e.range.getRow(),3,1,sheets.getLastColumn());
var values=myRange.getValues();
for(var j=0;j<values[0].length;j++){
if(values[0][j]=="ENDED"){
var cell=myRange.getCell(1,j+1);
var protection = cell.protect();
protection.removeEditors(protection.getEditors());
}
}
} else if (e.range.getValue() === "" || e.range.getValue() === null) {
// Delete all "ENDED" values:
var resetRange = sheets.getRange(e.range.getRow(), e.range.getColumn() + 1, 1, sheets.getMaxColumns() - e.range.getColumn());
var resetValues = resetRange.getValues()[0];
for(var i = 0; i < resetValues.length; i++) {
if(resetValues[i] == "ENDED") {
var resetCell = sheets.getRange(e.range.getRow(), e.range.getColumn() + 1 + i);
resetCell.clearContent();
}
}
Logger.log('date removed');
var row=e.range.getRow();
var protections=sheets.getProtections(SpreadsheetApp.ProtectionType.RANGE);
for (var i = 0; i < protections.length; i++) {
var protection = protections[i];
if (protection.getRange().getRow()==row) {
protection.remove();
}
}
}
}
}
function endColumns(rowNum, limitDate) {
...
}

Script to automatically insert a specific text in cells of a Google spreadsheet, based on a date in another cell, on the same row

I have the following script provided by #ZektorH in another question of mine.
function onEdit(e) {
if (e.range.getColumn() ==2) {
//User edited the date column
if (typeof e.range.getValue() === typeof new Date()) {
//Value of edit was a date
endColumns(e.range.getRow(), e.range.getValue());
} else if (e.range.getValue() === "" || e.range.getValue() === null) {
var sheets = SpreadsheetApp.getActiveSheet();
var resetRange = sheets.getRange(e.range.getRow(), e.range.getColumn()+1, 1, sheets.getMaxColumns()-e.range.getColumn());
resetRange.clear({contentsOnly: true}); //Will delete all text, not only the "ENDED" text.
}
}
}
function endColumns(rowNum, limitDate) {
var sheets = SpreadsheetApp.getActiveSheet();
var colOffset = 3; //Offset to account for your row Headers
var dateHeader = sheets.getRange(1, colOffset, 1, sheets.getMaxColumns()-colOffset);
var availableDates = dateHeader.getValues()[0];
var foundCol = 0;
for (var i=0; i<availableDates.length; i++) {
if (availableDates[i]>=limitDate) {
break;
}
foundCol++;
}
var rewriteCells = sheets.getRange(rowNum, foundCol+colOffset, 1, sheets.getMaxColumns()-(foundCol+colOffset-1));
//Add your formatting and text below:
rewriteCells.setValue("ENDED");
//Clear all cells that are "white" (no header)
for (var i=0; i<availableDates.length; i++) {
if (availableDates[i]==="" || availableDates[i] ===null) {
sheets.getRange(rowNum, colOffset+i).clear();
}
}
}
The script is working correctly after some small edits, but there is still one problem. When you clear the value in the date cell (col B) on a row, the script will clear all values in all cells on that row.
This is an issue for me because many rows have important data in the cells prior to the ENDED date.
Question
What do I need to change in this script so that it will only clear the cells with the ENDED text, after clearing the date cell?
I've reworked your code a bit, basically adding a condition to check whether the value in each cell equals "ENDED", and only deleting data if that's the case:
// Delete all "ENDED" values:
var resetRange = sheets.getRange(e.range.getRow(), e.range.getColumn() + 1, 1, sheets.getMaxColumns() - e.range.getColumn());
var resetValues = resetRange.getValues()[0];
for(var i = 0; i < resetValues.length; i++) {
if(resetValues[i] == "ENDED") {
var resetCell = sheets.getRange(e.range.getRow(), e.range.getColumn() + 1 + i);
resetCell.clearContent();
}
}
And also this, which deletes corresponding "ENDED" values if you edit to a later date:
// Clear past dates if new date is later:
var beforeDate = sheets.getRange(rowNum, colOffset, 1, foundCol);
var beforeValues = beforeDate.getValues()[0];
for(var i = 0; i < beforeValues.length; i++) {
if(beforeValues[i] == "ENDED") {
sheets.getRange(rowNum, colOffset + i).clearContent();
}
}
So, full code would be like this:
function onEdit(e) {
if (e.range.getColumn() == 2) {
//User edited the date column
if (typeof e.range.getValue() === typeof new Date()) {
//Value of edit was a date
endColumns(e.range.getRow(), e.range.getValue());
} else if (e.range.getValue() === "" || e.range.getValue() === null) {
var sheets = SpreadsheetApp.getActiveSheet();
// Delete all "ENDED" values:
var resetRange = sheets.getRange(e.range.getRow(), e.range.getColumn() + 1, 1, sheets.getMaxColumns() - e.range.getColumn());
var resetValues = resetRange.getValues()[0];
for(var i = 0; i < resetValues.length; i++) {
if(resetValues[i] == "ENDED") {
var resetCell = sheets.getRange(e.range.getRow(), e.range.getColumn() + 1 + i);
resetCell.clearContent();
}
}
}
}
}
function endColumns(rowNum, limitDate) {
var sheets = SpreadsheetApp.getActiveSheet();
var colOffset = 3; //Offset to account for your row Headers
var dateHeader = sheets.getRange(1, colOffset, 1, sheets.getMaxColumns() - colOffset);
var availableDates = dateHeader.getValues()[0];
var foundCol = 0;
for (var i = 0; i < availableDates.length; i++) {
if (availableDates[i] >= limitDate) {
break;
}
foundCol++;
}
var rewriteCells = sheets.getRange(rowNum, foundCol + colOffset, 1, sheets.getMaxColumns() - (foundCol + colOffset - 1));
//Add your formatting and text below:
rewriteCells.setValue("ENDED");
// Clear past dates if new date is later:
var beforeDate = sheets.getRange(rowNum, colOffset, 1, foundCol);
var beforeValues = beforeDate.getValues()[0];
for(var i = 0; i < beforeValues.length; i++) {
if(beforeValues[i] == "ENDED") {
sheets.getRange(rowNum, colOffset + i).clearContent();
}
}
// Clear all cells that are "white" (no header)
for (var i = 0; i < availableDates.length; i++) {
if (availableDates[i] === "" || availableDates[i] === null) {
sheets.getRange(rowNum, colOffset+i).clear();
}
}
}
I hope this is of any help to you.

Move a row from sheet to sheet with comments

I have the below script in place (1st script implemented 1 year ago) to move a row form 1 sheet to another (within a google sheet/workbook). The problem is that is does not take the comments with it. Does anyone know how I can include any unresolved comments in the transition from sheet to sheet?
var objSettings = {
sheets : ['CHECK', 'STAGE2', 'READY', 'SCHEDULED', 'ARCHIVE', 'WASTE'],
shActive : [1, 1, 1, 1, 1, 1],
column : 1,} function onEdit(e) {try{var sh = e.range.getSheet();if (e.range.getNumRows() == 1 && e.range.getNumColumns() == 1 && e.range.getColumn() == objSettings.column) {
var sheetName = '';
for (var i = 0; i < objSettings.sheets.length; i++) {
if (objSettings.sheets[i] == sh.getName().trim().toUpperCase()) {
if (objSettings.shActive[i] == 1) {
Logger.log(('' + e.value).trim().toUpperCase() );
Logger.log(sh.getName().trim().toUpperCase());
if (('' + e.value).trim().toUpperCase() != sh.getName().trim().toUpperCase()) {
var shDest = e.source.getSheetByName(e.value);
if (!(shDest)) {
var shDest = e.source.getSheetByName(('' + e.value).trim().toProperCase());
}
if (!(shDest)) {
var shDest = e.source.getSheetByName(('' + e.value).trim().toLowerCase());
}
if (!(shDest)) {
var shDest = e.source.getSheetByName(('' + e.value).trim().toUpperCase());
}
Logger.log(shDest);
if (shDest) {
var currRow = e.range.getRow();
var dataDest = shDest.getDataRange().getValues();
for (var j = 3; j < dataDest.length; j++) {
if (('' + dataDest[j][objSettings.column - 1]).length == 0) {
break;
}
}
var lastRow = j;
for (var k = 0; k < objSettings.sheets.length; k++) {
if (('' + e.value).trim().toUpperCase() == objSettings.sheets[k]) {
var type = objSettings.shActive[k];
break;
}
}
var dataR = sh.getRange(currRow, 1, 1, sh.getLastColumn()).getValues();
if (type == 1) {
shDest.getRange(lastRow + 1, 1, 1, dataR[0].length).setValues(dataR);
} else {
var dataR0 = dataR[0];
dataR0.shift();
shDest.getRange(lastRow + 1, 1, 1, dataR[0].length).setValues([dataR0]);
}
sh.deleteRow(currRow);
Logger.log(currRow);
Logger.log(lastRow + 1);
Logger.log(type);
sh.getParent().toast('The row has been moved!', 'Info');
}
}
}
break;
}
}
}}catch(e){
SpreadsheetApp.getUi().alert(e); } }
Alternatively, if you think there is a better more stable way of accomplishing this, please do let me know.
Use moveTo() to cut and paste ranges with comments.
Comments are a part of the Drive API.
Enable the Advanced Drive Service to use Drive.Comments.{}
Then you can check the status property for "open" || "resolved"
function moveComments () {
var ss = SpreadsheetApp.getActive();
var range_one = ss.getSheets()[0].getRange("A10");
var range_two = ss.getSheets()[1].getRange("A10");
// Get a list of all comments in the workbook
var workbook_comments = Drive.Comments.list(ss.getId());
/*
var comment_cell_value = workbook_comments.items[0].context.value;
var check_status = workbook_comments.items[0].status; // "open" || "resolved"
*/
// Move the range with comments to another sheet.range
range_one.moveTo(range_two);
}
See also Manage Comments and Discussions