mirror of
https://gitee.com/xiangheng/x_admin.git
synced 2025-09-29 21:42:17 +08:00
174 lines
5.3 KiB
Go
174 lines
5.3 KiB
Go
package excel2
|
||
|
||
import (
|
||
"fmt"
|
||
"net/http"
|
||
|
||
"github.com/xuri/excelize/v2"
|
||
)
|
||
|
||
type Col struct {
|
||
Name string
|
||
Key string
|
||
Width int
|
||
}
|
||
|
||
// GetExcelColumnName2 根据列数生成 Excel 列名
|
||
func GetExcelColumnName2(columnNumber int) string {
|
||
columnName := ""
|
||
for columnNumber > 0 {
|
||
remainder := (columnNumber - 1) % 26
|
||
columnName = string(rune('A'+remainder)) + columnName
|
||
columnNumber = (columnNumber - 1) / 26
|
||
}
|
||
return columnName
|
||
}
|
||
|
||
// NormalDynamicExport 导出excel
|
||
//
|
||
// 需要在传入的结构体中的字段加上tag:excel:"title:列头名称;index:列下标(从0开始);"
|
||
//
|
||
// list 要导出的数据
|
||
//
|
||
// cols 列
|
||
//
|
||
// sheet 文档
|
||
// title 标题
|
||
func NormalDynamicExport2(lists []map[string]interface{}, cols []Col, sheet string, title string) (file *excelize.File, err error) {
|
||
e := ExcelInit()
|
||
err = ExportExcel2(sheet, title, lists, cols, e)
|
||
if err != nil {
|
||
return
|
||
}
|
||
return e.F, err
|
||
}
|
||
|
||
// ExportExcel2 excel导出
|
||
func ExportExcel2(sheet, title string, lists []map[string]interface{}, cols []Col, e *Excel) (err error) {
|
||
index, _ := e.F.GetSheetIndex(sheet)
|
||
if index < 0 { // 如果sheet名称不存在
|
||
e.F.NewSheet(sheet)
|
||
}
|
||
// 构造表头
|
||
endColName, startDataRow, err := normalBuildTitle2(e, sheet, title, cols)
|
||
if err != nil {
|
||
return
|
||
}
|
||
// 构造数据行
|
||
err = normalBuildDataRow2(e, sheet, endColName, startDataRow, lists, cols)
|
||
return
|
||
}
|
||
|
||
// 构造表头(endColName 最后一列的列名 startDataRow 数据行开始的行号)
|
||
func normalBuildTitle2(e *Excel, sheet, title string, cols []Col) (endColName string, startDataRow int, err error) {
|
||
var titleRowData []interface{} // 列头行
|
||
for i, colTitle := range cols {
|
||
endColName := GetExcelColumnName2(i + 1)
|
||
if colTitle.Width > 0 { // 根据给定的宽度设置列宽
|
||
_ = e.F.SetColWidth(sheet, endColName, endColName, float64(colTitle.Width))
|
||
} else {
|
||
_ = e.F.SetColWidth(sheet, endColName, endColName, float64(20)) // 默认宽度为20
|
||
}
|
||
titleRowData = append(titleRowData, colTitle.Name)
|
||
}
|
||
endColName = GetExcelColumnName2(len(titleRowData)) // 根据列数生成 Excel 列名
|
||
if title != "" {
|
||
startDataRow = 3 // 如果有title,那么从第3行开始就是数据行,第1行是title,第2行是表头
|
||
e.F.SetCellValue(sheet, "A1", title)
|
||
e.F.MergeCell(sheet, "A1", endColName+"1") // 合并标题单元格
|
||
e.F.SetCellStyle(sheet, "A1", endColName+"1", e.TitleStyle)
|
||
e.F.SetRowHeight(sheet, 1, float64(30)) // 第一行行高
|
||
e.F.SetRowHeight(sheet, 2, float64(30)) // 第二行行高
|
||
e.F.SetCellStyle(sheet, "A2", endColName+"2", e.HeadStyle)
|
||
if err = e.F.SetSheetRow(sheet, "A2", &titleRowData); err != nil {
|
||
return
|
||
}
|
||
} else {
|
||
startDataRow = 2 // 如果没有title,那么从第2行开始就是数据行,第1行是表头
|
||
e.F.SetRowHeight(sheet, 1, float64(30))
|
||
e.F.SetCellStyle(sheet, "A1", endColName+"1", e.HeadStyle)
|
||
if err = e.F.SetSheetRow(sheet, "A1", &titleRowData); err != nil {
|
||
return
|
||
}
|
||
}
|
||
return
|
||
}
|
||
|
||
// 构造数据行
|
||
func normalBuildDataRow2(e *Excel, sheet, endColName string, startDataRow int, lists []map[string]interface{}, cols []Col) (err error) {
|
||
//实时写入数据
|
||
for i := 0; i < len(lists); i++ {
|
||
startCol := fmt.Sprintf("A%d", startDataRow)
|
||
endCol := fmt.Sprintf("%s%d", endColName, startDataRow)
|
||
|
||
var rowData []interface{} // 数据列
|
||
|
||
list := lists[i]
|
||
for j := 0; j < len(cols); j++ {
|
||
col := cols[j]
|
||
val := list[col.Key]
|
||
// switch val.(type) {
|
||
|
||
// default:
|
||
// v, _ := json.Marshal(list[col.Key])
|
||
// rowData = append(rowData, v)
|
||
// }
|
||
rowData = append(rowData, val)
|
||
}
|
||
|
||
// // 替换
|
||
// if dataCol.Replace != "" {
|
||
// split := strings.Split(dataCol.Replace, ",")
|
||
// for j := range split {
|
||
// s := strings.Split(split[j], "_") // 根据下划线进行分割,格式:需要替换的内容_替换后的内容
|
||
// value := fieldData.String()
|
||
// if strings.Contains(fieldData.Type().String(), "int") {
|
||
// value = strconv.Itoa(int(fieldData.Int()))
|
||
// } else if fieldData.Type().String() == "bool" {
|
||
// value = strconv.FormatBool(fieldData.Bool())
|
||
// } else if strings.Contains(fieldData.Type().String(), "float") {
|
||
// value = strconv.FormatFloat(fieldData.Float(), 'f', -1, 64)
|
||
// }
|
||
// if s[0] == value {
|
||
// dataCol.Value = s[1]
|
||
// }
|
||
// }
|
||
// } else {
|
||
// dataCol.Value = fieldData
|
||
// }
|
||
// if err != nil {
|
||
// return
|
||
// }
|
||
// exportRow = append(exportRow, dataCol)
|
||
// }
|
||
|
||
if startDataRow%2 == 0 {
|
||
_ = e.F.SetCellStyle(sheet, startCol, endCol, e.ContentStyle2)
|
||
} else {
|
||
_ = e.F.SetCellStyle(sheet, startCol, endCol, e.ContentStyle1)
|
||
}
|
||
|
||
_ = e.F.SetRowHeight(sheet, startDataRow, float64(25)) // 默认行高25
|
||
|
||
if err = e.F.SetSheetRow(sheet, startCol, &rowData); err != nil {
|
||
return
|
||
}
|
||
startDataRow++
|
||
}
|
||
return
|
||
}
|
||
|
||
// 下载
|
||
func DownLoadExcel2(fileName string, res http.ResponseWriter, file *excelize.File) {
|
||
// 设置响应头
|
||
res.Header().Set("Content-Type", "text/html; charset=UTF-8")
|
||
res.Header().Set("Content-Type", "application/octet-stream")
|
||
res.Header().Set("Content-Disposition", "attachment; filename="+fileName+".xlsx")
|
||
res.Header().Set("Access-Control-Expose-Headers", "Content-Disposition")
|
||
err := file.Write(res) // 写入Excel文件内容到响应体
|
||
if err != nil {
|
||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||
return
|
||
}
|
||
}
|