diff --git a/go.mod b/go.mod index cd87488a..be915556 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.22 require ( github.com/boombuler/barcode v1.0.2 + github.com/extrame/xls v0.0.2-0.20200426124601-4a6cf263071b github.com/gin-contrib/cache v1.3.0 github.com/gin-contrib/gzip v1.0.1 github.com/gin-gonic/gin v1.10.0 @@ -16,12 +17,12 @@ require ( github.com/minio/minio-go/v7 v7.0.74 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pquerna/otp v1.4.0 - github.com/shakinm/xlsReader v0.9.12 github.com/sirupsen/logrus v1.9.3 github.com/stretchr/testify v1.9.0 github.com/urfave/cli/v2 v2.27.3 github.com/wk8/go-ordered-map/v2 v2.1.8 golang.org/x/crypto v0.26.0 + golang.org/x/text v0.17.0 gopkg.in/ini.v1 v1.67.0 gopkg.in/mail.v2 v2.3.1 xorm.io/builder v0.3.13 @@ -42,6 +43,8 @@ require ( github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect + github.com/extrame/goyymmdd v0.0.0-20210114090516-7cc815f00d1a // indirect + github.com/extrame/ole2 v0.0.0-20160812065207-d69429661ad7 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-ini/ini v1.67.0 // indirect @@ -59,7 +62,6 @@ require ( github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/memcachier/mc/v3 v3.0.3 // indirect - github.com/metakeule/fmtdate v1.1.2 // indirect github.com/minio/md5-simd v1.1.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect @@ -70,6 +72,7 @@ require ( github.com/rs/xid v1.5.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/syndtr/goleveldb v1.0.0 // indirect + github.com/tealeg/xlsx v1.0.5 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect @@ -77,7 +80,6 @@ require ( golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect golang.org/x/net v0.26.0 // indirect golang.org/x/sys v0.23.0 // indirect - golang.org/x/text v0.17.0 // indirect google.golang.org/protobuf v1.34.1 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 7bb8296b..648383ae 100644 --- a/go.sum +++ b/go.sum @@ -32,6 +32,12 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/extrame/goyymmdd v0.0.0-20210114090516-7cc815f00d1a h1:c5k29baTzznteWs+9dxrtqpNxgtQ3V5NbU8d6laLK9Q= +github.com/extrame/goyymmdd v0.0.0-20210114090516-7cc815f00d1a/go.mod h1:xbpgo9r3xURoPa/l3sLKLGcnWlkz9UkfFsQ7lW0S6h8= +github.com/extrame/ole2 v0.0.0-20160812065207-d69429661ad7 h1:n+nk0bNe2+gVbRI8WRbLFVwwcBQ0rr5p+gzkKb6ol8c= +github.com/extrame/ole2 v0.0.0-20160812065207-d69429661ad7/go.mod h1:GPpMrAfHdb8IdQ1/R2uIRBsNfnPnwsYE9YYI5WyY1zw= +github.com/extrame/xls v0.0.2-0.20200426124601-4a6cf263071b h1:jqW/h4gcXYEB6kVf6iuxjU9ONWA0ugUB94TP9UNmgdg= +github.com/extrame/xls v0.0.2-0.20200426124601-4a6cf263071b/go.mod h1:iACcgahst7BboCpIMSpnFs4SKyU9ZjsvZBfNbUxZOJI= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= @@ -81,6 +87,9 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02 github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= @@ -93,8 +102,6 @@ github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/memcachier/mc/v3 v3.0.3 h1:qii+lDiPKi36O4Xg+HVKwHu6Oq+Gt17b+uEiA0Drwv4= github.com/memcachier/mc/v3 v3.0.3/go.mod h1:GzjocBahcXPxt2cmqzknrgqCOmMxiSzhVKPOe90Tpug= -github.com/metakeule/fmtdate v1.1.2 h1:n9M7H9HfAqp+6OA98wXGMdcAr6omshSNVct65Bks1lQ= -github.com/metakeule/fmtdate v1.1.2/go.mod h1:2JyMFlKxeoGy1qS6obQukT0AL0Y4iNANQL8scbSdT4E= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= github.com/minio/minio-go/v7 v7.0.74 h1:fTo/XlPBTSpo3BAMshlwKL5RspXRv9us5UeHEGYCFe0= @@ -123,8 +130,6 @@ github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/shakinm/xlsReader v0.9.12 h1:F6GWYtCzfzQqdIuqZJ0MU3YJ7uwH1ofJtmTKyWmANQk= -github.com/shakinm/xlsReader v0.9.12/go.mod h1:ME9pqIGf+547L4aE4YTZzwmhsij+5K9dR+k84OO6WSs= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -141,6 +146,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= +github.com/tealeg/xlsx v1.0.5 h1:+f8oFmvY8Gw1iUXzPk+kz+4GpbDZPK1FhPiQRd+ypgE= +github.com/tealeg/xlsx v1.0.5/go.mod h1:btRS8dz54TDnvKNosuAqxrM1QgN1udgk9O34bDCnORM= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= @@ -169,15 +176,14 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= diff --git a/pkg/converters/excel/excel_file_imported_data_table.go b/pkg/converters/excel/excel_file_imported_data_table.go index 30efc597..c008d12b 100644 --- a/pkg/converters/excel/excel_file_imported_data_table.go +++ b/pkg/converters/excel/excel_file_imported_data_table.go @@ -4,7 +4,7 @@ import ( "bytes" "fmt" - "github.com/shakinm/xlsReader/xls" + "github.com/extrame/xls" "github.com/mayswind/ezbookkeeping/pkg/converters/datatable" "github.com/mayswind/ezbookkeeping/pkg/errs" @@ -12,36 +12,35 @@ import ( // ExcelFileImportedDataTable defines the structure of excel file data table type ExcelFileImportedDataTable struct { - workbook *xls.Workbook + workbook *xls.WorkBook headerLineColumnNames []string } // ExcelFileDataRow defines the structure of excel file data table row type ExcelFileDataRow struct { - sheet *xls.Sheet + sheet *xls.WorkSheet rowIndex int } // ExcelFileDataRowIterator defines the structure of excel file data table row iterator type ExcelFileDataRowIterator struct { dataTable *ExcelFileImportedDataTable - currentTableIndex int - currentRowIndexInTable int + currentSheetIndex int + currentRowIndexInSheet uint16 } // DataRowCount returns the total count of data row func (t *ExcelFileImportedDataTable) DataRowCount() int { - allSheets := t.workbook.GetSheets() totalDataRowCount := 0 - for i := 0; i < len(allSheets); i++ { - sheet := allSheets[i] + for i := 0; i < t.workbook.NumSheets(); i++ { + sheet := t.workbook.GetSheet(i) - if sheet.GetNumberRows() <= 1 { + if sheet.MaxRow < 1 { continue } - totalDataRowCount += sheet.GetNumberRows() - 1 + totalDataRowCount += int(sheet.MaxRow) } return totalDataRowCount @@ -56,57 +55,41 @@ func (t *ExcelFileImportedDataTable) HeaderColumnNames() []string { func (t *ExcelFileImportedDataTable) DataRowIterator() datatable.ImportedDataRowIterator { return &ExcelFileDataRowIterator{ dataTable: t, - currentTableIndex: 0, - currentRowIndexInTable: 0, + currentSheetIndex: 0, + currentRowIndexInSheet: 0, } } // ColumnCount returns the total count of column in this data row func (r *ExcelFileDataRow) ColumnCount() int { - row, err := r.sheet.GetRow(r.rowIndex) - - if err != nil { - return 0 - } - - return len(row.GetCols()) + row := r.sheet.Row(r.rowIndex) + return row.LastCol() + 1 } // GetData returns the data in the specified column index func (r *ExcelFileDataRow) GetData(columnIndex int) string { - row, err := r.sheet.GetRow(r.rowIndex) - - if err != nil { - return "" - } - - cell, err := row.GetCol(columnIndex) - - if err != nil { - return "" - } - - return cell.GetString() + row := r.sheet.Row(r.rowIndex) + return row.Col(columnIndex) } // HasNext returns whether the iterator does not reach the end func (t *ExcelFileDataRowIterator) HasNext() bool { - allSheets := t.dataTable.workbook.GetSheets() + workbook := t.dataTable.workbook - if t.currentTableIndex >= len(allSheets) { + if t.currentSheetIndex >= workbook.NumSheets() { return false } - currentSheet := allSheets[t.currentTableIndex] + currentSheet := workbook.GetSheet(t.currentSheetIndex) - if t.currentRowIndexInTable+1 < currentSheet.GetNumberRows() { + if t.currentRowIndexInSheet+1 <= currentSheet.MaxRow { return true } - for i := t.currentTableIndex + 1; i < len(allSheets); i++ { - sheet := allSheets[i] + for i := t.currentSheetIndex + 1; i < workbook.NumSheets(); i++ { + sheet := workbook.GetSheet(i) - if sheet.GetNumberRows() <= 1 { + if sheet.MaxRow < 1 { continue } @@ -118,74 +101,67 @@ func (t *ExcelFileDataRowIterator) HasNext() bool { // CurrentRowId returns current index func (t *ExcelFileDataRowIterator) CurrentRowId() string { - return fmt.Sprintf("table#%d-row#%d", t.currentTableIndex, t.currentRowIndexInTable) + return fmt.Sprintf("table#%d-row#%d", t.currentSheetIndex, t.currentRowIndexInSheet) } // Next returns the next imported data row func (t *ExcelFileDataRowIterator) Next() datatable.ImportedDataRow { - allSheets := t.dataTable.workbook.GetSheets() - currentRowIndexInTable := t.currentRowIndexInTable + workbook := t.dataTable.workbook + currentRowIndexInTable := t.currentRowIndexInSheet - for i := t.currentTableIndex; i < len(allSheets); i++ { - sheet := allSheets[i] + for i := t.currentSheetIndex; i < workbook.NumSheets(); i++ { + sheet := workbook.GetSheet(i) - if currentRowIndexInTable+1 < sheet.GetNumberRows() { - t.currentRowIndexInTable++ - currentRowIndexInTable = t.currentRowIndexInTable + if currentRowIndexInTable+1 <= sheet.MaxRow { + t.currentRowIndexInSheet++ + currentRowIndexInTable = t.currentRowIndexInSheet break } - t.currentTableIndex++ - t.currentRowIndexInTable = 0 + t.currentSheetIndex++ + t.currentRowIndexInSheet = 0 currentRowIndexInTable = 0 } - if t.currentTableIndex >= len(allSheets) { + if t.currentSheetIndex >= workbook.NumSheets() { return nil } - currentSheet := allSheets[t.currentTableIndex] + currentSheet := workbook.GetSheet(t.currentSheetIndex) - if t.currentRowIndexInTable >= currentSheet.GetNumberRows() { + if t.currentRowIndexInSheet > currentSheet.MaxRow { return nil } return &ExcelFileDataRow{ - sheet: ¤tSheet, - rowIndex: t.currentRowIndexInTable, + sheet: currentSheet, + rowIndex: int(t.currentRowIndexInSheet), } } // CreateNewExcelFileImportedDataTable returns excel xls data table by file binary data func CreateNewExcelFileImportedDataTable(data []byte) (*ExcelFileImportedDataTable, error) { reader := bytes.NewReader(data) - workbook, err := xls.OpenReader(reader) + workbook, err := xls.OpenReader(reader, "") if err != nil { return nil, err } - allSheets := workbook.GetSheets() var headerRowItems []string - for i := 0; i < len(allSheets); i++ { - sheet := allSheets[i] + for i := 0; i < workbook.NumSheets(); i++ { + sheet := workbook.GetSheet(i) - if sheet.GetNumberRows() < 1 { + if sheet.MaxRow < 0 { continue } - row, err := sheet.GetRow(0) - - if err != nil { - return nil, err - } - - cells := row.GetCols() + row := sheet.Row(0) if i == 0 { - for j := 0; j < len(cells); j++ { - headerItem := cells[j].GetString() + for j := 0; j <= row.LastCol(); j++ { + headerItem := row.Col(j) if headerItem == "" { break @@ -194,8 +170,8 @@ func CreateNewExcelFileImportedDataTable(data []byte) (*ExcelFileImportedDataTab headerRowItems = append(headerRowItems, headerItem) } } else { - for j := 0; j < min(len(cells), len(headerRowItems)); j++ { - headerItem := cells[j].GetString() + for j := 0; j <= min(row.LastCol(), len(headerRowItems)-1); j++ { + headerItem := row.Col(j) if headerItem != headerRowItems[j] { return nil, errs.ErrFieldsInMultiTableAreDifferent @@ -205,7 +181,7 @@ func CreateNewExcelFileImportedDataTable(data []byte) (*ExcelFileImportedDataTab } return &ExcelFileImportedDataTable{ - workbook: &workbook, + workbook: workbook, headerLineColumnNames: headerRowItems, }, nil } diff --git a/third-party-dependencies.json b/third-party-dependencies.json index f4d05616..2708e8ad 100644 --- a/third-party-dependencies.json +++ b/third-party-dependencies.json @@ -112,9 +112,9 @@ "licenseUrl": "https://github.com/boombuler/barcode/blob/v1.0.2/LICENSE" }, { - "name": "xlsReader", - "url": "https://github.com/shakinm/xlsReader", - "licenseUrl": "https://github.com/shakinm/xlsReader/blob/v0.9.12/LICENSE" + "name": "xls", + "url": "https://github.com/extrame/xls", + "licenseUrl": "https://github.com/extrame/xls/blob/4a6cf263071b975a90abf74ca3e804b48243be28/LICENSE" }, { "name": "go-ordered-map",