Skip to content

Instantly share code, notes, and snippets.

@simonmichael
Created October 28, 2018 00:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save simonmichael/cca05bac19499ba4ac7a70d1944647fe to your computer and use it in GitHub Desktop.
Save simonmichael/cca05bac19499ba4ac7a70d1944647fe to your computer and use it in GitHub Desktop.
get-google-sheet-csv.hs - stack script to fetch google sheets as CSV
#!/usr/bin/env stack
{- stack --resolver=lts-9.21 script --compile
--package "bytestring cassava gogol gogol-core gogol-sheets lens pretty-show text"
--verbosity=info
-}
{-
INSTALL:
Get stack if needed, eg from https://haskell-lang.org/get-started
Run "get-google-sheet-csv.hs" once to compile. On Windows, run "stack get-googlesheet-csv.hs".
SET UP ACCESS:
Set up a service account at https://console.developers.google.com/iam-admin/serviceaccounts,
selecting or creating a project
Save the service account's email address
Create a key and download as json to ~/.config/gcloud/KEYFILE.json
Symlink this to ~/.config/gcloud/application_default_credentials.json
Share spreadsheets with the service account's email address
USAGE:
get-google-sheet-csv SPREADSHEETID SHEETNAME - print specified sheet as CSV
-}
{-# LANGUAGE PackageImports #-}
module Main
where
import "lens" Control.Lens
import qualified "bytestring" Data.ByteString.Lazy as B
import "cassava" Data.Csv
import qualified "text" Data.Text as T
import "gogol" Network.Google
import "gogol-sheets" Network.Google.Sheets
import "base" System.Environment
import "base" System.IO
-- import "base" Debug.Trace
-- import "pretty-show" Text.Show.Pretty (pPrint, ppShow)
main = do
[spreadsheetId, sheetName] <- map T.pack <$> getArgs
let range = sheetName -- ++"!A1:J10"
lgr <- newLogger Info stdout
env <- newEnv <&> (envLogger .~ lgr) . (envScopes .~ spreadsheetsReadOnlyScope)
values <- view vrValues <$> (runResourceT . runGoogle env $ send (spreadsheetsValuesGet spreadsheetId range))
B.putStr $ Data.Csv.encode $ map (map bs) values
where bs = drop 8 . init . show -- no more time for hilariously craptastic haskell libs
------------------------------
-- notes
-- import Data.Aeson
-- import Data.Text (Text)
-- import Network.Google.Data.JSON
-- import Network.Google.Resource.Sheets.Spreadsheets.Get
{-
TODO:
get-google-sheet-csv [-h] - show help
get-google-sheet-csv SPREADSHEETID - get first sheet
get-google-sheet-csv SPREADSHEETID SHEETNAME RANGE - get just the specified cells
-}
{-
Notes for developers of stack (1.9.1) scripts:
1. In the stack header above, flags' position and style are critical.
Minor variations cause very different behaviour.
2. For different run actions, adjust the stack command:
script --optimize - run compiled, after compiling if needed
script --compile - run compiled, after compiling if needed (without optimisation)
script - run interpreted (slower)
exec runghc - run interpreted using ambient GHC package db
exec ghc - compile
exec ghci - load in GHCI
exec ghcid - watch for compile errors
3. To silence "Using resolver:" output (but also deps install output), change --verbosity to warn
4. Declare which package each import is from, keep synced with --package; might as well be clear
5. Doc: https://docs.haskellstack.org/en/stable/GUIDE/#script-interpreter
-}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment