diff --git a/sheet.go b/sheet.go index 2d2ad308..591e016d 100644 --- a/sheet.go +++ b/sheet.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "strconv" + "strings" "github.com/shabbyrobe/xmlwriter" ) @@ -390,6 +391,39 @@ func (s *Sheet) SetColWidth(min, max int, width float64) { }) } +// This can be use as the default scale function for the autowidth. +// It works well with the default font sizes. +func DefaultAutoWidth(s string) float64 { + return (float64(strings.Count(s, "")) + 3.0 ) * 1.2 +} + +// Tries to guess the best width for a column, based on the largest +// cell content. A scale function needs to be provided. +func (s *Sheet) SetColAutoWidth(colIndex int, width func (string) float64) error { + largestWidth := 0.0 + rowVisitor := func (r *Row) error { + cell := r.GetCell(colIndex) + value, err := cell.FormattedValue() + if err != nil { + return err + } + + if width(value) > largestWidth { + largestWidth = width(value) + } + return nil + } + err := s.ForEachRow(rowVisitor) + + if err != nil { + return err + } + + s.SetColWidth(colIndex, colIndex, largestWidth) + + return nil +} + // Set the outline level for a range of columns. func (s *Sheet) SetOutlineLevel(minCol, maxCol int, outlineLevel uint8) { s.setCol(minCol, maxCol, func(col *Col) { diff --git a/sheet_test.go b/sheet_test.go index d478998e..e3775788 100644 --- a/sheet_test.go +++ b/sheet_test.go @@ -615,6 +615,33 @@ func TestMakeXLSXSheet(t *testing.T) { c.Assert(sheet.Cols.FindColByIndex(2).Min, qt.Equals, 2) }) + + csRunO(c, "SetColAutoWidth", func(c *qt.C, option FileOption) { + file := NewFile(option) + sheet, _ := file.AddSheet("Sheet1") + row := sheet.AddRow() + cell11 := row.AddCell() + cell11.Value = "test 1" + cell12 := row.AddCell() + cell12.Value = "something else" + + sheet.SetColAutoWidth(0, DefaultAutoWidth) + + scaleFunc := func (s string) float64 { + return float64(strings.Count(s, "")) * 1.5 + } + sheet.SetColAutoWidth(1, scaleFunc) + + c.Assert(*sheet.Cols.FindColByIndex(0).Width, qt.Equals, 12.0) + c.Assert(sheet.Cols.FindColByIndex(0).Max, qt.Equals, 0) + c.Assert(sheet.Cols.FindColByIndex(0).Min, qt.Equals, 0) + + c.Assert(*sheet.Cols.FindColByIndex(1).Width, qt.Equals, 22.5) + c.Assert(sheet.Cols.FindColByIndex(1).Max, qt.Equals, 1) + c.Assert(sheet.Cols.FindColByIndex(1).Min, qt.Equals, 1) + }) + + csRunO(c, "SetDataValidation", func(c *qt.C, option FileOption) { file := NewFile(option) sheet, _ := file.AddSheet("Sheet1")