Get array values from column - javascript

If my function gets the values of one column, say column I, how can I tell it to instead get the values of the column to the right (J) instead of I:K?
function headerSearch(e, activeCell, activeRow, activeCol, data, mode, secMode, terMode) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var foundValues = [];
var forConR = data.length;
var forConC = data[0].length;
Logger.log("data[0] = " + data[0]);
for (var i = 1; i < forConR; i++) {
for (var j = 0; j < forConC; j++) {
if (activeCell != "" && activeCol == 2 && data[0][j].indexOf(mode) > -1) {
if (activeCell.getValue() == data[0][j]) {
foundValues.push(data[i][j]);
}
} else if (activeCell != "" && activeCol == 3 && data[0][j].indexOf(mode) > -1 && data[i][j] != "") {
foundValues.push(data[i][j]);
Logger.log("foundValues = " + foundValues);
}
}
}
if (foundValues != "") {
var validationRule = SpreadsheetApp.newDataValidation().requireValueInList(foundValues).build();
activeCell.offset(0, 1).setDataValidation(validationRule);
}
}
EDIT:
I tried adding foundValues.push(data[i][j+1]); which gets me out of the first column (I), but then of course adds the NEXT column (L) that I don't want either. I'm just not sure how to isolate the column index. Once I figure that out, I'm sure it's just a matter of adding +1 or something to OFFSET to the column to the right.

You have two for loops - one of them iterating through all rows, the second through all columns of data
What you want instead is to retrieve only ONE column of data rather than iterating through ALL of them
You can do it by simply dropping the second for loop and instead hardcoding the value for j
If you are itnerested in the second column of your range - the column index should be 1 (since array indices start with 0)
Without having a deeper knowledge of the purpose of your if conditions and assuming that you use them only to assess the value in column J, you can modify your code as following:
...
for (var i = 1; i < forConR; i++) {
var j = 1;
if (activeCell != "" && activeCol == 2 && data[0][j].indexOf(mode) > -1) {
if (activeCell.getValue() == data[0][j]) {
foundValues.push(data[i][j]);
}
} else if (activeCell != "" && activeCol == 3 && data[0][j].indexOf(mode) > -1 && data[i][j] != "") {
foundValues.push(data[i][j]);
Logger.log("foundValues = " + foundValues);
}
}
...

I rearranged my if statements and added one to isolate the "mode" column (B) selected. At that point, I could add j + 1 to get the following column values for the next data validation selection.
function headerSearch(e, activeCell, activeRow, activeCol, data, mode, secMode, terMode) {
var foundValues = [];
var forConR = data.length;
var forConC = data[0].length;
if (activeCell != "") {
for (var i = 1; i < forConR; i++) {
for (var j = 0; j < forConC; j++) {
if (data[0][j] == mode && data[i][j] != "") {
var modeCol = j;
}
if (activeCol == 2 && data[i][j] != "") {
if (activeCell.getValue() == data[0][j]) {
foundValues.push(data[i][j]);
}
} else if (activeCol == 3 && data[0][j].indexOf(mode) > -1 && data[i][j] != "" && data[0][modeCol + 1].indexOf(mode) > -1) {
foundValues.push(data[i][modeCol + 1]);
} else if (activeCol == 4 && data[0][j].indexOf(mode) > -1 && data[i][j] != "" && data[0][modeCol + 2].indexOf(mode) > -1) {
foundValues.push(data[i][modeCol + 2]);
}
}
}
}
if (foundValues != "") {
var validationRule = SpreadsheetApp.newDataValidation().requireValueInList(foundValues).build();
activeCell.offset(0, 1).setDataValidation(validationRule);
}
}

Related

removing background color of rows that have nothing in column a

The script adds cell background color in non blank cells in a row based on a specified value in column "T" only if column "A" is not blank. problem i'm having is the script is not checking column "A" and then removing background color to the row if there is no value in column "A". I'm looking to see if someone can tell me where i'm going wrong, At the bottom of the script is where I have it checking column "A" and then setting background to 'none'. Is there anyway to optimize this script?, it takes a while to run.
function colors() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet_name = ['Current Sales','Pending Orders', 'Subcontract Orders', 'Partial Shipped', 'Quotes', 'Archived Sales'];
for (s=0; s<sheet_name.length; s++) {
var sheet = ss.getSheetByName(sheet_name[s]);
var range = sheet.getDataRange()
var values = range.getValues();
for (var i = 0; i < values.length; i++) {
for (var j = 0; j < values[i].length; j++) {
if (values[i][j] !== "" && values[i][19] == "Complete") {
range.getCell(i + 1, j + 1).setBackground("#99FF99");
}
if (values[i][j] !== "" && values[i][19] == "Revise") {
range.getCell(i + 1, j + 1).setBackground("#FA5959");
}
if (values[i][j] !== "" && values[i][19] == "Pending Next Step") {
range.getCell(i + 1, j + 1).setBackground("#FFFF33");
}
if (values[i][j] !== "" && values[i][19] == "Quoted") {
range.getCell(i + 1, j + 1).setBackground("#FFCCCC");
}
if (values[i][j] !== "" && values[i][19] == "Awaiting Vendor Response") {
range.getCell(i + 1, j + 1).setBackground("#FFCC99");
}
if (values[i][j] !== "" && values[i][19] == "Awaiting Customer Response") {
range.getCell(i + 1, j + 1).setBackground("#FF9999");
}
if (values[i][j] !== "" && values[i][19] == "Parts On Order") {
range.getCell(i + 1, j + 1).setBackground("#FF6666");
}
if (values[i][j] !== "" && values[i][19] == "Shipped Partial Order") {
range.getCell(i + 1, j + 1).setBackground("#FFB266");
}
if (values[i][j] !== "" && values[i][19] == "Awaiting SubContract Parts Work") {
range.getCell(i + 1, j + 1).setBackground("#66FFFF");
}
if (values[i][j] !== "" && values[i][19] == "Picking List Printed") {
range.getCell(i + 1, j + 1).setBackground("#FF9333");
}
if (values[i][j] !== "" && values[i][19] == "Waiting on BOL / Charges") {
range.getCell(i + 1, j + 1).setBackground("#3399FF");
}
if (values[i][j] !== "" && values[i][19] == "Quote Sold") {
range.getCell(i + 1, j + 1).setBackground("#FF66B2");
}
if (values[i][j] !== "" && values[i][19] == "Awaiting Vendor Confirmation") {
range.getCell(i + 1, j + 1).setBackground("#CC99FF");
}
if (values[i][j] !== "" && values[i][19] == "Ready To Ship") {
range.getCell(i + 1, j + 1).setBackground("#FFE5CC");
}
if (values [i][j] == "" && values[i][0] == "") {
range.getCell(i + 1, j + 1).setBackground('none');
}
}
}
}
}
function colors() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet_name = ['Current Sales','Pending Orders', 'Subcontract Orders', 'Partial Shipped', 'Quotes', 'Archived Sales'];
for (s=0; s<sheet_name.length; s++) {
var sheet = ss.getSheetByName(sheet_name[s]);
var range = sheet.getRange(2,1,sheet.getMaxRows(),sheet.getMaxColumns());
var values = range.getValues();
var cIndex;
var TArr = ['Complete','Revise','Pending Next Step','Quoted','Awaiting Vendor Response','Awaiting Customer Response','Parts On Order','Shipped Partial Order','Awaiting SubContract Parts Work','Picking List Printed','Waiting on BOL / Charges','Quote Sold','Awaiting Vendor Confirmation','Ready To Ship'];
var CArr = ['#99FF99','#FA5959','#FFFF33','#FFCCCC','#FFCC99','#FF9999','#FF6666','#FFB266','#66FFFF','#FF9333','#3399FF','#FF66B2','#CC99FF','#FFE5CC']
for (var i = 0; i < values.length; i++) {
if (values[i][0] !== "") { // only if A is not empty
for (var j = 0; j < values[i].length; j++) {
if (values[i][j] !== "") {
cIndex = TArr.indexOf(values[i][19]);
if (cIndex != -1) {
range.getCell(i + 1, j + 1).setBackground(CArr[cIndex]);
}
}
}
}
}
}
}
If you have an array with the values of T (TArr) and another one with the corresponding colors (CArr) in the same order, you could set the color like that: find index of T value in TArr and set the color to CArr[index], if A is not empty, otherwise to 'none'.
Cell T needs to be checked only ones per row to find the corresponding color.
var cIndex;
var cColor;
var TArr = ['Complete', 'Revise', ...];
var CArr = ['#99FF99', 'FA5959', ...];
for (var i = 0; i < values.length; i++) {
// find index of status (T) in TArr
cIndex = TArr.indexOf(values[i][19]);
// find the corresponding color in CArr
cColor = ((cIndex != -1) && (cIndex < CArr.length)) ? CArr[cIndex] : 'none';
for (var j = 0; j < values[i].length; j++) {
if (values[i][0] !== "") { // if A is not empty
if (values[i][j] !== "") { // if cell is not empty, set color
range.getCell(i + 1, j + 1).setBackground(cColor);
}
} else { // A is empty
range.getCell(i + 1, j + 1).setBackground('none');
}
}
}
I had assistance with fixing my code. here is the working script that greatly decreased execution time. #Olafant, your assistance was greatly appreciated.
function SetFormatting() {
SpreadsheetApp.getUi()
.createMenu('Apply Borders/Colors')
.addItem('Set Borders','bordersNoArg')
.addSeparator()
.addSubMenu(SpreadsheetApp.getUi().createMenu('Apply Colors')
.addItem('Apply Colors', 'colorsNoArg'))
.addToUi();
}
function borders(sheet_name) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
for (s=0; s<sheet_name.length; s++) {
var sheet = ss.getSheetByName(sheet_name[s]);
var range = sheet.getRange(2,1,sheet.getLastRow(),sheet.getLastColumn());
var values = range.getValues();
var offsetRow = range.getRowIndex();
range.setBorder(false, false, false, false, false, false);
SpreadsheetApp.flush();
for (var i = 0; i < values.length; i++) {
if (values[i][0]) { // Only for non-empty A column cells
sheet.getRange("A" + (i + offsetRow) + ":V" + (i + offsetRow)).setBorder(true, true, true, true, false, false, "black",SpreadsheetApp.BorderStyle.DOUBLE);
for (var j = 0; j < values[i].length; j++) {
if (values[i][j] !== "") {
range.getCell(i + 1, j + 1).setBorder(null,true,null,true,true,true);
}
}
}
}
}
}
function bordersNoArg(){
var sheet_name = ['Current Sales','Pending Orders', 'Subcontract Orders', 'Partial Shipped', 'Quotes', 'Archived Sales'];
borders(sheet_name)
}
function colors(sheet_name) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
for (s=0; s<sheet_name.length; s++) {
var sheet = ss.getSheetByName(sheet_name[s]);
var range = sheet.getRange(2,1,sheet.getLastRow(),sheet.getLastColumn());
var values = range.getValues();
var cIndex;
var TArr = ['Complete','Revise','Pending Next Step','Quoted','Awaiting Vendor Response','Awaiting Customer Response','Parts On Order','Shipped Partial Order','Awaiting SubContract Parts Work','Picking List Printed','Waiting on BOL / Charges','Quote Sold','Awaiting Vendor Confirmation','Ready To Ship'];
var CArr = ['#99ff99','#fa5959','#ffff33','#ffcccc','#ffcc99','#ff9999','#ff6666','#ffb266','#66ffff','#ff9333','#3399ff','#ff66b2','#cc99ff','#ffe5cc']
var exisBackGrounds = range.getBackgrounds();
//Set Empty rows background to null
var emptyRng = sheet.getRange((sheet.getLastRow() + 2),1,sheet.getMaxRows(),sheet.getMaxColumns());
emptyRng.setBackground(null);
for (var i = 0; i < values.length; i++) {
if (values[i][0] !== "") { // only if A is not empty
for (var j = 0; j < values[i].length; j++) {
if (values[i][j] !== "") {
cIndex = TArr.indexOf(values[i][19]);
if (cIndex != -1) {
if(exisBackGrounds[i][j] != CArr[cIndex]){
range.getCell(parseInt(i) + 1, parseInt(j) + 1).setBackground(CArr[cIndex]);
}
}
}else{
if(exisBackGrounds[i][j] != '#ffffff'){
range.getCell(parseInt(i) + 1, parseInt(j) + 1).setBackground(null);
}
}
}
}else{
sheet.getRange(parseInt(i) + 2,1,1,sheet.getLastColumn()).setBackground(null);
}
}
}
}
function colorsNoArg() {
var sheet_name = ['Current Sales','Pending Orders', 'Subcontract Orders', 'Partial Shipped', 'Quotes', 'Archived Sales'];
colors(sheet_name);
}

parse json to .csv in js

I found this script (works well) except that I want to skip few columns (i just want to extract column 1,2,3,9) so I have this :
$(document).ready(function(){
$('button').click(function(){
var data = $('#txt').val();
if(data == '') return;
JSONToCSVConvertor(data, "Agenda", true);
});
});
function JSONToCSVConvertor(JSONData, ReportTitle, ShowLabel) {
//If JSONData is not an object then JSON.parse will parse the JSON string in an Object
var arrData = typeof JSONData != 'object'
? JSON.parse(JSONData)
: JSONData;
var CSV = '';
//Set Report title in first row or line
CSV += ReportTitle + '\r\n\n';
//This condition will generate the Label/Header
if (ShowLabel) {
var row = "";
//This loop will extract the label from 1st index of on array
for (var index = 0; i<arrData.length-1; index++) {
if (index == 4 || index == 5 || index == 6 || index == 7 || index == 8) {
continue;
}
else{
//Now convert each value to string and comma-seprated
row += index + ';';
row = row.slice(0, -1);
//append Label row with line break
CSV += row + '\r\n';
}
}
//1st loop is to extract each row
for (var i = 0; i < arrData.length-1; i++) {
if (i == 4 || i == 5 || i == 6 || i == 7 || i == 8) {
continue;
}
else{
var row = "";
}
//2nd loop will extract each column and convert it in string comma-seprated
for (var j = 0; i<arrData.length-1; j++) {
if (j == 4 || j == 5 || j == 6 || j == 7 || j == 8) {
continue;
}
else{
row += '"' + arrData[i][j] + '";';
}
}
}
row.slice(0, row.length - 1);
//add a line break after each row
CSV += row + '\r\n';
}
if (CSV == '') {
alert("Invalid data");
return;
}
//Generate a file name
var fileName = "Formapelec_";
//this will remove the blank-spaces from the title and replace it with an underscore
fileName += ReportTitle.replace(/ /g,"_");
//Initialize file format you want csv or xls
var uri = 'data:text/csv;charset=utf-8,' + escape(CSV);
// Now the little tricky part.
// you can use either>> window.open(uri);
// but this will not work in some browsers
// or you will not get the correct file extension
//this trick will generate a temp <a /> tag
var link = document.createElement("a");
link.href = uri;
//set the visibility hidden so it will not effect on your web-layout
link.style = "visibility:hidden";
link.download = fileName + ".csv";
//this part will append the anchor tag and remove it after automatic click
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
It's supposed to generate a .csv with just column 1,2,3 & 9 but there's nothing in return. I tried different things with if() {continue} but I either have a return with all the columns or no return at all.
for (var i = 0; i < arrData.length-1; i++) {
//2nd loop will extract each column and convert it in string comma-seprated
for (var j = 0; j<arrData[i].length; j++) {
if (j == 4 || j == 5 || j == 6 || j == 7 || j == 8) {
continue;
}
else{
row += '"' + arrData[i][j] + '";';
}
}
}
row.slice(0, row.length - 1);
//add a line break after each row
CSV += row + '\r\n';
}
you skipped rows, your second for was also wrong(incrementing j, but checking i, this would either run for ever or never run
//1st loop is to extract each row
for (var i = 0; i < arrData.length-1; i++) {
if (i == 4 || i == 5 || i == 6 || i == 7 || i == 8) {
continue;
}
You are skipping rows too, that if shouln't be there

Refining Data 'Fetch/Match' in Google Scripts

I have some code that is working fine, just rather slow and clunky. Im sure there is a better way of doing this:
I have two sheets, one which the user edits ('MAIN') and one which the script pulls data from (over 5000 lines of data) ('REF'). Basically it checks for a match on column 1 and if it matches what the user has entered, it grabs the value from the same row but column 3.
The code works, but rather slowly:
function onEdit(){
var s = SpreadsheetApp.getActive().getSheetByName('MAIN');
var sref = SpreadsheetApp.getActive().getSheetByName('REF');
var activeRow = s.getActiveCell().getRow();
var activeCol = s.getActiveCell().getColumn();
var activeCell = s.getActiveCell().getValue();
var mainPageBranch = s.getRange(8,1).getValue();
var refPageBranch = sref.getRange('I4').getValue();
var lastrow = sref.getLastRow();
if(activeCol == '2' || activeCol == '5' || activeCol == '8' || activeCol == '11' || activeCol == '14' || activeCol == '17' || activeCol == '20'){
if(activeRow > 9 && activeRow < 41){
if(activeCell > 100000){
s.getRange(activeRow, activeCol+1).setValue(1);
}
else{
s.getRange(activeRow, activeCol+1).setValue('');
}
for(var i=5; i <lastrow; i++){
var productCode = sref.getRange(i, 1).getValue();
if(activeCell == productCode){
var essMould = sref.getRange(i,3).getValue();
s.getRange(activeRow+1,activeCol).setValue(essMould);
s.getRange(activeRow+1,activeCol+1).setValue('1');
break;
}
}
Logger.log('Product Code: ' + productCode);
Logger.log('Ess Mould: ' + essMould);
Logger.log('Last Row: ' + lastrow);
}
}
}
I understand it's kind of clunky - any help making it faster would be great!
Let me know if you need anything else :)
EDIT: here is the updated code thanks!
function onEdit(){
var s = SpreadsheetApp.getActive().getSheetByName('MAIN');
var sref = SpreadsheetApp.getActive().getSheetByName('REF');
var activeRow = s.getActiveCell().getRow();
var activeCol = s.getActiveCell().getColumn();
var activeCell = s.getActiveCell().getValue();
var mainPageBranch = s.getRange(8,1).getValue();
var refPageBranch = sref.getRange('I4').getValue();
var lastrow = sref.getLastRow();
var productCode,essMould,data,L;
data = sref.getRange(5, 1, lastrow-5,3).getValues();
L = data.length; //Length of data
if(activeCol == '2' || activeCol == '5' || activeCol == '8' || activeCol == '11' || activeCol == '14' || activeCol == '17' || activeCol == '20'){
if(activeRow > 9 && activeRow < 41){
if(activeCell > 100000){
s.getRange(activeRow, activeCol+1).setValue(1);
}
else{
s.getRange(activeRow, activeCol+1).setValue('');
}
for(var i=5; i <L; i++){
productCode = data[i][0];
if(activeCell == productCode){
essMould = data[i][2];
s.getRange(activeRow+1,activeCol).setValue(essMould);
s.getRange(activeRow+1,activeCol+1).setValue('1');
break;
}
}
Logger.log('Product Code: ' + productCode);
Logger.log('Ess Mould: ' + essMould);
}
}
}
You should not be getting individual values on every loop:
for(var i=5; i <lastrow; i++){
var productCode = sref.getRange(i, 1).getValue();
First get all the values, loop through the array of data, change the data in the array if needed, and then write the entire set of data back to the spreadsheet.
var data,essMould,i,L,productCode;
data = sref.getRange(5, 1, lastrow-5,activeCol).getValues();
L = data.length; //Length of data
for(i=0; i < L; i++){
productCode = data[i][0];
Logger.log("productCode: " + productCode);
if (activeCell == productCode) {
essMould = data[i][activeCol];
data[i][2] = essMould;
data[i + 1][activeCol + 1] = 1;
break;
}
}
sref.getRange(5,1,data.length,data[0].length).setValues(data);

Check and alert for the null value

I need to check for the null values and alert them if there are any before getting saved. I have used this code but I am not able to alert the null values instead it is getting saved . .
function fn_publish() {
var SessionNames = getParameterByName('SessionName');
var MenuType = getParameterByName('MenuType');
var Date = getParameterByName('ForDate');
var publish = "Y";
Dates = Date.split("-");
Date = Dates[1] + "/" + Dates[2] + "/" + Dates[0];
var rows = [];
cols = document.getElementById('product_table').rows[1].cells.length - 1;
table = document.getElementById('product_table');
for (var i = 1; i <= cols; i++) {
for (var j = 0, row; row = table.rows[j]; j++) {
if (j == 0) {
cust = row.cells[i].innerText;
alert(cust);
} else if (j == 1) {
catlg = row.cells[i].innerText;
alert(catlg);
} else {
if (typeof (row.cells[i]) != "undefined") {
if (row.cells[i].innerText != "") {
//alert(SessionNames+"::"+MenuType+"::"+Date+"::"+catlg+"::"+row.cells[0].innerText+"::"+row.cells[i].innerText+"::"+cust+"::"+publish);
fn_insert(SessionNames, MenuType, Date, catlg, row.cells[0].innerText, row.cells[i].innerText, cust, publish);
} else {
jAlert("Please select a product", "ok");
return false;
}
}
}
}
}
jAlert("Menu Published", "ok");
}
if (row.cells[i].innerText != "") {
May be the cells are containing empty space in that. Better trim ad then compare.
if (row.cells[i].innerText.trim() !== "") {
Also instead of innerText use textContent which is common in most modern browsers.
if (row.cells[i].textContent.trim() !== "") {

How to display the names of all controls(textboxes & dropdowns) which are empty in my page

I get the message Validation Failed if any of my controls are empty, but I would want to display the names of the controls which are empty. These controls are dynamically created on the page.
Below is the code that I am using now
function validateinput() {
var arrTextBox = document.getElementsByTagName("input");
var ddlTextBox = document.getElementsByTagName("select");
var retVal = 1;
for (i = 0; i < arrTextBox.length; i++) {
if (arrTextBox[i].type == "text" && arrTextBox[i].getAttribute("IsMandatory") == "Y" && arrTextBox[i].value == ""){
retVal = 0;
}
}
for (j = 0; j < ddlTextBox.length; j++) {
if (ddlTextBox[j].getAttribute("IsMandatory") == "Y" && ddlTextBox[j].value == "") {
retVal = 0;
}
}
if (retVal == 0) {
alert("Validation Failed");
return false;
}
else {
alert("Validation Success");
return true;
}
}
Okay, I see from the comments that you need some more specific assistance. Try this:
function validateinput() {
var emptySelects = '';
var emptyTextboxes = '';
var arrTextBox = document.getElementsByTagName("input");
var ddlTextBox = document.getElementsByTagName("select");
var retVal = 1;
for (i = 0; i < arrTextBox.length; i++) {
if (arrTextBox[i].type == "text" && arrTextBox[i].getAttribute("IsMandatory") == "Y" && arrTextBox[i].value == ""){
retVal = 0;
emptyTextboxes+= ' ' + arrTextBox[i].name;
}
}
for (j = 0; j < ddlTextBox.length; j++) {
if (ddlTextBox[j].getAttribute("IsMandatory") == "Y" && ddlTextBox[j].value == "") {
retVal = 0;
emptySelects += ' ' + ddlTextBox[j].name;
}
}
if (retVal == 0) {
alert("Validation Failed");
if (emptyTextboxes != '') alert('The following textboxes are empty:' + emptyTextboxes);
if (emptySelects != '') alert('The following selections are empty:' + emptySelects);
return false;
}
else {
alert("Validation Success");
return true;
}
}

Categories

Resources