Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Add xlsx output format #89

Merged
merged 3 commits into from
Apr 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"},
})
}