Skip to content
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

add auto fit columns function #1386

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 {
yyt030 marked this conversation as resolved.
Show resolved Hide resolved
startColIdx, endColIdx, err := f.parseColRange(columns)
if err != nil {
return err
}

cols, err := f.Cols(sheetName)
yyt030 marked this conversation as resolved.
Show resolved Hide resolved
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
yyt030 marked this conversation as resolved.
Show resolved Hide resolved

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 {
yyt030 marked this conversation as resolved.
Show resolved Hide resolved
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
yyt030 marked this conversation as resolved.
Show resolved Hide resolved
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))
yyt030 marked this conversation as resolved.
Show resolved Hide resolved
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
yyt030 marked this conversation as resolved.
Show resolved Hide resolved
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