diff --git a/src/dk/ative/docjure/spreadsheet.clj b/src/dk/ative/docjure/spreadsheet.clj index f5e7c16..b11afca 100644 --- a/src/dk/ative/docjure/spreadsheet.clj +++ b/src/dk/ative/docjure/spreadsheet.clj @@ -3,6 +3,7 @@ (java.io FileOutputStream FileInputStream InputStream OutputStream) (java.util Date Calendar) (org.apache.poi.xssf.usermodel XSSFWorkbook) + (org.apache.poi.xssf.streaming SXSSFWorkbook) (org.apache.poi.hssf.usermodel HSSFWorkbook) (org.apache.poi.ss.usermodel Workbook Sheet Cell Row FormulaError @@ -186,7 +187,7 @@ (when new-key {new-key (read-cell cell)}))) -(defn select-columns +(defn select-columns "Takes two arguments: column hashmap and a sheet. The column hashmap specifies the mapping from spreadsheet columns dictionary keys: its keys are the spreadsheet column names and the values represent @@ -289,6 +290,40 @@ (add-rows! sheet data) workbook)) +(defn with-streaming-workbook! + "Creates new XLSX workbook. + body-fn takes as an argument function that appends new + row to the worksheet. Works in streaming mode with constant + memory requirements. + + Example: + (with-streaming-workbook! \"Test.xlsx\" \"SHEETNAME\" + (fn [append-row!] + (doseq [i (range 2000)] + (append-row! (range i)))))" + [file-name sheet-name body-fn] + (let [wb (SXSSFWorkbook. 1) + ^Sheet sh (add-sheet! wb sheet-name) + row-num (atom 0) + append-row! + (fn [row-data] + (let [r (.createRow sh @row-num)] + (swap! row-num inc) + (doseq [[j value] (map-indexed #(list %1 %2) row-data)] + (set-cell! (.createCell r j) value))))] + (try + (body-fn append-row!) + (save-workbook-into-file! file-name wb) + (finally + (.dispose wb))))) + +(defn save-data-to-xlsx! + "Create new XLSX workbook and stream data into the sheet." + [file-name sheet-name data] + (with-streaming-workbook! file-name sheet-name + (fn [append-row!] + (doseq [row data] (append-row! row))))) + (defn create-xls-workbook "Create a new XLS workbook with a single sheet and the data specified." [sheet-name data]