package xvdoc import ( "bytes" "encoding/json" "fmt" ) func FromJSON(src []byte) (res []*XVDoc, err error) { var xv []*XVDoc if err = json.Unmarshal(src, &xv); err == nil { res = xv } return } type XVDoc struct { name string style string rows []*Row styles map[string]Style dropdowns []*dropDown merges []*rectMerge columnsWidth []*rectWidths styleRects []*styleRect images []*cellImage } func (s *XVDoc) UnmarshalJSON(src []byte) (err error) { dec := json.NewDecoder(bytes.NewReader(src)) var t json.Token for dec.More() && err == nil { if t, err = dec.Token(); err == nil { if _, check := t.(json.Delim); !check { switch t.(string) { case "name": err = dec.Decode(&s.name) case "style": err = dec.Decode(&s.style) case "rows": err = dec.Decode(&s.rows) case "styles": err = dec.Decode(&s.styles) case "merges": err = dec.Decode(&s.merges) case "style_rects": err = dec.Decode(&s.styleRects) case "columns_width": err = dec.Decode(&s.columnsWidth) case "images": err = dec.Decode(&s.images) case "dropdowns": err = dec.Decode(&s.dropdowns) default: err = dec.Decode(new(interface{})) } } } } return } func (s *XVDoc) String() (res string) { res = fmt.Sprintf("xvDoc %v\n*** rows ***\n", s.name) res += fmt.Sprintf("styles: %v\n", s.styles) res += fmt.Sprintf("name: %v\n", s.name) for i, v := range s.rows { res = res + fmt.Sprintf("%v: Cells: %v\n", i, v) } res = res + "*********************\n" return res } func (s *XVDoc) matrix() Matrix { var matrix [][]Cell row, rowsHeight := 0, make(map[int]float64) // create document matrix for _, v := range s.rows { // setup row if v.offsetY { row += v.oy } else if v.y >= 0 { row = v.y } // setup custom row height if v.IsCustomHeight() { rowsHeight[row] = v.Height() } // fill matrix rows if row >= len(matrix) { tmp := make([][]Cell, row-len(matrix)+1) matrix = append(matrix, tmp...) } // get row in matrix r := matrix[row] if v.x+len(v.cells) >= len(r) { tmp := make([]Cell, v.x+len(v.cells)-len(r)) r = append(r, tmp...) } for i := 0; i < len(v.cells); i++ { r[v.x+i] = v.cells[i] } // setup row in matrix matrix[row] = r // to next row row++ } res := Matrix{ Name: s.name, Cells: matrix, Styles: s.styles, RowsHeight: rowsHeight, Style: s.style, StyleRects: s.styleRects, Merges: s.merges, Images: s.images, Dropdowns: s.dropdowns, ColumnsWidth: s.columnsWidth, } return res } func Export(format string, docs []*XVDoc) ([]byte, error) { if method, check := exportMethods[format]; check { m := make([]Matrix, len(docs)) for i, v := range docs { m[i] = v.matrix() } return method(m) } else { return nil, fmt.Errorf("xvdoc export error :: unexpected format '%v'", format) } }