Writing google Javascript similar to vlookup - javascript

ColumnA ColumnB
jhinz 115
tom 116
The idea behind this code is someone enters a number (lets say 116), the computer looks it up in column B and returns the name in column A (tom)
The only part I need help on for the code is the computer looking up the value in column 116.
I was trying to do a for loop with a nested if statement but it wasn't working.
Could someone help me?

in its simplest form and to see the working principle you could try this :
function findinB() {
var sh = SpreadsheetApp.getActiveSheet();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var last=ss.getLastRow();
var data=sh.getRange(1,1,last,2).getValues();// create an array of data from columns A and B
var valB=Browser.inputBox('Enter value to search in B')
for(nn=0;nn<data.length;++nn){
if (data[nn][1]==valB){break} ;// if a match in column B is found, break the loop
}
Browser.msgBox(data[nn][0]);// show column A
}

I figured that #Serge's function can be made slightly more modular and might be worth sharing.
/*
Imitates the Vlookup function. Receives:
1. sheet - A reference to the sheet you would like to run Vlookup on
2. column - The number of the column the lookup should begin from
3. index - The number of columns the lookup should cover.
4. value - The desired value to look for in the column.
Once the cell of the [value] has been found, the returned parameter would be the value of the cell which is [index] cells to the right of the found cell.
*/
function vlookup(sheet, column, index, value) {
var lastRow=sheet.getLastRow();
var data=sheet.getRange(1,column,lastRow,column+index).getValues();
for(i=0;i<data.length;++i){
if (data[i][0]==value){
return data[i][index];
}
}
}
Any suggestions or improvements are appreciated.
This could also be a good opportunity to start a repo for much needed Google Sheet API functions that are missing. I started a new repo which might someday turn into something more useful, if you're up to contributing your own custom made functions, please don't hesitate to PR.
Cheers!

//~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`
//--//Dependent on isEmpty_()
// Script Look-up
/*
Benefit of this script is:
-That google sheets will not continually do lookups on data that is not changing with using this function as it is set with hard values until script is kicked off again.
-Unlike Vlookup you can have it look at for reference data at any Column in the row. Does not have to be in the first column for it to work like Vlookup.
-You can return the Lookup to Memory for further processing by other functions
Useage:
var LocNum = SpreadsheetApp.openById(SheetID).getSheetByName('Sheet1').getRange('J2:J').getValues();
Lookup_(Sheetinfo,"Sheet1!A:B",0,[1],"Sheet1!I1","n","y");
//or
Lookup_(Sheetinfo,"Sheet1!A:B",0,[1],"return","n","n");
//or
Lookup_(Sheetinfo,"Sheet1!A:B",0,[0,1],"return","n","n");
//or
Lookup_(Sheetinfo,"Sheet1!A:B",1,[0],"return","y","n");
//or
Lookup_(Sheetinfo,"Sheet1!A:G",4,[0],"Database!A1","y","y");
//or
Lookup_(Sheetinfo,LocationsArr,4,[0],"return","y","y");
*/
function Lookup_(Search_Key,RefSheetRange,SearchKey_Ref_IndexOffSet,IndexOffSetForReturn,SetSheetRange,ReturnMultiResults,Add_Note)
{
if(Object.prototype.toString.call(Search_Key) === '[object String]')
{
var Search_Key = new Array(Search_Key);
}
if(Object.prototype.toString.call(IndexOffSetForReturn) === '[object Number]')
{
var IndexOffSetForReturn = new Array(IndexOffSetForReturn.toString());
}
if(Object.prototype.toString.call(RefSheetRange) === '[object String]')
{
var RefSheetRangeArr = RefSheetRange.split("!");
var Ref_Sheet = RefSheetRangeArr[0];
var Ref_Range = RefSheetRangeArr[1];
var data = SpreadsheetApp.getActive().getSheetByName(Ref_Sheet).getRange(Ref_Range).getValues(); //Syncs sheet by name and range into var
}
if(Object.prototype.toString.call(RefSheetRange) === '[object Array]')
{
var data = RefSheetRange;
}
if(!/^return$/i.test(SetSheetRange))
{
var SetSheetRangeArr = SetSheetRange.split("!");
var Set_Sheet = SetSheetRangeArr[0];
var Set_Range = SetSheetRangeArr[1];
var RowVal = SpreadsheetApp.getActive().getSheetByName(Set_Sheet).getRange(Set_Range).getRow();
var ColVal = SpreadsheetApp.getActive().getSheetByName(Set_Sheet).getRange(Set_Range).getColumn();
}
var twoDimensionalArray = [];
for (var i = 0, Il=Search_Key.length; i<Il; i++) // i = number of rows to index and search
{
var Sending = []; //Making a Blank Array
var newArray = []; //Making a Blank Array
var Found ="";
for (var nn=0, NNL=data.length; nn<NNL; nn++) //nn = will be the number of row that the data is found at
{
if(Found==1 && /^n$/i.test(ReturnMultiResults)) //if statement for found if found = 1 it will to stop all other logic in nn loop from running
{
break; //Breaking nn loop once found
}
if (data[nn][SearchKey_Ref_IndexOffSet]==Search_Key[i]) //if statement is triggered when the search_key is found.
{
var newArray = [];
for (var cc=0, CCL=IndexOffSetForReturn.length; cc<CCL; cc++) //cc = numbers of columns to referance
{
var iosr = IndexOffSetForReturn[cc]; //Loading the value of current cc
var Sending = data[nn][iosr]; //Loading data of Level nn offset by value of cc
if(isEmpty_(Sending)) //if statement for if one of the returned Column level cells are blank
{
var Sending = "#N/A"; //Sets #N/A on all column levels that are blank
}
if (CCL>1) //if statement for multi-Column returns
{
newArray.push(Sending);
if(CCL-1 == cc) //if statement for pulling all columns into larger array
{
twoDimensionalArray.push(newArray);
var Found = 1; //Modifying found to 1 if found to stop all other logic in nn loop
break; //Breaking cc loop once found
}
}
else if (CCL<=1) //if statement for single-Column returns
{
twoDimensionalArray.push(Sending);
var Found = 1; //Modifying found to 1 if found to stop all other logic in nn loop
break; //Breaking cc loop once found
}
}
}
if(NNL-1==nn && isEmpty_(Sending)) //following if statement is for if the current item in lookup array is not found. Nessessary for data structure.
{
for(var na=0,NAL=IndexOffSetForReturn.length;na<NAL;na++) //looping for the number of columns to place "#N/A" in to preserve data structure
{
if (NAL<=1) //checks to see if it's a single column return
{
var Sending = "#N/A";
twoDimensionalArray.push(Sending);
}
else if (NAL>1) //checks to see if it's a Multi column return
{
var Sending = "#N/A";
newArray.push(Sending);
}
}
if (NAL>1) //checks to see if it's a Multi column return
{
twoDimensionalArray.push(newArray);
}
}
}
}
if(!/^return$/i.test(SetSheetRange))
{
if (CCL<=1) //checks to see if it's a single column return for running setValue
{
var singleArrayForm = [];
for (var l = 0,lL=twoDimensionalArray.length; l<lL; l++) //Builds 2d Looping-Array to allow choosing of columns at a future point
{
singleArrayForm.push([twoDimensionalArray[l]]);
}
SpreadsheetApp.getActive().getSheetByName(Set_Sheet).getRange(RowVal,ColVal,singleArrayForm.length,singleArrayForm[0].length).setValues(singleArrayForm);
}
if (CCL>1) //checks to see if it's a multi column return for running setValues
{
SpreadsheetApp.getActive().getSheetByName(Set_Sheet).getRange(RowVal,ColVal,twoDimensionalArray.length,twoDimensionalArray[0].length).setValues(twoDimensionalArray);
}
if(/^y$/i.test(Add_Note))
{
if(Object.prototype.toString.call(RefSheetRange) === '[object Array]')
{
SpreadsheetApp.getActive().getSheetByName(Set_Sheet).getRange(RowVal,ColVal,1,1).setNote("VLookup Script Ran On: " + Utilities.formatDate(new Date(), "PST", "MM-dd-yyyy hh:mm a") + "\nRange: Origin Variable" );
}
if(Object.prototype.toString.call(RefSheetRange) === '[object String]')
{
SpreadsheetApp.getActive().getSheetByName(Set_Sheet).getRange(RowVal,ColVal,1,1).setNote("VLookup Script Ran On: " + Utilities.formatDate(new Date(), "PST", "MM-dd-yyyy hh:mm a") + "\nRange: " + RefSheetRange);
}
}
SpreadsheetApp.flush();
}
if(/^return$/i.test(SetSheetRange))
{
return twoDimensionalArray
}
}
//~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`
//~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`
// Empty String Check
function isEmpty_(string)
{
if(Object.prototype.toString.call(string) === '[object Boolean]') return false;
if(!string) return true;
if(string == '') return true;
if(string === false) return true;
if(string === null) return true;
if(string == undefined) return true;
string = string+' '; // check for a bunch of whitespace
if('' == (string.replace(/^\s\s*/, '').replace(/\s\s*$/, ''))) return true;
return false;
}
//~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`

I'm still new to JavaScript and Google Script but this seems to work.
And I'm sure there's a better way to limit the for-loop than data.length, but I don't know it.
function vlookup(row, col) {
var x=1, y=1;
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getDataRange().getValues();
for(x=1; x<data.length; x++){
while(data[x][0]===row){
for(y=1; y<data.length; y++){
while(data[0][y]===col){
var result = data[x][y]
return result;
}
}
}
}
}

I know I'm late to the party, but I built this script a while back. As expected, it's slow, but it performs vlookup as a script function. Range should be passed as a multidimensional array (array[row][col]). In Google Sheets you can place the cell range in the attributes and it will work:
function vlookupscript(search_key,range,index){
var returnVal = null;
for(var i in range) {
if(range[i][0] == search_key){
returnVal = range[i][(index-1)];
break;
}
}
return returnVal;
}

Related

Google Apps Scripts - Add specific value to each row being processed in a loop

so I want to write a function that takes leads from a source sheet, and then, sends them to another sheet (the destsheet) if they haven't been sent yet. The difference between a lead that has been sent and a lead that hasn't been is that a lead sent should have "yes" in column K (column 10)
I have managed to get the first part working (sending leads from a sheet to another) but for some reason, I can't get the script to add "yes" when a lead is sent to the other sheet. As you can see below, I've tried adding "values[i][tstCol] = "yes";" in several different spots, but it's not working.
Any ideas of what I'm doing wrong? Thanks!
function newLeads() {
var sourceSheet = SpreadsheetApp.openById('ID').getSheetByName('SHEETNAME');
var destSheet = SpreadsheetApp.openById('ID').getSheetByName('SHEETNAME');
var values = sourceSheet.getDataRange().getDisplayValues();
var finalValues=[];
var columns = String("0,1,2,3,4,5,6,7,8").split(','); //only want these columns
var tstCol = 10;
for (var i=0;i<values.length;i++) {
var newValues=[];
//values[i][tstCol] = "yes";
if (values[i][tstCol] != "yes") {
//values[i][tstCol] = "yes";
for (var j=0;j<columns.length;j++) {
//values[i][tstCol] = "yes";
newValues.push(values[i][columns[j]]);
}
finalValues.push(newValues);
}
}
destSheet.getRange(destSheet.getLastRow() + 1, 1, finalValues.length, finalValues[0].length).setValues(finalValues);
}
Take a look at this.
function newLeads() {
try {
var sourceSheet = SpreadsheetApp.openById('ID').getSheetByName('SHEETNAME');
var destSheet = SpreadsheetApp.openById('ID').getSheetByName('SHEETNAME');
var values = sourceSheet.getDataRange().getDisplayValues();
var finalValues=[];
var columns = String("0,1,2,3,4,5,6,7,8").split(','); //only want these columns
var tstCol = 10;
for (var i=0;i<values.length;i++) {
var newValues=[];
if (values[i][tstCol] != "yes") {
values[i][tstCol] = "yes"; // is this where you want to set to yes
for (var j=0;j<columns.length;j++) {
newValues.push(values[i][columns[j]]);
}
finalValues.push(newValues);
}
values[i] = [values[i][tstCol]]; // this would extract column tstCol
}
destSheet.getRange(destSheet.getLastRow() + 1, 1, finalValues.length, finalValues[0].length).setValues(finalValues);
sourceSheet.getRange(1,tstCol+1,values.length,1).setValues(values);
}
catch(err) {
console.log(err);
}
}
Explanation:
The try block is used to see if an error occurs during the block between try and catch; if an error occurs, the catch(err) block is executed and the error is being displayed.
The values array is an array of rows [[1,2,3,4],[5,6,7,8],...] which I converted it to an array [[1],[2],[3]...] of a single column of the spreadsheet type in order to use the setValues(values) method.
Reference link:
Apps Script setValues().

Dynamic namedRange, Trying to print only cells with data in them

function readNamedRange() {
var app = SpreadsheetApp;
var activeSheet = app.getActiveSpreadsheet().getActiveSheet();
var listDown = activeSheet.getRange("listDown");
var result = activeSheet.getRange("listDown").getValues();
}
In the above code, my active sheet contains a namedRange which has the entire B column set to the namedRange called listDown. Cells B1 to B10 have data 1 through 10 in them.
I am trying to print only data cells with values in them using both for loop and an if statement inside it.
I have tried the following logic given below:
for(var i=0; i <result.length; i++){
if(result.length[i] != "" && result.length[i] != undefined ){
console.log(result);
}else{
console.log("namedRange is empty");
}
}
My above logic is not complete and I am unable to understand how to do it.
I believe your goal as follows.
You want to show the values of cells except for the empty cells at the log.
For this, how about this modification?
Modification points:
listDown is not used in your script.
The value retrieved by getValues() is 2 dimensional array. And your range is one column.
In this case, each value can be retrieved by result[i][0].
In your script, result.length[i] always becomes undefined.
At console.log(result), all values of result is shown.
In your case, result[i][0] != "" can be used for the if statement.
When above points are reflected to your script, it becomes as follows.
Modified script:
function readNamedRange() {
var activeSheet = SpreadsheetApp.getActiveSheet();
var result = activeSheet.getRange("listDown").getValues();
for (var i = 0; i < result.length; i++) {
if (result[i][0] != "") { // Modified
console.log(result[i][0]); // Modified
} else {
console.log("namedRange is empty");
}
}
}
References:
getValues()
Array
Added:
You want to show the values of only cells except for the empty cells.
For this, how about the following modified script?
The script in else was removed.
In order to reduce the process cost, var end = activeSheet.getLastRow() is used for the for loop.
Modified script:
function readNamedRange() {
var activeSheet = SpreadsheetApp.getActiveSheet();
var result = activeSheet.getRange("listDown").getValues();
var end = activeSheet.getLastRow();
for (var i = 0; i < end; i++) {
if (result[i][0] != "") {
console.log(result[i][0]);
}
}
}

Search for value and return row number

I'm struggle with this script. I need to search for today date, once match it return column number (done!). I need a script to do the same with row number. The script I have is works fine if I keep only one table on that sheet, but I have more tables and if I use values.length -1 will return last row from the sheet. Also, every table might not have a fixed row numbers, so need to be dynamic.
This is the script I have so far:
function getTodaysTotal() {
function toDateFormat(date) {
try {return date.setHours(0,0,0,0);}
catch(e) {return;}
}
var values = SpreadsheetApp
.openById("id")
.getSheetByName("Q3 - W27 - 39")
.getDataRange()
.getValues();
var today = toDateFormat(new Date());
var todaysColumn = values[5].map(toDateFormat).map(Number).indexOf(+today);
var output = values[values.length - 1][todaysColumn];
var emailDate = Utilities.formatDate(new Date(today),"GMT+1", "dd/MM/yyyy");
And that's a screen shoot of my table.
table
Hope it make sense. I have the column number and I need to find row number that contain Total.
Thank you!
Kind regards
You have to loop through an array of data which is probably the fastest.
Have a look at the below script and implement in your existing.
Not sure if it is only one column where you are looking but for example column C:
for (i in values){
if (values[i][2]=='Total'){
Logger.log(i);
var nr = i
}
}
var nr now contains i as the row number it found the word "Total" in column C (the #2 after [i]).
you can then use the variable in anything that you would like after the first closing bracket.
I add this to my script, but I get undefined on output. I get the right value if I use logger log, but I also get an empty value (undefined). So I need only the first value.
function getTodaysTotal() {
function toDateFormat(date) {
try {return date.setHours(0,0,0,0);}
catch(e) {return;}
}
var values = SpreadsheetApp
.openById("id")
.getSheetByName("Q3 - W27 - 39")
.getDataRange()
.getValues();
for (i in values){
if (values[i][0]=='Total'){
var nr = i;
var newNr = parseInt(nr);
// Logger.log(nr);
var today = toDateFormat(new Date());
var todaysColumn =
values[5].map(toDateFormat).map(Number).indexOf(+today);
var output = values[newNr][todaysColumn];
Logger.log(output);
var emailDate = Utilities.formatDate(new Date(today),"GMT+1", "dd/MM/yyyy");
// Logger.log(todaysColumn);
// Logger.log(output);
// return values[values.length - 1][todaysColumn];
}
}
if (output == undefined) {
GmailApp.sendEmail("email#company.com", "test data", "Today, " +emailDate +" we had no calls made or no values are inputed.");
}
else if (output == "") {
GmailApp.sendEmail("email#company.com", "test data", "Today, " +emailDate +" we had no calls made or no values are inputed.");
}
else {
GmailApp.sendEmail("email#company.com", "test data", "Today, " +emailDate +" we had " +output + " calls made.");
}
}

Array.push.setAnyFormatting('red')?

Description:
Stack Overflow user mhawksey recently did some fantastic optimization of my code, and in doing so, introduced me to super efficient array pushes. But working with arrays is kind of difficult, because I can't seem to be able to use functions I can when using the traditional .getRange/.setValue approach.
Problem:
I need to integrate .setFontColors('red') and .setBackgroundColors('white').
Code and Images:
First, I will post the code. Second, an image of what the currently code does. Third, an image of what the code needs to do.
function format() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getActiveSheet();
var lastRow = s.getLastRow();
var row;
//gets a [][] of all values in the column
var data = s.getRange("A:A").getValues();
//we are going to build a [][] to output result
var output = [];
//loop through all cells in column A
for (row = 0; row < lastRow; row++) {
var cellValue = data[row][0];
var dash = false;
if (typeof cellValue === 'string') {
dash = cellValue.substring(0, 1);
//if a number copy to our output array
} else {
output.push([cellValue]);
}
//if -dash
if (dash === "-") {
//build first + last name
var name = (data[(row+1)][0]+" "+data[(row+2)][0]).trim();
//add row for the -state (e.g. -MI)
output.push([cellValue]);
output.push([name]);
output.push(["Order complete"]);
//add a blank row
output.push([""]);
//jump an extra row to speed things up
row++;
}
}
//set the values we've made in our output [][] array
s.getRange(1, 1, output.length).setValues(output);
}
This is what the code does:
This is what I'm trying to achieve:
Update:
I've appended a simple, working formatting loop. The problem is, when I run it on a longer column of data, it takes too long to process. From what I understand of the comments, I cannot quickly format a spreadsheet. Am I wrong?
Appended formatting code:
//other variables
var range1;
//loop through column A
for (var row = 0; row < lastRow; row++) {
range1 = s.getRange(row + 1, 1);
//define offsets for if statement
var offset1 = range1.offset(1, 0);
var offset2 = range1.offset(2, 0);
//substring cannot run on numbers, so...
cellValue = range1.getValue();
if (typeof cellValue === 'number') {continue;};
dash = cellValue.substring(0, 1);
//if -
if (dash === "-") {
offset1.setFontColor('red');
offset2.setBackground('green');
};
};
You can use all the various spreadsheet methods to get and set colors, font sizes, font weights, etc. to and from distinct arrays but you can not mix these "attributes" in one single item. See the doc here.
Or even handier, in your script editor write a script that defines a range and play with the auto complete to see everything you can do with it...
(control+space keys)
edit following your code update.
You should create a second array that holds all the background colors of your range and fill it according to your needs.
In the code below I build the array in parrallels with your output array, not very elegantly but rather systematically to show how it works.
Note that null value means "no background color" while #0F0 is the hexadecimal code for green but you can also use the 'green' string if you prefer...
...
var output = [];
var backGrounds=[]
//loop through all cells in column A
for (row = 0; row < lastRow; row++) {
var cellValue = data[row][0];
var dash = false;
if (typeof cellValue === 'string') {
dash = cellValue.substring(0, 1);
//if a number copy to our output array
} else {
output.push([cellValue]);
backGrounds.push([null]);
}
//if -dash
if (dash === "-") {
//build first + last name
var name = (data[(row+1)][0]+" "+data[(row+2)][0]).trim();
//add row for the -state (e.g. -MI)
output.push([cellValue]);
backGrounds.push([null]);
output.push([name]);
backGrounds.push([null]);
output.push(["Order complete"]);
backGrounds.push(['#0F0']);
//add a blank row
output.push([""]);
backGrounds.push([null]);
//jump an extra row to speed things up
row++;
}
}
s.getRange(1, 1, output.length).setBackgrounds(backGrounds);
...
REMARK: The OP did a huge change from revision 1 to revision 3. Following is the content taken from the source of the revision 1.
Is it possible to push text to a spreadsheet with formatting such
as .setFontColor, .setBackgroundColor or .setBorder? I've been
monkeying around with code but never get an error message. It just
doesn't do anything. I'm working with something like this:
if (cell === "This should be red") {
var redCell = (data[(row)][0]).setFontColor('red');
array.push([redCell]);
}
Following is my answer to the revision 1.
To copy the value and format from one cell or range to another use copyTo(destination).
From the above link
// The code below will copy the first 5 columns over to the 6th column.
var sheet = SpreadsheetApp.getActiveSheet();
var rangeToCopy = sheet.getRange(1, 1, sheet.getMaxRows(), 5);
rangeToCopy.copyTo(sheet.getRange(1, 6));
}

How can I modify the existing email CSV script to skip blank rows, or rows with a single zero in either field?

I've been using the Google-provided script to generate and email CSVs from Google Sheets. I customised it so that it doesn't ask for a range or a file name. This way it just automatically emails me, periodically, with the contents of my range.
The problem is that the CSV contains empty rows, at the end, that I'd like the script to automatically filter out (which I can't achieve, because I just don't have the knowledge). The reason for this, in turn, is that the range contains empty rows - but there's a good reason for that, which is that the rows in the range sometimes expand, sometimes contract, depending on the underlying data. (The range in fact relates to a pivot table).
As a bonus prize, I'd also really like it to skip rows, if there is a single zero in either of the two columns in the rows. (I ought to be able to filter this out in the pivot table; I can, but then the filters don't work properly if new values appear).
This is an example of how my emailed CSVs are looking at the moment:
0,0
,0
0.65,0
0.75,16900
0.78,2000
0.79,500
0.8,110800
0.83,1200
0.85,20000
0.87,4500
0.9,3500
1,5000
1.1,4000
1.2,41500
,
,
,
,
,
,
,
,
,
,
,
,
,
,
This is an example of how I would like to receive that CSV:
0.75,16900
0.78,2000
0.79,500
0.8,110800
0.83,1200
0.85,20000
0.87,4500
0.9,3500
1,5000
1.1,4000
1.2,41500
Any help with this would be HUGELY appreciated. Thanks.
Here's the script I'm using currently:
var settings = {
"recipients": "myemailaddress",
"emailSubject": "CSV file",
"emailMessage": "Your CSV file is attached",
"fileExtension": ".csv",
"carriageReturn": "\r\n"
};
function onOpen() {
var subMenus = [];
subMenus.push({name: "Email Named Range as CSV", functionName: "run"});
SpreadsheetApp.getActiveSpreadsheet().addMenu("CSV", subMenus);
}
function run() {
/var namedRange = Browser.inputBox("Enter named range to convert to CSV (e.g. sampleDataRange):");/
var namedRange = "FORCSVEXPORT";
var fileName = "EPCSELLOFFERS.CSV";
if (namedRange.length !== 0 && fileName.length !== 0) {
settings.dataRangeName = namedRange;
settings.csvFileName = fileName + settings.fileExtension;
var csvFile = convertNamedRangeToCsvFile_(settings.dataRangeName, settings.csvFileName);
emailCSV_(csvFile);
}
else {
Browser.msgBox("Error: Please enter a named range and a CSV file name.");
}
}
function emailCSV_(csvFile) {
MailApp.sendEmail(settings.recipients, settings.emailSubject, settings.emailMessage, {attachments: csvFile});
}
function convertNamedRangeToCsvFile_(rngName, csvFileName) {
var ws = SpreadsheetApp.getActiveSpreadsheet().getRangeByName(rngName);
try {
var data = ws.getValues();
var csvFile = undefined;
if (data.length > 1) {
var csv = "";
for (var row = 0; row < data.length; row += 1) {
for (var col = 0; col < data[row].length; col += 1) {
if (data[row][col].toString().indexOf(",") != -1) {
data[row][col] = "\"" + data[row][col] + "\"";
}
}
// Join each rows columns
// Add carriage return to end of each row
csv += data[row].join(",") + settings.carriageReturn;
}
csvFile = [{fileName: csvFileName, content: csv}];
}
return csvFile;
}
catch(err) {
Logger.log(err);
Browser.msgBox(err);
}
}
Rather than hack the original convertNamedRangeToCsvFile_(), I propose adding an additional step to your run(), that will call a new function to remove the unwanted rows from the csv file. Here it is:
/**
* Remove unwanted lines from given csvFile
*/
function minimizeCsvFile( csvFile ) {
// take apart the csv file contents, into an array of rows
var rows = csvFile[0].content.replace(/\r\n/g, "\n").split("\n");
var newRows = [];
for (var i = 0; i < rows.length; i++ ) {
if (rows[i] == "") continue; // skip blanks
if (rows[i] == ",") continue; // skip null values
// skip rows with either numeric value == 0
var vals = rows[i].split(",");
if (parseFloat(vals[0]) == 0.0 || parseFloat(vals[1]) == 0.0) continue;
// If we got here, we have a keeper - add it to newRows
newRows.push(rows[i]);
}
debugger; // pause to observe in debugger
var csv = newRows.join(settings.carriageReturn);
// Return a single element array with an object, exactly like
// the one from convertNamedRangeToCsvFile_.
return [{fileName: csvFile[0].fileName, content: csv}];
}
To make use of it, change the emailCSV_() line in run() to:
var minimizedCsvFile = minimizeCsvFile(csvFile);
emailCSV_(minimizedCsvFile);
And as for this...
As a bonus prize... Any help with this would be HUGELY appreciated. Thanks.
All we ever want here is for new members of StackOverflow to acknowledge when they receive help! Have a look at this answer for tips on how to accept answers. (You can build rep by asking, answering and accepting answers!)
But I've always wanted a Ferrari...

Categories

Resources