README.md
1ASCII Table Writer
2=========
3
4[![Build Status](https://travis-ci.org/olekukonko/tablewriter.png?branch=master)](https://travis-ci.org/olekukonko/tablewriter)
5[![Total views](https://img.shields.io/sourcegraph/rrc/github.com/olekukonko/tablewriter.svg)](https://sourcegraph.com/github.com/olekukonko/tablewriter)
6[![Godoc](https://godoc.org/github.com/olekukonko/tablewriter?status.svg)](https://godoc.org/github.com/olekukonko/tablewriter)
7
8Generate ASCII table on the fly ... Installation is simple as
9
10 go get github.com/olekukonko/tablewriter
11
12
13#### Features
14- Automatic Padding
15- Support Multiple Lines
16- Supports Alignment
17- Support Custom Separators
18- Automatic Alignment of numbers & percentage
19- Write directly to http , file etc via `io.Writer`
20- Read directly from CSV file
21- Optional row line via `SetRowLine`
22- Normalise table header
23- Make CSV Headers optional
24- Enable or disable table border
25- Set custom footer support
26- Optional identical cells merging
27- Set custom caption
28- Optional reflowing of paragraphs in multi-line cells.
29
30#### Example 1 - Basic
31```go
32data := [][]string{
33 []string{"A", "The Good", "500"},
34 []string{"B", "The Very very Bad Man", "288"},
35 []string{"C", "The Ugly", "120"},
36 []string{"D", "The Gopher", "800"},
37}
38
39table := tablewriter.NewWriter(os.Stdout)
40table.SetHeader([]string{"Name", "Sign", "Rating"})
41
42for _, v := range data {
43 table.Append(v)
44}
45table.Render() // Send output
46```
47
48##### Output 1
49```
50+------+-----------------------+--------+
51| NAME | SIGN | RATING |
52+------+-----------------------+--------+
53| A | The Good | 500 |
54| B | The Very very Bad Man | 288 |
55| C | The Ugly | 120 |
56| D | The Gopher | 800 |
57+------+-----------------------+--------+
58```
59
60#### Example 2 - Without Border / Footer / Bulk Append
61```go
62data := [][]string{
63 []string{"1/1/2014", "Domain name", "2233", "$10.98"},
64 []string{"1/1/2014", "January Hosting", "2233", "$54.95"},
65 []string{"1/4/2014", "February Hosting", "2233", "$51.00"},
66 []string{"1/4/2014", "February Extra Bandwidth", "2233", "$30.00"},
67}
68
69table := tablewriter.NewWriter(os.Stdout)
70table.SetHeader([]string{"Date", "Description", "CV2", "Amount"})
71table.SetFooter([]string{"", "", "Total", "$146.93"}) // Add Footer
72table.SetBorder(false) // Set Border to false
73table.AppendBulk(data) // Add Bulk Data
74table.Render()
75```
76
77##### Output 2
78```
79
80 DATE | DESCRIPTION | CV2 | AMOUNT
81-----------+--------------------------+-------+----------
82 1/1/2014 | Domain name | 2233 | $10.98
83 1/1/2014 | January Hosting | 2233 | $54.95
84 1/4/2014 | February Hosting | 2233 | $51.00
85 1/4/2014 | February Extra Bandwidth | 2233 | $30.00
86-----------+--------------------------+-------+----------
87 TOTAL | $146 93
88 --------+----------
89
90```
91
92
93#### Example 3 - CSV
94```go
95table, _ := tablewriter.NewCSV(os.Stdout, "testdata/test_info.csv", true)
96table.SetAlignment(tablewriter.ALIGN_LEFT) // Set Alignment
97table.Render()
98```
99
100##### Output 3
101```
102+----------+--------------+------+-----+---------+----------------+
103| FIELD | TYPE | NULL | KEY | DEFAULT | EXTRA |
104+----------+--------------+------+-----+---------+----------------+
105| user_id | smallint(5) | NO | PRI | NULL | auto_increment |
106| username | varchar(10) | NO | | NULL | |
107| password | varchar(100) | NO | | NULL | |
108+----------+--------------+------+-----+---------+----------------+
109```
110
111#### Example 4 - Custom Separator
112```go
113table, _ := tablewriter.NewCSV(os.Stdout, "testdata/test.csv", true)
114table.SetRowLine(true) // Enable row line
115
116// Change table lines
117table.SetCenterSeparator("*")
118table.SetColumnSeparator("╪")
119table.SetRowSeparator("-")
120
121table.SetAlignment(tablewriter.ALIGN_LEFT)
122table.Render()
123```
124
125##### Output 4
126```
127*------------*-----------*---------*
128╪ FIRST NAME ╪ LAST NAME ╪ SSN ╪
129*------------*-----------*---------*
130╪ John ╪ Barry ╪ 123456 ╪
131*------------*-----------*---------*
132╪ Kathy ╪ Smith ╪ 687987 ╪
133*------------*-----------*---------*
134╪ Bob ╪ McCornick ╪ 3979870 ╪
135*------------*-----------*---------*
136```
137
138#### Example 5 - Markdown Format
139```go
140data := [][]string{
141 []string{"1/1/2014", "Domain name", "2233", "$10.98"},
142 []string{"1/1/2014", "January Hosting", "2233", "$54.95"},
143 []string{"1/4/2014", "February Hosting", "2233", "$51.00"},
144 []string{"1/4/2014", "February Extra Bandwidth", "2233", "$30.00"},
145}
146
147table := tablewriter.NewWriter(os.Stdout)
148table.SetHeader([]string{"Date", "Description", "CV2", "Amount"})
149table.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false})
150table.SetCenterSeparator("|")
151table.AppendBulk(data) // Add Bulk Data
152table.Render()
153```
154
155##### Output 5
156```
157| DATE | DESCRIPTION | CV2 | AMOUNT |
158|----------|--------------------------|------|--------|
159| 1/1/2014 | Domain name | 2233 | $10.98 |
160| 1/1/2014 | January Hosting | 2233 | $54.95 |
161| 1/4/2014 | February Hosting | 2233 | $51.00 |
162| 1/4/2014 | February Extra Bandwidth | 2233 | $30.00 |
163```
164
165#### Example 6 - Identical cells merging
166```go
167data := [][]string{
168 []string{"1/1/2014", "Domain name", "1234", "$10.98"},
169 []string{"1/1/2014", "January Hosting", "2345", "$54.95"},
170 []string{"1/4/2014", "February Hosting", "3456", "$51.00"},
171 []string{"1/4/2014", "February Extra Bandwidth", "4567", "$30.00"},
172}
173
174table := tablewriter.NewWriter(os.Stdout)
175table.SetHeader([]string{"Date", "Description", "CV2", "Amount"})
176table.SetFooter([]string{"", "", "Total", "$146.93"})
177table.SetAutoMergeCells(true)
178table.SetRowLine(true)
179table.AppendBulk(data)
180table.Render()
181```
182
183##### Output 6
184```
185+----------+--------------------------+-------+---------+
186| DATE | DESCRIPTION | CV2 | AMOUNT |
187+----------+--------------------------+-------+---------+
188| 1/1/2014 | Domain name | 1234 | $10.98 |
189+ +--------------------------+-------+---------+
190| | January Hosting | 2345 | $54.95 |
191+----------+--------------------------+-------+---------+
192| 1/4/2014 | February Hosting | 3456 | $51.00 |
193+ +--------------------------+-------+---------+
194| | February Extra Bandwidth | 4567 | $30.00 |
195+----------+--------------------------+-------+---------+
196| TOTAL | $146 93 |
197+----------+--------------------------+-------+---------+
198```
199
200#### Example 7 - Identical cells merging (specify the column index to merge)
201```go
202data := [][]string{
203 []string{"1/1/2014", "Domain name", "1234", "$10.98"},
204 []string{"1/1/2014", "January Hosting", "1234", "$10.98"},
205 []string{"1/4/2014", "February Hosting", "3456", "$51.00"},
206 []string{"1/4/2014", "February Extra Bandwidth", "4567", "$30.00"},
207}
208
209table := tablewriter.NewWriter(os.Stdout)
210table.SetHeader([]string{"Date", "Description", "CV2", "Amount"})
211table.SetFooter([]string{"", "", "Total", "$146.93"})
212table.SetAutoMergeCellsByColumnIndex([]int{2, 3})
213table.SetRowLine(true)
214table.AppendBulk(data)
215table.Render()
216```
217
218##### Output 7
219```
220+----------+--------------------------+-------+---------+
221| DATE | DESCRIPTION | CV2 | AMOUNT |
222+----------+--------------------------+-------+---------+
223| 1/1/2014 | Domain name | 1234 | $10.98 |
224+----------+--------------------------+ + +
225| 1/1/2014 | January Hosting | | |
226+----------+--------------------------+-------+---------+
227| 1/4/2014 | February Hosting | 3456 | $51.00 |
228+----------+--------------------------+-------+---------+
229| 1/4/2014 | February Extra Bandwidth | 4567 | $30.00 |
230+----------+--------------------------+-------+---------+
231| TOTAL | $146.93 |
232+----------+--------------------------+-------+---------+
233```
234
235
236#### Table with color
237```go
238data := [][]string{
239 []string{"1/1/2014", "Domain name", "2233", "$10.98"},
240 []string{"1/1/2014", "January Hosting", "2233", "$54.95"},
241 []string{"1/4/2014", "February Hosting", "2233", "$51.00"},
242 []string{"1/4/2014", "February Extra Bandwidth", "2233", "$30.00"},
243}
244
245table := tablewriter.NewWriter(os.Stdout)
246table.SetHeader([]string{"Date", "Description", "CV2", "Amount"})
247table.SetFooter([]string{"", "", "Total", "$146.93"}) // Add Footer
248table.SetBorder(false) // Set Border to false
249
250table.SetHeaderColor(tablewriter.Colors{tablewriter.Bold, tablewriter.BgGreenColor},
251 tablewriter.Colors{tablewriter.FgHiRedColor, tablewriter.Bold, tablewriter.BgBlackColor},
252 tablewriter.Colors{tablewriter.BgRedColor, tablewriter.FgWhiteColor},
253 tablewriter.Colors{tablewriter.BgCyanColor, tablewriter.FgWhiteColor})
254
255table.SetColumnColor(tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiBlackColor},
256 tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiRedColor},
257 tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiBlackColor},
258 tablewriter.Colors{tablewriter.Bold, tablewriter.FgBlackColor})
259
260table.SetFooterColor(tablewriter.Colors{}, tablewriter.Colors{},
261 tablewriter.Colors{tablewriter.Bold},
262 tablewriter.Colors{tablewriter.FgHiRedColor})
263
264table.AppendBulk(data)
265table.Render()
266```
267
268#### Table with color Output
269![Table with Color](https://cloud.githubusercontent.com/assets/6460392/21101956/bbc7b356-c0a1-11e6-9f36-dba694746efc.png)
270
271#### Example - 8 Table Cells with Color
272
273Individual Cell Colors from `func Rich` take precedence over Column Colors
274
275```go
276data := [][]string{
277 []string{"Test1Merge", "HelloCol2 - 1", "HelloCol3 - 1", "HelloCol4 - 1"},
278 []string{"Test1Merge", "HelloCol2 - 2", "HelloCol3 - 2", "HelloCol4 - 2"},
279 []string{"Test1Merge", "HelloCol2 - 3", "HelloCol3 - 3", "HelloCol4 - 3"},
280 []string{"Test2Merge", "HelloCol2 - 4", "HelloCol3 - 4", "HelloCol4 - 4"},
281 []string{"Test2Merge", "HelloCol2 - 5", "HelloCol3 - 5", "HelloCol4 - 5"},
282 []string{"Test2Merge", "HelloCol2 - 6", "HelloCol3 - 6", "HelloCol4 - 6"},
283 []string{"Test2Merge", "HelloCol2 - 7", "HelloCol3 - 7", "HelloCol4 - 7"},
284 []string{"Test3Merge", "HelloCol2 - 8", "HelloCol3 - 8", "HelloCol4 - 8"},
285 []string{"Test3Merge", "HelloCol2 - 9", "HelloCol3 - 9", "HelloCol4 - 9"},
286 []string{"Test3Merge", "HelloCol2 - 10", "HelloCol3 -10", "HelloCol4 - 10"},
287}
288
289table := tablewriter.NewWriter(os.Stdout)
290table.SetHeader([]string{"Col1", "Col2", "Col3", "Col4"})
291table.SetFooter([]string{"", "", "Footer3", "Footer4"})
292table.SetBorder(false)
293
294table.SetHeaderColor(tablewriter.Colors{tablewriter.Bold, tablewriter.BgGreenColor},
295 tablewriter.Colors{tablewriter.FgHiRedColor, tablewriter.Bold, tablewriter.BgBlackColor},
296 tablewriter.Colors{tablewriter.BgRedColor, tablewriter.FgWhiteColor},
297 tablewriter.Colors{tablewriter.BgCyanColor, tablewriter.FgWhiteColor})
298
299table.SetColumnColor(tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiBlackColor},
300 tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiRedColor},
301 tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiBlackColor},
302 tablewriter.Colors{tablewriter.Bold, tablewriter.FgBlackColor})
303
304table.SetFooterColor(tablewriter.Colors{}, tablewriter.Colors{},
305 tablewriter.Colors{tablewriter.Bold},
306 tablewriter.Colors{tablewriter.FgHiRedColor})
307
308colorData1 := []string{"TestCOLOR1Merge", "HelloCol2 - COLOR1", "HelloCol3 - COLOR1", "HelloCol4 - COLOR1"}
309colorData2 := []string{"TestCOLOR2Merge", "HelloCol2 - COLOR2", "HelloCol3 - COLOR2", "HelloCol4 - COLOR2"}
310
311for i, row := range data {
312 if i == 4 {
313 table.Rich(colorData1, []tablewriter.Colors{tablewriter.Colors{}, tablewriter.Colors{tablewriter.Normal, tablewriter.FgCyanColor}, tablewriter.Colors{tablewriter.Bold, tablewriter.FgWhiteColor}, tablewriter.Colors{}})
314 table.Rich(colorData2, []tablewriter.Colors{tablewriter.Colors{tablewriter.Normal, tablewriter.FgMagentaColor}, tablewriter.Colors{}, tablewriter.Colors{tablewriter.Bold, tablewriter.BgRedColor}, tablewriter.Colors{tablewriter.FgHiGreenColor, tablewriter.Italic, tablewriter.BgHiCyanColor}})
315 }
316 table.Append(row)
317}
318
319table.SetAutoMergeCells(true)
320table.Render()
321
322```
323
324##### Table cells with color Output
325![Table cells with Color](https://user-images.githubusercontent.com/9064687/63969376-bcd88d80-ca6f-11e9-9466-c3d954700b25.png)
326
327#### Example 9 - Set table caption
328```go
329data := [][]string{
330 []string{"A", "The Good", "500"},
331 []string{"B", "The Very very Bad Man", "288"},
332 []string{"C", "The Ugly", "120"},
333 []string{"D", "The Gopher", "800"},
334}
335
336table := tablewriter.NewWriter(os.Stdout)
337table.SetHeader([]string{"Name", "Sign", "Rating"})
338table.SetCaption(true, "Movie ratings.")
339
340for _, v := range data {
341 table.Append(v)
342}
343table.Render() // Send output
344```
345
346Note: Caption text will wrap with total width of rendered table.
347
348##### Output 9
349```
350+------+-----------------------+--------+
351| NAME | SIGN | RATING |
352+------+-----------------------+--------+
353| A | The Good | 500 |
354| B | The Very very Bad Man | 288 |
355| C | The Ugly | 120 |
356| D | The Gopher | 800 |
357+------+-----------------------+--------+
358Movie ratings.
359```
360
361#### Example 10 - Set NoWhiteSpace and TablePadding option
362```go
363data := [][]string{
364 {"node1.example.com", "Ready", "compute", "1.11"},
365 {"node2.example.com", "Ready", "compute", "1.11"},
366 {"node3.example.com", "Ready", "compute", "1.11"},
367 {"node4.example.com", "NotReady", "compute", "1.11"},
368}
369
370table := tablewriter.NewWriter(os.Stdout)
371table.SetHeader([]string{"Name", "Status", "Role", "Version"})
372table.SetAutoWrapText(false)
373table.SetAutoFormatHeaders(true)
374table.SetHeaderAlignment(ALIGN_LEFT)
375table.SetAlignment(ALIGN_LEFT)
376table.SetCenterSeparator("")
377table.SetColumnSeparator("")
378table.SetRowSeparator("")
379table.SetHeaderLine(false)
380table.SetBorder(false)
381table.SetTablePadding("\t") // pad with tabs
382table.SetNoWhiteSpace(true)
383table.AppendBulk(data) // Add Bulk Data
384table.Render()
385```
386
387##### Output 10
388```
389NAME STATUS ROLE VERSION
390node1.example.com Ready compute 1.11
391node2.example.com Ready compute 1.11
392node3.example.com Ready compute 1.11
393node4.example.com NotReady compute 1.11
394```
395
396#### Render table into a string
397
398Instead of rendering the table to `io.Stdout` you can also render it into a string. Go 1.10 introduced the `strings.Builder` type which implements the `io.Writer` interface and can therefore be used for this task. Example:
399
400```go
401package main
402
403import (
404 "strings"
405 "fmt"
406
407 "github.com/olekukonko/tablewriter"
408)
409
410func main() {
411 tableString := &strings.Builder{}
412 table := tablewriter.NewWriter(tableString)
413
414 /*
415 * Code to fill the table
416 */
417
418 table.Render()
419
420 fmt.Println(tableString.String())
421}
422```
423
424#### TODO
425- ~~Import Directly from CSV~~ - `done`
426- ~~Support for `SetFooter`~~ - `done`
427- ~~Support for `SetBorder`~~ - `done`
428- ~~Support table with uneven rows~~ - `done`
429- ~~Support custom alignment~~
430- General Improvement & Optimisation
431- `NewHTML` Parse table from HTML
432