electricity_bill_calc_service/excel/meter_reading.go

132 lines
4.3 KiB
Go

package excel
import (
"electricity_bill_calc/logger"
"electricity_bill_calc/model"
"electricity_bill_calc/tools"
"fmt"
"io"
"github.com/xuri/excelize/v2"
"go.uber.org/zap"
)
var meterReadingsRecognizers = []*ColumnRecognizer{
{Pattern: [][]string{{"表", "表计"}, {"编号"}}, Tag: "code", 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: "valley", MatchIndex: -1},
}
func NewMeterReadingsExcelAnalyzer(file io.Reader) (*ExcelAnalyzer[model.ReadingImportRow], error) {
return NewExcelAnalyzer[model.ReadingImportRow](file, meterReadingsRecognizers)
}
type MeterReadingsExcelTemplateGenerator struct {
file *excelize.File
log *zap.Logger
}
func NewMeterReadingsExcelTemplateGenerator() *MeterReadingsExcelTemplateGenerator {
return &MeterReadingsExcelTemplateGenerator{
file: excelize.NewFile(),
log: logger.Named("Excel", "MeterReadings"),
}
}
func (MeterReadingsExcelTemplateGenerator) titles() *[]interface{} {
return &[]interface{}{
"抄表序号",
"抄表时间",
"表计编号",
"表计名称",
"商户名称",
"倍率",
"有功(总)",
"有功(尖)",
"有功(峰)",
"有功(谷)",
}
}
func (g MeterReadingsExcelTemplateGenerator) Close() {
g.file.Close()
}
func (g MeterReadingsExcelTemplateGenerator) WriteTo(w io.Writer) (int64, error) {
return g.file.WriteTo(w)
}
func (g MeterReadingsExcelTemplateGenerator) WriteTemplateData(meters []*model.SimpleMeterDocument) error {
var err error
defaultSheet := g.file.GetSheetName(0)
g.log.Debug("选定默认输出表格", zap.String("sheet", defaultSheet))
err = g.file.SetColWidth(defaultSheet, "A", "E", 30)
if err != nil {
g.log.Error("未能设定长型单元格的宽度。", zap.Error(err))
return fmt.Errorf("未能设定长型单元格的宽度,%w", err)
}
err = g.file.SetColWidth(defaultSheet, "F", "F", 10)
if err != nil {
g.log.Error("未能设定倍率单元格的宽度。", zap.Error(err))
return fmt.Errorf("未能设定倍率单元格的宽度,%w", err)
}
err = g.file.SetColWidth(defaultSheet, "G", "J", 20)
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, 30)
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)
}
endCellCoord, _ := excelize.CoordinatesToCellName(2, len(meters)+1)
g.file.SetCellStyle(defaultSheet, "B2", endCellCoord, 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)
}
endCellCoord, _ = excelize.CoordinatesToCellName(9, len(meters)+1)
g.file.SetCellStyle(defaultSheet, "F2", endCellCoord, numColStyle)
for i, meter := range meters {
cellCoord, _ := excelize.CoordinatesToCellName(1, i+2)
ratio, _ := meter.Ratio.Float64()
if err := g.file.SetSheetRow(defaultSheet, cellCoord, &[]interface{}{
meter.Seq,
"",
meter.Code,
tools.DefaultTo(meter.Address, ""),
tools.DefaultTo(meter.TenementName, ""),
ratio,
}); err != nil {
g.log.Error("向模板写入数据出现错误。", zap.Error(err))
return fmt.Errorf("向模板写入数据出现错误,%w", err)
}
}
return err
}