Lookup and clear cell content google script - cell

Sorry, I am new to scripting and this is probably a simple one to write; apologies!
I am trying to create a script that gets a range of order numbers in a column, then looks it up on another tab, and then clears a certain cell in that row.
I can get the script to look up the 1st ordernumber at the top of the list andd clear the cell I need clearing, but I cannot work out how to lookup and clear more than one order number at a time.
The logger returns all the values, so I think I need a loop, but I do not knwo where to start with that.
This is for a work project, but I have created a basic sample sheet to play around with:
https://docs.google.com/spreadsheets/d/19koKxFcOfWRz0mEaYs_lHQFgBrU19kDoeYaBY2WBe98/edit?usp=sharing
Can anyone help??
Thanks,
John
Here is the script so far:
function clearpostagecells(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName('Order Control');
var sheet2 = ss.getSheetByName('Order Database');
var find = sheet1.getRange(2,2,sheet1.getLastRow()-1).getDisplayValues();
Logger.log(find)
var values = sheet2.getRange(2, 1, sheet2.getLastRow()-1).getDisplayValues();
for (var i = 0; i < values.length; i++) {
var row = "";
for (var j = 0; j < values[i].length; j++) {
if (values[i][j] == find) {
row = i+2;
sheet2.getRange(row,7).clearContent();
}
}
}}

Related

Google Sheets If Function Not running when true

I wanted to add a button to a report in google sheets. The button works but you can not use it on a phone so I'm told you must use onEdit. The problem I'm having is to only make changes when the certain box is edited, but when it is the correct box it seems google freezes and doesn't run the script.
I've already tried with my if as (row = 8) , (Row == 8) and (Row == "8").
function onEdit(evt) {
var range = evt.range;
var row = range.getRow().toString();
Logger.log("line 1");
Logger.log("edited!! Row: " + row + " and column: " + range.getColumn ());
if (row == "8"){ // && range.getColumn() = 6 ){ (This bit is for after I figure the row issue out.
Logger.Log("right");
} else {// esstsgs
Logger.log("Wasnt the right cell");
}
Logger.log("Done the thing");
}
So with that code, if I edit any row but 8 my log looks like:
line 1 edited!!
Row x and Column x
done the thing
But if it is row 8 my log says:
line 1
Edited!! Row x and Column x
And nothing more, when is it freezing in the if statement?
Let me know what you would really like to do with this and I'll set it up for you. For now hopefully this will help you to figure the logic.
I don't use Logger.log() for debugging this kind of code. Instead I use the e.source.toast() function.
function onEdit(e) {
var sh=e.range.getSheet();
if(sh.getName()!='Sheet189')return;//this is important so that you don't get edits from unwanted pages
//e.source.toast('Flag1');
if(e.range.rowStart==8 && e.range.columnStart==6) {
var msg=Utilities.formatString('You are editing %s.',sh.getRange(e.range.rowStart,e.range.columnStart).getA1Notation());
SpreadsheetApp.getUi().alert(msg);
}
if(e.range.rowStart!=8 || e.range.columnStart!=6) {
var msg=Utilities.formatString('You are not editing F8. Instead you are editing %s.',sh.getRange(e.range.rowStart,e.range.columnStart).getA1Notation());
SpreadsheetApp.getUi().alert(msg);
}
}
You will probably want to change the sheet number before running this. I didn't set up the Logger.log because I don't like to use it for this kind of code. I did test this and it works fine.
I'd like to point out some mistakes in your code first of all.
You don't need to make the Row variable a string. var row = range.getRow(); is just fine.
You are always Logging "Line 1", why not update it to actually say which line was updated? Logger.log("line " + row);
Your code will output "Done the thing" regardless of what it did. Maybe just say it did anything when it's the right box?
Your fixed code would look like:
function onEdit(evt) {
var range = evt.range;
var row = range.getRow();
var col = range.getColumn();
Logger.log("line " + row + "edited!! Row: " + row + " and column: " + col);
if (row == 8 && col == 6 ) {
Logger.log("Right cell. Did the thing.");
//Call here whatever you want to trigger when this cell changes.
} //Don't need a "else" if you are not going process anything
}
Hope this helps!

In POSTMAN how do i get substring of response header item?

I am using postman to get response header value like below:
var data = postman.getResponseHeader("Location") . //value is "http://aaa/bbb" for example
I can print the value via console.log(data) easily.
However, what I really want is "bbb". So I need some substring() type of function. And apparently 'data' is not a javascript string type, because data.substring(10) for example always return null.
Does anyone what i need to do in this case?
If any postman API doc existing that explains this?
You can set an environment variable in postman. try something like
var data = JSON.parse(postman.getResponseHeader("Location"));
postman.setEnvironmentVariable("dataObj", data.href.substring(10));
You have the full flexibility of JavaScript at your fingertips here, so just split the String and use the part after the last /:
var data = pm.response.headers.get("Location").split("/").pop());
See W3 school's documentation of split and pop if you need more in depth examples of JavaScript internals.
Some initial thought - I needed a specific part of the "Location" header like the OP, but I had to also get a specific value from that specific part.
My header would look something like this
https://example.com?code_challenge_method=S256&redirect_uri=https://localhost:8080&response_type=code&state=vi8qPxcvv7I&nonce=uq95j99qBCGgJvrHjGoFtJiBoo
And I need the "state" value to pass on to the next request as a variable
var location_header = pm.response.headers.get("Location");
var attributes = location_header.split('&');
console.log(attributes);
var len = attributes.length;
var state_attribute_value = ""
var j = 0;
for (var i = 0; i < len; i++) {
attribute_key = attributes[i].split('=')[0];
if (attribute_key == "state") {
state_attribute_value = attributes[i].split('=')[1];
}
j = j + 1;
}
console.log(state_attribute_value);
pm.environment.set("state", state_attribute_value);
Might you get the point here, "split" is the choice to give you some array of values.
If the text you are splitting is always giving the same array length it should be easy to catch the correct number

Best way to run through the entire sheet looking for a text in Google Sheets

I want to create a script that needs to find a certain string and replace it automatically. I've managed to do that, but it takes over 1 minute to run through all rows and columns to find it.
This is what I'm doing now:
for (i=1; i<=rows; i++) {
for (j=1; j<=cols; j++) {
cell = content.getCell(i, j).getValue();
if (content.getCell(i, j).getFormula()) {continue;}
try {
cell = cell.replace (find, replace);
content.getCell(i, j).setValue(cell);
}
catch (err) {continue;}
}
}
The built-in method replaces a text instantly, so I assume there is a better way to approach this. Any ideas?
Instead of retrieving each cell from the sheet one by one, use getDataRange() and getValues() to get all of the data in an array in one call, then perform your search on the array.
Then, depending on if you might have live users editing at the same time your script is run or not, you can either replace the values within the array and re-write the entire sheet with setValues(), or you can use setValue() to update the specific cells with matches one by one as you are currently doing.
See:
https://developers.google.com/apps-script/reference/spreadsheet/sheet#getdatarange
https://developers.google.com/apps-script/reference/spreadsheet/range#getvalues
Try this...
for (i=1; i<=rows; i++) {
for (j=1; j<=cols; j++) {
cellLoc = content.getCell(i, j);
cellValue = cellLoc.getValue();
if (cellLoc.getFormula()) {continue;}
try {
cellValue = cellValue.replace (find, replace);
cellLoc.setValue(cell);
}
catch (err) {continue;}
}
}
I took off every instance of content.getCell(i,j) and instead stored it into cellLoc. That way every time you need content.getCell(i,j), the program doesn't have to find the cell in the content, it can just look what the value of cellLoc is. Let me know if it works and if time has improved...
Well, I don't see much difference between this approach and my first one, but it replaces all matches instantly now:
function findReplace() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getDataRange();
var values = range.getValues();
var i, j, find, replace;
find = "hello";
replace = "bravo!!";
for (i = 0; i < values.length; i++) { //Run through all rows
for (j = 0; j < values[i].length; j++) { //Run through all columns
if (values[i][j] == find){
values[i][j] = replace;
}
}
}
range.setValues(values);
}

Select a record where value is max in CouchDB

I have a couchdb database with 156 json documents. I want to find the max of a certain value in the documents and then emit the whole document that contains that maximun value. I used this code but it doesnt seem to work. This may help you understand what i mean.
function(doc) {
var i,m;
for (i = 0; i < doc.watchers.length; i++)
m = Math.max(m,doc.watchers[i]);
for (i = 0; i < doc.watchers.length; i++)
if (m = doc.watchers[i])
emit(doc.watchers[i], doc.watchers);
}
I would also like to select the 2 top documents, that have the max value.
Just using a map function won't work because the way map/reduce works doesn't make available the complete set of keys and values to the map function at the same time.
I would use a reduce function for that. Something like this:
Map function
function(doc) {
var i,m;
for (i = 0; i < doc.watchers.length; i++) {
emit([doc._id, doc.watchers[i]], doc.watchers);
}
}
Reduce function
function(keys, values) {
var top=0;
var index=0;
for (i=0;i<keys.length;i++) {
if (keys[i][1] > top) {
top = keys[i][1];
index = i;
}
}
return({keys[index], values[index]})
}
For this strategy to work you need to query using group_level=1, so that couch passes the results grouped by document id to the map function.
I haven't tested this solution and it doesn't solve your second question yet. I can refine it if you think it goes the right way.

C# Loop through a collection and assign each object to a variable

I am sure this is quite simple but I cannot seem to get this right.
I have a built up a ICollection of Users. This collection could have 1 or many.
I now want to loop through this collection and assign a variable to each user that I can then use to fill in a spread sheet.
At present I have this code :
string username = null;
foreach (var user in dailyReport)
{
username = user.UserName;
}
Cell cell= worksheet.Cells["B5"];
cell.PutValue(username);
Now obviously this just puts the last user of the collection into cell B5!
How do I collect all user.UserNames so I can place them in B5, B6, B7 and so on????
To get a list of the user names:
List<string> userNames = dailyReport.Select( x=> x.UserName).ToList();
Alternatively you can just do the assignment in the loop directly:
int index = 5;
foreach (var user in dailyReport)
{
Cell cell= worksheet.Cells["B"+ index.ToString()];
cell.PutValue(user.UserName);
index++;
}
You need to put the value inside the foreach loop. The specific thing you are asking for--getting a different variable for every value in the collection--is not possible, and isn't what you want anyway.
string column = "B"; // or whatever your column is
int row = 1; // or whatever your starting value is
foreach (var user in dailyReport)
{
string username = user.UserName;
string cellAddress = String.Format("{0}{1}", column, row);
Cell cell = worksheet.Cells[cellAddress];
cell.PutValue(username);
row++; // make sure to increment the row, or every username goes in the same cell
}
int i = 5;
foreach (var user in dailyReport)
{
worksheet.Cells["B" + (i++).ToString()].PutValue(user.UserName);
}