123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- package excels
- import (
- "github.com/druidcaesa/gotool"
- "github.com/xuri/excelize/v2"
- "reflect"
- "strconv"
- )
- // 获取title头list
- func getTitle(list []map[string]string) []string {
- titleList := make([]string, 0)
- for _, item := range list {
- for _, s := range item {
- titleList = append(titleList, s)
- }
- }
- return titleList
- }
- // ExportExcel 导出excel
- func ExportExcel(list []interface{}, title string) (error, *excelize.File) {
- //获取标题
- headerList, expList := ExcelCreate(list[0])
- headers := getTitle(headerList)
- // 默认存在第一个工作簿是 Sheet1 首字母要大写,否则会报错。
- // 如果想额外的创建工作簿,可以使用,sheet2 := file.NewSheet("Sheet2"),工作簿的名称不区分大小写。
- // 如果有多个工作簿,可以使用 file.SetActiveSheet(index) 来指定打开文件时focus到哪个工作簿
- sheet1 := "Sheet1"
- files := excelize.NewFile()
- character := string(65 + len(headers) - 1)
- /* -------------------- 第一行大标题 -------------------- */
- // 设置行高
- err := files.SetRowHeight(sheet1, 1, 25)
- if err != nil {
- return err, nil
- }
- // 合并单元格
- err = files.MergeCell(sheet1, "A1", character+"1")
- if err != nil {
- return err, nil
- }
- // 设置单元格样式:对齐;字体,大小;单元格边框
- styleTitle, _ := files.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center"},"font":{"bold":true,"italic":false,"family":"Calibri","size":16,"color":"#000000"},"border":[{"type":"left","color":"#3FAD08","style":0},{"type":"top","color":"#3FAD08","style":0},{"type":"bottom","color":"#3FAD08","style":2},{"type":"right","color":"#3FAD08","style":0}]}`)
- err = files.SetCellStyle(sheet1, "A1", character+"1", styleTitle)
- if err != nil {
- return err, nil
- }
- err = files.SetCellValue(sheet1, "A1", title)
- if err != nil {
- return err, nil
- }
- /* -------------------- 字段标题 -------------------- */
- styleHeader, _ := files.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center"},"font":{"bold":false,"italic":false,"family":"Calibri","size":10,"color":"#000000"}}`)
- err = files.SetCellStyle(sheet1, "A2", character+"2", styleHeader)
- if err != nil {
- return err, nil
- }
- for k, v := range headers {
- if k < 26 {
- err = files.SetCellValue(sheet1, string(65+k)+"2", v)
- } else {
- err = files.SetCellValue(sheet1, "A"+string(65+k-26)+"2", v)
- }
- if err != nil {
- return err, nil
- }
- }
- // 设置最后一列宽度
- err = files.SetColWidth(sheet1, "C", character, 20)
- if err != nil {
- return err, nil
- }
- // 冻结窗口:冻结第一行和第二行
- err = files.SetPanes(sheet1, `{"freeze":true,"split":false,"x_split":0,"y_split":2}`)
- if err != nil {
- return err, nil
- }
- ///* -------------------- 填充行数据 -------------------- */
- line := 3
- for _, v := range list {
- var num = 0
- lineChr := strconv.Itoa(line)
- // 设置样式
- err = files.SetCellStyle(sheet1, "A"+lineChr, character+lineChr, styleHeader)
- if err != nil {
- return err, nil
- }
- // 反射获取数据和类型
- getValue := reflect.ValueOf(v)
- getType := reflect.TypeOf(v)
- n := getValue.NumField()
- for i := 0; i < n; i++ {
- val := getValue.Field(i)
- name := getType.Field(i).Name
- if !getIsTitle(name, headerList) {
- continue
- }
- if num < 26 {
- err = files.SetCellValue(sheet1, string(65+num)+lineChr, getExp(name, expList, val.Interface()))
- } else {
- err = files.SetCellValue(sheet1, "A"+string(65-26+num)+lineChr, getExp(name, expList, val.Interface()))
- }
- /* err = files.SetCellValue(sheet1, string(65+num)+lineChr, getExp(name, expList, val.Interface()))*/
- if err != nil {
- return err, nil
- }
- num++
- }
- line++
- }
- return nil, files
- }
- func getIsTitle(name string, headerList []map[string]string) bool {
- flag := false
- for _, m := range headerList {
- if gotool.StrUtils.HasNotEmpty(m[name]) {
- flag = true
- }
- }
- return flag
- }
- func getExp(name string, expList []map[string][]map[string]string, value interface{}) interface{} {
- for _, m := range expList {
- if len(m[name]) > 0 {
- maps := m[name]
- for _, m2 := range maps {
- if gotool.StrUtils.HasNotEmpty(m2[interfaceToString(value)]) {
- value = m2[interfaceToString(value)]
- }
- }
- }
- }
- return value
- }
- func interfaceToString(inter interface{}) string {
- switch inter.(type) {
- case string:
- return inter.(string)
- case int:
- return strconv.Itoa(inter.(int))
- case int64:
- return strconv.FormatInt(inter.(int64), 10)
- default:
- return inter.(string)
- }
- }
|