由需求而產生的一款db導出excel的工具

程序員最大的毛病可能就是懶,因為懶所以做出了許許多多提高自己工作效率的工具.

起因於我是商業開發,既然是商業項目避免不了各種數據統計,雖然公司有專門的數據平台,但是應對一些臨時性需求還是免不了開發人員去導出一些數據.每一次有需求來我都是寫一個複雜的sql,然後放到DataGrip中執行,利用其功能導出cvs,然而越來越多的需求該功能無法滿足,比如導出組合表,也就是一個excel中有多個sheet表.那麼應該這個需求我寫了一個為自己的工具.

我理想中的工具

1.簡單模式使用sql查詢直接導出

2.複雜模式可以定義一些複雜的bean,然後通過組合代碼中自定義實現導出邏輯

3.可以自己定義表頭,以及對應的數據處理,比如把時間戳轉換為yyy-MM-dd hh:MM:ss這樣的形式

4.支持一個excel中含有多個sheet

5.不需要很複雜的配置,因為自用,所以能約定俗成的地方就約定俗成.

語言的選擇

這個很隨意了,我是選擇自己最熟悉的語言,也就是Java.

同事聽說我用Java寫這種工具,強烈推薦我用py,但天生動態語言無感,可以說是反感,所以放棄.

實現

DB連接: DBUtils

Excel: POI

具體過程很簡單,代碼邏輯也很清晰,這裡就不敘述了,直接放出Github地址,另外由於個人使用,所以沒有太多的校驗和異常考慮.

easy-excel github.com/mrdear/easy-)

另外分享一個IDEA從資料庫表生成對應Bean的腳本,使用方法自定義自己的extensions script即可.

import com.google.common.collect.Setsnimport com.intellij.database.model.DasTablenimport com.intellij.database.model.ObjectKindnimport com.intellij.database.util.Casenimport com.intellij.database.util.DasUtilnimport org.apache.commons.lang3.StringUtilsn/*n * Available context bindings:n * SELECTION Iterable<DasObject>n * PROJECT projectn * FILES files helpern */ntypeMapping = [n (~/(?i)tinyint/) : "Integer",n (~/(?i)int/) : "Long",n (~/(?i)float|double|decimal|real/): "Double",n (~/(?i)date|datetime|timestamp/) : "java.util.Date",n (~/(?i)time/) : "java.sql.Time",n (~/(?i)/) : "String"n]ncolTypeMapping = [n (~/(?i)tinyint/) : "TINYINT",n (~/(?i)int/) : "BIGINT",n (~/(?i)float|double|decimal|real/): "DECIMAL",n (~/(?i)datetime|timestamp/) : "TIMESTAMP",n (~/(?i)date/) : "TIMESTAMP",n (~/(?i)time/) : "TIMESTAMP",n (~/(?i)text/) : "LONGVARCHAR",n (~/(?i)/) : "VARCHAR"n]nFILES.chooseDirectoryAndSave("Choose directory", "Choose where to store generated files") { dir ->n SELECTION.filter { it instanceof DasTable && it.getKind() == ObjectKind.TABLE }.each {n generate(it, dir)n }n}ndef generate(table, dir) {n def packageName = getPackageName(dir)n def className = javaName(table.getName(), true)n def fields = calcFields(table)n //創建相關目錄 repository目錄下的n def path = dir.toString()n //創建pojo與xmln new File(path + File.separator + className + ".java").withPrintWriter { out -> generatePojo(out,n packageName, className, fields) }n}n/**n * 生成POJOn * @param outn * @param packageNamen * @param classNamen * @param fieldsn * @returnn */ndef generatePojo(out, packageName, className, fields) {n out.println "package ${packageName};"n out.println ""n out.println "@Data"n out.println "public class ${className} {"n out.println ""n fields.each() {n // 輸出注釋n if (StringUtils.isNoneEmpty(it.comment)) {n out.println " /**"n out.println " * ${it.comment}"n out.println " */"n }n if (it.annos != "") out.println " ${it.annos}"n out.println " private ${it.type} ${it.name};"n }n out.println ""n out.println "}"n}n// ------------方法 ---------------n/**n * 拿到所有的欄位n * @param table 資料庫表n * @return 欄位Objectn */ndef calcFields(table) {n DasUtil.getColumns(table).reduce([]) { fields, col ->n def spec = Case.LOWER.apply(col.getDataType().getSpecification())n def typeStr = typeMapping.find { p, t -> p.matcher(spec).find() }.valuen def colTypeStr = colTypeMapping.find { p, t -> p.matcher(spec).find() }.valuen fields += [[n colName: col.getName(),n name : javaName(col.getName(), false),n type : typeStr,n colType: colTypeStr,n comment: col.getComment(),n annos : ""]]n }n}n/**n * 獲取欄位對應的Java類名稱n */ndef javaName(str, capitalize) {n def s = str.split(/(?<=[^p{IsLetter}])/).collect { Case.LOWER.apply(it).capitalize() }n .join("").replaceAll("_", "")n capitalize || s.length() == 1 ? s : Case.LOWER.apply(s[0]) + s[1..-1]n}n/**n * 獲取包名稱n * @param dir 實體類所在目錄n * @returnn */ndef getPackageName(dir) {n def target = dir.toString().replaceAll("/", ".").replaceAll("^.*src(.main.java.)?", "")n return target.charAt(0) == . ? target.substring(1) : targetn}n

總結

本文的主要目的是表達迷茫的時候不知道自己該做什麼,那麼就從自己身邊的需求開始,分析自己所遇到的痛點,然後用你喜歡的方式去解決這個痛點,那麼這個過程就是你的進步.

本文作者:屈定

本文來源:由需求而產生的一款db導出excel的工具

版權說明:本文由極樂科技簽約作者原創,版權歸作者所有,轉載請註明作者及出處,謝謝!

小程序解決方案:99抵999元,開搶啦>>

推薦閱讀:

五步教你設計成功而有價值的數據可視化
Python幾種分組計數方法比較
數據化管理-商品採購
談談流計算
Human Resources Analytics——你會是下一個辭職的嗎?

TAG:SQL | 数据 | 数据分析 |