diff --git a/Table.xls b/Table.xls new file mode 100644 index 0000000..963d872 Binary files /dev/null and b/Table.xls differ diff --git a/col.go b/col.go index a092659..7717529 100644 --- a/col.go +++ b/col.go @@ -46,7 +46,7 @@ func (xf *XfRk) String(wb *WorkBook) string { switch wb.Xfs[21].formatNo() { case 27: if f, e := xf.Rk.Float(); e == nil { - t := TimeFromExcelTime(f, true) + t := timeFromExcelTime(f, true) return t.Format("2006.01") //TODO it should be international } } diff --git a/date.go b/date.go index 6c0ef1a..b7d2d04 100644 --- a/date.go +++ b/date.go @@ -69,7 +69,7 @@ func doTheFliegelAndVanFlandernAlgorithm(jd int) (day, month, year int) { } // Convert an excelTime representation (stored as a floating point number) to a time.Time. -func TimeFromExcelTime(excelTime float64, date1904 bool) time.Time { +func timeFromExcelTime(excelTime float64, date1904 bool) time.Time { var date time.Time var intPart int64 = int64(excelTime) // Excel uses Julian dates prior to March 1st 1900, and diff --git a/workbook.go b/workbook.go index f56e596..0abd21f 100644 --- a/workbook.go +++ b/workbook.go @@ -10,13 +10,14 @@ import ( //xls workbook type type WorkBook struct { - Is5ver bool - Type uint16 - Codepage uint16 - Xfs []st_xf_data - Fonts []Font - Formats map[uint16]*Format - Sheets []*WorkSheet + Is5ver bool + Type uint16 + Codepage uint16 + Xfs []st_xf_data + Fonts []Font + Formats map[uint16]*Format + //All the sheets from the workbook + sheets []*WorkSheet Author string rs io.ReadSeeker sst []string @@ -29,7 +30,7 @@ func newWorkBookFromOle2(rs io.ReadSeeker) *WorkBook { wb.Formats = make(map[uint16]*Format) // wb.bts = bts wb.rs = rs - wb.Sheets = make([]*WorkSheet, 0) + wb.sheets = make([]*WorkSheet, 0) wb.Parse(rs) return wb } @@ -199,22 +200,32 @@ func (w *WorkBook) get_string_from_bytes(bts []byte, size uint16) string { func (w *WorkBook) addSheet(sheet *boundsheet, buf io.ReadSeeker) { name := w.get_string(buf, uint16(sheet.Name)) - w.Sheets = append(w.Sheets, &WorkSheet{bs: sheet, Name: name, wb: w}) + w.sheets = append(w.sheets, &WorkSheet{bs: sheet, Name: name, wb: w}) } //reading a sheet from the compress file to memory, you should call this before you try to get anything from sheet -func (w *WorkBook) PrepareSheet(sheet *WorkSheet) { +func (w *WorkBook) prepareSheet(sheet *WorkSheet) { w.rs.Seek(int64(sheet.bs.Filepos), 0) sheet.parse(w.rs) } +func (w *WorkBook) GetSheet(num int) *WorkSheet { + if num < len(w.sheets) { + s := w.sheets[num] + w.prepareSheet(s) + return s + } else { + return nil + } +} + //helper function to read all cells from file func (w *WorkBook) ReadAllCells(max int) (res [][]string) { res = make([][]string, 0) - for _, sheet := range w.Sheets { + for _, sheet := range w.sheets { if len(res) < max { max = max - len(res) - w.PrepareSheet(sheet) + w.prepareSheet(sheet) if sheet.MaxRow != 0 { leng := int(sheet.MaxRow) + 1 if max < leng { diff --git a/worksheet.go b/worksheet.go index 8a661af..1d530b1 100644 --- a/worksheet.go +++ b/worksheet.go @@ -17,10 +17,11 @@ type boundsheet struct { //WorkSheet in one WorkBook type WorkSheet struct { - bs *boundsheet - wb *WorkBook - Name string - Rows map[uint16]*Row + bs *boundsheet + wb *WorkBook + Name string + Rows map[uint16]*Row + //NOTICE: this is the max row number of the sheet, so it should be count -1 MaxRow uint16 } diff --git a/xls.go b/xls.go index 1a54d58..2c93292 100644 --- a/xls.go +++ b/xls.go @@ -47,7 +47,6 @@ func parse(bts []byte, charset string) (wb *WorkBook, err error) { return } } - } return } diff --git a/xls_test.go b/xls_test.go new file mode 100644 index 0000000..7391115 --- /dev/null +++ b/xls_test.go @@ -0,0 +1,67 @@ +package xls + +import ( + "bytes" + "fmt" + "os" + "testing" +) + +func TestOpen(t *testing.T) { + xlFile, _ := Open("Table.xls", "") + sheet1 := xlFile.GetSheet(0) + fmt.Println(sheet1.Name) + fmt.Print(sheet1.Rows) + for k, row1 := range sheet1.Rows { + // row1 := sheet1.Rows[1] + fmt.Printf("\n[%d]", k) + for _, col1 := range row1.Cols { + // col1 := row1.Cols[0] + fmt.Print(col1.LastCol()) + fmt.Print(" ") + } + } +} + +func TestBof(t *testing.T) { + b := new(bof) + b.Id = 0x41E + b.Size = 55 + buf := bytes.NewReader([]byte{0x07, 0x00, 0x19, 0x00, 0x01, 0x22, 0x00, 0xE5, 0xFF, 0x22, 0x00, 0x23, 0x00, 0x2C, 0x00, 0x23, 0x00, 0x23, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x30, 0x00, 0x30, 0x00, 0x3B, 0x00, 0x22, 0x00, 0xE5, 0xFF, 0x22, 0x00, 0x5C, 0x00, 0x2D, 0x00, 0x23, 0x00, 0x2C, 0x20, 0x00}) + new(WorkBook).parseBof(buf, b, b, 0) +} + +func TestMaxRow(t *testing.T) { + xlFile, err := Open("Table.xls", "utf-8") + if err != nil { + fmt.Fprintf(os.Stderr, "Failure: %v\n", err) + t.Error(err) + } + + if sheet1 := xlFile.GetSheet(0); sheet1 != nil { + if sheet1.MaxRow != 11 { + t.Errorf("max row is error,is %d instead of 11", sheet1.MaxRow) + } + } +} + +//read the content of first two cols in each row +func ExampleReadXls(t *testing.T) { + xlFile, err := Open("Table.xls", "utf-8") + if err != nil { + fmt.Fprintf(os.Stderr, "Failure: %v\n", err) + t.Error(err) + } + + if sheet1 := xlFile.GetSheet(0); sheet1 != nil { + fmt.Print("Total Lines ", sheet1.MaxRow, sheet1.Name) + col1 := sheet1.Rows[0].Cols[0] + col2 := sheet1.Rows[0].Cols[0] + for i := 0; i <= (int(sheet1.MaxRow)); i++ { + row1 := sheet1.Rows[uint16(i)] + col1 = row1.Cols[0] + col2 = row1.Cols[1] + fmt.Print("\n", col1.String(xlFile), ",", col2.String(xlFile)) + } + } +}