mirror of
https://gitee.com/xiangheng/x_admin.git
synced 2026-04-22 22:57:15 +08:00
140 lines
3.9 KiB
Go
140 lines
3.9 KiB
Go
package excel2
|
|
|
|
import (
|
|
"fmt"
|
|
"x_admin/util"
|
|
|
|
"github.com/xuri/excelize/v2"
|
|
)
|
|
|
|
// GetExcelColumnName 根据列数生成 Excel 列名
|
|
func GetExcelColumnName(columnNumber int) string {
|
|
columnName := ""
|
|
for columnNumber > 0 {
|
|
remainder := (columnNumber - 1) % 26
|
|
columnName = string(rune('A'+remainder)) + columnName
|
|
columnNumber = (columnNumber - 1) / 26
|
|
}
|
|
return columnName
|
|
}
|
|
|
|
// Export 导出excel
|
|
// lists 要导出的数据
|
|
// cols 列
|
|
// sheet 文档
|
|
// title 标题
|
|
func Export(lists any, cols []Col, sheet string, title string) (file *excelize.File, err error) {
|
|
e := ExcelInit()
|
|
|
|
data := util.ConvertUtil.ShallowStructsToMaps(lists)
|
|
|
|
err = ExportExcel(sheet, title, data, cols, e)
|
|
if err != nil {
|
|
return
|
|
}
|
|
return e.F, err
|
|
}
|
|
|
|
// ExportExcel excel导出
|
|
func ExportExcel(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 := buildTitle(e, sheet, title, cols)
|
|
if err != nil {
|
|
return
|
|
}
|
|
// 构造数据行
|
|
err = buildDataRow(e, sheet, endColName, startDataRow, lists, cols)
|
|
return
|
|
}
|
|
|
|
// 构造表头(endColName 最后一列的列名 startDataRow 数据行开始的行号)
|
|
func buildTitle(e *Excel, sheet, title string, cols []Col) (endColName string, startDataRow int, err error) {
|
|
var titleRowData []interface{} // 列头行
|
|
for i, colTitle := range cols {
|
|
endColName := GetExcelColumnName(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 = GetExcelColumnName(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 buildDataRow(e *Excel, sheet, endColName string, startDataRow int, lists []map[string]any, 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]
|
|
replace := col.Replace
|
|
|
|
val := list[col.Key]
|
|
|
|
// 先编码
|
|
if col.Encode != nil {
|
|
val = col.Encode(val)
|
|
} else if v, ok := val.(Encode); ok {
|
|
val = v.String()
|
|
}
|
|
|
|
// 再替换
|
|
for replaceKey, v := range replace {
|
|
|
|
if replaceKey == fmt.Sprintf("%v", val) {
|
|
val = fmt.Sprintf("%v", v)
|
|
break
|
|
}
|
|
}
|
|
|
|
rowData = append(rowData, val)
|
|
}
|
|
|
|
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
|
|
|
|
}
|