# Writing bindings for Google Apps Script (GAS)

**URL:** <https://discuss.ocaml.org/t/writing-bindings-for-google-apps-script-gas/6293>\
**Category:** Learning\
**Created:** [August 25, 2020, 8:05pm UTC](https://discuss.ocaml.org/t/writing-bindings-for-google-apps-script-gas/6293 "2020-08-25T20:05:42Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Danielo\_Rodriguez](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/danielo_rodriguez/32/1202_2.png) [@Danielo\_Rodriguez](https://discuss.ocaml.org/u/Danielo_Rodriguez)\
**Post date:** [August 25, 2020, 8:05pm UTC](https://discuss.ocaml.org/t/writing-bindings-for-google-apps-script-gas/6293/1 "2020-08-25T20:05:42Z")

</div>

Hello,  
Thanks to the help of this community I successfully completed a crazy idea: To write some ocaml functions to use inside [Google Apps Script](https://developers.google.com/apps-script) for a small stupid spreadsheet that I had.

The way it works now is by having a main index.js file that calls the Ocaml functions that are available under a global Lib namespace. Everything is bundled using parcel and the Idea was to use as few JS code as possible. Because it was easier than I expected I decided to go one step further and write some bindings for the GAS functions I was using and reduce the glue JS code even more.

This are the bindings that I wrote so far. They work, but are not usable inside Ocaml yet.

```ocaml
type spreadsheet
type sheet
type range
external getActiveSpreadsheet : unit -> spreadsheet = "getActiveSpreadsheet" [@@bs.val][@@bs.scope "SpreadsheetApp"]
external getSheets : spreadsheet -> sheet array = "getSheets" [@@bs.send]
external getSheetByName : spreadsheet -> string -> sheet = "getSheetByName" [@@bs.send]
external getDataRange : sheet -> range = "getDataRange" [@@bs.send]
external getValues : range -> 'a array array = "getValues" [@@bs.send]

```

My doubt are on the edges. When it is just obscure GAS stuff I have no doubt, abstract types and functions to interact with them. Is when a GAS function returns data where I have doubts. Usually they are just arrays of arrays of Numbers or Strings. In the example above, the last definition says that you will get an array of arrays of `'a`, but that is not true because it will be an array of “stuff” (strings, numbers, floats).  
How should I type it in a way that it’s flexible but not cumbersome? For example, I don’t think using a functor will help because you will need to create a functor for every possible return type, in my case if you have 3 sheets with 3 different shapes, you will need 3 functors.  
An alternative that I have used was to provide some helper functions to convert from JS to Ocaml types and then unwrap the Ocaml types, like the example I’m doing with Number\_or\_string.  
This is nothing serious and I will just add the bindings that I may need for now, but I want to hear what the community (and potential users) thinks.

If anyone is interested in taking a look on the project, it is here: [https://github.com/danielo515/ElectronicProjectsSpreadsheet](https://github.com/danielo515/ElectronicProjectsSpreadsheet)

Regards

---

<div class="post-metadata">

**Author:** ![ttamttam](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/ttamttam/32/132_2.png) [@ttamttam](https://discuss.ocaml.org/u/ttamttam)\
**Post date:** [August 26, 2020, 1:51am UTC](https://discuss.ocaml.org/t/writing-bindings-for-google-apps-script-gas/6293/2 "2020-08-26T01:51:50Z")

</div>

Not answering directly to your question, sorry.

But here is a binding I have been using for around 4 years: [https://dubuget.fr/gitea/matthieu/ocaml-google-app.git](https://dubuget.fr/gitea/matthieu/ocaml-google-app.git).

Best regards

---

<div class="post-metadata">

**Author:** ![bobzhang](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/bobzhang/32/553_2.png) [@bobzhang](https://discuss.ocaml.org/u/bobzhang)\
**Post date:** [August 26, 2020, 3:14am UTC](https://discuss.ocaml.org/t/writing-bindings-for-google-apps-script-gas/6293/3 "2020-08-26T03:14:50Z")

</div>

> Is when a GAS function returns data where I have doubts. Usually they are just arrays of arrays of Numbers or Strings.

For return type polymorphism, you can use GADT with bs.ignore, the rough idea:

```ocaml
type 'a t = Int : int t | String : string t 
external f : ('a t [@bs.ignore]) -> ... -> 'a = "xx"

```

I read [discuss.ocaml.org](http://discuss.ocaml.org) from time to time, but checks [https://forum.rescript-lang.org/](https://forum.rescript-lang.org/) daily where you can get a quick answer

---

<div class="post-metadata">

**Author:** ![Danielo\_Rodriguez](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/danielo_rodriguez/32/1202_2.png) [@Danielo\_Rodriguez](https://discuss.ocaml.org/u/Danielo_Rodriguez)\
**Post date:** [August 26, 2020, 6:12am UTC](https://discuss.ocaml.org/t/writing-bindings-for-google-apps-script-gas/6293/4 "2020-08-26T06:12:27Z")

</div>

Not a direct answer, but a very interesting one.  
I would love to see some usage examples, specially out of the Range module, because It’s how you manage Ojs.t data what I’m most intrigued by. There are some modules that has a conversion function, but the ones that return actual data do not, and I don’t know how you handle such data later in a type safe way in ocaml.

---

<div class="post-metadata">

**Author:** ![Danielo\_Rodriguez](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/danielo_rodriguez/32/1202_2.png) [@Danielo\_Rodriguez](https://discuss.ocaml.org/u/Danielo_Rodriguez)\
**Post date:** [August 26, 2020, 6:20am UTC](https://discuss.ocaml.org/t/writing-bindings-for-google-apps-script-gas/6293/5 "2020-08-26T06:20:59Z")

</div>

Thanks for the answer @bobzhang  
Is that OCaml or rescript syntax?  
It’s impressive how many times I read that two lines of code and I’m still trying to understand it. Are the `...`a placeholder or it’s the actual thing to put there?  
What is the usage of `f`? Is it meant to convert to whatever type you want or what?

I’m not sure if I made clear what my doubt is, but what I want is, to run a GAS function that returns an array of unknown JS types and being able to process/manipulate/read those types as safely as possible from OCaml, even if that requires some helper functions to check the type.  
So for example, I run `Range.getValues(r)` and then pass that data as row to below function to work with it:

```ocaml
let pick_columns (a,b) (row: row): (string * int) option =
  let open Number_or_string in
  match classify(row.(a)), classify(row.(b)) with
  | String x, Int y -> Some (x, y)
  | _ -> None

```

---

<div class="post-metadata">

**Author:** ![ttamttam](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/ttamttam/32/132_2.png) [@ttamttam](https://discuss.ocaml.org/u/ttamttam)\
**Post date:** [November 14, 2020, 4:09pm UTC](https://discuss.ocaml.org/t/writing-bindings-for-google-apps-script-gas/6293/6 "2020-11-14T16:09:47Z")

</div>

Sorry for the late reply… I just found your question some minutes ago.

I simply use the conversion functions provided by Ojs when needed ([Ojs signature](https://github.com/LexiFi/gen_js_api/blob/master/lib/ojs.mli)).

As an example, here is one function of my codebase (randomly picked) using `Ojs.string_o_js`:

```ocaml
let next_num_bon () =
  let datas = all_data_range () in
  Range.offset datas ~row_offset:0 ~column_offset:(col "Id")
    ~num_rows:(Range.get_num_rows datas) ~num_columns:1
  |> Range.get_values
  |> Array.fold_left
       (fun last n ->
         let nb =
           try Ojs.string_of_js n.(0) |> int_of_string with Failure _ -> 0
         in
         if nb > last then nb else last)
       0
  |> succ

```

Best regards
