140 lines
5.0 KiB
Go
140 lines
5.0 KiB
Go
package excel
|
|
|
|
import (
|
|
"electricity_bill_calc/logger"
|
|
"electricity_bill_calc/model"
|
|
"fmt"
|
|
"io"
|
|
|
|
"github.com/samber/lo"
|
|
"github.com/xuri/excelize/v2"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
var meterArchiveRecognizers = []*ColumnRecognizer{
|
|
{Pattern: [][]string{{"表号"}}, Tag: "code", MatchIndex: -1, MustFill: true},
|
|
{Pattern: [][]string{{"表址", "地址", "户址"}}, Tag: "address", MatchIndex: -1},
|
|
{Pattern: [][]string{{"类型"}}, Tag: "meterType", MatchIndex: -1, MustFill: true},
|
|
{Pattern: [][]string{{"建筑"}}, Tag: "building", MatchIndex: -1},
|
|
{Pattern: [][]string{{"楼层"}}, Tag: "onFloor", MatchIndex: -1},
|
|
{Pattern: [][]string{{"面积"}}, Tag: "area", MatchIndex: -1},
|
|
{Pattern: [][]string{{"倍率"}}, Tag: "ratio", MatchIndex: -1, MustFill: true},
|
|
{Pattern: [][]string{{"序号"}}, Tag: "seq", MatchIndex: -1, MustFill: true},
|
|
{Pattern: [][]string{{"抄表"}, {"时间", "日期"}}, Tag: "readAt", MatchIndex: -1, MustFill: true},
|
|
{Pattern: [][]string{{"有功", "表底", "底数"}, {"总"}}, Tag: "overall", MatchIndex: -1, MustFill: true},
|
|
{Pattern: [][]string{{"有功", "表底", "底数"}, {"尖"}}, Tag: "critical", MatchIndex: -1},
|
|
{Pattern: [][]string{{"有功", "表底", "底数"}, {"峰"}}, Tag: "peak", MatchIndex: -1},
|
|
{Pattern: [][]string{{"有功", "表底", "底数"}, {"平"}}, Tag: "flat", MatchIndex: -1},
|
|
{Pattern: [][]string{{"有功", "表底", "底数"}, {"谷"}}, Tag: "valley", MatchIndex: -1},
|
|
}
|
|
|
|
func NewMeterArchiveExcelAnalyzer(file io.Reader) (*ExcelAnalyzer[model.MeterImportRow], error) {
|
|
return NewExcelAnalyzer[model.MeterImportRow](file, meterArchiveRecognizers)
|
|
}
|
|
|
|
type MeterArchiveExcelTemplateGenerator struct {
|
|
file *excelize.File
|
|
log *zap.Logger
|
|
}
|
|
|
|
func NewMeterArchiveExcelTemplateGenerator() *MeterArchiveExcelTemplateGenerator {
|
|
return &MeterArchiveExcelTemplateGenerator{
|
|
file: excelize.NewFile(),
|
|
log: logger.Named("Excel", "MeterArchive"),
|
|
}
|
|
}
|
|
|
|
func (MeterArchiveExcelTemplateGenerator) titles() *[]interface{} {
|
|
return &[]interface{}{
|
|
"序号",
|
|
"表址",
|
|
"表号",
|
|
"表计类型",
|
|
"倍率",
|
|
"所在建筑",
|
|
"所在楼层",
|
|
"辖盖面积",
|
|
"抄表时间",
|
|
"有功(总)",
|
|
"有功(尖)",
|
|
"有功(峰)",
|
|
"有功(平)",
|
|
"有功(谷)",
|
|
}
|
|
}
|
|
|
|
func (g *MeterArchiveExcelTemplateGenerator) Close() {
|
|
g.file.Close()
|
|
}
|
|
|
|
func (g MeterArchiveExcelTemplateGenerator) WriteTo(w io.Writer) (int64, error) {
|
|
return g.file.WriteTo(w)
|
|
}
|
|
|
|
func (g *MeterArchiveExcelTemplateGenerator) WriteTemplateData(buildings []*model.ParkBuilding) error {
|
|
var err error
|
|
defaultSheet := g.file.GetSheetName(0)
|
|
g.log.Debug("选定默认输出表格", zap.String("sheet", defaultSheet))
|
|
err = g.file.SetColWidth(defaultSheet, "B", "I", 20)
|
|
if err != nil {
|
|
g.log.Error("未能设定长型列宽。", zap.Error(err))
|
|
return fmt.Errorf("未能设定长型列宽,%w", err)
|
|
}
|
|
err = g.file.SetColWidth(defaultSheet, "J", "N", 15)
|
|
if err != nil {
|
|
g.log.Error("未能设定短型列宽。", zap.Error(err))
|
|
return fmt.Errorf("未能设定短型列宽,%w", err)
|
|
}
|
|
err = g.file.SetSheetRow(defaultSheet, "A1", g.titles())
|
|
if err != nil {
|
|
g.log.Error("未能输出模板标题。", zap.Error(err))
|
|
return fmt.Errorf("未能输出模板标题,%w", err)
|
|
}
|
|
err = g.file.SetRowHeight(defaultSheet, 1, 20)
|
|
if err != nil {
|
|
g.log.Error("未能设定标题行高度。", zap.Error(err))
|
|
return fmt.Errorf("未能设定标题行高度,%w", err)
|
|
}
|
|
|
|
dateTimeExp := "yyyy-mm-dd hh:mm"
|
|
dateTimeColStyle, err := g.file.NewStyle(&excelize.Style{
|
|
CustomNumFmt: &dateTimeExp,
|
|
})
|
|
if err != nil {
|
|
g.log.Error("未能创建日期时间格式。", zap.Error(err))
|
|
return fmt.Errorf("未能创建日期时间格式,%w", err)
|
|
}
|
|
g.file.SetCellStyle(defaultSheet, "I2", "I1048576", dateTimeColStyle)
|
|
|
|
numExp := "0.0000"
|
|
numColStyle, err := g.file.NewStyle(&excelize.Style{
|
|
CustomNumFmt: &numExp,
|
|
})
|
|
if err != nil {
|
|
g.log.Error("未能创建抄表数字格式。", zap.Error(err))
|
|
return fmt.Errorf("未能创建抄表数字格式,%w", err)
|
|
}
|
|
g.file.SetCellStyle(defaultSheet, "J2", "N1048576", numColStyle)
|
|
|
|
meterInstallationTypeValidation := excelize.NewDataValidation(false)
|
|
meterInstallationTypeValidation.SetDropList([]string{"商户表", "公共表", "楼道表"})
|
|
meterInstallationTypeValidation.Sqref = "D2:D1048576"
|
|
err = g.file.AddDataValidation(defaultSheet, meterInstallationTypeValidation)
|
|
if err != nil {
|
|
g.log.Error("未能设定表计类型选择器。", zap.Error(err))
|
|
return fmt.Errorf("未能设定表计类型选择器,%w", err)
|
|
}
|
|
buildingValidation := excelize.NewDataValidation(true)
|
|
buildingNames := lo.Map(buildings, func(b *model.ParkBuilding, _ int) string {
|
|
return b.Name
|
|
})
|
|
buildingValidation.SetDropList(buildingNames)
|
|
buildingValidation.Sqref = "F2:F1048576"
|
|
err = g.file.AddDataValidation(defaultSheet, buildingValidation)
|
|
if err != nil {
|
|
g.log.Error("未能设定所在建筑选择器。", zap.Error(err))
|
|
return fmt.Errorf("未能设定所在建筑选择器,%w", err)
|
|
}
|
|
return nil
|
|
}
|