I hope I can make this makes sense....
I have gone through a bunch of other functions to end up with a variable that contains the data selected by a user from a drop down list on a sidebar to my google sheet.
The final function that that variable is sent to is like this:
function processFormResponse(formObject ){
reportMonth = formObject.chosenReport;
//result of reportMonth is a string. Example "Report_Nov 2017"
}
So now I have a variable called reportMonth that has what I need. But now, I want to write a vlookup that will select the same range every time but on a different sheet depending on the user selection (reportMonth).
From what I have researched, I cant use variable inside the vlookup, so I was going to write a custom function that does the lookup for me.
But here's my paradox: I cant use processFormResponse as my custom function because it has the formObject already inside its parameters because its already receiving information from the previous function and I cant do a separate function because I can't seem to get reportMonth to be global... (I with and without var)
I basically something like this:
=IFERROR(VLOOKUP($E3, reportMonth !$F:$J,2,false),"")
As mentioned in the Google Apps script documentation:
For the Range object:
setValue(value)
Sets the value of the range. The value can be numeric, string, boolean or date. If it begins with '=' it is interpreted as a formula.
So, if you have a 1-cell Range (a.k.a. a block of cells), then you could run
range.setValue("=IFERROR(VLOOKUP($E3,"+reportMonth+"!$F:$J,2,false),"")");
For Reference: https://developers.google.com/apps-script/reference/spreadsheet/range#setvaluevalue
Related
I have a Google Sheet where I am tracking various asset prices including crypto.
The easiest way to get crypto prices is by importing from cryptocurrencies.cc:
=importdata("https://cryptoprices.cc/AION/");
However, now my spreadheet is full of references to the cryptoprices.cc website. If it ever goes down or changes domain, I would have to replace the URL everywhere in my sheet, which is quite uncontrolled. So I thought about making a wrapper function:
function cryptofinance(token) {
return importdata("https://cryptoprices.cc/"+ token);
}
This returns an #Error! however: ReferenceError: importdata is not defined (line 94). I am assuming that you cannot call Google Sheet functions outside of the context of the Sheets cells, correct?
If not, what is the proper way to call importdata from within this function?
If yes, then what is the best alternative to retrieve the same information using javascript?
You cant use importdata like a formula at this place.
first you need to get cell refernce then
you need to put formula inside the setvalue() function;
var currentCell = SpreadsheetApp.getCurrentCell(); // Select cell here
currentCell.setValue('=importdata("https://cryptoprices.cc/"+ token)');
for select a range of cells you can use getRange() function
SpreadsheetApp.getRange(row,col).setValue('=importdata("https://cryptoprices.cc/AION/")');
change row, col with cells range.
I'm using a custom function to pull price data for EVE Online and I would only like the function to update upon a specific cell change. Instead it's updating every ~10-20 minutes which is using up a ton of my daily quota for URL Fetches.
Looking below you can see the main function is in a page labeled "Warehouse Stock". It pulls all price data for items in the "Item" column. The cell refreshes with a custom function that changes cell B4 in the utility sheet. When that cell changes it updates the values in the custom function because of the IF/THEN statement. Lastly the prices are loaded into the main sheet and sorted by the "product" column.
Also I have recalculation "On Change" and Iterative Calculation turned off.
Thank you for reading and any help you can provide.
The custom function is:
/**
* Query's Fuzz market API for the given types
* #param {range} A vertical range of type_ids.
* #return maxBuy and minSell for each type_id
* #customfunction
*/
function fuzzApiPriceData(type_ids) {
if (!type_ids) throw 'type_ids is required';
const ids = Array.isArray(type_ids) ? type_ids.map(id => id[0]) : [type_ids];
const fuzz_price_data = JSON.parse(UrlFetchApp.fetch(`https://market.fuzzwork.co.uk/aggregates/?station=60008494&types=${ids.join(',')}`));
return [['minSell', 'maxBuy']].concat(type_ids.map(type_id => [parseFloat(fuzz_price_data[type_id]['sell']['min']), parseFloat(fuzz_price_data[type_id]['buy']['max'])]));
}
i think there's a fairly basic misunderstanding here.
"Custom functions" are designed to be written in cells on a sheet. they are by there nature designed to run ALL the time, constantly updating.
If you are attempting to run a custom script, you do that from the script editor itself, you don't even write the function in a cell at ALL.
I'm assuming you didn't write the "custom function" you're using(?) So it will be a bit difficult (but not impossible!) to convert it to a script that writes to a certain place on the sheet at a certain time. But you might research a bit more about the difference between custom functions designed to be executed in cells, and scripts designed to be run on a time trigger.
Regarding you answer:
I would like the function to refresh everyday, aswell as having the option to manually refresh the function by the contents of the cell Utility!B4
I propose you to use Installable Triggers:
Time-driven trigger: It can execute a function each day at specific time.
Installable edit trigger: It can execute a function when a certain value in a specific cell changes.
However, if you want to execute a function manually, I recommend you to insert a drawing and assign a function to it.
Reference
Installable Triggers
Clickable images and drawings in Google Sheets
What I usually do for that is : put a checkbox in a cell. Then, when calling your custom function, add an extra reference to that cell, even if the parameter is not included in your custom function. Each time you will switch true/false, your custom function will be reactivated. Then you can also define another function with a trigger that just change the value of true/false. Here is an example in sheet 'Data' cell A3 : the function is getDataJSON(C1,A2:U2,A1) with A1 even if the custom function take into account only the first and second parameter. https://docs.google.com/spreadsheets/d/1DN0Gfim0LC098zVgrUpt2crPWUn4pWfZnCpuuL1ZiMs/edit?usp=sharing
I have a table in a form with a list of products where there is an input for each (let's call it 'pc'). Each input is named as 'pc' and product id with an id as the same. IE: 'pc100', 'pc101', etc. Each input has an onkeyup event to call a function to populate a price where I pass the product id (onkeyup='myfunction(100) The function receives the id but I cannot configure the javascript to that id. I will have the rest of the code as long as I can get the dynamic variable name. The internet is full of all kinds of things like eval() and window[] and I have tried every possible combination I can think of/find. I know it's possible to get this to work. So...how can I get this alert to work?
Most the results I will give me 'pc100' when I need 'Heres my test'
function myfunction(idpro) {
var pc331 = 'Heres my test';
alert( "pc" + idpro );
}
Don't use dynamic variable names. Do use look-ups in data structures:
function f(id) {
var pc = {
331: "Here's my test"
}
console.log(pc[id]);
}
Dynamic variables are a huge problem, especially from a security perspective. If you were naive and used eval someone could construct an id value that executes arbitrary JavaScript and then you have an XSS problem.
I have a large set of embedded data fields that are called rnd1, rnd2, rnd3 etc. In a certain question block, I stored to each of these a certain value (each a different random number).
I also have a Loop and Merge question block, and in each round, I would like to access the stored data of a different field (i.e. in the 1st round I'd like to access whatever is in rnd1, in the 2nd round access rnd2 etc.) Can this be done in Qualtrics?
I tried something like:
Qualtrics.SurveyEngine.addOnload(function()
{
var trialNum = this.questionId.split('_')[0]; // getting the loop's current round number
var EDname = "rnd"+trialNum; // name of desired EF field
var rndNum = "${e://Field/" + EDname + "}"; // this is where I'd like stored the right ED value
// some more code that uses rndNum
});
but this does not work. It seems that while EDname gets the right string, I cannot access the value of that embedded field this way (though var rndNum = "${e://Field/rnd1} does work and returns the right value, so the problem seems to be in the looping strucutre).
If I cannot loop over the different fields in the JS code for some reason, is there another clever way to get that done in Qualtrics? For example, I thought it may be possible to use the different field names in the Loop and Merge section as "Field 2", but this seem to require me setting manually each and every ED field name.
Thanks.
Piped embedded data fields are resolved on the server before the page gets sent to your browser. So, it is impossible to dynamically create an embedded data field name and resolve it on the client side with JavaScript.
The way you are doing it with a loop & merge field is the best way.
How can I change or update a data set's query after a parameter has been passed in BIRT report designing?
Detailing:
I've got a query that looks like this:
WHERE ?
That parameter marker can hold different values, after user input parameter, it would look like this e.g.:
WHERE column_name = 1
or
WHERE column_name = 2
or even
WHERE column_name IN (1,2)
I created a Report Parameter(RP) for that Data Set Parameter(DSP) and after trying for hours, I couldn't get to change it.
I tried:
Creating all sorts of javascript expressions on both, RP and DSP
Creating a RP that would change the value of the first RP and back to previous step
Editing the Property Binding, though I couldn't figure it out how exactly it should be done.
Just to make it clear, I'm designing a report and not integrating the runtime to an existing application.
I hope this is clear enough, I'm still editing the question so if you need more information just let me know.
Thanks
Assuming that you are on an Oracle DB (other systems may behave differently) you should be aware that a bind variable (in JDBC speech: the question mark) can replace a scalar value only, e.g. a string or a number.
But you want something like a list of numbers as input.
Thus a bind variable won't help you in this case.
Probably the easiest way to achieve what you want is this:
In your query, write:
WHERE column_name in (1) -- $REPLACE_THIS$
Note that I am using a comment in the query as a marker.
Then, in the query's beforeOpen event, modify the query text like this:
// construct a comma-separated string representation of your list
// based on your report parameter (exercise left to the reader)
// var replacement = my_to_sql_csv(params["my_report_parameter"].value);
// for demonstration use:
var replacement = "1,2";
// modify the `IN` expression inside the SQL
this.queryText = this.queryText.replaceAll("(1) -- $REPLACE_THIS$", "(" + replacement + ")";
That's it.