diff --git a/BigTable.xls b/BigTable.xls new file mode 100644 index 0000000..e7c7481 Binary files /dev/null and b/BigTable.xls differ diff --git a/bigtable_test.go b/bigtable_test.go new file mode 100644 index 0000000..356579a --- /dev/null +++ b/bigtable_test.go @@ -0,0 +1,59 @@ +package xls + +import ( + "fmt" + "testing" + "time" +) + +func TestBigTable(t *testing.T) { + xlFile, err := Open("BigTable.xls", "utf-8") + if err != nil { + t.Fatalf("Cant open xls file: %s", err) + } + + sheet := xlFile.GetSheet(0) + if sheet == nil { + t.Fatal("Cant get sheet") + } + + cnt1 := 1 + cnt2 := 10000 + cnt3 := 20000 + date1, _ := time.Parse("2006-01-02", "2015-01-01") + date2, _ := time.Parse("2006-01-02", "2016-01-01") + date3, _ := time.Parse("2006-01-02", "2017-01-01") + + for i := 1; i <= 4999; i++ { + row := sheet.Row(i) + if row == nil { + continue + } + + col2sample := fmt.Sprintf("%d от %s", cnt1, date1.Format("02.01.2006")) + col5sample := fmt.Sprintf("%d от %s", cnt2, date2.Format("02.01.2006")) + col8sample := fmt.Sprintf("%d от %s", cnt3, date3.Format("02.01.2006")) + + col2 := row.Col(2) + col5 := row.Col(5) + col8 := row.Col(8) + + if col2 != col2sample { + t.Fatalf("Row %d: col 2 val not eq base value: %s != %s", i, col2, col2sample) + } + if col5 != col5sample { + t.Fatalf("Row %d: col 5 val not eq base value: %s != %s", i, col5, col5sample) + } + if col8 != col8sample { + t.Fatalf("Row %d: col 8 val not eq base value: %s != %s", i, col8, col8sample) + } + + cnt1++ + cnt2++ + cnt3++ + date1 = date1.AddDate(0, 0, 1) + date2 = date2.AddDate(0, 0, 1) + date3 = date3.AddDate(0, 0, 1) + + } +} diff --git a/comparexlsxlsx.go b/comparexlsxlsx.go new file mode 100644 index 0000000..080f50a --- /dev/null +++ b/comparexlsxlsx.go @@ -0,0 +1,40 @@ +package xls + +import ( + "fmt" + "github.com/tealeg/xlsx" + "path" +) + +//Compares xls and xlsx files +func compareXlsXlsx(filepathname string) string { + xlsFile, err := Open(path.Join("testdata", filepathname)+".xls", "utf-8") + if err != nil { + return fmt.Sprintf("Cant open xls file: %s", err) + } + + xlsxFile, err := xlsx.OpenFile(path.Join("testdata", filepathname) + ".xlsx") + if err != nil { + return fmt.Sprintf("Cant open xlsx file: %s", err) + } + + for sheet, xlsxSheet := range xlsxFile.Sheets { + xlsSheet := xlsFile.GetSheet(sheet) + if xlsSheet == nil { + return fmt.Sprintf("Cant get xls sheet") + } + for row, xlsxRow := range xlsxSheet.Rows { + xlsRow := xlsSheet.Row(row) + for cell, xlsxCell := range xlsxRow.Cells { + xlsText := xlsRow.Col(cell) + xlsxText := xlsxCell.String() + if xlsText != xlsxText { + return fmt.Sprintf("Sheet: %d, row: %d, col: %d, xlsx: (%s)[%d], xls: (%s)[%d].", + sheet, row, cell, xlsxText, len(xlsxText), xlsText, len(xlsText)) + } + } + } + } + + return "" +} diff --git a/issue47_test.go b/issue47_test.go new file mode 100644 index 0000000..ab5a713 --- /dev/null +++ b/issue47_test.go @@ -0,0 +1,14 @@ +package xls + +import ( + "testing" +) + +func TestIssue47(t *testing.T) { + e := compareXlsXlsx("issue47") + + if e != "" { + t.Fatalf("XLS an XLSX are not equal: %s", e) + } + +} diff --git a/testdata/bigtable.xls b/testdata/bigtable.xls new file mode 100644 index 0000000..e7c7481 Binary files /dev/null and b/testdata/bigtable.xls differ diff --git a/testdata/bigtable.xlsx b/testdata/bigtable.xlsx new file mode 100644 index 0000000..b54c6fb Binary files /dev/null and b/testdata/bigtable.xlsx differ diff --git a/testdata/issue47.xls b/testdata/issue47.xls new file mode 100644 index 0000000..866f246 Binary files /dev/null and b/testdata/issue47.xls differ diff --git a/testdata/issue47.xlsx b/testdata/issue47.xlsx new file mode 100644 index 0000000..146e84c Binary files /dev/null and b/testdata/issue47.xlsx differ diff --git a/workbook.go b/workbook.go index fd655e5..aea1a83 100644 --- a/workbook.go +++ b/workbook.go @@ -3,6 +3,7 @@ package xls import ( "bytes" "encoding/binary" + "golang.org/x/text/encoding/charmap" "io" "os" "unicode/utf16" @@ -97,10 +98,8 @@ func (wb *WorkBook) parseBof(buf io.ReadSeeker, b *bof, pre *bof, offset_pre int } for err == nil && offset_pre < len(wb.sst) { var str string - if size > 0 { - str, err = wb.get_string(buf_item, size) - wb.sst[offset_pre] = wb.sst[offset_pre] + str - } + str, err = wb.get_string(buf_item, size) + wb.sst[offset_pre] = wb.sst[offset_pre] + str if err == io.EOF { break @@ -119,9 +118,12 @@ func (wb *WorkBook) parseBof(buf io.ReadSeeker, b *bof, pre *bof, offset_pre int wb.sst = make([]string, info.Count) var size uint16 var i = 0 + // dont forget to initialize offset + offset = 0 for ; i < int(info.Count); i++ { var err error - if err = binary.Read(buf_item, binary.LittleEndian, &size); err == nil { + err = binary.Read(buf_item, binary.LittleEndian, &size) + if err == nil { var str string str, err = wb.get_string(buf_item, size) wb.sst[i] = wb.sst[i] + str @@ -132,7 +134,7 @@ func (wb *WorkBook) parseBof(buf io.ReadSeeker, b *bof, pre *bof, offset_pre int } } offset = i - case 0x85: // bOUNDSHEET + case 0x85: // boundsheet var bs = new(boundsheet) binary.Read(buf_item, binary.LittleEndian, bs) // different for BIFF5 and BIFF8 @@ -162,9 +164,9 @@ func (wb *WorkBook) parseBof(buf io.ReadSeeker, b *bof, pre *bof, offset_pre int return } func decodeWindows1251(enc []byte) string { - dec := charmap.Windows1251.NewDecoder() - out, _ := dec.Bytes(enc) - return string(out) + dec := charmap.Windows1251.NewDecoder() + out, _ := dec.Bytes(enc) + return string(out) } func (w *WorkBook) get_string(buf io.ReadSeeker, size uint16) (res string, err error) { if w.Is5ver { @@ -195,11 +197,19 @@ func (w *WorkBook) get_string(buf io.ReadSeeker, size uint16) (res string, err e for ; i < size && err == nil; i++ { err = binary.Read(buf, binary.LittleEndian, &bts[i]) } - runes := utf16.Decode(bts[:i]) + + // when eof found, we dont want to append last element + var runes []rune + if err == io.EOF { + i = i - 1 + } + runes = utf16.Decode(bts[:i]) + res = string(runes) if i < size { - w.continue_utf16 = size - i + 1 + w.continue_utf16 = size - i } + } else { var bts = make([]byte, size) var n int