-
Notifications
You must be signed in to change notification settings - Fork 40
/
Copy pathtitle.go
129 lines (119 loc) · 3.1 KB
/
title.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package excel
import (
"encoding/xml"
"fmt"
"reflect"
"strings"
convert "github.com/szyhf/go-convert"
twentysix "github.com/szyhf/go-excel/internal/twenty_six"
)
type titleRow struct {
// map[A1]0
dstMap map[string]int
// map[0]A1
srcMap map[int]string
// sorted titles
titles []string
typeFieldMap map[reflect.Type]map[int][]*fieldConfig
}
func newRowAsMap(rd *read) (r *titleRow, err error) {
defer func() {
if rc := recover(); rc != nil {
err = fmt.Errorf("%s", rc)
}
}()
r = &titleRow{
dstMap: make(map[string]int),
srcMap: make(map[int]string),
titles: make([]string, 0),
}
tempCell := &xlsxC{}
for t, err := rd.decoder.Token(); err == nil; t, err = rd.decoder.Token() {
switch token := t.(type) {
case xml.StartElement:
switch token.Name.Local {
case _RowPrefix:
// start of row
case _C:
// start of row.cell
tempCell.R = ""
tempCell.T = ""
tempCell.V = ""
tempCell.columnIndex = -1
for _, a := range token.Attr {
switch a.Name.Local {
case _R:
tempCell.R = a.Value
case _T:
tempCell.T = a.Value
}
}
case _V:
// start of row.cell.value
}
case xml.EndElement:
switch token.Name.Local {
case _RowPrefix:
// end of row
r.typeFieldMap = make(map[reflect.Type]map[int][]*fieldConfig)
return r, nil
case _C:
// end of row.cell
for i := len(r.titles); i < tempCell.columnIndex; i++ {
// fill the skipped empty cell with blank
const blankText = ""
r.dstMap[blankText] = i
r.srcMap[i] = blankText
r.titles = append(r.titles, blankText)
}
r.dstMap[tempCell.V] = tempCell.columnIndex
r.srcMap[tempCell.columnIndex] = tempCell.V
r.titles = append(r.titles, tempCell.V)
case _V:
// end of row.cell.value
}
case xml.CharData:
trimedColumnName := strings.TrimRight(tempCell.R, _AllNumber)
tempCell.columnIndex = twentysix.ToDecimalism(trimedColumnName)
if tempCell.T == _S {
// get string from shared
tempCell.V = rd.connecter.getSharedString(convert.MustInt(string(token)))
} else {
tempCell.V = string(token)
}
}
}
return nil, ErrNoRow
}
// return: a copy of map[ColumnIndex][]*fieldConfig
func (tr *titleRow) MapToFields(s *schema) (rowToFiled map[int][]*fieldConfig, err error) {
fieldsMap, ok := tr.typeFieldMap[s.Type]
if !ok {
fieldsMap = make(map[int][]*fieldConfig)
for _, field := range s.Fields {
var cloIndex int
// Use ColumnName to find index
if i, ok := tr.dstMap[field.ColumnName]; ok {
cloIndex = i
} else if field.IsRequired {
// Use 26-number-system to find
// cloIndex = twentysix.ToDecimalism(field.ColumnName)
return nil, fmt.Errorf("go-excel: column name = \"%s\" is not exist", field.ColumnName)
} else {
// continue if is not required.
continue
}
if fAry, ok := fieldsMap[cloIndex]; !ok {
fieldsMap[cloIndex] = []*fieldConfig{field}
} else {
fieldsMap[cloIndex] = append(fAry, field)
}
}
tr.typeFieldMap[s.Type] = fieldsMap
}
copyMap := make(map[int][]*fieldConfig)
for k, v := range fieldsMap {
copyMap[k] = v
}
return copyMap, nil
}