Skip to content

Commit

Permalink
Merge pull request #735 from mauserzjeh/master
Browse files Browse the repository at this point in the history
colLimit function
  • Loading branch information
tealeg authored Dec 13, 2021
2 parents 3e04a57 + e749444 commit b769600
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 24 deletions.
11 changes: 11 additions & 0 deletions file.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ type File struct {
DefinedNames []*xlsxDefinedName
cellStoreConstructor CellStoreConstructor
rowLimit int
colLimit int
valueOnly bool
}

const NoRowLimit int = -1
const NoColLimit int = -1

type FileOption func(f *File)

Expand All @@ -42,6 +44,14 @@ func RowLimit(n int) FileOption {
}
}

// ColLimit will limit the columns handled in any given sheet to the
// first n, where n is the number of columns
func ColLimit(n int) FileOption {
return func(f *File) {
f.colLimit = n
}
}

// ValueOnly treats all NULL values as meaningless and it will delete all NULL value cells,
// before decode worksheet.xml. this option can save memory and time when parsing files
// with a large number of NULL values. But it may also cause accidental injury,
Expand All @@ -60,6 +70,7 @@ func NewFile(options ...FileOption) *File {
Sheets: make([]*Sheet, 0),
DefinedNames: make([]*xlsxDefinedName, 0),
rowLimit: NoRowLimit,
colLimit: NoColLimit,
cellStoreConstructor: NewMemoryCellStore,
}
for _, opt := range options {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ module github.com/tealeg/xlsx/v3
go 1.15

require (
golang.org/x/text v0.3.3
github.com/frankban/quicktest v1.11.2
github.com/google/btree v1.0.0 // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible
github.com/pkg/profile v1.5.0
github.com/rogpeppe/fastuuid v1.2.0
github.com/shabbyrobe/xmlwriter v0.0.0-20200208144257-9fca06d00ffa
golang.org/x/text v0.3.3 // indirect
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b
)
1 change: 0 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ 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/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/peterbourgon/diskv v1.0.0 h1:bRU92KzrX3TQ6IYobfie/PnZkFC+1opBfHpf/PHPDoo=
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/profile v1.5.0 h1:042Buzk+NhDI+DeSAA62RwJL8VAuZUMQZUjCsRz1Mug=
Expand Down
29 changes: 20 additions & 9 deletions lib.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ func getMaxMinFromDimensionRef(ref string) (minx, miny, maxx, maxy int, err erro
// calculateMaxMinFromWorkSheet works out the dimensions of a spreadsheet
// that doesn't have a DimensionRef set. The only case currently
// known where this is true is with XLSX exported from Google Docs.
func calculateMaxMinFromWorksheet(worksheet *xlsxWorksheet) (minx, miny, maxx, maxy int, err error) {
func calculateMaxMinFromWorksheet(worksheet *xlsxWorksheet, colLimit int) (minx, miny, maxx, maxy int, err error) {
// Note, this method could be very slow for large spreadsheets.
var x, y int
var maxVal int
Expand All @@ -202,6 +202,12 @@ func calculateMaxMinFromWorksheet(worksheet *xlsxWorksheet) (minx, miny, maxx, m
if err != nil {
return wrap(err)
}

// break out of the loop if a column limit is set
if colLimit != NoColLimit && x+1 > colLimit {
break
}

if x < minx {
minx = x
}
Expand Down Expand Up @@ -457,7 +463,7 @@ func fillCellDataFromInlineString(rawcell xlsxC, cell *Cell) {
// rows from a XSLXWorksheet, populates them with Cells and resolves
// the value references from the reference table and stores them in
// the rows and columns.
func readRowsFromSheet(Worksheet *xlsxWorksheet, file *File, sheet *Sheet, rowLimit int, linkTable hyperlinkTable) error {
func readRowsFromSheet(Worksheet *xlsxWorksheet, file *File, sheet *Sheet, rowLimit, colLimit int, linkTable hyperlinkTable) error {
var row *Row
var maxCol, maxRow, colCount, rowCount int
var reftable *RefTable
Expand All @@ -474,10 +480,10 @@ func readRowsFromSheet(Worksheet *xlsxWorksheet, file *File, sheet *Sheet, rowLi
return nil
}
reftable = file.referenceTable
if len(Worksheet.Dimension.Ref) > 0 && len(strings.Split(Worksheet.Dimension.Ref, cellRangeChar)) == 2 && rowLimit == NoRowLimit {
if len(Worksheet.Dimension.Ref) > 0 && len(strings.Split(Worksheet.Dimension.Ref, cellRangeChar)) == 2 && rowLimit == NoRowLimit && colLimit == NoColLimit {
_, _, maxCol, maxRow, err = getMaxMinFromDimensionRef(Worksheet.Dimension.Ref)
} else {
_, _, maxCol, maxRow, err = calculateMaxMinFromWorksheet(Worksheet)
_, _, maxCol, maxRow, err = calculateMaxMinFromWorksheet(Worksheet, colLimit)
}
if err != nil {
return wrap(err)
Expand Down Expand Up @@ -545,6 +551,11 @@ func readRowsFromSheet(Worksheet *xlsxWorksheet, file *File, sheet *Sheet, rowLi
return wrap(err)
}

// break out of the loop if column limit is set
if colLimit != NoColLimit && colLimit < x+1 {
break
}

cellX := x

cell := newCell(row, cellX)
Expand Down Expand Up @@ -687,7 +698,7 @@ func makeHyperlinkTable(worksheet *xlsxWorksheet, fi *File, rsheet *xlsxSheet) (
// into a Sheet struct. This work can be done in parallel and so
// readSheetsFromZipFile will spawn an instance of this function per
// sheet and get the results back on the provided channel.
func readSheetFromFile(rsheet xlsxSheet, fi *File, sheetXMLMap map[string]string, rowLimit int, valueOnly bool) (sheet *Sheet, errRes error) {
func readSheetFromFile(rsheet xlsxSheet, fi *File, sheetXMLMap map[string]string, rowLimit, colLimit int, valueOnly bool) (sheet *Sheet, errRes error) {
defer func() {
if x := recover(); x != nil {
errRes = errors.New(fmt.Sprintf("%v\n%s\n", x, debug.Stack()))
Expand All @@ -714,7 +725,7 @@ func readSheetFromFile(rsheet xlsxSheet, fi *File, sheetXMLMap map[string]string
}

sheet.File = fi
err = readRowsFromSheet(worksheet, fi, sheet, rowLimit, linkTable)
err = readRowsFromSheet(worksheet, fi, sheet, rowLimit, colLimit, linkTable)
if err != nil {
return wrap(err)
}
Expand Down Expand Up @@ -743,7 +754,7 @@ func readSheetFromFile(rsheet xlsxSheet, fi *File, sheetXMLMap map[string]string
// readSheetsFromZipFile is an internal helper function that loops
// over the Worksheets defined in the XSLXWorkbook and loads them into
// Sheet objects stored in the Sheets slice of a xlsx.File struct.
func readSheetsFromZipFile(f *zip.File, file *File, sheetXMLMap map[string]string, rowLimit int, valueOnly bool) (map[string]*Sheet, []*Sheet, error) {
func readSheetsFromZipFile(f *zip.File, file *File, sheetXMLMap map[string]string, rowLimit, colLimit int, valueOnly bool) (map[string]*Sheet, []*Sheet, error) {
var workbook *xlsxWorkbook
var err error
var rc io.ReadCloser
Expand Down Expand Up @@ -787,7 +798,7 @@ func readSheetsFromZipFile(f *zip.File, file *File, sheetXMLMap map[string]strin
i, rawsheet := i, rawsheet
go func() {
sheet, err := readSheetFromFile(rawsheet, file,
sheetXMLMap, rowLimit, valueOnly)
sheetXMLMap, rowLimit, colLimit, valueOnly)
sheetChan <- &indexedSheet{
Index: i,
Sheet: sheet,
Expand Down Expand Up @@ -1073,7 +1084,7 @@ func ReadZipReader(r *zip.Reader, options ...FileOption) (*File, error) {

file.styles = style
}
sheetsByName, sheets, err = readSheetsFromZipFile(workbook, file, sheetXMLMap, file.rowLimit, file.valueOnly)
sheetsByName, sheets, err = readSheetsFromZipFile(workbook, file, sheetXMLMap, file.rowLimit, file.colLimit, file.valueOnly)
if err != nil {
return wrap(err)
}
Expand Down
26 changes: 13 additions & 13 deletions lib_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ func TestLib(t *testing.T) {
worksheet := new(xlsxWorksheet)
err := xml.NewDecoder(sheetxml).Decode(worksheet)
c.Assert(err, qt.IsNil)
minx, miny, maxx, maxy, err := calculateMaxMinFromWorksheet(worksheet)
minx, miny, maxx, maxy, err := calculateMaxMinFromWorksheet(worksheet, NoColLimit)
c.Assert(err, qt.IsNil)
c.Assert(minx, qt.Equals, 0)
c.Assert(miny, qt.Equals, 0)
Expand Down Expand Up @@ -346,7 +346,7 @@ func TestLib(t *testing.T) {
sheet, err := NewSheet("test")
c.Assert(err, qt.IsNil)
lt := make(hyperlinkTable)
err = readRowsFromSheet(worksheet, file, sheet, NoRowLimit, lt)
err = readRowsFromSheet(worksheet, file, sheet, NoRowLimit, NoColLimit, lt)
c.Assert(err, qt.IsNil)
c.Assert(sheet.MaxRow, qt.Equals, 2)
c.Assert(sheet.MaxCol, qt.Equals, 2)
Expand Down Expand Up @@ -445,7 +445,7 @@ func TestLib(t *testing.T) {

// Discarding all return values; this test is a regression for
// a panic due to an "index out of range."
readRowsFromSheet(worksheet, file, sheet, NoRowLimit, lt)
readRowsFromSheet(worksheet, file, sheet, NoRowLimit, NoColLimit, lt)
})

csRunC(c, "ReadRowsFromSheetWithLeadingEmptyRows", func(c *qt.C, constructor CellStoreConstructor) {
Expand Down Expand Up @@ -495,7 +495,7 @@ func TestLib(t *testing.T) {
c.Assert(err, qt.IsNil)
lt := make(hyperlinkTable)

err = readRowsFromSheet(worksheet, file, sheet, NoRowLimit, lt)
err = readRowsFromSheet(worksheet, file, sheet, NoRowLimit, NoColLimit, lt)
c.Assert(err, qt.IsNil)
c.Assert(sheet.MaxRow, qt.Equals, 5)
c.Assert(sheet.MaxCol, qt.Equals, 1)
Expand Down Expand Up @@ -577,7 +577,7 @@ func TestLib(t *testing.T) {
c.Assert(err, qt.IsNil)
lt := make(hyperlinkTable)

err = readRowsFromSheet(worksheet, file, sheet, NoRowLimit, lt)
err = readRowsFromSheet(worksheet, file, sheet, NoRowLimit, NoColLimit, lt)
c.Assert(err, qt.IsNil)
c.Assert(sheet.MaxRow, qt.Equals, 2)
c.Assert(sheet.MaxCol, qt.Equals, 4)
Expand Down Expand Up @@ -725,7 +725,7 @@ func TestLib(t *testing.T) {
c.Assert(err, qt.IsNil)
lt := make(hyperlinkTable)

err = readRowsFromSheet(worksheet, file, sheet, NoRowLimit, lt)
err = readRowsFromSheet(worksheet, file, sheet, NoRowLimit, NoColLimit, lt)
c.Assert(err, qt.IsNil)
c.Assert(sheet.MaxRow, qt.Equals, 3)
c.Assert(sheet.MaxCol, qt.Equals, 3)
Expand Down Expand Up @@ -773,7 +773,7 @@ func TestLib(t *testing.T) {
c.Assert(err, qt.IsNil)
lt := make(hyperlinkTable)

err = readRowsFromSheet(worksheet, file, sheet, NoRowLimit, lt)
err = readRowsFromSheet(worksheet, file, sheet, NoRowLimit, NoColLimit, lt)
c.Assert(err, qt.IsNil)
c.Assert(sheet.MaxCol, qt.Equals, 4)
c.Assert(sheet.MaxRow, qt.Equals, 8)
Expand Down Expand Up @@ -891,7 +891,7 @@ func TestLib(t *testing.T) {

lt := make(hyperlinkTable)

err = readRowsFromSheet(worksheet, file, sheet, NoRowLimit, lt)
err = readRowsFromSheet(worksheet, file, sheet, NoRowLimit, NoColLimit, lt)
c.Assert(err, qt.IsNil)
c.Assert(sheet.MaxRow, qt.Equals, 2)
c.Assert(sheet.MaxCol, qt.Equals, 4)
Expand Down Expand Up @@ -972,7 +972,7 @@ func TestLib(t *testing.T) {
c.Assert(err, qt.IsNil)
lt := make(hyperlinkTable)

err = readRowsFromSheet(worksheet, file, sheet, NoRowLimit, lt)
err = readRowsFromSheet(worksheet, file, sheet, NoRowLimit, NoColLimit, lt)
c.Assert(err, qt.IsNil)
c.Assert(sheet.MaxRow, qt.Equals, 1)
c.Assert(sheet.MaxCol, qt.Equals, 6)
Expand Down Expand Up @@ -1051,7 +1051,7 @@ func TestLib(t *testing.T) {
c.Assert(err, qt.IsNil)
lt := make(hyperlinkTable)

err = readRowsFromSheet(worksheet, file, sheet, NoRowLimit, lt)
err = readRowsFromSheet(worksheet, file, sheet, NoRowLimit, NoColLimit, lt)
c.Assert(err, qt.IsNil)
c.Assert(sheet.MaxRow, qt.Equals, 1)
c.Assert(sheet.MaxCol, qt.Equals, 2)
Expand Down Expand Up @@ -1197,7 +1197,7 @@ func TestLib(t *testing.T) {

lt := make(hyperlinkTable)

err = readRowsFromSheet(worksheet, file, sheet, NoRowLimit, lt)
err = readRowsFromSheet(worksheet, file, sheet, NoRowLimit, NoColLimit, lt)
c.Assert(err, qt.IsNil)
c.Assert(sheet.MaxCol, qt.Equals, 3)
c.Assert(sheet.MaxRow, qt.Equals, 2)
Expand Down Expand Up @@ -1345,7 +1345,7 @@ func TestLib(t *testing.T) {

lt := make(hyperlinkTable)

err = readRowsFromSheet(worksheet, file, sheet, NoRowLimit, lt)
err = readRowsFromSheet(worksheet, file, sheet, NoRowLimit, NoColLimit, lt)
c.Assert(err, qt.IsNil)
row, err := sheet.Row(3)
c.Assert(err, qt.Equals, nil)
Expand Down Expand Up @@ -1440,7 +1440,7 @@ func TestReadRowsFromSheet(t *testing.T) {
sheet, err := NewSheetWithCellStore("test", constructor)
c.Assert(err, qt.IsNil)
lt := make(hyperlinkTable)
err = readRowsFromSheet(worksheet, file, sheet, NoRowLimit, lt)
err = readRowsFromSheet(worksheet, file, sheet, NoRowLimit, NoColLimit, lt)
c.Assert(err, qt.IsNil)
row, err := sheet.Row(0)
c.Assert(err, qt.Equals, nil)
Expand Down

0 comments on commit b769600

Please sign in to comment.