Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Export excel file easily with go tags #1540

Closed
anruence opened this issue May 19, 2023 · 1 comment
Closed

Export excel file easily with go tags #1540

anruence opened this issue May 19, 2023 · 1 comment
Labels
duplicate This issue or pull request already exists

Comments

@anruence
Copy link

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
}

@xuri
Copy link
Member

xuri commented May 19, 2023

Thanks for your feedback. This issue was similar to #619, #992, #1208, #1302, #1303, #1357 (I have explain the reason about why no plan to add this feature in this issue).

@xuri xuri added the duplicate This issue or pull request already exists label May 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
duplicate This issue or pull request already exists
Projects
None yet
Development

No branches or pull requests

2 participants