1 Star 0 Fork 0

Erdian718/xlsx

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
fragment.go 4.56 KB
一键复制 编辑 原始数据 按行查看 历史
Erdian718 提交于 5个月前 . Review package internal
package internal
import (
"fmt"
"reflect"
)
// Fragment represents a fragment of a template.
type Fragment interface {
// Key returns the key of the fragment.
Key(level int) string
// Clone clones the fragment.
Clone(ctx map[*Cell]*Cell) Fragment
// Fill applies a parsed fragment to the specified data, and writes the output to the sheet.
Fill(sheet *Sheet, level int, data reflect.Value) error
}
// BuildFragment build fragment from sheet.
func BuildFragment(sheet *Sheet) (Fragment, error) {
if err := sheet.parse(); err != nil {
return nil, err
}
fragment, _, err := buildFragment(nil, sheet.Rows())
return fragment, err
}
// SimpleFragment represents a simple fragment of a template.
type SimpleFragment struct {
params [][]struct {
key string
ridx int
cidx int
vidx int
}
rows []*Row
}
// Key returns the key of the fragment.
func (sf *SimpleFragment) Key(level int) string {
return ""
}
// Clone clones the fragment.
func (sf *SimpleFragment) Clone(ctx map[*Cell]*Cell) Fragment {
f := *sf
f.rows = make([]*Row, len(sf.rows))
for i, row := range sf.rows {
f.rows[i] = row.clone(ctx)
}
return &f
}
// Fill applies a parsed fragment to the specified data, and writes the output to the sheet.
func (sf *SimpleFragment) Fill(sheet *Sheet, level int, data reflect.Value) (err error) {
defer func() {
if x := recover(); x != nil {
if e, ok := x.(error); ok {
err = e
} else {
err = fmt.Errorf("%v", x)
}
}
}()
k := len(sf.params) - 1
if level > k {
return nil
}
for _, param := range sf.params[level] {
v, err := getValueByKey(data, param.key)
if err != nil {
return err
}
sf.rows[param.ridx].xml.Cells[param.cidx].extra.values[param.vidx] = v
}
if level == k {
sheet.xml.Rows = append(sheet.xml.Rows, sf.rows...)
}
return nil
}
// ComplexFragment represents a complex fragment of a template.
type ComplexFragment struct {
keys []string
fragments []Fragment
}
// Key returns the key of the fragment.
func (cf *ComplexFragment) Key(level int) string {
if len(cf.keys)-1 == level {
return cf.keys[level]
}
return ""
}
// Clone clones the fragment.
func (cf *ComplexFragment) Clone(ctx map[*Cell]*Cell) Fragment {
f := *cf
f.fragments = make([]Fragment, len(cf.fragments))
for i, fragment := range cf.fragments {
f.fragments[i] = fragment.Clone(ctx)
}
return &f
}
// Fill applies a parsed fragment to the specified data, and writes the output to the sheet.
func (cf *ComplexFragment) Fill(sheet *Sheet, level int, data reflect.Value) error {
nlevel := level + 1
for _, fragment := range cf.fragments {
if err := fragment.Fill(sheet, level, data); err != nil {
return err
}
if key := fragment.Key(level); key != "" {
v, err := getValueByKey(data, key)
if err != nil {
return err
}
if v.Kind() == reflect.Slice {
n := v.Len()
if n > 0 {
if err := fragment.Fill(sheet, nlevel, v.Index(0)); err != nil {
return err
}
for i := 1; i < n; i++ {
if err := fragment.Clone(make(map[*Cell]*Cell)).Fill(sheet, nlevel, v.Index(i)); err != nil {
return err
}
}
}
} else {
if err := fragment.Fill(sheet, nlevel, v); err != nil {
return err
}
}
}
}
return nil
}
// BuildFragment builds fragments from rows.
func buildFragment(keys []string, rows []*Row) (Fragment, []*Row, error) {
cf := &ComplexFragment{keys: keys}
for {
var sf *SimpleFragment
var err error
sf, rows, err = buildSimpleFragment(keys, rows)
if err != nil {
return nil, rows, err
}
if sf != nil {
cf.fragments = append(cf.fragments, sf)
}
if len(rows) < 1 {
return cf, rows, nil
}
ks := rows[0].extra.keys
if !isSubKeys(keys, ks) {
return cf, rows, nil
}
var f Fragment
f, rows, err = buildFragment(ks[:len(keys)+1], rows)
if err != nil {
return cf, rows, err
}
cf.fragments = append(cf.fragments, f)
}
}
func buildSimpleFragment(keys []string, rows []*Row) (*SimpleFragment, []*Row, error) {
sf := new(SimpleFragment)
n := 0
for ridx, row := range rows {
if len(row.extra.keys) != len(keys) || !isSubKeys(keys, row.extra.keys) {
break
}
for cidx, cell := range row.Cells() {
for _, param := range cell.extra.params {
for len(sf.params) <= param.level {
sf.params = append(sf.params, nil)
}
sf.params[param.level] = append(sf.params[param.level], struct {
key string
ridx int
cidx int
vidx int
}{
key: param.key,
ridx: ridx,
cidx: cidx,
vidx: param.idx,
})
}
}
n++
}
if n < 1 {
return nil, rows, nil
}
sf.rows = rows[:n]
return sf, rows[n:], nil
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/erdian718/xlsx.git
git@gitee.com:erdian718/xlsx.git
erdian718
xlsx
xlsx
v0.4.0

搜索帮助