Skip to content

Export excel file easily with go tags #1540

@anwu4

Description

@anwu4

if we define a struct like this, we can convert data to this struct easily, finally we can write this struct into excelize File
Description

type EasyExport struct {
	ID    string `excel:"id"`
	Name  string `excel:"名称"`
	Name2 string `excel:"名称2"`
	Num   int64  `excel:"数量"`
}

Steps to reproduce the issue:

  1. define the meta struct
type Meta struct {
	// 序号
	Idx int `json:"idx"`
	// 字段名称
	Key string `json:"key"`
	// excel列的标识 A B
	Col string `json:"col"`
	// 表头名称
	Value string `json:"value"`
}
  1. parse the meta
func parseMeta(obj interface{}) ([]*Meta, error) {
	refValue := reflect.TypeOf(obj)
	elem := refValue.Elem()
	if elem.Kind() == reflect.Ptr {
		elem = elem.Elem()
	}
	if elem.Kind() != reflect.Struct {
		return nil, errors.New("kind not support")
	}
	result := make([]*Meta, 0)
	for i := 0; i < elem.NumField(); i++ {
		col, err := excelize.ColumnNumberToName(i + 1)
		if err != nil {
			return nil, err
		}
		field := elem.Field(i)
		tagValue := strings.Split(field.Tag.Get("excel"), ",")
		value := field.Name
		if len(tagValue) >= 1 {
			value = tagValue[0]
		}
		meta := &Meta{
			Idx:   i,
			Key:   field.Name,
			Col:   col,
			Value: value,
		}
		result = append(result, meta)
	}
	return result, nil
}
  1. write file with meta
type ExportTask struct {
	sheetName string
	metas     []*Meta
	f         *excelize.File
}

func (s *ExportTask) metaMap() map[string]*Meta {
	result := make(map[string]*Meta)
	for _, v := range s.metas {
		result[v.Key] = v
	}
	return result
}

func (s *ExportTask) WriteObj(obj interface{}) error {
	metaMap := s.metaMap()
	name := s.sheetName
	f := s.f
	for _, meta := range metaMap {
		// write the table header
		col := fmt.Sprintf("%s%d", meta.Col, 1)
		err := f.SetCellValue(name, col, meta.Value)
		if err != nil {
			return err
		}
	}
	refValue := reflect.ValueOf(obj)
	for i := 0; i < refValue.Len(); i++ {
		objElem := reflect.ValueOf(refValue.Index(i).Interface()).Elem()
		for _, meta := range metaMap {
			// from line 2
			col := fmt.Sprintf("%s%d", meta.Col, i+2)
			err := f.SetCellValue(name, col, objElem.FieldByName(meta.Key).Interface())
			if err != nil {
				return err
			}
		}
	}
	return nil
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    duplicateThis issue or pull request already exists

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions