Files
zmkgC/test/excel_test.go
2025-07-07 20:11:59 +08:00

1002 lines
29 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package test
import (
"context"
"encoding/json"
"fmt"
"strconv"
"strings"
"testing"
"github.com/samber/lo"
"github.com/tiger1103/gfast/v3/api/v1/system"
"github.com/tiger1103/gfast/v3/internal/app/system/dao"
"github.com/tiger1103/gfast/v3/internal/app/system/model"
"github.com/tiger1103/gfast/v3/internal/app/system/model/entity"
"github.com/tiger1103/gfast/v3/third/excel"
"github.com/xuri/excelize/v2"
)
// 测试 Excel 解析数据
func TestExcel(t *testing.T) {
fileName := "test.xlsx"
f, err := excelize.OpenFile(fileName)
if err != nil {
t.Fatal(err)
}
defer func() {
if err := f.Close(); err != nil {
t.Fatal(err)
}
}()
rows, err := f.GetRows("方阵统计分析")
if err != nil {
t.Fatal(err)
}
type group struct {
Name string
MatrixNumber string
NominalTiltAngle string
}
groups := map[string][]group{}
// groups := []group{}
for _, row := range rows[1:] {
// Matrix Name
matrixName := row[0]
// Nominal Tilt Angle
nominalTiltAngle := row[2]
// Nominal Azimuth Angle
nominalAzimuthAngle := row[3]
// 对 matrixNumber 拆分取出第一位
a := strings.ReplaceAll(strings.Split(matrixName, ".")[0], "G", "T")
groups[a] = append(groups[a], group{
Name: matrixName,
MatrixNumber: nominalTiltAngle,
NominalTiltAngle: nominalAzimuthAngle,
})
// groups = append(groups, group{
// Name: matrixName,
// MatrixNumber: nominalTiltAngle,
// NominalTiltAngle: nominalAzimuthAngle,
// })
}
for _, v := range groups {
fmt.Println(v)
}
}
// 测试导出 Excel
func TestExportExcel(t *testing.T) {
fangZhenID := "1964"
startAt := "2023-12-05"
endAt := "2024-03-22"
list := exportExcel(fangZhenID)
// 打开
f, err := excelize.OpenFile("test.xlsx")
if err != nil {
t.Fatal(err)
}
sheetName := "Sheet1"
headerPrefixes := []string{"一、", "二、", "三、", "四、", "五、", "六、"}
childPrefixes := []string{"1、", "2、", "3、", "4、", "5、", "6、", "7、", "8、", "9、", "10、", "11、", "12、"}
// 修改表头
f.SetCellValue(sheetName, "A1", fmt.Sprintf("%s (%s - %s)", fangZhenID, startAt, endAt))
// 遍历 list
rowIndex := 3
lo.ForEach(list, func(item *model.WorkStatusProgressRes, index int) {
setExcelValues(f, sheetName, rowIndex, item, headerPrefixes[index])
rowIndex++
// 遍历子集
lo.ForEach(item.Children, func(child model.WorkStatusProgressRes, childIndex int) {
setExcelValues(f, sheetName, rowIndex, &child, childPrefixes[childIndex])
rowIndex++
})
})
if err := f.SaveAs("asd.xlsx"); err != nil {
t.Fatal(err)
}
}
func setExcelValues(f *excelize.File, sheetName string, i int, item *model.WorkStatusProgressRes, prefix string) {
// 单元格 A
f.SetCellValue(sheetName, fmt.Sprintf("A%d", i), prefix+item.Name) // 父名
f.SetCellValue(sheetName, fmt.Sprintf("B%d", i), item.Total) // 总量
f.SetCellValue(sheetName, fmt.Sprintf("C%d", i), item.Finished) // 完成
var percentComplete float64
if item.Total != 0 {
percentComplete = float64(item.Finished) / float64(item.Total) * 100
} else {
percentComplete = 0
}
f.SetCellValue(sheetName, fmt.Sprintf("D%d", i), fmt.Sprintf("%.2f%%", percentComplete)) // 总量完成百分比
if item.PlanProgress != nil {
total := 0
if item.PlanProgress.Total != nil {
total = *item.PlanProgress.Total
}
f.SetCellValue(sheetName, fmt.Sprintf("E%d", i), total) // 计划量
finished := 0
if item.PlanProgress.Finished != nil {
finished = *item.PlanProgress.Finished
}
f.SetCellValue(sheetName, fmt.Sprintf("F%d", i), finished) // 计划完成量
var plannedPercentComplete float64
if item.PlanProgress != nil && item.PlanProgress.Finished != nil && item.PlanProgress.Total != nil && *item.PlanProgress.Total != 0 {
plannedPercentComplete = float64(*item.PlanProgress.Finished) / float64(*item.PlanProgress.Total) * 100
} else {
plannedPercentComplete = 0
}
f.SetCellValue(sheetName, fmt.Sprintf("G%d", i), fmt.Sprintf("%.2f%%", plannedPercentComplete)) // 计划完成百分比
}
}
func exportExcel(fangzhenID string) []*model.WorkStatusProgressRes {
startAt := "2023-12-05"
endAt := "2024-03-22"
type scheduler struct {
// 实体
WorkStatus *entity.WorkSchedule
// 总进度
FinishedPtr int
// 总量
Total int
}
type Schdule map[string]scheduler
Get := func(scheduleMap Schdule, workID string) (int, int) {
if scheduler, ok := scheduleMap[workID]; ok {
return scheduler.FinishedPtr, scheduler.Total
}
return 0, 0
}
ctx := context.Background()
// 获取指定方阵ID的所有计划
ScheduleData := []entity.WorkSchedule{}
if err := dao.WorkSchedule.Ctx(ctx).Where(dao.WorkSchedule.Columns().FangzhenId, fangzhenID).
Scan(&ScheduleData); err != nil {
return nil
}
scheduleMap := make(Schdule)
// 遍历 ScheduleData 将数据按照 WorkID 分组
lo.ForEach(ScheduleData, func(item entity.WorkSchedule, _ int) {
bb := item.StartAt.Format("Y-m-d")
if bb > startAt {
return
}
// 如果不存在则直接添加
_, ok := scheduleMap[item.WorkId]
if !ok {
scheduleMap[item.WorkId] = scheduler{
WorkStatus: &item,
}
}
// 反序列化 item.Detail 字段
var scheduleDetails []model.WorkScheduleDetail
if err := json.Unmarshal([]byte(item.Detail), &scheduleDetails); err != nil {
return
}
lo.ForEach(scheduleDetails, func(detail model.WorkScheduleDetail, _ int) {
// 如果 Date 大于开始时间并小于结束时间
if detail.Date <= endAt {
scheduler := scheduleMap[item.WorkId]
scheduler.Total += detail.PlanNum
scheduler.FinishedPtr += detail.FinishedNum
scheduleMap[item.WorkId] = scheduler
}
})
})
// 获取指定方阵ID的所有项目
workStatusList := []entity.WorkStatus{}
if err := dao.WorkStatus.Ctx(ctx).Where(dao.WorkStatus.Columns().FangzhenId, fangzhenID).Scan(&workStatusList); err != nil {
return nil
}
// 父列表
parentList := []entity.WorkStatus{}
// 子列表,使用 map 存储,键为父元素的 ID
childrenMap := make(map[int][]entity.WorkStatus)
// 遍历所有数据,将父级和子集分开
for i := 0; i < len(workStatusList); i++ {
item := workStatusList[i]
if item.Parent == 0 {
parentList = append(parentList, item)
} else {
childrenMap[item.Parent] = append(childrenMap[item.Parent], item)
}
}
index := 1
projectList := make([]*model.WorkStatusProgressRes, 0, len(parentList))
// 遍历父级,将子集添加到父级的字段中
for _, parent := range parentList {
projectItem := model.WorkStatusProgressRes{
ID: index,
WorkID: parent.WorkId,
Startat: parent.StartAt.String(),
Endat: parent.EndAt.String(),
Name: parent.WorkName,
Total: parent.Total,
Finished: parent.Finished,
Status: parent.Status,
WorkType: parent.Type,
Children: make([]model.WorkStatusProgressRes, 0, len(workStatusList)),
}
index++
// 子类的总量和完成量
var subTotal, subDone int
// 从 map 中获取子元素,将子元素添加到父元素的字段中
for _, child := range childrenMap[int(parent.Id)] {
// 如果计划数量等于实际数量且原状态非3则更新状态为2
if child.Total == child.Finished && child.Status != 3 {
// 并且 total,finished 不为 0
if child.Total != 0 && child.Finished != 0 {
child.Status = 2
}
}
// 根据 WorkID 获取计划总量和实际进度
finishedPtr, total := Get(scheduleMap, child.WorkId)
subTotal += child.Total
subDone += child.Finished
projectItem.Children = append(projectItem.Children, model.WorkStatusProgressRes{
ID: index,
WorkID: child.WorkId,
Startat: child.StartAt.String(),
Endat: child.EndAt.String(),
Name: child.WorkName,
Total: child.Total,
Finished: child.Finished,
IsPercent: child.IsPercent,
Status: child.Status,
WorkType: child.Type,
PlanProgress: &model.PlanProgress{
Finished: &finishedPtr,
Total: &total,
},
})
index++
}
// 修改父项目的总量和进度
projectItem.Total = subTotal
projectItem.Finished = subDone
projectList = append(projectList, &projectItem)
}
return projectList
}
// 获取整个子项目的
func getChildren(subProjectId int) []*model.WorkStatusProgressRes {
startAt := "2023-12-05"
endAt := "2024-03-22"
type scheduler struct {
// 实体
WorkStatus *entity.WorkSchedule
// 总进度
FinishedPtr int
// 总量
Total int
}
type Schdule map[string]scheduler
Get := func(scheduleMap Schdule, workID string) (int, int) {
if scheduler, ok := scheduleMap[workID]; ok {
return scheduler.FinishedPtr, scheduler.Total
}
return 0, 0
}
ctx := context.Background()
// 获取指定小项目的所有计划
ScheduleData := []entity.WorkSchedule{}
if err := dao.WorkSchedule.Ctx(ctx).Where(dao.WorkSchedule.Columns().SubProjectid, subProjectId).
Scan(&ScheduleData); err != nil {
return nil
}
scheduleMap := make(Schdule)
// 遍历 ScheduleData 将数据按照 WorkID 分组
lo.ForEach(ScheduleData, func(item entity.WorkSchedule, _ int) {
bb := item.StartAt.Format("Y-m-d")
if bb > startAt {
return
}
// 如果不存在则直接添加
_, ok := scheduleMap[item.WorkId]
if !ok {
scheduleMap[item.WorkId] = scheduler{
WorkStatus: &item,
}
}
// 反序列化 item.Detail 字段
var scheduleDetails []model.WorkScheduleDetail
if err := json.Unmarshal([]byte(item.Detail), &scheduleDetails); err != nil {
return
}
lo.ForEach(scheduleDetails, func(detail model.WorkScheduleDetail, _ int) {
// 如果 Date 大于开始时间并小于结束时间
if detail.Date <= endAt {
scheduler := scheduleMap[item.WorkId]
scheduler.Total += detail.PlanNum
scheduler.FinishedPtr += detail.FinishedNum
scheduleMap[item.WorkId] = scheduler
}
})
})
// 获取指定方阵ID的所有方阵数据
workStatusList := []entity.WorkStatus{}
if err := dao.WorkStatus.Ctx(ctx).Where(dao.WorkStatus.Columns().SubProjectid, subProjectId).Scan(&workStatusList); err != nil {
return nil
}
// 父列表
parentList := []entity.WorkStatus{}
// 子列表,使用 map 存储,键为父元素的 ID
childrenMap := make(map[int][]entity.WorkStatus)
// 遍历所有数据,将父级和子集分开
for i := 0; i < len(workStatusList); i++ {
item := workStatusList[i]
if item.Parent == 0 {
parentList = append(parentList, item)
} else {
childrenMap[item.Parent] = append(childrenMap[item.Parent], item)
}
}
index := 1
projectList := make([]*model.WorkStatusProgressRes, 0, len(parentList))
// 遍历父级,将子集添加到父级的字段中
for _, parent := range parentList {
projectItem := model.WorkStatusProgressRes{
ID: index,
WorkID: parent.WorkId,
Startat: parent.StartAt.String(),
Endat: parent.EndAt.String(),
Name: parent.WorkName,
Total: parent.Total,
Finished: parent.Finished,
Status: parent.Status,
WorkType: parent.Type,
Children: make([]model.WorkStatusProgressRes, 0, len(workStatusList)),
}
index++
// 子类的总量和完成量
var subTotal, subDone int
// 从 map 中获取子元素,将子元素添加到父元素的字段中
for _, child := range childrenMap[int(parent.Id)] {
// 如果计划数量等于实际数量且原状态非3则更新状态为2
if child.Total == child.Finished && child.Status != 3 {
// 并且 total,finished 不为 0
if child.Total != 0 && child.Finished != 0 {
child.Status = 2
}
}
// 根据 WorkID 获取计划总量和实际进度
finishedPtr, total := Get(scheduleMap, child.WorkId)
subTotal += child.Total
subDone += child.Finished
projectItem.Children = append(projectItem.Children, model.WorkStatusProgressRes{
ID: index,
WorkID: child.WorkId,
Startat: child.StartAt.String(),
Endat: child.EndAt.String(),
Name: child.WorkName,
Total: child.Total,
Finished: child.Finished,
IsPercent: child.IsPercent,
Status: child.Status,
WorkType: child.Type,
PlanProgress: &model.PlanProgress{
Finished: &finishedPtr,
Total: &total,
},
})
index++
}
// 修改父项目的总量和进度
projectItem.Total = subTotal
projectItem.Finished = subDone
projectList = append(projectList, &projectItem)
}
return projectList
}
// 测试子项目
func Test_subProject(t *testing.T) {
// 根据子项目ID获取所有的方阵
subProjectID := 23
fangzhenList := []entity.QianqiFangzhen{}
if err := dao.QianqiFangzhen.Ctx(context.Background()).
Where(dao.QianqiFangzhen.Columns().ProjectId, subProjectID).Scan(&fangzhenList); err != nil {
t.Fatal(err)
}
cumulativeProjects := []*model.WorkStatusProgressRes{}
// 用于判断是否为第一次迭代
firstTime := true
// 遍历项目列表
for index := 0; index < len(fangzhenList); index++ {
// 获取当前项目
project := fangzhenList[index]
// 获取当前项目的子项目
childProjects := exportExcel(strconv.Itoa(project.Id))
// 如果是第一次迭代,将子项目列表赋值给累积项目列表
if firstTime {
cumulativeProjects = childProjects
// 更新标志变量,表示已经不是第一次迭代
firstTime = false
continue
}
// 遍历子项目列表
for childIndex := 0; childIndex < len(childProjects); childIndex++ {
// 获取当前子项目和对应的累积项目
singleChild := childProjects[childIndex]
cumulativeChild := cumulativeProjects[childIndex]
// 更新累积项目的总数和完成数
cumulativeChild.Total += singleChild.Total
cumulativeChild.Finished += singleChild.Finished
// 如果当前子项目还有子项目,也进行同样的操作
if len(singleChild.Children) > 0 {
for subChildIndex := 0; subChildIndex < len(singleChild.Children); subChildIndex++ {
// 获取当前子项目的子项目和对应的累积项目
singleSubChild := singleChild.Children[subChildIndex]
cumulativeSubChild := cumulativeChild.Children[subChildIndex]
// 更新累积项目的总数和完成数
cumulativeSubChild.Total += singleSubChild.Total
cumulativeSubChild.Finished += singleSubChild.Finished
}
}
}
}
// 序列化 cumulativeProjects
data, err := json.Marshal(cumulativeProjects)
if err != nil {
t.Fatal(err)
}
fmt.Println(string(data))
}
// 根据方阵ID获取子项目名
func Test_GetSubName(t *testing.T) {
excel.GetSubProjectName("1959")
}
// 测试导出
func TestExport(t *testing.T) {
req := system.WorkScheduleExportWeekReq{
FangzhenID: "1964",
StartTime: "2023-09-07",
EndTime: "2024-10-22",
ProjectID: "45",
}
ctx := context.Background()
var (
list []*model.WorkStatusProgressRes
err error
projectName, subProjectName string
excelMap = make(map[string]excel.ExcelInfo)
)
// 导出指定方阵的情况下
if req.FangzhenID != "" {
// 获取方阵下的所有工作计划
list, excelMap, err = excel.ExportExcel(req.FangzhenID, req.StartTime, req.EndTime)
if err != nil {
t.Fatal(err)
}
// 子项目名,方阵名
projectName, subProjectName = excel.GetSubProjectName(req.FangzhenID)
} else {
// 导出一个子项目的情况
list, excelMap, err = excel.AccumulateProject(req.SubProjectID, req.StartTime, req.EndTime)
if err != nil {
t.Fatal(err)
}
// 大项目名,子项目名
projectName, subProjectName = excel.GetNameById(req.SubProjectID)
}
_, _, _ = projectName, subProjectName, list
_ = excelMap
// f, err := excelize.OpenFile("../resource/book.xlsx")
// if err != nil {
// t.Fatal(err)
// }
f, err := excel.CreateExcelTemplate()
if err != nil {
t.Fatal(err)
}
// 设置表头 k2 日期
// startat - endat
f.SetCellValue("Sheet1", "K2", fmt.Sprintf("%s - %s", req.StartTime, req.EndTime))
// 获取周数
week, err := excel.GetWeekNumbers(req.EndTime)
if err != nil {
t.Fatal(err)
}
// i2 周数
f.SetCellValue("Sheet1", "I2", week)
// D4 开工日期: 2023-03-20
projectInfo := entity.SysProject{}
err = dao.SysProject.Ctx(ctx).Where(dao.SysProject.Columns().Id, req.ProjectID).Scan(&projectInfo)
if err != nil {
t.Fatal(err)
}
// A1 项目名称 + "周报"
f.SetCellValue("Sheet1", "A1", projectInfo.ProjectName+"周报")
// C2 项目名称
f.SetCellValue("Sheet1", "C2", projectInfo.ProjectName)
f.SetCellValue("Sheet1", "D4", "开工日期:"+projectInfo.OnStreamTime.Format("Y-m-d"))
sheetName := "Sheet1"
index := 10
for i := 0; i < len(list); i++ {
postionName := list[i].Name
for j := 0; j < len(list[i].Children); j++ {
setExcelValue(f, sheetName, index, list[i].Children[j], excelMap, postionName)
// 如果 C 的下一格为 "设备材料名称" 则新增一行
if lo.Must(f.GetCellValue(sheetName, fmt.Sprintf("C%d", index+1))) == "设备材料名称" && index+1 != 38 {
f.InsertRows(sheetName, index+1, 1)
}
index++
}
}
// A9 ,B9 向下合并到 index
_ = f.MergeCell(sheetName, "A9", fmt.Sprintf("A%d", index-1))
f.SetCellStyle(sheetName, "A9", fmt.Sprintf("A%d", index-1), lo.Must(f.NewStyle(&GlobalStyle)))
_ = f.MergeCell(sheetName, "B9", fmt.Sprintf("B%d", index-1))
f.SetCellStyle(sheetName, "B9", fmt.Sprintf("B%d", index-1), lo.Must(f.NewStyle(&GlobalStyle)))
if err := f.SaveAs("test.xlsx"); err != nil {
t.Fatal(err)
}
}
var GlobalStyle = excelize.Style{
// 边框
Border: []excelize.Border{
{Type: "left", Color: "000000", Style: 1},
{Type: "top", Color: "000000", Style: 1},
{Type: "bottom", Color: "000000", Style: 1},
{Type: "right", Color: "000000", Style: 1},
},
// 居中
Alignment: &excelize.Alignment{
Vertical: "center", // 上下居中
Horizontal: "center", // 左右居中
WrapText: true, // 自动换行
},
}
func CalculateTotalProgress(list []*model.WorkStatusProgressRes) float64 {
var totalFinished, total int
var calculate func(w model.WorkStatusProgressRes)
calculate = func(w model.WorkStatusProgressRes) {
totalFinished += w.Finished
total += w.Total
for _, child := range w.Children {
calculate(child)
}
}
for _, item := range list {
calculate(*item)
}
if total == 0 {
return 0
}
return (float64(totalFinished) / float64(total)) * 100
}
// Test_ExportWeek 导出周报
func Test_ExportWeek(t *testing.T) {
req := system.WorkScheduleExportWeekReq{
ProjectID: "45",
FangzhenID: "1964",
StartTime: "2023-09-07",
EndTime: "2024-10-22",
}
var (
list []*model.WorkStatusProgressRes
err error
projectName, subProjectName string
excelMap = make(map[string]excel.ExcelInfo)
)
// 判断传入的方阵或子项目是否为空
// if !service.WorkSchedule().IsExistWorkSchedule(ctx, req.SubProjectID, req.FangzhenID, req.StartTime, req.EndTime) {
// list = []*model.WorkStatusProgressRes{}
// }
// 导出指定方阵的情况下
if req.FangzhenID != "" {
// 获取方阵下的所有工作计划
list, excelMap, err = excel.ExportExcel(req.FangzhenID, req.StartTime, req.EndTime)
if err != nil {
t.Fatal(err)
}
// 子项目名,方阵名
projectName, subProjectName = excel.GetSubProjectName(req.FangzhenID)
} else {
// 导出一个子项目的情况
list, excelMap, err = excel.AccumulateProject(req.SubProjectID, req.StartTime, req.EndTime)
if err != nil {
t.Fatal(err)
}
// 大项目名,子项目名
projectName, subProjectName = excel.GetNameById(req.SubProjectID)
}
_, _, _ = projectName, subProjectName, list
// dd, _ := json.Marshal(list)
// fmt.Println(string(dd))
ddd := CalculateTotalProgress(list)
fmt.Println(ddd)
// 创建 Excel 模板
f, err := excel.CreateExcelTemplate()
if err != nil {
t.Fatal(err)
}
sheetName := "Sheet1"
index := 10
for _, item := range list {
postionName := item.Name
for _, child := range item.Children {
excel.SetExcelValue(f, sheetName, index, child, excelMap, postionName)
if lo.Must(f.GetCellValue(sheetName, fmt.Sprintf("C%d", index+1))) == "设备材料名称" && index+1 != 38 {
f.InsertRows(sheetName, index+1, 1)
}
index++
}
}
// A9 ,B9 向下合并到 index
mergeAndStyle := func(col string) {
cellRange := fmt.Sprintf("%s9", col)
_ = f.MergeCell(sheetName, cellRange, fmt.Sprintf("%s%d", col, index-1))
f.SetCellStyle(sheetName, cellRange, fmt.Sprintf("%s%d", col, index-1), lo.Must(f.NewStyle(excel.Style)))
}
mergeAndStyle("A")
mergeAndStyle("B")
// 材料
equipmentMaterials, err := excel.GetEquipmentMaterials(req.ProjectID, req.StartTime, req.EndTime)
if err != nil {
t.Fatal(err)
}
index = 39 // 从第 39 行开始
for _, item := range equipmentMaterials {
// 如果 B + index 为 "存在问题及需要协调的事项" 则新增一行
if lo.Must(f.GetCellValue(sheetName, fmt.Sprintf("B%d", index))) == "存在问题及需要协调的事项" {
f.InsertRows(sheetName, index, 1)
}
f.SetCellValue(sheetName, fmt.Sprintf("C%d", index), item.EquipmentMaterialsName) // 设备材料名称
f.SetCellStyle(sheetName, fmt.Sprintf("C%d", index), fmt.Sprintf("C%d", index), lo.Must(f.NewStyle(excel.Style)))
f.SetCellStyle(sheetName, fmt.Sprintf("D%d", index), fmt.Sprintf("D%d", index), lo.Must(f.NewStyle(excel.Style)))
f.SetCellStyle(sheetName, fmt.Sprintf("E%d", index), fmt.Sprintf("E%d", index), lo.Must(f.NewStyle(excel.Style)))
f.SetCellValue(sheetName, fmt.Sprintf("F%d", index), item.TotalQuantityCount) // 设计数量
f.SetCellStyle(sheetName, fmt.Sprintf("F%d", index), fmt.Sprintf("F%d", index), lo.Must(f.NewStyle(excel.Style)))
f.SetCellValue(sheetName, fmt.Sprintf("G%d", index), item.TotalNumber) // 本周
f.SetCellStyle(sheetName, fmt.Sprintf("G%d", index), fmt.Sprintf("G%d", index), lo.Must(f.NewStyle(excel.Style)))
f.SetCellValue(sheetName, fmt.Sprintf("H%d", index), item.CumulativeArrivalQuantity) // 累计到货数量
f.SetCellStyle(sheetName, fmt.Sprintf("H%d", index), fmt.Sprintf("H%d", index), lo.Must(f.NewStyle(excel.Style)))
// 累计到货率
cumulativeArrivalRate := 0.0
if item.TotalQuantityCount != 0 {
cumulativeArrivalRate = float64(item.CumulativeArrivalQuantity) / float64(item.TotalQuantityCount)
}
f.SetCellValue(sheetName, fmt.Sprintf("I%d", index), cumulativeArrivalRate)
f.SetCellStyle(sheetName, fmt.Sprintf("I%d", index), fmt.Sprintf("I%d", index), lo.Must(f.NewStyle(excel.Style)))
// 合并 jk 单元格
_ = f.MergeCell(sheetName, fmt.Sprintf("J%d", index), fmt.Sprintf("K%d", index))
f.SetCellStyle(sheetName, fmt.Sprintf("J%d", index), fmt.Sprintf("K%d", index), lo.Must(f.NewStyle(excel.Style)))
// 水平居中 jk 单元格
f.SetCellStyle(sheetName, fmt.Sprintf("J%d", index), fmt.Sprintf("K%d", index), lo.Must(f.NewStyle(&excelize.Style{
Border: []excelize.Border{
{Type: "left", Color: "000000", Style: 1},
{Type: "top", Color: "000000", Style: 1},
{Type: "bottom", Color: "000000", Style: 1},
{Type: "right", Color: "000000", Style: 1},
},
Fill: excelize.Fill{},
Font: nil,
Alignment: &excelize.Alignment{
Horizontal: "center", // 水平居中
Indent: 0,
JustifyLastLine: false,
ReadingOrder: 0,
RelativeIndent: 0,
ShrinkToFit: false,
TextRotation: 0,
Vertical: "", // 垂直居中
WrapText: false,
},
})))
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", "L", index), fmt.Sprintf("%s%d", "L", index), lo.Must(f.NewStyle(excel.Style)))
index++
}
// 合并 A38 和 B38 至 index
f.MergeCell(sheetName, "A38", fmt.Sprintf("A%d", index-1))
f.SetCellStyle(sheetName, "A38", fmt.Sprintf("A%d", index-1), lo.Must(f.NewStyle(excel.Style)))
f.MergeCell(sheetName, "B38", fmt.Sprintf("B%d", index-1))
f.SetCellStyle(sheetName, "B38", fmt.Sprintf("B%d", index-1), lo.Must(f.NewStyle(excel.Style)))
// j4 总进度完成率
f.SetCellValue(sheetName, "J4", excel.CalculateTotalProgress(list))
if err := f.SaveAs("test.xlsx"); err != nil {
t.Fatal(err)
}
}
// 材料到货情况
func Test_Materials(t *testing.T) {
// SELECT
// bem.equipment_materials_name,
// SUM(bmi.number) AS total_number,
// SUM(bem.quantity_count) AS total_quantity_count,
// (
// SELECT
// SUM(bi.number)
// FROM
// `bus_equipment_materials_inventory` bi
// WHERE
// bi.equipment_materials_id = bmi.equipment_materials_id
// AND bi.deleted_at IS NULL
// AND bi.out_put = 2
// ) AS cumulative_arrival_quantity
// FROM
// `bus_equipment_materials_inventory` AS bmi
// LEFT JOIN `bus_equipment_materials` bem ON (
// bmi.equipment_materials_id = bem.equipment_materials_id
// )
// WHERE
// bem.project_id = 45
// AND bmi.out_put = 2
// AND bmi.created_at >= '2022-09-07'
// AND bmi.created_at <= '2024-10-22'
// AND bmi.deleted_at IS NULL
// AND bem.deleted_at IS NULL
// GROUP BY
// bem.equipment_materials_name;
var list []struct {
EquipmentMaterialsName string `json:"equipment_materials_name"` // 设备材料名称
TotalNumber int `json:"total_number"` // 本周到货量
TotalQuantityCount int `json:"total_quantity_count"` // 设计数量
CumulativeArrivalQuantity int `json:"cumulative_arrival_quantity"` // 累计到货量
}
startAT := "2022-09-07"
endAT := "2024-10-22"
// 查询
if err := dao.BusEquipmentMaterialsInventory.Ctx(context.Background()).As("bmi").
Fields("bem.equipment_materials_name, SUM(bmi.number) AS total_number, SUM(bem.quantity_count) AS total_quantity_count, (SELECT SUM(bi.number) FROM `bus_equipment_materials_inventory` bi WHERE bi.equipment_materials_id = bmi.equipment_materials_id AND bi.deleted_at IS NULL AND bi.out_put = 2) AS cumulative_arrival_quantity").
LeftJoin("bus_equipment_materials bem", "bmi.equipment_materials_id = bem.equipment_materials_id").
Where("bem.project_id = ?", 45).
Where("bmi.out_put = ?", 2).
Where("bmi.created_at >= ?", startAT).
Where("bmi.created_at <= ?", endAT).
Group("bem.equipment_materials_name").
Scan(&list); err != nil {
t.Fatal(err)
}
// // C39
// index := 39
// for _, item := range list {
// // 设备材料名称
// equipmentMaterialsName := item.EquipmentMaterialsName
// // 设计数量
// totalQuantityCount := item.TotalQuantityCount
// // 本周到货量
// totalNumber := item.TotalNumber
// // 累计到货量
// cumulativeArrivalQuantity := item.CumulativeArrivalQuantity
// // 累计到货率
// cumulativeArrivalRate := 0.0
// if totalQuantityCount != 0 {
// cumulativeArrivalRate = float64(cumulativeArrivalQuantity) / float64(totalQuantityCount) * 100
// }
// }
}
func setExcelValue(f *excelize.File, sheetName string, index int, item model.WorkStatusProgressRes, excelmap map[string]excel.ExcelInfo, postionName string) {
// 设计数量 F10
total := item.Total
// 本周完成量 G10
finished := item.Finished
// 累计完成量和下周计划量
accumulated, nextWeek := 0, 0
if data, exists := excelmap[item.WorkID]; exists {
accumulated = data.Accumulated
nextWeek = data.NextWeek
}
// 累计完成百分比 单元格 I10
percentComplete := 0.0
if total != 0 {
percentComplete = float64(accumulated) / float64(total) * 100
}
// 名称
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", "C", index), item.Name)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", "C", index), fmt.Sprintf("%s%d", "C", index), lo.Must(f.NewStyle(&GlobalStyle)))
// 位置
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", "D", index), postionName)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", "D", index), fmt.Sprintf("%s%d", "D", index), lo.Must(f.NewStyle(&GlobalStyle)))
// 单位 样式
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", "E", index), fmt.Sprintf("%s%d", "E", index), lo.Must(f.NewStyle(&GlobalStyle)))
// 设计数量
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", "F", index), total)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", "F", index), fmt.Sprintf("%s%d", "F", index), lo.Must(f.NewStyle(&GlobalStyle)))
// 本周
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", "G", index), finished)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", "G", index), fmt.Sprintf("%s%d", "G", index), lo.Must(f.NewStyle(&GlobalStyle)))
// 累计完成量
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", "H", index), accumulated)
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", "H", index), fmt.Sprintf("%s%d", "H", index), lo.Must(f.NewStyle(&GlobalStyle)))
// 累计完成百分比
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", "I", index), fmt.Sprintf("%.f%%", percentComplete))
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", "I", index), fmt.Sprintf("%s%d", "I", index), lo.Must(f.NewStyle(&GlobalStyle)))
// 合并 jk 单元格
_ = f.MergeCell(sheetName, fmt.Sprintf("J%d", index), fmt.Sprintf("K%d", index))
f.SetCellStyle(sheetName, fmt.Sprintf("J%d", index), fmt.Sprintf("K%d", index), lo.Must(f.NewStyle(&GlobalStyle)))
// 水平居中 jk 单元格
f.SetCellStyle(sheetName, fmt.Sprintf("J%d", index), fmt.Sprintf("K%d", index), lo.Must(f.NewStyle(&excelize.Style{
Border: []excelize.Border{
{Type: "left", Color: "000000", Style: 1},
{Type: "top", Color: "000000", Style: 1},
{Type: "bottom", Color: "000000", Style: 1},
{Type: "right", Color: "000000", Style: 1},
},
Fill: excelize.Fill{},
Font: nil,
Alignment: &excelize.Alignment{
Horizontal: "center", // 水平居中
Indent: 0,
JustifyLastLine: false,
ReadingOrder: 0,
RelativeIndent: 0,
ShrinkToFit: false,
TextRotation: 0,
Vertical: "", // 垂直居中
WrapText: false,
},
})))
// 下周计划量
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", "J", index), nextWeek)
// L
f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", "L", index), fmt.Sprintf("%s%d", "L", index), lo.Must(f.NewStyle(&GlobalStyle)))
}