Skip to content

Commit

Permalink
Merge pull request #89 from k1LoW/xlsx
Browse files Browse the repository at this point in the history
Add `xlsx` output format
  • Loading branch information
k1LoW authored Apr 25, 2019
2 parents 82baf91 + d834c7c commit 470738e
Show file tree
Hide file tree
Showing 4 changed files with 243 additions and 13 deletions.
3 changes: 3 additions & 0 deletions cmd/out.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/k1LoW/tbls/output/dot"
"github.com/k1LoW/tbls/output/json"
"github.com/k1LoW/tbls/output/md"
"github.com/k1LoW/tbls/output/xlsx"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -97,6 +98,8 @@ var outCmd = &cobra.Command{
o = new(dot.Dot)
case "md":
o = md.NewMd(false, false, "")
case "xlsx":
o = new(xlsx.Xlsx)
default:
printError(fmt.Errorf("unsupported format '%s'", format))
os.Exit(1)
Expand Down
9 changes: 6 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ module github.com/k1LoW/tbls

require (
github.com/go-sql-driver/mysql v1.4.1
github.com/gobuffalo/packr v1.24.1
github.com/gobuffalo/packd v0.1.0 // indirect
github.com/gobuffalo/packr v1.25.0
github.com/labstack/gommon v0.2.8
github.com/lib/pq v1.0.0
github.com/lib/pq v1.1.0
github.com/loadoff/excl v0.0.0-20171207172601-c6a9e4c4b4c4
github.com/mattn/go-colorable v0.1.1 // indirect
github.com/mattn/go-isatty v0.0.7 // indirect
github.com/mattn/go-runewidth v0.0.4
Expand All @@ -13,7 +15,8 @@ require (
github.com/pmezard/go-difflib v1.0.0
github.com/spf13/cobra v0.0.3
github.com/xo/dburl v0.0.0-20190203050942-98997a05b24f
golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67 // indirect
golang.org/x/sys v0.0.0-20190424175732-18eb32c0e2f0 // indirect
golang.org/x/text v0.3.1 // indirect
google.golang.org/appengine v1.5.0 // indirect
gopkg.in/yaml.v2 v2.2.2
)
27 changes: 17 additions & 10 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTq
github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
github.com/gobuffalo/envy v1.6.15 h1:OsV5vOpHYUpP7ZLS6sem1y40/lNX1BZj+ynMiRi21lQ=
github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
github.com/gobuffalo/envy v1.7.0 h1:GlXgaiBkmrYMHco6t4j7SacKO4XUjvh5pwXh0f4uxXU=
github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs=
github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk=
Expand All @@ -21,10 +23,12 @@ github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9h
github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0 h1:P6naWPiHm/7R3eYx/ub3VhaW9G+1xAMJ6vzACePaGPI=
github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
github.com/gobuffalo/packr v1.24.1 h1:OHj/GZSjbG5B96rcf0m32hrBKDibssSx/CUDiYUJe20=
github.com/gobuffalo/packr v1.24.1/go.mod h1:absPnW/XUUa4DmIh5ga7AipGXXg0DOcd5YWKk5RZs8Y=
github.com/gobuffalo/packd v0.1.0 h1:4sGKOD8yaYJ+dek1FDkwcxCHA40M4kfKgFHx8N2kwbU=
github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
github.com/gobuffalo/packr v1.25.0 h1:NtPK45yOKFdTKHTvRGKL+UIKAKmJVWIVJOZBDI/qEdY=
github.com/gobuffalo/packr v1.25.0/go.mod h1:NqsGg8CSB2ZD+6RBIRs18G7aZqdYDlYNNvsSqP6T4/U=
github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
github.com/gobuffalo/packr/v2 v2.0.10/go.mod h1:n90ZuXIc2KN2vFAOQascnPItp9A2g9QYSvYvS3AjQEM=
github.com/gobuffalo/packr/v2 v2.1.0/go.mod h1:n90ZuXIc2KN2vFAOQascnPItp9A2g9QYSvYvS3AjQEM=
github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754 h1:tpom+2CJmpzAWj5/VEHync2rJGi+epHNIeRSWjzGA+4=
github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
Expand All @@ -35,16 +39,17 @@ github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqx
github.com/karrick/godirwalk v1.8.0 h1:ycpSqVon/QJJoaT1t8sae0tp1Stg21j+dyuS7OoagcA=
github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/labstack/gommon v0.2.8 h1:JvRqmeZcfrHC5u6uVleB4NxxNbzx6gpbJiQknDbKQu0=
github.com/labstack/gommon v0.2.8/go.mod h1:/tj9csK2iPSBvn+3NLM9e52usepMtrd5ilFYA+wQNJ4=
github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.1.0 h1:/5u4a+KGJptBRqGzPvYQL9p0d/tPR4S31+Tnzj9lEO4=
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/loadoff/excl v0.0.0-20171207172601-c6a9e4c4b4c4 h1:DNMe4L3ukcDtRt3Q/5Y4VcLnqs8iIo4hm6bPPt1OR1s=
github.com/loadoff/excl v0.0.0-20171207172601-c6a9e4c4b4c4/go.mod h1:nVZOIVwZIBGHgJj8QWr2IsA5E/hpqGObvtWfZHLkchM=
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2 h1:JgVTCPf0uBVcUSWpyXmGpgOc62nK5HWUBKAGc3Qqa5k=
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI=
Expand Down Expand Up @@ -88,18 +93,20 @@ github.com/xo/dburl v0.0.0-20190203050942-98997a05b24f/go.mod h1:g6rdekR8vgfVZrk
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190403202508-8e1b8d32e692/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67 h1:1Fzlr8kkDLQwqMP8GxrhptBLqZG/EDpiATneiZHY998=
golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190424175732-18eb32c0e2f0 h1:V+O002es++Mnym06Rj/S6Fl7VCsgRBgVDGb/NoZVHUg=
golang.org/x/sys v0.0.0-20190424175732-18eb32c0e2f0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1 h1:nsUiJHvm6yOoRozW9Tz0siNk9sHieLzR+w814Ihse3A=
golang.org/x/text v0.3.1/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190404132500-923d25813098/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c=
Expand Down
217 changes: 217 additions & 0 deletions output/xlsx/xlsx.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
package xlsx

import (
"fmt"
"io"
"io/ioutil"
"strings"

"github.com/k1LoW/tbls/schema"
"github.com/loadoff/excl"
"github.com/pkg/errors"
)

// Xlsx struct
type Xlsx struct{}

// OutputSchema output Xlsx format for full relation.
func (x *Xlsx) OutputSchema(wr io.Writer, s *schema.Schema) error {
w, err := excl.Create()
if err != nil {
return err
}
err = createSchemaSheet(w, s)
if err != nil {
return err
}
for _, t := range s.Tables {
err = createTableSheet(w, t)
if err != nil {
return err
}
}
tf, _ := ioutil.TempFile("", "tbls.xlsx")
path := tf.Name()
defer tf.Close()
w.Save(path)
b, err := ioutil.ReadFile(path)
if err != nil {
return err
}
_, err = wr.Write(b)
if err != nil {
return err
}
return nil
}

// OutputTable output Xlsx format for table.
func (x *Xlsx) OutputTable(wr io.Writer, t *schema.Table) error {
w, err := excl.Create()
if err != nil {
return err
}
err = createTableSheet(w, t)
if err != nil {
return err
}
tf, _ := ioutil.TempFile("", "tbls.xlsx")
path := tf.Name()
defer tf.Close()
w.Save(path)
b, err := ioutil.ReadFile(path)
if err != nil {
return err
}
_, err = wr.Write(b)
if err != nil {
return err
}
return nil
}

func createSchemaSheet(w *excl.Workbook, s *schema.Schema) error {
sheetName := fmt.Sprintf("Tables of %s", s.Name)
sheet, err := w.OpenSheet(sheetName)
defer sheet.Close()
if err != nil {
return errors.WithStack(err)
}
setString(sheet, 1, 1, s.Name).SetFont(excl.Font{Bold: true})

setString(sheet, 3, 1, "Tables").SetFont(excl.Font{Bold: true})
setHeader(sheet, 4, []string{"Name", "Columns", "Comment", "Type"})
n := 5
for i, t := range s.Tables {
setStringWithBorder(sheet, n+i, 1, t.Name)
setNumberWithBorder(sheet, n+i, 2, len(t.Columns))
setStringWithBorder(sheet, n+i, 3, t.Comment)
setStringWithBorder(sheet, n+i, 4, t.Type)
}

return nil
}

func createTableSheet(w *excl.Workbook, t *schema.Table) error {
sheetName := t.Name
sheet, err := w.OpenSheet(sheetName)
defer sheet.Close()
if err != nil {
return errors.WithStack(err)
}

setString(sheet, 1, 1, t.Name).SetFont(excl.Font{Bold: true})
setString(sheet, 2, 1, t.Comment)

setString(sheet, 4, 1, "Columns").SetFont(excl.Font{Bold: true})
setHeader(sheet, 5, []string{"Name", "Type", "Default", "Nullable", "Children", "Parents", "Comment"})
r := 6
for i, c := range t.Columns {
setStringWithBorder(sheet, r+i, 1, c.Name)
setStringWithBorder(sheet, r+i, 2, c.Type)
setStringWithBorder(sheet, r+i, 3, c.Default.String)
setStringWithBorder(sheet, r+i, 4, fmt.Sprintf("%v", c.Nullable))
children := []string{}
for _, child := range c.ChildRelations {
children = append(children, child.Table.Name)
}
setStringWithBorder(sheet, r+i, 5, strings.Join(children, "\n"))
parents := []string{}
for _, parent := range c.ParentRelations {
parents = append(parents, parent.ParentTable.Name)
}
setStringWithBorder(sheet, r+i, 6, strings.Join(parents, "\n"))
setStringWithBorder(sheet, r+i, 7, c.Comment)
}
r = r + len(t.Columns)

if len(t.Constraints) > 0 {
r++
setString(sheet, r, 1, "Constraints").SetFont(excl.Font{Bold: true})
r++
setHeader(sheet, r, []string{"Name", "Type", "Definition"})
r++
for i, c := range t.Constraints {
setStringWithBorder(sheet, r+i, 1, c.Name)
setStringWithBorder(sheet, r+i, 2, c.Type)
setStringWithBorder(sheet, r+i, 3, c.Def)
}
}
r = r + len(t.Constraints)

if len(t.Indexes) > 0 {
r++
setString(sheet, r, 1, "Indexes").SetFont(excl.Font{Bold: true})
r++
setHeader(sheet, r, []string{"Name", "Definition"})
r++
for i, idx := range t.Indexes {
setStringWithBorder(sheet, r+i, 1, idx.Name)
setStringWithBorder(sheet, r+i, 2, idx.Def)
}
}
r = r + len(t.Indexes)

if len(t.Triggers) > 0 {
r++
setString(sheet, r, 1, "Triggers").SetFont(excl.Font{Bold: true})
r++
setHeader(sheet, r, []string{"Name", "Definition"})
r++
for i, trg := range t.Triggers {
setStringWithBorder(sheet, r+i, 1, trg.Name)
setStringWithBorder(sheet, r+i, 2, trg.Def)
}
}

return nil
}

func setHeader(sheet *excl.Sheet, rowNo int, values []string) {
for i, v := range values {
sheet.SetColWidth(10, i+1)
setStringWithBorder(sheet, rowNo, i+1, v).SetFont(excl.Font{Bold: true})
}
}

func setNumber(sheet *excl.Sheet, rowNo int, colNo int, v int) *excl.Cell {
row := sheet.GetRow(rowNo)
return row.SetNumber(v, colNo)
}

func setNumberWithBorder(sheet *excl.Sheet, rowNo int, colNo int, v int) *excl.Cell {
return setNumber(sheet, rowNo, colNo, v).SetBorder(excl.Border{
Left: &excl.BorderSetting{Style: "thin"},
Right: &excl.BorderSetting{Style: "thin"},
Top: &excl.BorderSetting{Style: "thin"},
Bottom: &excl.BorderSetting{Style: "thin"},
})
}

func setString(sheet *excl.Sheet, rowNo int, colNo int, v string) *excl.Cell {
row := sheet.GetRow(rowNo)
return row.SetString(v, colNo)
}

func setStringWithBorder(sheet *excl.Sheet, rowNo int, colNo int, v string) *excl.Cell {
return setString(sheet, rowNo, colNo, v).SetBorder(excl.Border{
Left: &excl.BorderSetting{Style: "thin"},
Right: &excl.BorderSetting{Style: "thin"},
Top: &excl.BorderSetting{Style: "thin"},
Bottom: &excl.BorderSetting{Style: "thin"},
})
}

func setFormula(sheet *excl.Sheet, rowNo int, colNo int, v string) *excl.Cell {
row := sheet.GetRow(rowNo)
return row.SetFormula(v, colNo)
}

func setFormulaWithBorder(sheet *excl.Sheet, rowNo int, colNo int, v string) *excl.Cell {
return setFormula(sheet, rowNo, colNo, v).SetBorder(excl.Border{
Left: &excl.BorderSetting{Style: "thin"},
Right: &excl.BorderSetting{Style: "thin"},
Top: &excl.BorderSetting{Style: "thin"},
Bottom: &excl.BorderSetting{Style: "thin"},
})
}

0 comments on commit 470738e

Please # to comment.