Skip to content

add auto fit columns function #1386

New issue

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

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

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 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
61 changes: 61 additions & 0 deletions col.go
Original file line number Diff line number Diff line change
Expand Up @@ -479,9 +479,15 @@ func (f *File) SetColWidth(sheet, startCol, endCol string, width float64) error
if err != nil {
return err
}

return f.setColWidth(sheet, min, max, width)
}

func (f *File) setColWidth(sheet string, min, max int, width float64) error {
if width > MaxColumnWidth {
return ErrColumnWidth
}

ws, err := f.workSheetReader(sheet)
if err != nil {
return err
Expand Down Expand Up @@ -512,6 +518,61 @@ func (f *File) SetColWidth(sheet, startCol, endCol string, width float64) error
return err
}

// AutoFitColWidth provides a function to autofit columns according to
// their text content
// Note: this only works on the column with cells which not contains
// formula cell and style with a number format.
//
// For example set column of column H on Sheet1:
//
// err = f.AutoFitColWidth("Sheet1", "H")
//
// Set style of columns C:F on Sheet1:
//
// err = f.AutoFitColWidth("Sheet1", "C:F", style)
func (f *File) AutoFitColWidth(sheetName string, columns string) error {
startColIdx, endColIdx, err := f.parseColRange(columns)
if err != nil {
return err
}

cols, err := f.Cols(sheetName)
if err != nil {
return err
}

colIdx := 1
for cols.Next() {
if colIdx >= startColIdx && colIdx <= endColIdx {
rowCells, _ := cols.Rows()
max := defaultColWidth
for i := range rowCells {
rowCell := rowCells[i]
cellWidth := float64(len(rowCell) + 3) // + 3 for margin

if cellWidth > max && cellWidth < MaxColumnWidth {
max = cellWidth
} else if cellWidth >= MaxColumnWidth {
max = MaxColumnWidth
}
}

if err := f.setColWidth(sheetName, colIdx, colIdx, max); err != nil {
return err
}
}

// fast go away
if colIdx == endColIdx {
break
}

colIdx++
}

return nil
}

// flatCols provides a method for the column's operation functions to flatten
// and check the worksheet columns.
func flatCols(col xlsxCol, cols []xlsxCol, replacer func(fc, c xlsxCol) xlsxCol) []xlsxCol {
Expand Down
60 changes: 60 additions & 0 deletions col_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package excelize

import (
"math/rand"
"path/filepath"
"testing"

Expand Down Expand Up @@ -360,6 +361,65 @@ func TestColWidth(t *testing.T) {
convertRowHeightToPixels(0)
}

func TestAutoFitColWidth(t *testing.T) {
randStr := func(n int) string {
var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

b := make([]rune, n)
for i := range b {
b[i] = letterRunes[rand.Intn(len(letterRunes))]
}
return string(b)
}

f := NewFile()
// Test null data columns
assert.NoError(t, f.AutoFitColWidth("Sheet1", "A"))
width, err := f.GetColWidth("Sheet1", "A")
assert.Equal(t, defaultColWidth, width)
assert.NoError(t, err)

// Test some data
for _, max := range []int{1, 10, 100, 1000} {
f.SetCellValue("Sheet1", "B2", randStr(max/2))
f.SetCellValue("Sheet1", "B3", randStr(max))
assert.NoError(t, f.AutoFitColWidth("Sheet1", "B:A"))
width, err = f.GetColWidth("Sheet1", "A")
assert.Equal(t, defaultColWidth, width)
assert.NoError(t, err)

width, err = f.GetColWidth("Sheet1", "B")
if float64(max) < defaultColWidth {
assert.Equal(t, defaultColWidth, width)
} else if max > MaxColumnWidth {
assert.Equal(t, float64(MaxColumnWidth), width)
} else {
assert.Equal(t, float64(max+3), width)
}
assert.NoError(t, err)
}

// Test All columns
f.SetCellValue("sheet1", "C2", randStr(10))
f.SetCellValue("sheet1", "D2", randStr(20))
f.SetCellValue("sheet1", "E2", randStr(30))
assert.NoError(t, f.AutoFitColWidth("Sheet1", "XFD:D"))
width, err = f.GetColWidth("Sheet1", "C")
assert.Equal(t, defaultColWidth, width)
assert.NoError(t, err)

width, err = f.GetColWidth("Sheet1", "D")
assert.Equal(t, float64(23), width)
assert.NoError(t, err)

width, err = f.GetColWidth("Sheet1", "E")
assert.Equal(t, float64(33), width)
assert.NoError(t, err)

assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAutoColWidth.xlsx")))
convertRowHeightToPixels(0)
}

func TestGetColStyle(t *testing.T) {
f := NewFile()
styleID, err := f.GetColStyle("Sheet1", "A")
Expand Down