|
|
package ExcelUtil
|
|
|
|
|
|
import (
|
|
|
"dsBaseRpc/Const"
|
|
|
"dsBaseRpc/Utils/CommonUtil"
|
|
|
"dsBaseRpc/Utils/DbUtil"
|
|
|
"dsBaseRpc/Utils/FileUtil"
|
|
|
"encoding/json"
|
|
|
"fmt"
|
|
|
"github.com/xuri/excelize/v2"
|
|
|
"strconv"
|
|
|
"strings"
|
|
|
)
|
|
|
|
|
|
//中文文档: xuri.me/excelize/zh-hans
|
|
|
|
|
|
type ColStruct struct {
|
|
|
ColName string `json:"col_name"`
|
|
|
ColField string `json:"col_field"`
|
|
|
Width float64 `json:"width"`
|
|
|
Require bool `json:"require"`
|
|
|
Level1Sql bool `json:"level_1_sql"`
|
|
|
Level2Sql bool `json:"level_2_sql"`
|
|
|
SqlNum int64 `json:"sql_num"`
|
|
|
SqlParameter []interface{} `json:"sql_parameter"`
|
|
|
}
|
|
|
type TemplateStruct struct {
|
|
|
Title string `json:"title"`
|
|
|
Level1Sql []string `json:"level_1_sql"`
|
|
|
Level2Sql [][]string `json:"level_2_sql"`
|
|
|
Cols []ColStruct `json:"cols"`
|
|
|
}
|
|
|
|
|
|
var db = DbUtil.Engine
|
|
|
|
|
|
//样式文件的前缀路径
|
|
|
var stylePathPrefix = "./Config/ExcelStyle/"
|
|
|
|
|
|
/**
|
|
|
功能:设置指定EXCEL SHEET的某个单元格的背景色为红色
|
|
|
作者:黄海
|
|
|
时间:2020-06-08
|
|
|
*/
|
|
|
func GetBackgroundColorStyle(hexColor string) string {
|
|
|
tableStyleWarningPath := stylePathPrefix + "tableStyleTemplate.json"
|
|
|
if !FileUtil.PathExists(tableStyleWarningPath) {
|
|
|
tableStyleWarningPath = "." + tableStyleWarningPath
|
|
|
}
|
|
|
content := FileUtil.ReadFileContent(tableStyleWarningPath)
|
|
|
content = strings.Replace(content, "\r\n", "", -1)
|
|
|
styleTemplate := strings.Replace(content, "#color#", hexColor, -1)
|
|
|
return styleTemplate
|
|
|
}
|
|
|
|
|
|
//导出标识
|
|
|
const ExportFlag = 1
|
|
|
|
|
|
//导入标识
|
|
|
const ImportFlag = 2
|
|
|
|
|
|
/**
|
|
|
功能:判断是不是合法的导入模板
|
|
|
作者:黄海
|
|
|
时间:2020-06-17
|
|
|
*/
|
|
|
func IsValidTemplate(excelPath string, s1 TemplateStruct) bool {
|
|
|
f, _ := excelize.OpenFile(excelPath)
|
|
|
//如果 sheet名称不正确
|
|
|
if f.GetSheetName(0) != s1.Title {
|
|
|
return false
|
|
|
}
|
|
|
var isValidTemplate = true
|
|
|
for i := range s1.Cols {
|
|
|
colName, _ := excelize.ColumnNumberToName(i + 1)
|
|
|
v, _ := f.GetCellValue(s1.Title, colName+CommonUtil.ConvertIntToString(HiddenRows+1))
|
|
|
if s1.Cols[i].Require {
|
|
|
if v != s1.Cols[i].ColName+"[*]" {
|
|
|
isValidTemplate = false
|
|
|
break
|
|
|
}
|
|
|
} else {
|
|
|
if v != s1.Cols[i].ColName {
|
|
|
isValidTemplate = false
|
|
|
break
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return isValidTemplate
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
功能:读取配置JSON
|
|
|
作者:黄海
|
|
|
时间:2020-06-17
|
|
|
*/
|
|
|
func ReadJson(jsonTemplate string, ExportOrImport int) TemplateStruct {
|
|
|
if ExportOrImport == 1 {
|
|
|
jsonTemplate = "./Config/ExportExcelTemplate/" + jsonTemplate
|
|
|
} else {
|
|
|
jsonTemplate = "./Config/ImportExcelTemplate/" + jsonTemplate
|
|
|
}
|
|
|
if !FileUtil.PathExists(jsonTemplate) {
|
|
|
jsonTemplate = "." + jsonTemplate
|
|
|
}
|
|
|
var jsonContent = FileUtil.ReadFileContent(jsonTemplate)
|
|
|
jsonContent = strings.Replace(jsonContent, "\r\n", "", -1)
|
|
|
var s1 TemplateStruct
|
|
|
json.Unmarshal([]byte(jsonContent), &s1)
|
|
|
return s1
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
功能:通过JSON模板定义导出EXCEL
|
|
|
作者:黄海
|
|
|
时间:2020-06-05
|
|
|
*/
|
|
|
func ExportExcel(jsonTemplate string, listData []map[string]interface{}, targetPath string) {
|
|
|
var s1 = ReadJson(jsonTemplate, ExportFlag)
|
|
|
rows := len(listData) //行数
|
|
|
cols := len(s1.Cols) //列数
|
|
|
//初始化excel
|
|
|
f := excelize.NewFile()
|
|
|
titleStylePath := stylePathPrefix + "titleStyle.json"
|
|
|
tableStylePath := stylePathPrefix + "tableStyleNormal.json"
|
|
|
|
|
|
if !FileUtil.PathExists(titleStylePath) {
|
|
|
titleStylePath = "." + titleStylePath
|
|
|
}
|
|
|
if !FileUtil.PathExists(tableStylePath) {
|
|
|
tableStylePath = "." + tableStylePath
|
|
|
}
|
|
|
|
|
|
titleStyle, _ := f.NewStyle(FileUtil.ReadFileContent(titleStylePath))
|
|
|
tableStyle, _ := f.NewStyle(FileUtil.ReadFileContent(tableStylePath))
|
|
|
|
|
|
var oldName = "Sheet1"
|
|
|
var SheetName = s1.Title
|
|
|
var RowHeight = 28.0
|
|
|
f.SetSheetName(oldName, SheetName)
|
|
|
//设置标题行行高
|
|
|
f.SetRowHeight(SheetName, 1, RowHeight)
|
|
|
//合并单元格(标题行)
|
|
|
lastCol, _ := excelize.ColumnNumberToName(cols)
|
|
|
f.MergeCell(SheetName, "A1", lastCol+"1")
|
|
|
// 设置单元格的值(标题)
|
|
|
f.SetCellValue(SheetName, "A1", s1.Title)
|
|
|
//测试设置单元格背景颜色
|
|
|
//设置字体(标题)
|
|
|
f.SetCellStyle(SheetName, "A1", "A1", titleStyle)
|
|
|
//设置列宽
|
|
|
for i := 0; i < cols; i++ {
|
|
|
m, _ := excelize.ColumnNumberToName(i + 1)
|
|
|
f.SetColWidth(SheetName, m, m, s1.Cols[i].Width)
|
|
|
}
|
|
|
//设置边框
|
|
|
for i := 2; i <= rows+2; i++ {
|
|
|
for j := 0; j < cols; j++ {
|
|
|
cName, _ := excelize.ColumnNumberToName(j + 1)
|
|
|
cName = cName + strconv.Itoa(i)
|
|
|
f.SetCellStyle(SheetName, cName, cName, tableStyle)
|
|
|
f.SetRowHeight(SheetName, i, RowHeight)
|
|
|
}
|
|
|
}
|
|
|
//写入标题头
|
|
|
for i := 0; i < cols; i++ {
|
|
|
cName, _ := excelize.ColumnNumberToName(i + 1)
|
|
|
cName = cName + strconv.Itoa(2)
|
|
|
f.SetCellValue(SheetName, cName, s1.Cols[i].ColName)
|
|
|
}
|
|
|
//写入内容
|
|
|
for i := 0; i < rows; i++ {
|
|
|
for j := 0; j < cols; j++ {
|
|
|
cName, _ := excelize.ColumnNumberToName(j + 1)
|
|
|
cName = cName + strconv.Itoa(i+1+2)
|
|
|
fieldName := s1.Cols[j].ColField
|
|
|
if fieldName == "number" {
|
|
|
f.SetCellValue(SheetName, cName, CommonUtil.ConvertIntToString(i+1))
|
|
|
} else {
|
|
|
f.SetCellValue(SheetName, cName, listData[i][fieldName])
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
// 根据指定路径保存文件
|
|
|
if err := f.SaveAs(targetPath); err != nil {
|
|
|
println(err.Error())
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//5000个
|
|
|
const RowsCount = 5000
|
|
|
|
|
|
//隐藏用来装字典的行数
|
|
|
const HiddenRows = 200
|
|
|
|
|
|
/**
|
|
|
功能:通用的导入模板函数
|
|
|
作者:黄海
|
|
|
时间:2020-06-06
|
|
|
*/
|
|
|
func GenerateTemplate(jsonTemplate string, excelPath string) {
|
|
|
var f *excelize.File
|
|
|
var s1 TemplateStruct
|
|
|
var SheetName string
|
|
|
jsonTemplate = "./Config/ImportExcelTemplate/" + jsonTemplate
|
|
|
if !FileUtil.PathExists(jsonTemplate) {
|
|
|
jsonTemplate = "." + jsonTemplate
|
|
|
}
|
|
|
var jsonContent = FileUtil.ReadFileContent(jsonTemplate)
|
|
|
//2、还原成结构体
|
|
|
json.Unmarshal([]byte(jsonContent), &s1)
|
|
|
//3、准备根据结构体进行创建导入模板
|
|
|
var oldName = "Sheet1"
|
|
|
SheetName = s1.Title
|
|
|
f = excelize.NewFile()
|
|
|
f.SetSheetName(oldName, SheetName)
|
|
|
cols := len(s1.Cols) //列数
|
|
|
//隐藏前hiddenRows行
|
|
|
for i := 0; i < HiddenRows; i++ {
|
|
|
f.SetRowVisible(SheetName, i+1, false)
|
|
|
}
|
|
|
//4、声明样式描述文件
|
|
|
titleStylePath := stylePathPrefix + "titleStyle.json"
|
|
|
tableStylePath := stylePathPrefix + "tableStyleNormal.json"
|
|
|
if !FileUtil.PathExists(titleStylePath) {
|
|
|
titleStylePath = "." + titleStylePath
|
|
|
}
|
|
|
if !FileUtil.PathExists(tableStylePath) {
|
|
|
tableStylePath = "." + tableStylePath
|
|
|
}
|
|
|
tableStyle, _ := f.NewStyle(FileUtil.ReadFileContent(tableStylePath))
|
|
|
|
|
|
//5、表头
|
|
|
for i := 0; i < cols; i++ {
|
|
|
//设置列宽
|
|
|
cName, _ := excelize.ColumnNumberToName(i + 1)
|
|
|
f.SetColWidth(SheetName, cName, cName, s1.Cols[i].Width)
|
|
|
//写入文字
|
|
|
cName = cName + strconv.Itoa(HiddenRows+1) //第hiddenRows+1行
|
|
|
f.SetCellStyle(SheetName, cName, cName, tableStyle)
|
|
|
//加上红星提醒
|
|
|
if s1.Cols[i].Require {
|
|
|
f.SetCellValue(SheetName, cName, s1.Cols[i].ColName)
|
|
|
f.SetCellRichText(SheetName, cName, []excelize.RichTextRun{
|
|
|
{
|
|
|
Text: s1.Cols[i].ColName,
|
|
|
Font: &excelize.Font{
|
|
|
Family: "宋体",
|
|
|
Size: 14,
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
Text: "[*]",
|
|
|
Font: &excelize.Font{
|
|
|
Bold: true,
|
|
|
Color: "e83723",
|
|
|
Family: "宋体",
|
|
|
Size: 14,
|
|
|
},
|
|
|
},
|
|
|
})
|
|
|
} else {
|
|
|
f.SetCellValue(SheetName, cName, s1.Cols[i].ColName)
|
|
|
}
|
|
|
}
|
|
|
//6、设置足够多的行是28这个高度,RowsCount行应该够用了
|
|
|
var RowHeight = 28.0
|
|
|
//表头设置行高
|
|
|
f.SetRowHeight(SheetName, 1, RowHeight)
|
|
|
//设置边框
|
|
|
for i := HiddenRows + 1; i <= HiddenRows+RowsCount; i++ {
|
|
|
for j := 0; j < cols; j++ {
|
|
|
cName, _ := excelize.ColumnNumberToName(j + 1)
|
|
|
cName = cName + strconv.Itoa(i)
|
|
|
f.SetCellStyle(SheetName, cName, cName, tableStyle)
|
|
|
}
|
|
|
f.SetRowHeight(SheetName, i, RowHeight)
|
|
|
}
|
|
|
//白色
|
|
|
WhiteJson := GetBackgroundColorStyle(Const.WhiteStyle)
|
|
|
WhiteStyle, _ := f.NewStyle(WhiteJson)
|
|
|
f.SetCellStyle(SheetName, Const.WhiteCell, Const.WhiteCell, WhiteStyle)
|
|
|
//红色
|
|
|
RedJson := GetBackgroundColorStyle(Const.RedStyle)
|
|
|
RedStyle, _ := f.NewStyle(RedJson)
|
|
|
f.SetCellStyle(SheetName, Const.RedCell, Const.RedCell, RedStyle)
|
|
|
//蓝色
|
|
|
BlueJson := GetBackgroundColorStyle(Const.BlueStyle)
|
|
|
BlueStyle, _ := f.NewStyle(BlueJson)
|
|
|
f.SetCellStyle(SheetName, Const.BlueCell, Const.BlueCell, BlueStyle)
|
|
|
//黄色
|
|
|
YellowJson := GetBackgroundColorStyle(Const.YellowStyle)
|
|
|
YellowStyle, _ := f.NewStyle(YellowJson)
|
|
|
f.SetCellStyle(SheetName, Const.YellowCell, Const.YellowCell, YellowStyle)
|
|
|
//保存
|
|
|
// 根据指定路径保存文件(不管是不是通过,都保存一次)
|
|
|
if err := f.SaveAs(excelPath); err != nil {
|
|
|
println(err.Error())
|
|
|
}
|
|
|
return
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
功能:按SQL定义添加字典
|
|
|
作者:黄海
|
|
|
时间:2020-06-18
|
|
|
*/
|
|
|
func TemplateAddDict(excelPath string, jsonTemplate string) (*excelize.File, TemplateStruct, int, string) {
|
|
|
excelPath = "./Config/ImportExcelTemplate/" + excelPath
|
|
|
if !FileUtil.PathExists(excelPath) {
|
|
|
excelPath = "." + excelPath
|
|
|
}
|
|
|
f, _ := excelize.OpenFile(excelPath)
|
|
|
var s1 TemplateStruct
|
|
|
|
|
|
jsonTemplate = "./Config/ImportExcelTemplate/" + jsonTemplate
|
|
|
if !FileUtil.PathExists(jsonTemplate) {
|
|
|
jsonTemplate = "." + jsonTemplate
|
|
|
}
|
|
|
var jsonContent = FileUtil.ReadFileContent(jsonTemplate)
|
|
|
//2、还原成结构体
|
|
|
json.Unmarshal([]byte(jsonContent), &s1)
|
|
|
cols := len(s1.Cols) //列数
|
|
|
var SheetName = s1.Title
|
|
|
//字典的列开始值
|
|
|
dictCols := cols + 1
|
|
|
//设置下拉框
|
|
|
for i := 0; i < cols; i++ {
|
|
|
//如果需要设置一级下接框
|
|
|
if s1.Cols[i].Level1Sql {
|
|
|
//查询值域
|
|
|
args := s1.Cols[i].SqlParameter
|
|
|
list, err := db.SQL(s1.Level1Sql[s1.Cols[i].SqlNum-1], args...).Query().List()
|
|
|
if err != nil {
|
|
|
fmt.Println(err.Error())
|
|
|
}
|
|
|
//字典列从cols+1开始
|
|
|
dictCName, _ := excelize.ColumnNumberToName(dictCols)
|
|
|
dictCols++
|
|
|
for j := range list {
|
|
|
f.SetCellValue(SheetName, dictCName+CommonUtil.ConvertIntToString(j+1), list[j]["dict_value"])
|
|
|
}
|
|
|
//隐藏字典列
|
|
|
f.SetColVisible(SheetName, dictCName, false)
|
|
|
//要设置下拉框的列
|
|
|
cName, _ := excelize.ColumnNumberToName(i + 1)
|
|
|
dvRange := excelize.NewDataValidation(true)
|
|
|
dvRange.Sqref = cName + CommonUtil.ConvertIntToString(2) + ":" + cName + CommonUtil.ConvertIntToString(RowsCount)
|
|
|
c := "$" + dictCName + "$1:$" + dictCName + "$" + CommonUtil.ConvertIntToString(len(list))
|
|
|
dvRange.SetSqrefDropList(c)
|
|
|
f.AddDataValidation(SheetName, dvRange)
|
|
|
}
|
|
|
}
|
|
|
return f, s1, dictCols, SheetName
|
|
|
}
|