Google Docs - Scripts, copy cell from one sheet to another sheet - google-apps-script

I need to copy a cell from a sheet to corresponding cell in another sheet
From here:
to here:
My sheet can be viewed here.

Please report back if this is not achieving what you require.
function updateVerified() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var source = ss.getRange('Calculates!D5:K').getValues();
var respSheet = ss.getSheetByName('Responses');
var respTs = respSheet.getRange('A2:A').getValues();
var respRange = respSheet.getRange('F2:F');
var respValues = respRange.getValues();
var convTs = [], temp;
for (var i = 0; i < respTs.length; i++) {
convTs[i] = respTs[i][0] ? respTs[i][0].getTime() : '';
}
for (var j = 0; j < source.length; j++) {
if (!source[j][0]) break;
temp = convTs.indexOf(source[j][0].getTime());
if (temp > -1) respValues[temp][0] = source[j][7];
}
respRange.setValues(respValues);
}

Related

Find all empty cells in several columns

Is there an easy way to color the rows containing empty cells in specific columns? So far, I only came up with a solution to highlight the cells themselves, but this script also takes some time to run.
Will appreciate any advice or guidance!
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('FRs & NFRs')
var columns = ['J17:J','L17:L', 'V17:V', 'AB17:AB','AI17:AI', 'AK17:AK'];
for(var col in columns){ //loop to iterate the desired ranges
var range = sheet.getRange(columns[col]);
//range.activate();
var values = range.getValues();
var formulas = range.getFormulas();
//for each row that data is present
for(var i = 0; i < values.length; i++) { //loop to iterate the rows
for( var j = 0; j< values[i].length ; j++){ //loop to iterate the columns
var cell = range.getCell(i+1, j+1);
if ( values[i][j] == "" )
{
cell.setBackground('red');
cell.activate
}
else
{ cell.setBackground('white')
}
Use ConditionalFormatRuleBuilder instead. This will create a Conditional format rule in your Sheet.
Try this.
Code:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('FRs & NFRs');
var ranges = sheet.getRangeList(['J17:J','L17:L', 'V17:V', 'AB17:AB','AI17:AI', 'AK17:AK']);
var rule = SpreadsheetApp.newConditionalFormatRule()
.whenCellEmpty()
.setBackground('red')
.setRanges(ranges.getRanges())
.build();
var sheetRules = sheet.getConditionalFormatRules();
sheetRules.push(rule);
sheet.setConditionalFormatRules(sheetRules);
}
Output:
Conditional Formatting:
Highlighting empty cells using rangeList.setBackgroundColor(color) ​
In my code below, I collected the cell name of the empty cells and use it to create a RangeList. Then I used the RangeList to set the background to red. This reduced the Google Sheet Service calls from thousands to 11.
function columnToLetter(column)
{
var temp, letter = '';
while (column > 0)
{
temp = (column - 1) % 26;
letter = String.fromCharCode(temp + 65) + letter;
column = (column - temp - 1) / 26;
}
return letter;
}
function highlightEmptyCell(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('FRs & NFRs')
var rangeList = sheet.getRangeList(['J17:J','L17:L', 'V17:V', 'AB17:AB','AI17:AI', 'AK17:AK']);
var rangeArray = rangeList.getRanges();
var ranges = [];
rangeArray.forEach(range =>{
var data = range.getValues();
for( var i = 0; i < data.length; i++ ){
for( var j = 0; j < data[0].length; j++ ){
if(data[i][j] == ""){
var cellName = columnToLetter(range.getColumn()) + (i + 17)
ranges.push(cellName);
}
}
}
});
sheet.getRangeList(ranges).setBackground("red");
}
Reference:
Class ConditionalFormatRuleBuilder
RangeList.setBackgroundColor(color)

Creating sheets with from master sheet

I have a sheet named form responses which gets input from google
forms,Then I created sheets with names from Column C which is
employee code and append all the respective rows from form responses
to the newly created sheets.
Now I have sheets with name as employee code ( which is in column c of the sheet). Then I want to create secondary sheets from this master sheet(sheets with name as employee code) whose name is using the column E value as attached to the Employee code.for eg : if Emp code is 10003825 and value in column E is ASR, the sheet name should be 10001515ASR.
In Column E there are only 4 values ADC,ASR ACC,RSR. let the master sheet(sheets with name as employee code) retain ADC rows always while when other rows containing ASR,ACC,RSR comes append the respective row to the newly created sheet(ie if ASR the row goes to 10001515ASR).
I have shown my present sheet and expected output
The code I developed is shown below:
function switchSheet(){
var activeSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheets = activeSpreadsheet.getSheets();
for (var i = 1; i < sheets.length; i++) {
var p = sheets[i].getSheetName();
sheetCreateChannel(p);
}
}
function sheetCreateChannel(ss){
var activeSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = activeSpreadsheet.getSheetByName(ss);
var getNames = sheet1.getDataRange().getValues();
getNames.shift();
var sheets = activeSpreadsheet.getSheets();
var sheetsObj = {};
for (var i = 0; i < sheets.length; i++) {
sheetsObj[sheets[i].getSheetName()] = sheets[i];
for (var i = 0; i < getNames.length; i++) {
var r = getNames[i];
if (r[4].toString()== "ASR"&& !((ss+(r[4])) in sheetsObj)) {
var newSheet = activeSpreadsheet.insertSheet(ss + "ASR");
sheetsObj[ss+"ASR"] = newSheet;
}
else if (r[4].toString()== "ACC"&&!((ss+(r[4])) in sheetsObj)) {
var newSheet = activeSpreadsheet.insertSheet(ss + "ACC");
sheetsObj[ss+"ACC"] = newSheet;
}
else if (r[4].toString()== "RSR"&& !((ss+(r[4])) in sheetsObj)) {
var newSheet = activeSpreadsheet.insertSheet(ss + "RSR");
sheetsObj[ss+"RSR"] = newSheet;
}
else {
break;
}
}
}
var deleteRows = 0;
for (var i = 0; i < getNames.length; i++) {
var r = getNames[i];
if (r[4].toString() != "") {
if ((ss+(r[4])) in sheetsObj) {
var Q =ss+(r[4]);
sheetsObj[Q].appendRow(r);
}
deleteRows = i + 2;
}
}
sheet1.getRange(2, 1, deleteRows - 1, sheet1.getLastColumn()).clearContent();
}
This code works fine for my above issue
function sheetCreate(){
var activeSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = activeSpreadsheet.getSheetByName("Form Responses 1");
var getNames = sheet1.getDataRange().getValues();
getNames.shift();
var sheets = activeSpreadsheet.getSheets();
var sheetsObj = {};
for (var i = 0; i < sheets.length; i++) {
sheetsObj[sheets[i].getSheetName()] = sheets[i];
}
var deleteRows = 0;
for (var i = 0; i < getNames.length; i++) {
var r = getNames[i];
var N=r[2].toString()+r[4].toString();
if (N != "") {
if (N in sheetsObj) {
sheetsObj[N].appendRow(r);
} else {
var newSheet = activeSpreadsheet.insertSheet((N));
var cell1 = newSheet.getRange("A1").setValue("Timestamp");
var cell2 = newSheet.getRange("B1").setValue("Score");
var cell3 = newSheet.getRange("C1").setValue("Employee ID");
var cell4 = newSheet.getRange("D1").setValue("Name of the ATCO");
var cell5 = newSheet.getRange("E1").setValue("The channel on which duty is performed ");
var cell6 = newSheet.getRange("F1").setValue("DATE on which duty is performed");
var cell7 = newSheet.getRange("G1").setValue("Total duration of duty done");
newSheet.appendRow(r);
sheetsObj[N] = newSheet;
}
deleteRows = i + 2;
}
}
sheet1.getRange(2, 1, deleteRows - 1, sheet1.getLastColumn()).clearContent();
}

Using onEdit to bind a specific cell change value

This is my script. I need to populate the values in I2:I range when the cell value of C2 changes. I have created an array_temp but these are not getting pasted in I2. Can anybody please help me throw some light on it?
function onEdit(e) {
var spreadsheet = SpreadsheetApp.getActive();
var ss = e.getSheetByName('UserInterface');
var count = ss.getRange("H2").setFormula('=countif(TalukaName!B:B,UserInterface!C2)').getValue();
var DistrictName = ss.getRange('C2').getValue();
var matchindex = ss.getRange('H3').setFormula('=match(C2,TalukaName!B:B,0)').getValue();
var indexvalue = ss.getRange('H4').setFormula('=index(TalukaName!B:B,H3)').getValue();
var array = [] ;
ss.getRange('F2').clearcontent;
var ssTaluka= e.getSheetByName('TalukaName');
var range = ssTaluka.getDataRange();
var data = range.getValues();
for (var i = 0; i < count; i++) {
array[i]= data[i + matchindex - 1][0];
}
var array_temp = [];
for (var j = 0; j < array.length; j++) {
array_temp.push([
array[j]
])
}
ss.getRange('I2:I').clearContent();
ss.getRange('I2:I'+ (count+1)).setValues(array_temp) ;
}

When I change a cell's background color, how can I get all cells containing the same text to change the same color in all sheets?

I'm working with a set-list for a cover band in which I have listed all of our songs by decade on separate sheets, including a full set list on its own sheet. When we work on new songs, I color those cells green. I would like to see those same songs highlighted green wherever they may appear on the other sheets whenever I change color (onEdit, that is).
Here's what I've got so far pieced together from other sources:
function replace() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var activecell = ss.getActiveSheet().getActiveCell().getA1Notation();
var activecellvalue = ss.getActiveSheet().getActiveCell().getValue();
var activecellcolor = ss.getActiveSheet().getActiveCell().getBackground();
var allsheets = ss.getSheets();
var s = 0;
var cells = [];
if (activecellvalue != 'Yes'|'No' && activecellcolor == '#00ff00'){
for (var s=0; s < allsheets.length; s++) {
var allcells = allsheets[s].getDataRange().getValues();
for (var i=0; i < allcells.length; i++) {
for (var j=0; j < allcells[i].length; j++) {
if (allcells[i][j].toString().match(activecellvalue) == activecellvalue) {
var newcells = allsheets[s].getRange(i+1,j+1).getA1Notation();
cells.push(newcells);}
}
}
allsheets[s].getRange(newcells).setBackground('#00ff00');
// cells.push(newcells);
Logger.log(newcells);
Logger.log(allsheets);
Logger.log(cells)
}
}
}
The "Yes" and "No" refer to cells containing messages in the negative or affirmative as to whether or not we have finished a song.
I have been able to get the script to color the same text in different cells in different sheets, but something still needs to be fixed which is allowing the same cell values in EVERY sheet to be highlighted, as well.
Thank you in advance for your help!
EDIT:
I have a working (albeit, seemingly inefficient) code that will seek out the text of an active cell elsewhere and change its cell color:
function colorchange() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var activecell = ss.getActiveSheet().getActiveCell().getA1Notation();
var activecellvalue = ss.getActiveSheet().getActiveCell().getValue();
var activecellcolor = ss.getActiveSheet().getActiveCell().getBackground();
var allsheets = ss.getSheets();
var s = 0;
var name = allsheets[s].getName();
if (activecellvalue != 'Yes'|'No' && activecellcolor == '#00ff00'){
for (var s=0; s < allsheets.length; s++) {
var cells = allsheets[s].getDataRange().getValues();
for (var i=0; i < cells.length; i++) {
for (var j=0; j < cells[i].length; j++) {
if (cells[i][j].toString().match(activecellvalue) == activecellvalue) {
var check = cells[i][j]
var newcells = allsheets[s].getRange(i+1,j+1).getA1Notation();
allsheets[s].getRange(newcells).setBackground('#00ff00');
}
}
}
}
}
else if (activecellvalue != 'Yes'|'No' && activecellcolor == '#ffffff'){
for (var s=0; s < allsheets.length; s++) {
var cells = allsheets[s].getDataRange().getValues();
for (var i=0; i < cells.length; i++) {
for (var j=0; j < cells[i].length; j++) {
if (cells[i][j].toString().match(activecellvalue) == activecellvalue) {
var check = cells[i][j]
var newcells = allsheets[s].getRange(i+1,j+1).getA1Notation();
allsheets[s].getRange(newcells).setBackground('#ffffff');
}
}
}
}
}
}
The problem is getting this script to trigger on a change to background color. According to this, such a feature is not yet possible. Can anyone provide a potential solution?
UPDATE:
Working solution. Triggered by a drop-down menu selection.
function songStatus()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var range = ss.getDataRange();
var curCell = sheet.getActiveCell();
var curCol = curCell.getColumn();
var curRow = curCell.getRow();
var allSheets = ss.getSheets();
var songs = [];
var status = sheet.getRange(curRow, 3).getValue();
var genre = sheet.getRange(curRow, 11).getValue();
if (status == "Now") {
sheet.getRange(curRow, 1).setBackground('#f884ff');
sheet.getRange(curRow, 3).setBackground('#f884ff');
var song = sheet.getRange(curRow, 1).getValue().toString();
for (var s=7; s < allSheets.length; s++) {
var row = allSheets[s].getDataRange().getLastRow();
var col = allSheets[s].getDataRange().getLastColumn();
var cells = allSheets[s].getDataRange().getValues();
for (var i=0; i < row; i++) {
for (var j=0; j < col; j++) {
if (cells[i][j].toString().match(song) == song) {
allSheets[s].getRange(i+1,j+1).setBackground('#f884ff');
}
}
}
}
}
else if (status == "Next")
{
sheet.getRange(curRow, 1).setBackground('#f2a2a2');
sheet.getRange(curRow, 3).setBackground('#f2a2a2');
var song = sheet.getRange(curRow, 1).getValue().toString();
for (var s=7; s < allSheets.length; s++) {
var row = allSheets[s].getDataRange().getLastRow();
var col = allSheets[s].getDataRange().getLastColumn();
var cells = allSheets[s].getDataRange().getValues();
for (var i=0; i < row; i++) {
for (var j=0; j < col; j++) {
if (cells[i][j].toString().match(song) == song) {
allSheets[s].getRange(i+1,j+1).setBackground('#f2a2a2');
}
}
}
}
}
}
Unfortunately, onEdit trigger only fires when an "Edit" is made by the user. However, you are right, changing the color is not considered as an edit. I would suggest a slightly different approach that would work in such a scenario. Instead of tracking your new songs by highlighting them with green and having the sheet run a script to detect if the color has been changed for that cell and then running a script to find that same song in other sheets, I'd suggest either tying your Yes/No drop-down to the onEdit function to fire the color change and the other scirpt to search for that song in other sheets, or making a new New/Old drop-down list to do that for you. Here's a small pseudo-code to do that:
function onEdit()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Sheet1");
var range = ss.getDataRange();
var curCell = sheet.getActiveCell();
var curCol = curCell.getColumn();
var curRow = curCell.getRow();
var allSheets = ss.getSheets();
//Assuming your New/Old column in E
var status = sheet.getRange(curRow, 6).getValue();
if (status == "New")
{
sheet.getRange(curRow, 1, 1, range.getLastColumn()).setBackgroundRGB(230,240,220);
//Assuming your song name is in Column B
var song = sheet.getRange(curRow, 3).getValue();
for (var i=0; i<allSheets.length; i++)
{
var sRange = allSheets[i].getDataRange();
var sData = sRange.getValues();
var sRows = sRange.getLastRow();
for (var j=0; j<sRows; j++)
{
if (sData[j][1] == song)
{
allSheets[i].getRange(j+1, 1, 1, sRange.getLastColumn()).setBackgroundRGB(230,240,220);
}
}
}
}
}
Another advantage of having a code like this is that if your sheet evolves to say, track all the songs that were Old, New, In-progress, On hold or any different statuses that you could think of, and each of these had to be tracked by a color code at a glance, it's much easier to add else-if statements to do that for you.
Hope this helps!

How can i set a range to be the last row of data in the spreadsheet? Using Google Apps Script

How can I change my variable "range" to be the last row of data entered into the spreadsheet instead of 'A2:Z2'?
function findFault() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Inspections");
//Set the range to be search through
var range = sheet.getRange('A2:Z2');
//Turn the range into data values
var data = range.getValues();
//Declare fault and the value to search for
var fault = "Fault";
//Iterate through data to find fault
for (var i = 0; i < data.length; i++) {
for (var j = 0; j < data[i].length; j++) {
if (data[i][j] == fault) {
//log to test if working
Logger.log("Found Fault");
}
}
}
}
I updated my code and got it working. If anyone has tips on making it more efficient please post.
function findFault() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Inspections");
//Get the last row if data
var lastRowNumber = sheet.getDataRange().getNumRows();
var allColumns = sheet.getDataRange().getNumColumns();
//Set the range to be search through
var range = sheet.getRange(lastRowNumber, 1, 1, allColumns);
//Turn the range into data values
var data = range.getValues();
//Declare fault and the value to search for
var fault = "Fault";
//Iterate through data to dinf fault
for (var i = 0; i < data.length; i++) {
for (var j = 0; j < data[i].length; j++) {
if (data[i][j] == fault) {
//log to test if working
Logger.log("Found Fault");
}
}
}
}