github.com/shakinm/xlsReader@v0.9.12/xls/workbook.go (about) 1 package xls 2 3 import ( 4 "bytes" 5 "errors" 6 "github.com/shakinm/xlsReader/helpers" 7 "github.com/shakinm/xlsReader/xls/record" 8 ) 9 10 // Workbook struct 11 type Workbook struct { 12 sheets []Sheet 13 codepage record.CodePage 14 sst record.SST 15 xf []record.XF 16 formats map[int]record.Format 17 vers [2]byte 18 } 19 20 // GetNumberSheets - Number of sheets in the workbook 21 func (wb *Workbook) GetNumberSheets() int { 22 return len(wb.sheets) 23 } 24 25 // GetSheets - Get sheets in the workbook 26 func (wb *Workbook) GetSheets() []Sheet { 27 return wb.sheets 28 } 29 30 // GetSheet - Get Sheet by ID 31 func (wb *Workbook) GetSheet(sheetID int) (sheet *Sheet, err error) { // nolint: golint 32 33 if len(wb.sheets) >= 1 && len(wb.sheets) >= sheetID { 34 return &wb.sheets[sheetID], err 35 } 36 37 return nil, errors.New("error. Sheet not found") 38 } 39 40 // GetXF - Return Extended Format Record by index 41 func (wb *Workbook) GetXFbyIndex(index int) record.XF { 42 if len(wb.xf)-1<index { 43 return wb.xf[15] 44 } 45 return wb.xf[index] 46 } 47 48 // GetXF - Return FORMAT record describes a number format in the workbook 49 func (wb *Workbook) GetFormatByIndex(index int) record.Format { 50 return wb.formats[index] 51 } 52 53 // GetCodePage - codepage 54 func (wb *Workbook) GetCodePage() record.CodePage { 55 return wb.codepage 56 } 57 58 // GetVersionBIFF - version BIFF 59 func (wb *Workbook) GetVersionBIFF() []byte { 60 return wb.vers[:] 61 } 62 63 func (wb *Workbook) addSheet(bs *record.BoundSheet) (sheet Sheet) { // nolint: golint 64 sheet.boundSheet = bs 65 sheet.wb = wb 66 wb.sheets = append(wb.sheets, sheet) 67 return sheet 68 } 69 70 func (wb *Workbook) read(stream []byte) (err error) { // nolint: gocyclo 71 72 var point int32 73 var SSTContinue = false 74 var sPoint, prevLen int32 75 var readType string 76 var grbit byte 77 var grbitOffset int32 78 79 eof := false 80 81 Next: 82 83 recordNumber := stream[point : point+2] 84 recordDataLength := int32(helpers.BytesToUint16(stream[point+2 : point+4])) 85 sPoint = point + 4 86 87 if bytes.Compare(recordNumber, record.IndexRecord[:]) == 0 { 88 _ = new(record.LabelSSt) 89 goto EIF 90 } 91 92 //BoundSheet 93 94 if bytes.Compare(recordNumber, record.BoundSheetRecord[:]) == 0 { 95 var bs record.BoundSheet 96 bs.Read(stream[sPoint+grbitOffset : sPoint+recordDataLength], wb.vers[:]) 97 _ = wb.addSheet(&bs) 98 goto EIF 99 } 100 101 //Continue 102 if bytes.Compare(recordNumber, record.ContinueRecord[:]) == 0 { 103 104 if SSTContinue { 105 readType = "continue" 106 107 if len(wb.sst.RgbSrc) == 0 { 108 grbitOffset = 0 109 } else { 110 grbitOffset = 1 111 } 112 113 grbit = stream[sPoint] 114 115 wb.sst.RgbSrc = append(wb.sst.RgbSrc, stream[sPoint+grbitOffset:sPoint+recordDataLength]...) 116 wb.sst.Read(readType, grbit, prevLen) 117 } 118 goto EIF 119 } 120 121 //SST 122 if bytes.Compare(recordNumber, record.SSTRecord[:]) == 0 { 123 wb.sst.NewSST(stream[sPoint : sPoint+recordDataLength]) 124 125 wb.sst.Read(readType, grbit, prevLen) 126 totalSSt := helpers.BytesToUint32(wb.sst.CstTotal[:]) 127 if recordDataLength >= 8224 || uint32(len(wb.sst.Rgb)) < totalSSt-1 { 128 SSTContinue = true 129 } 130 goto EIF 131 } 132 133 if bytes.Compare(recordNumber, record.XFRecord[:]) == 0 { 134 xf := new(record.XF) 135 xf.Read(stream[sPoint : sPoint+recordDataLength]) 136 wb.xf=append(wb.xf, *xf) 137 goto EIF 138 } 139 140 if bytes.Compare(recordNumber, record.FormatRecord[:]) == 0 { 141 format := new(record.Format) 142 143 format.Read(stream[sPoint : sPoint+recordDataLength], wb.vers[:]) 144 145 if wb.formats==nil { 146 wb.formats = make(map[int]record.Format,0) 147 } 148 wb.formats[format.GetIndex()]=*format 149 goto EIF 150 } 151 152 //CodePage 153 if bytes.Compare(recordNumber, record.CodePageRecord[:]) == 0 { 154 wb.codepage.Read(stream[sPoint : sPoint+recordDataLength]) 155 goto EIF 156 } 157 158 //EOF 159 if bytes.Compare(recordNumber, record.EOFRecord[:]) == 0 && recordDataLength == 0 { 160 eof = true 161 } 162 163 if bytes.Compare(recordNumber, record.BOFMARKS[:]) == 0 { 164 copy(wb.vers[:], stream[sPoint : sPoint+2]) 165 goto EIF 166 } 167 168 EIF: 169 point = point + recordDataLength + 4 170 if !eof { 171 goto Next 172 } 173 174 return err 175 }