-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathbbexcel
executable file
·140 lines (122 loc) · 4.21 KB
/
bbexcel
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#!/usr/bin/env bb
(require '[babashka.deps :as deps])
(deps/add-deps '{:deps {com.github.kbosompem/bb-excel {:mvn/version "0.1.1"}}})
(ns bbexcel
(:require [bb-excel.core :refer [get-sheets get-range get-sheet]]
[clojure.java.io :refer [file make-parents copy]]
[org.httpkit.client :as c]
[clojure.tools.cli :refer [parse-opts]]
[clojure.string :refer [split join lower-case trim] :as str]
[clojure.pprint :refer [print-table]])
(:gen-class))
(set! *warn-on-reflection* true)
(defn ts [] (str (.getTime (java.util.Date.)) ".xlsx"))
(defn- fetch-spreadsheet!
[url]
(let [req @(c/get url {:as :byte-array :throw-exceptions false})]
(when (= (:status req) 200)
(:body req))))
(defn- save-spreadsheet!
[{:keys [url name]}]
(println "Saving spreadsheet to " name)
(some-> (fetch-spreadsheet! url) (copy (file "./" name)))
name)
(defn left
"Takes up to n characters from a string"
[s n]
(cond (and s (string? s))
(subs s 0 (max 0 (min (count s) n)))
(coll? s) (take n s)))
(defn skeyword
"Sanitizes column headers and converts them to keywords.
1. Removes slashes and spaces
2. Lower cases
3. Takes up to 50 characters
4. Replaces non-ascii characters with an underscore.
**Not appropriate for foreign language headers"
[s]
(keyword
(left
(str/replace
(str/replace (trim (lower-case (str s))) #"[\[\]]" "")
#"[^A-Za-z0-9\-]+" "_") 50)))
(def fxns
"Map of functions"
{:str str
"str" str
:keyword keyword
"keyword" keyword
:skeyword skeyword
"skeyword" skeyword
nil str})
(defn bbexcel
"Extract Excel Sheets into EDN"
[input-file options]
(let [l4 (lower-case (left input-file 4))
tx (ts)
input (if (= "http" l4)
(save-spreadsheet! {:url input-file :name tx})
input-file)]
(cond
(:print options) (doseq [y (get-sheets input options)]
(println :SHEET= (:name y))
(print-table (:sheet y)))
(:output options) (let [_ (make-parents (:output options))]
(spit (:output options)
(with-out-str (clojure.pprint/pprint
(get-sheets input options)))))
(:range options) (get-range (get-sheet input (:sheet options)) (:range options))
:else (spit (str input ".edn")
(pr-str (get-sheets input options))))))
(def cli-options
"Command Line Options"
[["-d" "--hdr" "Use Header Row"]
["-r" "--row r" "Start Row"
:parse-fn #(parse-long %)
:desc "Start Row e.g -r 2 will start reading from row 2"]
["-n" "--rows s" "End Row"
:parse-fn #(parse-long %)
:desc "End Row .e.g -n 10 will stop reading at the 10th row"]
["-f" "--fxn f" "Header Function"
:parse-fn fxns
:desc "Header Functions to choose from str, keyword, skeyword "]
["-o" "--output o" "Output"
:desc "Save output to file"]
["-s" "--sheet x" "Sheet"
:desc "Sheet Name"]
["-p" "--print"
:desc "Print Tables"]
["-g" "--range g" "Range"
:desc "Range to Export"]
["-c" "--columns c"
:parse-fn #(map keyword (split % #" "))
:desc "Columns"]
["-h" "--help"]])
(defn error-msg
"Error messages"
[errors]
(str "The following errors occurred while parsing your command:\n"
(join \newline errors)))
(defn help
"Command line options"
[summary]
(->> ["bbexcel 0.1.1 Read Excel Files with Babashka"
""
"Usage: bbexcel input-file options"
""
"Options:"
summary
""
"Please refer to the manual page for more information."]
(join \newline)))
(defn -main [& args]
(let [{:keys [options arguments summary errors]}
(parse-opts (first args) cli-options)
[input] arguments]
(cond
errors (println (error-msg errors))
(nil? input) (println (help summary))
(or (nil? (first args))
(:help options)) (println (help summary))
:else (bbexcel input options))))
(-main *command-line-args*)