github.com/shakinm/xlsReader@v0.9.12/xls/sheet.go (about) 1 package xls 2 3 import ( 4 "bytes" 5 "fmt" 6 "github.com/shakinm/xlsReader/helpers" 7 "github.com/shakinm/xlsReader/xls/record" 8 "github.com/shakinm/xlsReader/xls/structure" 9 ) 10 11 type rw struct { 12 cols map[int]structure.CellData 13 } 14 15 type Sheet struct { 16 boundSheet *record.BoundSheet 17 rows map[int]*rw 18 wb *Workbook 19 maxCol int // maxCol index, countCol=maxCol+1 20 maxRow int // maxRow index, countRow=maxRow+1 21 hasAutofilter bool 22 } 23 24 func (s *Sheet) GetName() string { 25 return s.boundSheet.GetName() 26 } 27 28 // Get row by index 29 30 func (s *Sheet) GetRow(index int) (row *rw, err error) { 31 32 if row, ok := s.rows[index]; ok { 33 return row, err 34 } else { 35 r := new(rw) 36 r.cols = make(map[int]structure.CellData) 37 return r, nil 38 } 39 } 40 41 func (rw *rw) GetCol(index int) (c structure.CellData, err error) { 42 43 if col, ok := rw.cols[index]; ok { 44 return col, err 45 } else { 46 c = new(record.FakeBlank) 47 return c, nil 48 } 49 50 } 51 52 func (rw *rw) GetCols() (cols []structure.CellData) { 53 54 var maxColKey int 55 56 for k, _ := range rw.cols { 57 if k > maxColKey { 58 maxColKey = k 59 } 60 } 61 62 for i := 0; i <= maxColKey; i++ { 63 if rw.cols[i] == nil { 64 cols = append(cols, new(record.FakeBlank)) 65 } else { 66 cols = append(cols, rw.cols[i]) 67 } 68 } 69 70 return cols 71 } 72 73 // Get all rows 74 func (s *Sheet) GetRows() (rows []*rw) { 75 for i := 0; i <= s.GetNumberRows()-1; i++ { 76 if s.rows[i] == nil { 77 r := new(rw) 78 r.cols = make(map[int]structure.CellData) 79 rows = append(rows, r) 80 } else { 81 rows = append(rows, s.rows[i]) 82 } 83 } 84 85 return rows 86 } 87 88 // Get number of rows 89 func (s *Sheet) GetNumberRows() (n int) { 90 91 var maxRowKey int 92 93 for k, _ := range s.rows { 94 if k > maxRowKey { 95 maxRowKey = k 96 } 97 } 98 99 return maxRowKey + 1 100 } 101 102 func (s *Sheet) read(stream []byte) (err error) { // nolint: gocyclo 103 104 var point int64 105 point = int64(helpers.BytesToUint32(s.boundSheet.LbPlyPos[:])) 106 var sPoint int64 107 eof := false 108 records := make(map[string]string ) 109 Next: 110 111 recordNumber := stream[point : point+2] 112 recordDataLength := int64(helpers.BytesToUint16(stream[point+2 : point+4])) 113 sPoint = point + 4 114 records[fmt.Sprintf("%x",recordNumber)]=fmt.Sprintf("%x",recordNumber) 115 if bytes.Compare(recordNumber, record.AutofilterInfoRecord[:]) == 0 { 116 c := new(record.AutofilterInfo) 117 c.Read(stream[sPoint : sPoint+recordDataLength]) 118 if c.GetCountEntries() > 0 { 119 s.hasAutofilter = true 120 } else { 121 s.hasAutofilter = false 122 } 123 goto EIF 124 125 } 126 127 //LABELSST - String constant that uses BIFF8 shared string table (new to BIFF8) 128 if bytes.Compare(recordNumber, record.LabelSStRecord[:]) == 0 { 129 c := new(record.LabelSSt) 130 c.Read(stream[sPoint:sPoint+recordDataLength], &s.wb.sst) 131 s.addCell(c, c.GetRow(), c.GetCol()) 132 goto EIF 133 } 134 135 //LABEL - Cell Value, String Constant 136 if bytes.Compare(recordNumber, record.LabelRecord[:]) == 0 { 137 if bytes.Compare(s.wb.vers[:], record.FlagBIFF8) == 0 { 138 c := new(record.LabelBIFF8) 139 c.Read(stream[sPoint : sPoint+recordDataLength]) 140 s.addCell(c, c.GetRow(), c.GetCol()) 141 } else { 142 c := new(record.LabelBIFF5) 143 c.Read(stream[sPoint : sPoint+recordDataLength]) 144 s.addCell(c, c.GetRow(), c.GetCol()) 145 } 146 147 goto EIF 148 } 149 150 if bytes.Compare(recordNumber, []byte{0xFD, 0x00}) == 0 { 151 //todo: сделать 152 goto EIF 153 } 154 155 //ARRAY - An array-entered formula 156 if bytes.Compare(recordNumber, record.ArrayRecord[:]) == 0 { 157 //todo: сделать 158 goto EIF 159 } 160 //BLANK - An empty col 161 if bytes.Compare(recordNumber, record.BlankRecord[:]) == 0 { 162 c := new(record.Blank) 163 c.Read(stream[sPoint : sPoint+recordDataLength]) 164 s.addCell(c, c.GetRow(), c.GetCol()) 165 goto EIF 166 } 167 168 //BOOLERR - A Boolean or error value 169 if bytes.Compare(recordNumber, record.BoolErrRecord[:]) == 0 { 170 c := new(record.BoolErr) 171 c.Read(stream[sPoint : sPoint+recordDataLength]) 172 s.addCell(c, c.GetRow(), c.GetCol()) 173 goto EIF 174 } 175 176 //FORMULA - A col formula, stored as parse tokens 177 if bytes.Compare(recordNumber, record.FormulaRecord[:]) == 0 { 178 //todo: сделать 179 goto EIF 180 } 181 182 //NUMBER - An IEEE floating-point number 183 if bytes.Compare(recordNumber, record.NumberRecord[:]) == 0 { 184 c := new(record.Number) 185 c.Read(stream[sPoint : sPoint+recordDataLength]) 186 s.addCell(c, c.GetRow(), c.GetCol()) 187 goto EIF 188 } 189 190 //MULBLANK - Multiple empty rows (new to BIFF5) 191 if bytes.Compare(recordNumber, record.MulBlankRecord[:]) == 0 { 192 c := new(record.MulBlank) 193 c.Read(stream[sPoint : sPoint+recordDataLength]) 194 blRecords := c.GetArrayBlRecord() 195 for i := 0; i <= len(blRecords)-1; i++ { 196 s.addCell(blRecords[i].Get(), blRecords[i].GetRow(), blRecords[i].GetCol()) 197 } 198 goto EIF 199 } 200 201 //RK - An RK number 202 if bytes.Compare(recordNumber, record.RkRecord[:]) == 0 { 203 c := new(record.Rk) 204 c.Read(stream[sPoint : sPoint+recordDataLength]) 205 s.addCell(c, c.GetRow(), c.GetCol()) 206 goto EIF 207 } 208 209 //MULRK - Multiple RK numbers (new to BIFF5) 210 if bytes.Compare(recordNumber, record.MulRKRecord[:]) == 0 { 211 c := new(record.MulRk) 212 c.Read(stream[sPoint : sPoint+recordDataLength]) 213 rkRecords := c.GetArrayRKRecord() 214 for i := 0; i <= len(rkRecords)-1; i++ { 215 s.addCell(rkRecords[i].Get(), rkRecords[i].GetRow(), rkRecords[i].GetCol()) 216 } 217 goto EIF 218 219 } 220 221 //RSTRING - Cell with character formatting 222 if bytes.Compare(recordNumber, record.RStringRecord[:]) == 0 { 223 //todo: сделать 224 goto EIF 225 } 226 227 //SHRFMLA - A shared formula (new to BIFF5) 228 if bytes.Compare(recordNumber, record.SharedFormulaRecord[:]) == 0 { 229 //todo: сделать 230 goto EIF 231 } 232 233 //STRING - A string that represents the result of a formula 234 if bytes.Compare(recordNumber, record.StringRecord[:]) == 0 { 235 //todo: сделать 236 goto EIF 237 } 238 239 if bytes.Compare(recordNumber, record.RowRecord[:]) == 0 { 240 //todo: сделать 241 goto EIF 242 } 243 244 //EOF 245 if bytes.Compare(recordNumber, record.EOFRecord[:]) == 0 && recordDataLength == 0 { 246 eof = true 247 } 248 EIF: 249 point = point + recordDataLength + 4 250 if !eof { 251 goto Next 252 } 253 254 return 255 256 } 257 258 func (s *Sheet) addCell(cd structure.CellData, row [2]byte, column [2]byte) { 259 260 r := int(helpers.BytesToUint16(row[:])) 261 c := int(helpers.BytesToUint16(column[:])) 262 263 if s.rows == nil { 264 s.rows = map[int]*rw{} 265 } 266 if _, ok := s.rows[r]; !ok { 267 s.rows[r] = new(rw) 268 269 if _, ok := s.rows[r].cols[c]; !ok { 270 271 colVal := map[int]structure.CellData{} 272 colVal[c] = cd 273 274 s.rows[r].cols = colVal 275 } 276 277 } 278 279 s.rows[r].cols[c] = cd 280 281 }