I have a query statement pulling data from multiple sheets, which works fine:
=QUERY({'A Physical Science'!A2:L; 'B Physical Science'!A2:L; 'E Physical Science'!A2:L; 'F Physical Science'!A2:L; 'G Physical Science'!A2:L},"select Col11 where Col6 is not null",0)
When I tried creating a dynamic source for the data range though, it no longer works. I successfully created a text string formula that matches the original data range exactly
{'A Physical Science'!A2:L; 'B Physical Science'!A2:L; 'E Physical Science'!A2:L; 'F Physical Science'!A2:L; 'G Physical Science'!A2:L}
but no matter how I call the data range in a neighboring QUERY statement, it just returns the text string. INDEX, ARRAYFORMULA, INDIRECT, curly brackets, nothing brings the data range text string to life.
#Ruben, I added my old function to your script to be dynamic, and have it triggered to run when the google sheet is opened. Just checking if there is a more elegant way of accomplishing this?
function RangeArray() {
const skiplast = 5; //last 5 sheets need not be arrayed
var data = ""; //initialize string that will be the data range
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
for (var i=0 ; i<sheets.length - skiplast ; i++) {
data = data + "'"+ [ sheets[i].getName() ] + "'!A2:Z" ; //append the sheet names to the data string, plus necessary bits for parsing
if (i<sheets.length - skiplast -1) {data = data + ";"} //except for the last sheet, also append a semicolon
else {}
}
const here = SpreadsheetApp.getActiveSpreadsheet().getRange('DO NOT EDIT!A1');
const formula = '{'+ data +'}'; // make an array out of the data string
here.setFormula(formula);
}
There is no way to convert a cell value like
{'A Physical Science'!A2:L; 'B Physical Science'!A2:L; 'E Physical Science'!A2:L; 'F Physical Science'!A2:L; 'G Physical Science'!A2:L}
into an Google Sheets array using Google Sheets built-in functions but it is possible to use Google Apps Script, to use this value as the parameter of one of the setFormula methods, i.e.:
function addArray(){
const a1 = SpreadsheetApp.getActiveSpreadsheet().getRange('Sheet1!A1');
const formula = `{'A Physical Science'!A2:L; 'B Physical Science'!A2:L; 'E Physical Science'!A2:L; 'F Physical Science'!A2:L; 'G Physical Science'!A2:L}`;
a1.setFormula(formula);
}
Related
I want to present the user with a list of 'FParsec parsers'-plus-'test data' from which they can interactively select and see the results of the parser run on the supplied text.
Specifically, am trying to collect my parser tests in a list of records of this type:
type FUNCTION_TEST =
| XELEMENT_MATCH of label : string * func : Parser<(int * string), unit> * data : string
| XKEYVALUE_MATCH of label : string * func : Parser<(string * string), unit> * data : string
let testable_parsers = [( "xElement", xElement, xElement_text3)
( "xKeyValue", xKeyValue, xKeyValue_text)]
xKeyValue above throws the error...
val xKeyValue: Parser<(string * string), unit>
Full name CustomParser.xKeyValue
FS0001:the type '(int * string)' does not match the type 'string * string'
I want the user to see and choose a label string and see the results of running the parser.
I understand that the parser xElement : Parser<int * string, unit> does not match parser xKeyValue : Parser<(string * string), unit>. Both sub-types are part of the FUNCTION_TEST discriminated union BUT I cannot put the parsers in the same list because their sub-types (XELEMENT_MATCH versus XKEYVALUE_MATCH) disagree.
I wanted to handle this using a match ... with over the discriminated union.
I am new to F# and FParsec and out of elegant ideas. Do I have to hard-code a menu with do! and printfs?
How do experienced F# and FParsec developers allow users to select from a menu of options of different types?
I think the best approach would be to restructure your data so that you keep all the common things (label and data) in a record, together with a value representing the function - which can then be a discriminated union with a case for each type:
type Function =
| Element of Parser<(int * string), unit>
| KeyValue of Parser<(string * string), unit>
type Test =
{ Label : string
Data : string
Function : Function }
Now you can create a list of Test values, which you can easily iterate over to get all the labels & data:
let testableParsers =
[ { Label = "xElement"; Function = Element(xElement); Data = xElement_text3 }
{ Label = "xKeyValue"; Function = KeyValue(xKeyValue); Datta = xKeyValue_text } ]
You will still need to use pattern matching when you want to run a specific Function, because this will have to handle the different values you get as a result, but you won't need pattern matching elsewhere.
I'm a bit confounded by the FUNCTION_TEST type. It looks like you're never using the type or any of its constructors, and if so, why did you define that type in the first place?
After pondering the possible motives you may have had, it looks like perhaps you wanted the testable_parsers list to contain values of the FUNCTION_TEST type so that you can later match on them?
If that is the case, then what you have is not what you intended: the list that you have constructed contains tuples of three values.
In order to construct values of the FUNCTION_TEST type, you need to apply its constructors:
testableParsers = [
XELEMENT_MATCH ("xElement", xElement, xElement_text3)
XKEYVALUE_MATCH ("xKeyValue", xKeyValue, xKeyValue_text)
]
But if your only purpose is to present a choice to the user, then I wouldn't even bother with a special type to represent the options. You can just pair labels with functions to be called when the user chooses the label:
testableParsers = [
"xElement", fun() -> runParser xElement xElement_text3
"xKeyValue", fun() -> runParser xKeyValue xKeyValue_text
]
This way you don't have to do a match on the values of FUNCTION_TEST either, just call the function.
For a class I'm following, I have to do the following exercise:
Implement a function
let splitAt (i : int) (l : List<'a>) : List<'a> * List<'a> = ...
that splits the list into two lists, the rst one containing all the elements of l from position 0 to position i
included, and the second one containing all the remaining elements. The two resulting lists are returned
in a tuple. For example:
split 3 [3;5;4;-1;2;2] = ([3;5;4;-1],[2;2])
We have to do these problems only using functional programming, and thus I'm not allowed to use pre-existing functions.
I have the following code which seems to me to (logically) be correct:
let splitAt (i:int)(l: List<'a>): List<'a> * List<'a> =
let rec loop n startlist restlist =
if n = i then
restlist * startlist
else
match startlist with
| h :: t -> loop (n+1) [t] [(restlist :: h)]
| h :: [] -> None
loop 0 l []
and below my [<EntryPoint>]
printfn "%A" (splitAt stringlist 3)
However, this gives me a couple of errors, namely:
None of the types 'a list, 'a list support the operator *
This expression was expected to have type int but here has type char list
This expression was expected to have type List<'a> but here has type int
The * operator is used for declaring a tuple type, but when you're building a tuple you use , instead. So you want restlist, startlist.
Then you'll discover that there's another type error, because one branch of your match expression returns None. That's an option type, so the value you return should be a Some. So you want Some (restlist, startlist).
And now you'll discover one more type error, which is that you've declared that the function returns a tuple but in fact it returns a tuple option (that is, either None or Some tuple). So your type declaration needs to become (List<'a> * List<'a>) option.
For more on why * is used in declaring tuple types rather than ,, https://fsharpforfunandprofit.com/posts/tuples/ is a good read.
I am currently studying F# and at the same time, a bit struggling to get the hang of how discriminated unions and records exactly work.
I'd like to know how I can update some values from a list of type <'T>?
My code
type Position =
| Location of (int * int)
type Ship =
{
Position : Position;
Projectiles : List<Position>;
}
I create an instance of a ship:
let aShip =
{
Position: Location(1,5);
Projectiles: [Location(1,1);Location(2,5)]
}
Now, I tried to loop over the projectiles, but I get this:
for elem in aShip.Projectiles do
printfn "%A" elem
// prints out
Location(1,1)
Location(2,5)
But I only like to get the values (1,1) and (2,5) back, how would I achieve this?
Discriminated unions can be destructured by providing a pattern with some places in it occupied by identifiers. The compiler will then generate code that tries to match this pattern to the data, and bind data points to appropriate identifiers. For example:
let loc = Location (1,2)
let (Location (x,y)) = loc
For the second line, the compiler will generate code to the effect of "make sure this is a Location, then bind the first int to name x, and the second int to name y"
Alternatively, you can use more verbose match syntax:
let x = match loc with Location(x,y) -> x
For your specific case, this is overkill, but for discriminated unions with more than one case, match is the only way to handle them all, for example:
type Position =
| Location of int*int
| Unknown
let xOrZero =
match loc with
| Location(x,y) -> x
| Unknown -> 0
Above examples demonstrate how patterns can appear in let-bindings and within match expressions, but this is not all. In F# pretty much anything that you'd think of as "variable declaration" is actually a pattern. It's just most of the time patterns are trivial, as in let x = 5, but they don't have to be - e.g. let x,y = 5,6
The corollary from the above is that the elem in for elem in ... is also a pattern. Which means that you can destructure the element in place:
for Location(x,y) in aShip.Projectiles do
printfn "%d,%d" x y
Or, if you'd like to extract the pair as a whole, rather than x and y individually, that is also possible:
for Location xy in aShip.Projectiles do
printfn "%A" xy
When using union types with quite a few constructors I almost always find myself implementing lots of logic in single function, i.e. handling all cases in one function. Sometimes I would like to extract logic for single case to separate function, but one cannot have a function accepting only one "constructor" as parameter.
Example:
Assume that we have typical "expression" type :
type Formula =
| Operator of OperatorKind * Formula * Formula
| Number of double
| Function of string * Formula list
[...]
Then, we would like to calculate expression :
let rec calculate efValues formula =
match formula with
| Number n -> [...]
| Operator (kind, lFormula, rFormula) -> [...]
| [...]
Such function would be very long and growing with every new Formula constructor.
How can I avoid that and clean up such code? Are long pattern matching constructs inevitable?
You can define the Operator case of the Formula union using an explicit tuple:
type Formula =
| Operator of (string * Formula * Formula)
| Number of double
If you do this, the compiler will let you pattern match using both Operator(name, left, right) and using a single argument Operator args, so you can write something like:
let evalOp (name, l, r) = 0.0
let eval f =
match f with
| Number n -> 0.0
| Operator args -> evalOp args
I would find this a bit confusing, so it might be better to be more explicit in the type definition and use a named tuple (which is equivalent to the above):
type OperatorInfo = string * Formula * Formula
and Formula =
| Operator of OperatorInfo
| Number of double
Or perhaps be even more explicit and use a record:
type OperatorInfo =
{ Name : string
Left : Formula
Right : Formula }
and Formula =
| Operator of OperatorInfo
| Number of double
Then you can pattern match using one of the following:
| Operator args -> (...)
| Operator { Name = n; Left = l; Right = r } -> (...)
I would say you typically want to handle all the cases in a single function. That's the main selling point of unions - they force you to handle all the cases in one way or another. That said, I can see where you're coming from.
If I had a big union and only cared about a single case, I would handle it like this, wrapping the result in an option:
let doSomethingForOneCase (form: Formula) =
match form with
| Formula (op, l, r) ->
let result = (...)
Some result
| _ -> None
And then handle None in whatever way is appropriate at the call site.
Note that this is in line with the signature required by partial active patterns, so if you decide that you need to use this function as a case in another match expression, you can easily wrap it up in an active pattern to get the nice syntax.
I'm using an active pattern to parse usage events in a csv formatted usage log. The active pattern part is listed below. Parsing the whole file in works well and the sequence that is produced is filled with all sorts of UsageEvents.
type SystemName = string
type SystemVersion = string
type MAC = string
type Category = string
type Game = string
type Setting = string
type StartupLocation = string
type UsageEvent =
| SystemStart of DateTime * SystemVersion * SystemName * MAC
| SystemEnd of DateTime
| GameStart of DateTime * Category * Game * Setting * StartupLocation
| GameEnd of DateTime * Category * Game
| Other
let (|SystemStart|SystemEnd|GameStart|GameEnd|Other|) (input : string list) =
match List.nth input 0 with
| "SystemStartedEvent" ->
SystemStart (DateTime.Parse (List.nth input 1), List.nth input 2, List.nth input 3, List.nth input 4)
| "SystemEndedEvent" ->
SystemEnd (DateTime.Parse (List.nth input 1))
| "GameStartedEvent" ->
GameStart (DateTime.Parse (List.nth input 1), List.nth input 2, List.nth input 3, List.nth input 4, List.nth input 5)
| "GameEndedEvent" ->
GameEnd (DateTime.Parse (List.nth input 1), List.nth input 2, List.nth input 3)
| _ ->
Other
The problem I have is that I'm probably using the ActivePattern in the wrong way. I'd like to walk the list to create a tree out of it based on some logic, but I have no way to match an entry in the sequence after parsing.
let CountSystemStart (entries : UsageEvent list) =
let rec loop sum = function
| SystemStart(_,_,_,_) -> sum + 1
| _ -> sum
loop 0 entries
This matching does not work because the loop function required a string list. In what other way could I use the data contained in the unions or should I match the input and then store it in a regular type?
To add to #Petr's answer - UsageEvent cases and your active pattern cases have the same names, so the active pattern which is defined later shadows the union type. That's where the string list thing comes from, most likely.
I would just drop the active pattern altogether, and add a Parse function (or rather a ParseParts, since you want to feed it a list of strings) to the UsageEvent.
type UsageEvent =
| SystemStart of DateTime * SystemVersion * SystemName * MAC
| (...and so on...)
static member ParseParts (input: string list) =
match input with
| ["SystemStartedEvent"; date; version; name; mac] ->
SystemStart (DateTime.Parse date, version, name, mac)
| (...and so on...)
Active patterns are cute, but you really need a good scenario for them to shine. Otherwise if you can get away with using a plain function, just use a plain function.
There are 2 problems with this code:
Discriminated union UsageEvent and active pattern choice functions have the same names
recursive loop function is not recursive as it is written - it doesn't call itself.
When you are matching on UsageEvent list try use full type name.
I would rewrite your CountSystemStart function as:
let CountSystemStart (entries : UsageEvent list) =
let rec loop sum = function
| [] -> sum
| (UsageEvent.SystemStart(_))::rest -> loop (sum + 1) rest
| _::rest -> loop sum rest
loop 0 entries