Skip to content

Commit 8318efb

Browse files
committed
Add transpose / juxtapose helpers for working with grids
1 parent ca5c313 commit 8318efb

File tree

1 file changed

+72
-3
lines changed

1 file changed

+72
-3
lines changed

src/excel_clj/core.clj

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,12 +202,81 @@
202202
(file/quick-open! {"Defaults" (table ["" 2018 2017] table-data)})))
203203

204204

205+
;;; Helpers to manipulate [[cell]] data structures
206+
207+
205208
(defn with-title
206-
[title [row & _ :as rows]]
209+
"Prepend a centered `title` row to the `grid` with the same width as the
210+
first row of the grid."
211+
[title [row & _ :as grid]]
207212
(let [width (count row)]
208213
(cons
209-
[(dims title {:width width})]
210-
rows)))
214+
[(-> title (dims {:width width}) (style {:alignment :center}))]
215+
grid)))
216+
217+
218+
(defn transpose
219+
"Transpose a grid."
220+
[grid]
221+
(apply mapv vector grid))
222+
223+
224+
(defn juxtapose
225+
"Put grids side by side (whereas `concat` works vertically, this works
226+
horizontally).
227+
228+
Optionally, supply some number of blank `padding` columns between the two
229+
grids.
230+
231+
Finds the maximum row width in the left-most grid and pads all of its rows
232+
to that length before sticking them together."
233+
([left-grid right-grid]
234+
(juxtapose left-grid right-grid 0))
235+
([left-grid right-grid padding]
236+
(let [;; First pad the height of both grids
237+
height (max (count left-grid) (count right-grid))
238+
empty-row []
239+
pad-height (fn [xs]
240+
(concat xs (repeat (- height (count xs)) empty-row)))
241+
242+
;; Then pad the width of the left grid so that it's uniform
243+
row-width (fn [row] (apply + (map (comp :width dims) row)))
244+
max-row-width (apply max (map row-width left-grid))
245+
pad-to (fn [width row]
246+
(let [cells-needed (- width (row-width row))]
247+
(into row (repeat cells-needed ""))))
248+
padded-left-grid (map
249+
(partial pad-to (+ max-row-width padding))
250+
(pad-height left-grid))]
251+
(map into padded-left-grid (pad-height right-grid)))))
252+
253+
254+
(comment
255+
"Example: juxtaposing two grids with different widths and heights"
256+
(let [squares (-> (table (for [i (range 10)] {"X" i "X^2" (* i i)}))
257+
(vec)
258+
(update 5 into [(dims "<- This one is 4^2" {:width 2})])
259+
(update 6 into ["^ Juxt should make room for that cell"]))
260+
cubes (table (for [i (range 20)] {"X" i "X^3" (* i i i)}))]
261+
(file/quick-open!
262+
{"Juxtapose" (juxtapose squares cubes)}))
263+
264+
"Example: A multiplication table"
265+
(let [highlight {:fill-pattern :solid-foreground
266+
:fill-foreground-color :yellow}
267+
268+
grid (for [x (range 1 11)]
269+
(for [y (range 1 11)]
270+
(cond-> (* x y) (= x y) (style highlight))))
271+
272+
cols (map #(style % {:font {:bold true}}) (range 1 11))
273+
274+
grid (concat [cols] grid)
275+
grid (juxtapose (transpose [(cons nil cols)]) grid)]
276+
(file/quick-open!
277+
{"Transpose & Juxtapose"
278+
(with-title "Multiplication Table" grid)})))
279+
211280

212281
;;; File interaction
213282

0 commit comments

Comments
 (0)