I know this question might sound wierd. But i am a noob to google sheets and trigger operations.Here's the problem, Lets say I have two cols in a sheet col_Link and col_value. col_link contains a link to another sheet and second one is obvious. I have to get the value from the col_link first and perform some operations then while performing second operation I still need this col_Link's link.
Now i have a installed onEdit() trigger which performs this operation but Im stuck on this little thing.
Code:
var c = e.range.getColumn();
var r = e.range.getRow();
var val = e.range.getValue();
if (c==1){
Link_operation(val,row,col); // this val contains link.
}
else if(c==2){
Value_operation(link,val,row,col);
// here val is some value. I want this function to somehow also has the link from col_Link.
}
Since the value can only contain either the link or the value.
What should be my approach to get this? Should I change the way I'm approaching this problem or is it possible to achieve multiple values like this?
Will appreciate any help.
Your question is a little vague and probably should include a screenshot or better detail of what exactly is your expected outcome.
If you want to get multiple values from an onEdit(e) trigger that weren't in the edited range then as master suggested, offsetting is the way to do it.
function onEdit(e) {
var sheet = SpreadsheetApp.getActiveSheet();
var c = e.range.getColumn();
var r = e.range.getRow();
var val = e.range.getValue();
var link = sheet.getRange(r, c - 1).getValue();
Logger.log(link);
}
In this example if the cell B6 is edited then the value in A6 will be logged.
Related
I might not be able to explain better, but I will try my best. I have two columns say A and B, in column A there are formulas so values in them get changed depending on some other conditions, Now what I want in column B is to paste/setvalue the value for the first time whenever a value appears in column A, so that when there are any further changes in column A, it wouldn't affect the value that is pasted in column B. Although I have tried my best to write the script, it does paste the value but it pastes in all the column and does not care if any cell in column A is empty.
I have gone through a lot of research but could not find an answer. Although OnEdit can work but as the column from which the value is to be got has formulas in it and OnEdit doesn't work on formulas. So once the script is corrected, we can trigger it to time driven.
I just need the help to make this function work correctly, I will be highly thankful for any help. thank you.
function pastevalue(){
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('sheet1');
var lastrow = ss.getRange("A2:B").getValues().filter(String).length;
var range = ss.getRange(2,1,lastrow);
var pasterange = ss.getRange(2,2,lastrow);
var values = range.getValues().filter(String);
var pastevalues = pasterange.getValues();
for (i=0; i<values.length; i++){
if(pastevalues[i] == ""){
var value = pasterange.setValue(values[i])
}
}
}
I presume that your goal is to grab the numerical value of a formula immediately after you enter it, so that if the displayed value in the cell of the formula changes in the future, you still possess the original value that the formula yielded. The following script accomplishes that:
function onEvent(e){
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
if (e.range.getColumn() == 1 && typeof e.oldValue == 'undefined'){
sheet.getRange(e.range.getRow(), 2).setValue(e.range.getValue());
}
}
Note that it is an event trigger, meaning it runs every time the spreadsheet is, well, edited. As the parameter of the function we grab the event that triggered the script (you can read how they are structured here), and then we check for two conditions that both have to be true to copy the value into the B column:
First we check that the column of the cell modified is the A (1st) column.
Then we check that the cell was blank before modification. This will mean that the value will only be copied when a formula is written in a blank cell.
first of all I need to say that I do not have any experience in programming. I tried to wrap my head around JavaScript in the course of the last 7 days and although I find the world that opens up through programming really fascinating, I did not get past a very, very rough general understanding.
What I have so far:
I´m currently working on a Google Sheet that automatically imports JSON data out of a list from a webpage. The import of the JSON data works fine und the result is a Google Sheet with 100 cells and 13 columns after the JSON-Import that gets updated every minute through a Timer.
What my problem is:
The list on the webpage I´m scraping my data from contains only 100 cells (never more then 100 cells). So when new data is fed in the list of the webpage, older entries just vanish out of the list and make space for newer entries. This leads to the situation that with every JSON import I do, only the most recent 100 cells will be imported, although I still want to keep the old cells in my Google Sheet that are not shown on the webpage anymore.
Basically I´m looking for a script that extracts the most recent JSON import from my main sheet (Name:"TXs") into a new sheet (Name:Convert). "Convert" should then be constantly compared to "TXs" if new values have been added/scraped. What will happen is that after some time the list of the most recent JSON Imports in "TXs" will contain cells that are not yet updated in "Convert" and cells that vanished/made space in "TXs" that are still present in "Convert".
Webpage Scrapes in "TXs" before cell update on webpage:
Type
Result balance
Column C
ADDRESS D
3947
...
ADDRESS C
9386
...
ADDRESS B
9286
...
ADDRESS A
1837
...
Webpage Scrapes in "TXs" after cell update on webpage:
Type
Result balance
Column C
ADDRESS E
1456
...
ADDRESS D
3947
...
ADDRESS C
9386
...
ADDRESS B
9286
...
While Address E is a new cell that got updated on the page, Address A is now missing and not listed anymore.
Sheet "Convert" however should contain ALL the information, even the Addresses that are not present anymore on the webpage:
Sheet "Convert" after running the script:
Type
Result balance
Column C
ADDRESS E
1456
...
ADDRESS D
3947
...
ADDRESS C
9386
...
ADDRESS B
9286
...
ADDRESS A
1837
...
What I´ve tried so far:
I experimented a bit with the code someone provided here on stackoverflow, however this code does not really work for me. It keeps copying all rows from "TXs" into "Convert" after it detects a change in "TXs".
function updateSheet() {
var ss = SpreadsheetApp.getActive();
var sourceValues = ss.getSheetByName("TXs").getRange("A2:M").getValues().filter(String);
var targetSheet = ss.getSheetByName("Convert");
var targetRange = targetSheet.getRange("A2:M");
var targetColumn = targetRange.getColumn();
var targetRow = targetRange.getRow();
var targetValues = targetRange.getValues().filter(String);
var diff = targetValues.showDif(sourceValues)
targetRange.clearContent();
targetValues = (diff && diff.length) ? targetValues.concat(diff) : targetValues;
targetSheet.getRange(targetRow, targetColumn, targetValues.length, targetValues[0].length).setValues(targetValues);
}
Array.prototype.showDif = function (array) {
var that = this;
return array.filter(function (r) {
return !that.some(function (x) {
return r.join() === x.join();
})
})
}
I hope I explained it more or less understandable. Sorry in case I´ve used wrong terminology at some points, as I said: I´m a total newbie.
Many thanks in advance,
Jan
Here the link to my sheet:
https://docs.google.com/spreadsheets/d/1js11rdG6IWdfps00kuFaWk5VOP_Ve7ltvfdPWKlKVrA/
I have a script that successfully copies data from one Google Spreadsheet to another. What I'm trying to figure out is how to write the data to say Column 5 and not Column 1. When I alter the script to write the data to Column 5, it processes the data but shows a "cell reference out of range" error.
Here is the code that successfully copies data to Column 1.
'function copy_data() {
var source = SpreadsheetApp.openById('1iQm5NDahmUqXXLDAFvVkrNqooHd2-AAEDVRXndEWXbw').getSheetByName('Account-Category Database');
var target = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet25');
var lastdatarow = source.getLastRow();
var criteria = target.getRange('A1').getValue();
var codedata = source.getRange(3,2,lastdatarow,2).getValues();
var codeout = [];
for (var i=2 in codedata) {
if (codedata[i][0] == criteria || codedata[i][0] == "All") {
codeout.push(codedata[i])
}
}
target.getRange(2,1,codedata.length,codedata[0].length).setValues(codedata).sort(2);
}
PROBLEM:
When I change the bottom of the formula to:
target.getRange(2,5,codedata.length,codedata[0].length).setValues(codedata).sort(2);
}
That's when I get the "Cell reference out of range" error. Again, the data still copies, it just stops the next function from running because of the error.
Turns out I'm just an idiot =) The error with the code was trying to ".sort(2)"... That means I was trying to sort the target sheet by Column 2, when I was writing data to columns 5... thus Column 2 was out of range... Changing it to ".sort(5)" corrected the issue.
Hopes this helps others understand their potential future issue.
I have a small problem with a program I am trying to create. It is supposed to figure out how much exp it would take to bring an ability to a certain level. I have not yet gotten that far, as I am having trouble with the return at the end of the CalculateCost function. I was trying to pass an array of strings back to the function which called CalculateCost, however, this wasn't working, so I tried to join all the values into a single string. This also didn't work. I know that the variable that I am trying to return is not null, as I am using ui.alert() quite frequently to check variables' values. Any help would be greatly appreciated.
Here is the google sheet in question.
https://docs.google.com/spreadsheets/d/1Xo_uppFDI_C65EVi-TZ1iHTseK-Fg1izyCRkeTKaV9k/edit?usp=sharing
The script with the issue is called Ability Price Calculator.
It seems the problem was that function CalculateCost did not return anything...
function CalculateCost(abilityValues,index,level) {
var ui = SpreadsheetApp.getUi();
var ss = SpreadsheetApp.getActive();
var sheet = ss.getActiveSheet();
ui.alert("CalculateCost");
FindRequirements(abilityValues,index,sheet,level);
// current function returns nothing!
}
/* You may have thought, "oh but CalculateCost() already does the return,
so there's no need". However, when we call a function that contains
a return, it's as though we just paste the value that it returns.
Plus, there was no command (alert, prompt, etc) at the end of your
non-return-function, which made no sense. It made no sense to Google
at least, so it was... undefined. */
So I changed it to
function CalculateCost(abilityValues,index,level) {
var ui = SpreadsheetApp.getUi();
var ss = SpreadsheetApp.getActive();
var sheet = ss.getActiveSheet();
ui.alert("CalculateCost");
var reqs = FindRequirements(abilityValues,index,sheet,level); // notice the reqs var
return reqs; // this line was missing
}
Besides, I ran into problems when troubleshooting your code: my main issue was that when we click on CalculateCost in the menu, we normally expect to call the CalculateCost() function, however we actually call the InputValues() function. It's easy to get lost when custom functions are not tied to the same menu item, so maybe you could change that later.
Please, could you let me know if my answer helped you with your code?
This one might be a bit basic and easy to answer, but I've been pulling out my hair for a while now!
I've built the following code - which is semi-pseudo as I can't find the right way to make things work!
var s = "Test";
function onEdit(event)
{
var ss = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if (ss.getName() == s)
{
results = {"Currently On": 0, "Next Up": 0, "On Hold": 0, "Waiting on someone else": 0, "zDone": 0};
last = ss.getMaxRows();
start = ss.getRange("F3:"+last).getValues();
var output = "J11";
for (x=0;x<start.length;x++)
{
results[start[x]]++;
}
for (y=0;y<results.length;y++)
{
row = ss.getRow(output);
row.value = results[y];
output++;
}
}
}
I've got an example of the data in this image
The basic idea is to run through all the possible categories of each task and keep a numeric list on the side of how many of each there are. I'd also like to make it dynamic (so I don't have to hard code in the list of categories) but I'm more interested in just making it work for the moment.
The Google Apps debugger is very frustrating!
Thanks for your help all!
Firstly, this particular use case would be easily achievable with a spreadsheet formula, eg:
=QUERY(A2:F;"select F, count(A) where F != '' group by F label count(A) 'Count'";1)
but there may be a reason why you want to do this with GAS.
So secondly, this is where I think there may be some syntax issues:
last = ss.getMaxRows();
I would just use var last = ss.getLastRow() here.
start = ss.getRange("F3:"+last).getValues();
The range reference would evaluate to something like "F3:100", which is a valid reference in GSheets (don't know about whether GAS can handle it), but nevertheless you really want something like "F3:F100", so I would use var start = ss.getRange("F3:F"+last).getValues();.
results[start[x]]++;
When you create an array from a getValues() call it is a 2D array, so you would need to use results[start[x][0]]++;.
With the next loop and the output variable, I must admit I'm a bit lost with what you're doing there. How did you want your result table laid out?
You have
output = "J11";
And then you do
ss.getRow(output);
output++;
This is invalid.First of all, ss is a Sheet under which there is not getRow method. So, what you should really be doing is something like this
var row = 11 ;
var col = 10 ; //Col J
for (y=0;y<results.length;y++)
{
ss.getRange(row,col,1,1).setValue(results[y]);
row++:
}
Like AdamL, I suggest that this is better handled within the native capability of the spreadsheet. Seems to me that you want a pivot table, which would update dynamically. Alternatively a formula like =countif(F:F,"Currently On" ) would meet your immediate request. =Unique(F:F) will give you the list of categories in an array