From e7a933588c0ba5972a6cbd51d54c20ead7fe9c7b Mon Sep 17 00:00:00 2001 From: Liu Ming Date: Wed, 30 Sep 2015 10:40:01 +0800 Subject: [PATCH] clean code and add some comments --- bof.go | 28 +++++----------------------- cell_range.go | 4 ++++ col.go | 3 ++- row.go | 2 +- workbook.go | 16 +++++++++------- worksheet.go | 46 +++++++++++++++++++++++----------------------- xls.go | 50 +++++++++++++++++++++++++++++--------------------- 7 files changed, 73 insertions(+), 76 deletions(-) diff --git a/bof.go b/bof.go index f963a58..ecb1f1e 100644 --- a/bof.go +++ b/bof.go @@ -1,31 +1,26 @@ package xls import ( - "bytes" "encoding/binary" "io" "unicode/utf16" ) -type BOF struct { +//the information unit in xls file +type bof struct { Id uint16 Size uint16 } -func (b *BOF) Reader(buf io.ReadSeeker) io.ReadSeeker { - rts := make([]byte, b.Size) - buf.Read(rts) - return bytes.NewReader(rts) -} - -func (b *BOF) Utf16String(buf io.ReadSeeker, count uint32) string { +//read the utf16 string from reader +func (b *bof) utf16String(buf io.ReadSeeker, count uint32) string { var bts = make([]uint16, count) binary.Read(buf, binary.LittleEndian, &bts) runes := utf16.Decode(bts[:len(bts)-1]) return string(runes) } -type BIFFHeader struct { +type biffHeader struct { Ver uint16 Type uint16 Id_make uint16 @@ -33,16 +28,3 @@ type BIFFHeader struct { Flags uint32 Min_ver uint32 } - -// func parseBofsForWb(bts []byte, wb *WorkBook) { -// bof := new(BOF) -// var bof_pre *BOF -// buf := bytes.NewReader(bts) -// for { -// if err := binary.Read(buf, binary.LittleEndian, bof); err == nil { -// bof_pre = bof.ActForWb(buf, wb, bof_pre) -// } else { -// break -// } -// } -// } diff --git a/cell_range.go b/cell_range.go index 3e7525b..2dde04e 100644 --- a/cell_range.go +++ b/cell_range.go @@ -4,11 +4,13 @@ import ( "fmt" ) +// range type of multi rows type Ranger interface { FirstRow() uint16 LastRow() uint16 } +// range type of multi cells in multi rows type CellRange struct { FirstRowB uint16 LastRowB uint16 @@ -32,6 +34,7 @@ func (c *CellRange) LastCol() uint16 { return c.LastColB } +//hyperlink type's content type HyperLink struct { CellRange Description string @@ -43,6 +46,7 @@ type HyperLink struct { IsUrl bool } +//get the hyperlink string, use the public variable Url to get the original Url func (h *HyperLink) String(wb *WorkBook) []string { res := make([]string, h.LastColB-h.FristColB+1) var str string diff --git a/col.go b/col.go index f4b7227..a092659 100644 --- a/col.go +++ b/col.go @@ -5,7 +5,8 @@ import ( "math" ) -type ContentHandler interface { +//content type +type contentHandler interface { String(*WorkBook) []string FirstCol() uint16 LastCol() uint16 diff --git a/row.go b/row.go index ebe6cf1..fc8b766 100644 --- a/row.go +++ b/row.go @@ -12,5 +12,5 @@ type RowInfo struct { type Row struct { info *RowInfo - Cols map[uint16]ContentHandler + Cols map[uint16]contentHandler } diff --git a/workbook.go b/workbook.go index d48e605..f56e596 100644 --- a/workbook.go +++ b/workbook.go @@ -8,6 +8,7 @@ import ( "unicode/utf16" ) +//xls workbook type type WorkBook struct { Is5ver bool Type uint16 @@ -22,7 +23,8 @@ type WorkBook struct { continue_utf16 uint16 } -func newWookBookFromOle2(rs io.ReadSeeker) *WorkBook { +//read workbook from ole2 file +func newWorkBookFromOle2(rs io.ReadSeeker) *WorkBook { wb := new(WorkBook) wb.Formats = make(map[uint16]*Format) // wb.bts = bts @@ -33,13 +35,13 @@ func newWookBookFromOle2(rs io.ReadSeeker) *WorkBook { } func (w *WorkBook) Parse(buf io.ReadSeeker) { - bof := new(BOF) - bof_pre := new(BOF) + b := new(bof) + bof_pre := new(bof) // buf := bytes.NewReader(bts) offset := 0 for { - if err := binary.Read(buf, binary.LittleEndian, bof); err == nil { - bof_pre, bof, offset = w.parseBof(buf, bof, bof_pre, offset) + if err := binary.Read(buf, binary.LittleEndian, b); err == nil { + bof_pre, b, offset = w.parseBof(buf, b, bof_pre, offset) } else { break } @@ -59,7 +61,7 @@ func (w *WorkBook) addFormat(format *Format) { w.Formats[format.Head.Index] = format } -func (wb *WorkBook) parseBof(buf io.ReadSeeker, b *BOF, pre *BOF, offset_pre int) (after *BOF, after_using *BOF, offset int) { +func (wb *WorkBook) parseBof(buf io.ReadSeeker, b *bof, pre *bof, offset_pre int) (after *bof, after_using *bof, offset int) { after = b after_using = pre var bts = make([]byte, b.Size) @@ -67,7 +69,7 @@ func (wb *WorkBook) parseBof(buf io.ReadSeeker, b *BOF, pre *BOF, offset_pre int buf_item := bytes.NewReader(bts) switch b.Id { case 0x809: - bif := new(BIFFHeader) + bif := new(biffHeader) binary.Read(buf_item, binary.LittleEndian, bif) if bif.Ver != 0x600 { wb.Is5ver = true diff --git a/worksheet.go b/worksheet.go index b7853f5..8a661af 100644 --- a/worksheet.go +++ b/worksheet.go @@ -26,12 +26,12 @@ type WorkSheet struct { func (w *WorkSheet) parse(buf io.ReadSeeker) { w.Rows = make(map[uint16]*Row) - bof := new(BOF) - var bof_pre *BOF + b := new(bof) + var bof_pre *bof for { - if err := binary.Read(buf, binary.LittleEndian, bof); err == nil { - bof_pre = w.parseBof(buf, bof, bof_pre) - if bof.Id == 0xa { + if err := binary.Read(buf, binary.LittleEndian, b); err == nil { + bof_pre = w.parseBof(buf, b, bof_pre) + if b.Id == 0xa { break } } else { @@ -41,9 +41,9 @@ func (w *WorkSheet) parse(buf io.ReadSeeker) { } } -func (w *WorkSheet) parseBof(buf io.ReadSeeker, bof *BOF, pre *BOF) *BOF { +func (w *WorkSheet) parseBof(buf io.ReadSeeker, b *bof, pre *bof) *bof { var col interface{} - switch bof.Id { + switch b.Id { // case 0x0E5: //MERGEDCELLS // ws.mergedCells(buf) case 0x208: //ROW @@ -52,7 +52,7 @@ func (w *WorkSheet) parseBof(buf io.ReadSeeker, bof *BOF, pre *BOF) *BOF { w.addRow(r) case 0x0BD: //MULRK mc := new(MulrkCol) - size := (bof.Size - 6) / 6 + size := (b.Size - 6) / 6 binary.Read(buf, binary.LittleEndian, &mc.Col) mc.Xfrks = make([]XfRk, size) for i := uint16(0); i < size; i++ { @@ -62,7 +62,7 @@ func (w *WorkSheet) parseBof(buf io.ReadSeeker, bof *BOF, pre *BOF) *BOF { col = mc case 0x0BE: //MULBLANK mc := new(MulBlankCol) - size := (bof.Size - 6) / 2 + size := (b.Size - 6) / 2 binary.Read(buf, binary.LittleEndian, &mc.Col) mc.Xfs = make([]uint16, size) for i := uint16(0); i < size; i++ { @@ -76,7 +76,7 @@ func (w *WorkSheet) parseBof(buf io.ReadSeeker, bof *BOF, pre *BOF) *BOF { case 0x06: //FORMULA c := new(FormulaCol) binary.Read(buf, binary.LittleEndian, &c.Header) - c.Bts = make([]byte, bof.Size-20) + c.Bts = make([]byte, b.Size-20) binary.Read(buf, binary.LittleEndian, &c.Bts) col = c case 0x27e: //RK @@ -98,11 +98,11 @@ func (w *WorkSheet) parseBof(buf io.ReadSeeker, bof *BOF, pre *BOF) *BOF { if flag&0x14 != 0 { binary.Read(buf, binary.LittleEndian, &count) - hy.Description = bof.Utf16String(buf, count) + hy.Description = b.utf16String(buf, count) } if flag&0x80 != 0 { binary.Read(buf, binary.LittleEndian, &count) - hy.TargetFrame = bof.Utf16String(buf, count) + hy.TargetFrame = b.utf16String(buf, count) } if flag&0x1 != 0 { var guid [2]uint64 @@ -110,7 +110,7 @@ func (w *WorkSheet) parseBof(buf io.ReadSeeker, bof *BOF, pre *BOF) *BOF { if guid[0] == 0xE0C9EA79F9BACE11 && guid[1] == 0x8C8200AA004BA90B { //URL hy.IsUrl = true binary.Read(buf, binary.LittleEndian, &count) - hy.Url = bof.Utf16String(buf, count/2) + hy.Url = b.utf16String(buf, count/2) } else if guid[0] == 0x303000000000000 && guid[1] == 0xC000000000000046 { //URL{ var upCount uint16 binary.Read(buf, binary.LittleEndian, &upCount) @@ -123,7 +123,7 @@ func (w *WorkSheet) parseBof(buf io.ReadSeeker, bof *BOF, pre *BOF) *BOF { if count > 0 { binary.Read(buf, binary.LittleEndian, &count) buf.Seek(2, 1) - hy.ExtendedFilePath = bof.Utf16String(buf, count/2+1) + hy.ExtendedFilePath = b.utf16String(buf, count/2+1) } log.Println(hy) } @@ -139,21 +139,21 @@ func (w *WorkSheet) parseBof(buf io.ReadSeeker, bof *BOF, pre *BOF) *BOF { w.addRange(&hy.CellRange, &hy) case 0x809: log.Println("sheet start") - buf.Seek(int64(bof.Size), 1) + buf.Seek(int64(b.Size), 1) case 0xa: log.Println("sheet end") default: - // log.Printf("Unknow %X,%d\n", bof.Id, bof.Size) - buf.Seek(int64(bof.Size), 1) + // log.Printf("Unknow %X,%d\n", b.Id, b.Size) + buf.Seek(int64(b.Size), 1) } if col != nil { w.add(col) } - return bof + return b } func (w *WorkSheet) add(content interface{}) { - if ch, ok := content.(ContentHandler); ok { + if ch, ok := content.(contentHandler); ok { if col, ok := content.(Coler); ok { w.addCell(col, ch) } @@ -161,18 +161,18 @@ func (w *WorkSheet) add(content interface{}) { } -func (w *WorkSheet) addCell(col Coler, ch ContentHandler) { +func (w *WorkSheet) addCell(col Coler, ch contentHandler) { w.addContent(col.Row(), ch) } -func (w *WorkSheet) addRange(rang Ranger, ch ContentHandler) { +func (w *WorkSheet) addRange(rang Ranger, ch contentHandler) { for i := rang.FirstRow(); i <= rang.LastRow(); i++ { w.addContent(i, ch) } } -func (w *WorkSheet) addContent(row_num uint16, ch ContentHandler) { +func (w *WorkSheet) addContent(row_num uint16, ch contentHandler) { var row *Row var ok bool if row, ok = w.Rows[row_num]; !ok { @@ -191,7 +191,7 @@ func (w *WorkSheet) addRow(info *RowInfo) (row *Row) { if row, ok = w.Rows[info.Index]; ok { row.info = info } else { - row = &Row{info: info, Cols: make(map[uint16]ContentHandler)} + row = &Row{info: info, Cols: make(map[uint16]contentHandler)} w.Rows[info.Index] = row } return diff --git a/xls.go b/xls.go index 68811db..1a54d58 100644 --- a/xls.go +++ b/xls.go @@ -6,8 +6,8 @@ import ( "io/ioutil" ) +//Open one xls file func Open(file string, charset string) (*WorkBook, error) { - if bts, err := ioutil.ReadFile(file); err == nil { return parse(bts, charset) } else { @@ -16,30 +16,38 @@ func Open(file string, charset string) (*WorkBook, error) { } +//Open xls file from reader func OpenReader(reader io.ReadCloser, charset string) (*WorkBook, error) { - bts, _ := ioutil.ReadAll(reader) - return parse(bts, charset) + if bts, err := ioutil.ReadAll(reader); err == nil { + return parse(bts, charset) + } else { + return nil, err + } } -func parse(bts []byte, charset string) (*WorkBook, error) { - ole, _ := ole2.Open(bts, charset) - dir, err := ole.ListDir() - var book *ole2.File - for _, file := range dir { - name := file.Name() - if name == "Workbook" { - book = file - // break - } - if name == "Book" { - book = file - // break +func parse(bts []byte, charset string) (wb *WorkBook, err error) { + var ole *ole2.Ole + if ole, err = ole2.Open(bts, charset); err == nil { + var dir []*ole2.File + if dir, err = ole.ListDir(); err == nil { + var book *ole2.File + for _, file := range dir { + name := file.Name() + if name == "Workbook" { + book = file + // break + } + if name == "Book" { + book = file + // break + } + } + if book != nil { + wb = newWorkBookFromOle2(ole.OpenFile(book)) + return + } } } - if book != nil { - wb := newWookBookFromOle2(ole.OpenFile(book)) - return wb, nil - } - return nil, err + return }