20
0

clean code and add some comments

This commit is contained in:
Liu Ming 2015-09-30 10:40:01 +08:00
parent 4b7153c0ef
commit e7a933588c
7 changed files with 73 additions and 76 deletions

28
bof.go
View File

@ -1,31 +1,26 @@
package xls package xls
import ( import (
"bytes"
"encoding/binary" "encoding/binary"
"io" "io"
"unicode/utf16" "unicode/utf16"
) )
type BOF struct { //the information unit in xls file
type bof struct {
Id uint16 Id uint16
Size uint16 Size uint16
} }
func (b *BOF) Reader(buf io.ReadSeeker) io.ReadSeeker { //read the utf16 string from reader
rts := make([]byte, b.Size) func (b *bof) utf16String(buf io.ReadSeeker, count uint32) string {
buf.Read(rts)
return bytes.NewReader(rts)
}
func (b *BOF) Utf16String(buf io.ReadSeeker, count uint32) string {
var bts = make([]uint16, count) var bts = make([]uint16, count)
binary.Read(buf, binary.LittleEndian, &bts) binary.Read(buf, binary.LittleEndian, &bts)
runes := utf16.Decode(bts[:len(bts)-1]) runes := utf16.Decode(bts[:len(bts)-1])
return string(runes) return string(runes)
} }
type BIFFHeader struct { type biffHeader struct {
Ver uint16 Ver uint16
Type uint16 Type uint16
Id_make uint16 Id_make uint16
@ -33,16 +28,3 @@ type BIFFHeader struct {
Flags uint32 Flags uint32
Min_ver 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
// }
// }
// }

View File

@ -4,11 +4,13 @@ import (
"fmt" "fmt"
) )
// range type of multi rows
type Ranger interface { type Ranger interface {
FirstRow() uint16 FirstRow() uint16
LastRow() uint16 LastRow() uint16
} }
// range type of multi cells in multi rows
type CellRange struct { type CellRange struct {
FirstRowB uint16 FirstRowB uint16
LastRowB uint16 LastRowB uint16
@ -32,6 +34,7 @@ func (c *CellRange) LastCol() uint16 {
return c.LastColB return c.LastColB
} }
//hyperlink type's content
type HyperLink struct { type HyperLink struct {
CellRange CellRange
Description string Description string
@ -43,6 +46,7 @@ type HyperLink struct {
IsUrl bool IsUrl bool
} }
//get the hyperlink string, use the public variable Url to get the original Url
func (h *HyperLink) String(wb *WorkBook) []string { func (h *HyperLink) String(wb *WorkBook) []string {
res := make([]string, h.LastColB-h.FristColB+1) res := make([]string, h.LastColB-h.FristColB+1)
var str string var str string

3
col.go
View File

@ -5,7 +5,8 @@ import (
"math" "math"
) )
type ContentHandler interface { //content type
type contentHandler interface {
String(*WorkBook) []string String(*WorkBook) []string
FirstCol() uint16 FirstCol() uint16
LastCol() uint16 LastCol() uint16

2
row.go
View File

@ -12,5 +12,5 @@ type RowInfo struct {
type Row struct { type Row struct {
info *RowInfo info *RowInfo
Cols map[uint16]ContentHandler Cols map[uint16]contentHandler
} }

View File

@ -8,6 +8,7 @@ import (
"unicode/utf16" "unicode/utf16"
) )
//xls workbook type
type WorkBook struct { type WorkBook struct {
Is5ver bool Is5ver bool
Type uint16 Type uint16
@ -22,7 +23,8 @@ type WorkBook struct {
continue_utf16 uint16 continue_utf16 uint16
} }
func newWookBookFromOle2(rs io.ReadSeeker) *WorkBook { //read workbook from ole2 file
func newWorkBookFromOle2(rs io.ReadSeeker) *WorkBook {
wb := new(WorkBook) wb := new(WorkBook)
wb.Formats = make(map[uint16]*Format) wb.Formats = make(map[uint16]*Format)
// wb.bts = bts // wb.bts = bts
@ -33,13 +35,13 @@ func newWookBookFromOle2(rs io.ReadSeeker) *WorkBook {
} }
func (w *WorkBook) Parse(buf io.ReadSeeker) { func (w *WorkBook) Parse(buf io.ReadSeeker) {
bof := new(BOF) b := new(bof)
bof_pre := new(BOF) bof_pre := new(bof)
// buf := bytes.NewReader(bts) // buf := bytes.NewReader(bts)
offset := 0 offset := 0
for { for {
if err := binary.Read(buf, binary.LittleEndian, bof); err == nil { if err := binary.Read(buf, binary.LittleEndian, b); err == nil {
bof_pre, bof, offset = w.parseBof(buf, bof, bof_pre, offset) bof_pre, b, offset = w.parseBof(buf, b, bof_pre, offset)
} else { } else {
break break
} }
@ -59,7 +61,7 @@ func (w *WorkBook) addFormat(format *Format) {
w.Formats[format.Head.Index] = 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 = b
after_using = pre after_using = pre
var bts = make([]byte, b.Size) 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) buf_item := bytes.NewReader(bts)
switch b.Id { switch b.Id {
case 0x809: case 0x809:
bif := new(BIFFHeader) bif := new(biffHeader)
binary.Read(buf_item, binary.LittleEndian, bif) binary.Read(buf_item, binary.LittleEndian, bif)
if bif.Ver != 0x600 { if bif.Ver != 0x600 {
wb.Is5ver = true wb.Is5ver = true

View File

@ -26,12 +26,12 @@ type WorkSheet struct {
func (w *WorkSheet) parse(buf io.ReadSeeker) { func (w *WorkSheet) parse(buf io.ReadSeeker) {
w.Rows = make(map[uint16]*Row) w.Rows = make(map[uint16]*Row)
bof := new(BOF) b := new(bof)
var bof_pre *BOF var bof_pre *bof
for { for {
if err := binary.Read(buf, binary.LittleEndian, bof); err == nil { if err := binary.Read(buf, binary.LittleEndian, b); err == nil {
bof_pre = w.parseBof(buf, bof, bof_pre) bof_pre = w.parseBof(buf, b, bof_pre)
if bof.Id == 0xa { if b.Id == 0xa {
break break
} }
} else { } 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{} var col interface{}
switch bof.Id { switch b.Id {
// case 0x0E5: //MERGEDCELLS // case 0x0E5: //MERGEDCELLS
// ws.mergedCells(buf) // ws.mergedCells(buf)
case 0x208: //ROW case 0x208: //ROW
@ -52,7 +52,7 @@ func (w *WorkSheet) parseBof(buf io.ReadSeeker, bof *BOF, pre *BOF) *BOF {
w.addRow(r) w.addRow(r)
case 0x0BD: //MULRK case 0x0BD: //MULRK
mc := new(MulrkCol) mc := new(MulrkCol)
size := (bof.Size - 6) / 6 size := (b.Size - 6) / 6
binary.Read(buf, binary.LittleEndian, &mc.Col) binary.Read(buf, binary.LittleEndian, &mc.Col)
mc.Xfrks = make([]XfRk, size) mc.Xfrks = make([]XfRk, size)
for i := uint16(0); i < size; i++ { 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 col = mc
case 0x0BE: //MULBLANK case 0x0BE: //MULBLANK
mc := new(MulBlankCol) mc := new(MulBlankCol)
size := (bof.Size - 6) / 2 size := (b.Size - 6) / 2
binary.Read(buf, binary.LittleEndian, &mc.Col) binary.Read(buf, binary.LittleEndian, &mc.Col)
mc.Xfs = make([]uint16, size) mc.Xfs = make([]uint16, size)
for i := uint16(0); i < size; i++ { 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 case 0x06: //FORMULA
c := new(FormulaCol) c := new(FormulaCol)
binary.Read(buf, binary.LittleEndian, &c.Header) 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) binary.Read(buf, binary.LittleEndian, &c.Bts)
col = c col = c
case 0x27e: //RK case 0x27e: //RK
@ -98,11 +98,11 @@ func (w *WorkSheet) parseBof(buf io.ReadSeeker, bof *BOF, pre *BOF) *BOF {
if flag&0x14 != 0 { if flag&0x14 != 0 {
binary.Read(buf, binary.LittleEndian, &count) binary.Read(buf, binary.LittleEndian, &count)
hy.Description = bof.Utf16String(buf, count) hy.Description = b.utf16String(buf, count)
} }
if flag&0x80 != 0 { if flag&0x80 != 0 {
binary.Read(buf, binary.LittleEndian, &count) binary.Read(buf, binary.LittleEndian, &count)
hy.TargetFrame = bof.Utf16String(buf, count) hy.TargetFrame = b.utf16String(buf, count)
} }
if flag&0x1 != 0 { if flag&0x1 != 0 {
var guid [2]uint64 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 if guid[0] == 0xE0C9EA79F9BACE11 && guid[1] == 0x8C8200AA004BA90B { //URL
hy.IsUrl = true hy.IsUrl = true
binary.Read(buf, binary.LittleEndian, &count) 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{ } else if guid[0] == 0x303000000000000 && guid[1] == 0xC000000000000046 { //URL{
var upCount uint16 var upCount uint16
binary.Read(buf, binary.LittleEndian, &upCount) 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 { if count > 0 {
binary.Read(buf, binary.LittleEndian, &count) binary.Read(buf, binary.LittleEndian, &count)
buf.Seek(2, 1) buf.Seek(2, 1)
hy.ExtendedFilePath = bof.Utf16String(buf, count/2+1) hy.ExtendedFilePath = b.utf16String(buf, count/2+1)
} }
log.Println(hy) log.Println(hy)
} }
@ -139,21 +139,21 @@ func (w *WorkSheet) parseBof(buf io.ReadSeeker, bof *BOF, pre *BOF) *BOF {
w.addRange(&hy.CellRange, &hy) w.addRange(&hy.CellRange, &hy)
case 0x809: case 0x809:
log.Println("sheet start") log.Println("sheet start")
buf.Seek(int64(bof.Size), 1) buf.Seek(int64(b.Size), 1)
case 0xa: case 0xa:
log.Println("sheet end") log.Println("sheet end")
default: default:
// log.Printf("Unknow %X,%d\n", bof.Id, bof.Size) // log.Printf("Unknow %X,%d\n", b.Id, b.Size)
buf.Seek(int64(bof.Size), 1) buf.Seek(int64(b.Size), 1)
} }
if col != nil { if col != nil {
w.add(col) w.add(col)
} }
return bof return b
} }
func (w *WorkSheet) add(content interface{}) { func (w *WorkSheet) add(content interface{}) {
if ch, ok := content.(ContentHandler); ok { if ch, ok := content.(contentHandler); ok {
if col, ok := content.(Coler); ok { if col, ok := content.(Coler); ok {
w.addCell(col, ch) 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) 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++ { for i := rang.FirstRow(); i <= rang.LastRow(); i++ {
w.addContent(i, ch) 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 row *Row
var ok bool var ok bool
if row, ok = w.Rows[row_num]; !ok { 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 { if row, ok = w.Rows[info.Index]; ok {
row.info = info row.info = info
} else { } else {
row = &Row{info: info, Cols: make(map[uint16]ContentHandler)} row = &Row{info: info, Cols: make(map[uint16]contentHandler)}
w.Rows[info.Index] = row w.Rows[info.Index] = row
} }
return return

50
xls.go
View File

@ -6,8 +6,8 @@ import (
"io/ioutil" "io/ioutil"
) )
//Open one xls file
func Open(file string, charset string) (*WorkBook, error) { func Open(file string, charset string) (*WorkBook, error) {
if bts, err := ioutil.ReadFile(file); err == nil { if bts, err := ioutil.ReadFile(file); err == nil {
return parse(bts, charset) return parse(bts, charset)
} else { } 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) { func OpenReader(reader io.ReadCloser, charset string) (*WorkBook, error) {
bts, _ := ioutil.ReadAll(reader) if bts, err := ioutil.ReadAll(reader); err == nil {
return parse(bts, charset) return parse(bts, charset)
} else {
return nil, err
}
} }
func parse(bts []byte, charset string) (*WorkBook, error) { func parse(bts []byte, charset string) (wb *WorkBook, err error) {
ole, _ := ole2.Open(bts, charset) var ole *ole2.Ole
dir, err := ole.ListDir() if ole, err = ole2.Open(bts, charset); err == nil {
var book *ole2.File var dir []*ole2.File
for _, file := range dir { if dir, err = ole.ListDir(); err == nil {
name := file.Name() var book *ole2.File
if name == "Workbook" { for _, file := range dir {
book = file name := file.Name()
// break if name == "Workbook" {
} book = file
if name == "Book" { // break
book = file }
// break if name == "Book" {
book = file
// break
}
}
if book != nil {
wb = newWorkBookFromOle2(ole.OpenFile(book))
return
}
} }
} }
if book != nil { return
wb := newWookBookFromOle2(ole.OpenFile(book))
return wb, nil
}
return nil, err
} }