|
10 | 10 |
|
11 | 11 | See the (comment) form with examples at the bottom of this namespace."
|
12 | 12 | {:author "Matthew Downey"}
|
13 |
| - (:require [excel-clj.cell :refer [style data dims wrapped?]] |
| 13 | + (:require [clojure.pprint :as pprint] |
| 14 | + [clojure.string :as string] |
| 15 | + |
| 16 | + [excel-clj.cell :refer [data dims style wrapped?]] |
| 17 | + [excel-clj.deprecated :as deprecated] |
14 | 18 | [excel-clj.file :as file]
|
15 | 19 | [excel-clj.tree :as tree]
|
16 |
| - [excel-clj.deprecated :as deprecated] |
17 |
| - |
18 |
| - [clojure.string :as string] |
19 | 20 |
|
20 | 21 | [taoensso.tufte :as tufte])
|
21 | 22 | (:import (clojure.lang Named)
|
|
53 | 54 |
|
54 | 55 | :else nil)))
|
55 | 56 |
|
56 |
| - |
57 | 57 | (defn table-grid
|
58 | 58 | "Build a lazy sheet grid from `rows`.
|
59 | 59 |
|
|
374 | 374 | (file/quick-open-pdf! workbook))
|
375 | 375 |
|
376 | 376 |
|
| 377 | +;; Convenience macro to redirect print-table / print-tree to excel |
| 378 | + |
| 379 | + |
| 380 | +(defonce ^:private var->excel-rebinding (atom {})) |
| 381 | + |
| 382 | + |
| 383 | +(defn declare-excelable! |
| 384 | + "Redefine some function's `var` to generate Excel output when enclosed in an |
| 385 | + `excel` macro. |
| 386 | +
|
| 387 | + The `fn` returns a grid (optionally with :excel/sheet-name metadata)." |
| 388 | + [var fn] |
| 389 | + (swap! var->excel-rebinding assoc var fn)) |
| 390 | + |
| 391 | + |
| 392 | +(declare-excelable! #'pprint/print-table |
| 393 | + (fn ;; This fn has the same signature as the var it's redefining |
| 394 | + ([rows] (vary-meta (table-grid rows) merge (meta rows))) |
| 395 | + ([ks rows] (vary-meta (table-grid ks rows) merge (meta rows))))) |
| 396 | + |
| 397 | + |
| 398 | +(declare-excelable! #'tree/print-table |
| 399 | + (fn this |
| 400 | + ([rows] |
| 401 | + (this |
| 402 | + (into [""] (remove #{"" :tree/indent}) (keys (data (first rows)))) |
| 403 | + rows)) |
| 404 | + ([ks rows] |
| 405 | + (vary-meta |
| 406 | + (table-grid ks |
| 407 | + (map |
| 408 | + (fn [{:keys [tree/indent] :as row}] |
| 409 | + (update row "" #(str (apply str (repeat (or indent 0) " ")) %))) |
| 410 | + rows)) |
| 411 | + merge (meta rows))))) |
| 412 | + |
| 413 | + |
| 414 | +(defn -build-excel-rebindings [wb-atom var->excel-rebinding] |
| 415 | + (letfn [(conj-page [sheets contents] |
| 416 | + (let [sheet-name (or (:excel/sheet-name (meta contents)) |
| 417 | + (str "Sheet" (inc (count sheets))))] |
| 418 | + (conj sheets [sheet-name contents]))) |
| 419 | + (conj-page! [contents] (swap! wb-atom conj-page contents))] |
| 420 | + (update-vals var->excel-rebinding |
| 421 | + (fn [grid-fn] (comp conj-page! grid-fn))))) |
| 422 | + |
| 423 | + |
| 424 | +(defmacro excel |
| 425 | + "Build an Excel workbook with whatever data is emitted during the execution |
| 426 | + of `body` from functions on which `declare-excelable!` has been called. |
| 427 | +
|
| 428 | + If the first argument is a compile-time map, it may contain a :hook function |
| 429 | + to be called with the final workbook. If no hook is passed, it defaults to |
| 430 | + `quick-open!`. |
| 431 | +
|
| 432 | + (Compatible by default for `clojure.pprint/print-table` and |
| 433 | + `excel-clj.tree/print-table`.) |
| 434 | +
|
| 435 | + Returns the return value of `body`." |
| 436 | + [& body] |
| 437 | + (let [[opts body] (if (map? (first body)) |
| 438 | + [(first body) (rest body)] |
| 439 | + [{} body]) |
| 440 | + hook (or (:hook opts) quick-open!)] |
| 441 | + `(let [wb# (atom [])] |
| 442 | + (with-redefs-fn (-build-excel-rebindings wb# ~(deref var->excel-rebinding)) |
| 443 | + (fn [] |
| 444 | + (let [ret# (do ~@body)] |
| 445 | + (~hook (apply array-map (mapcat identity @wb#))) |
| 446 | + ret#)))))) |
| 447 | + |
| 448 | + |
| 449 | +(comment |
| 450 | + ;; For example |
| 451 | + (excel |
| 452 | + (do |
| 453 | + ;; Print a table to one sheet |
| 454 | + (pprint/print-table (map (fn [i] {"Ch" (char i) "i" i}) (range 33 43))) |
| 455 | + ;; And a tree to another |
| 456 | + (let [tbl (tree/table (tree/combined-header) tree/mock-balance-sheet)] |
| 457 | + (tree/print-table tbl)) |
| 458 | + :ok))) |
| 459 | + |
| 460 | + |
377 | 461 | ;; Some v1.X backwards compatibility
|
378 | 462 |
|
379 | 463 |
|
|
0 commit comments