GO 数据库内容导出到Excel表格

1.导出列表

bash 复制代码
func exportTaskList(c *gin.Context) {
	u := user.GetCookie(c)
	Data, err := handleData(c)
	if err != nil {
		c.JSON(http.StatusInternalServerError, err.Error())
		return
	}
	warehouseId, _ := Data["warehouse_id"].(string)
	if ok, err := order.GetWareHouseEmpty(warehouseId); ok {
		c.JSON(http.StatusBadRequest, err)
		return
	}
	allList, err := queryAllTaskFromDB(warehouseId, u)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 500, "msg": "查询失败"})
		return
	}

	// 1. 创建文件
	f := excelize.NewFile()
	sheetName := "任务列表"

	// 2. v1 用法:NewSheet 只返回一个 int 索引,没有 error
	index := f.NewSheet(sheetName) // 这里只接收一个值,不再报错

	// 3. 设置活动工作表
	f.SetActiveSheet(index)
	f.DeleteSheet("Sheet1")

	// 4. 设置表头
	headers := []string{"订单编号", "状态", "类型", "容器码", "起点位置", "目标位置", "下发时间", "完成时间", "用时", "执行结果", "组盘人", "创建人", "分拣人", "所属仓库"}
	for i, h := range headers {
		cell := fmt.Sprintf("%c1", 'A'+i)
		f.SetCellValue(sheetName, cell, h)
	}

	// 5. v1 用法:NewStyle 返回 (int, error),用两个变量接收
	style, err := f.NewStyle(`{"font":{"bold":true}}`) // v1 样式用 JSON 字符串
	if err == nil {
		f.SetCellStyle(sheetName, "A1", fmt.Sprintf("%c1", 'A'+len(headers)-1), style)
	}
	users, _ := getUserAll(u)
	inventorys, _ := getInventoryAll(u)
	// 6. 填充数据
	for rowIdx, row := range allList {
		rowNum := rowIdx + 2

		wcs_sn, _ := row["wcs_sn"].(string)
		status, _ := row["status"].(string)
		ss := ""
		switch status {
		case "status_wait":
			ss = "待执行"
			break
		case "status_progress":
			ss = "进行中"
			break
		case "status_success":
			ss = "已完成"
			break
		case "status_cancel":
			ss = "已取消"
			break
		case "status_fail":
			ss = "失败"
			break
		case "status_delete":
			ss = "已删除"
			break
		case "status_suspend":
			ss = "已暂停"
			break

		}
		types, _ := row["types"].(string)
		tt := ""
		switch types {
		case "in":
			tt = "入库"
			break
		case "out":
			tt = "出库"
			break
		case "return":
			tt = "回库"
			break
		case "move":
			tt = "移库"
			break
		case "outEmpty":
			tt = "空托出库"
			break
		case "inEmpty":
			tt = "空托入库"
			break
		case "outMaterial":
			tt = "空筐出库"
			break
		case "inreturn":
			tt = "盘点回库"
			break
		case "nin":
			tt = "移车"
			break
		}
		container_code, _ := row["container_code"].(string)
		port_addr, _ := row["port_addr"].(mo.M)
		src := ""
		if port_addr != nil {
			src = fmt.Sprintf("%d-%d-%d", port_addr["f"], port_addr["c"], port_addr["r"])
		}
		dst := ""
		addr, _ := row["addr"].(mo.M)
		if addr != nil {
			dst = fmt.Sprintf("%d-%d-%d", addr["f"], addr["c"], addr["r"])
		}
		send_time, _ := row["send_time"].(mo.DateTime)
		p := send_time.Time()
		send_time_str := p.Format("2006-01-02")
		if send_time_str == "1970-01-01" {
			send_time_str = ""
		}
		complete_time, _ := row["complete_time"].(mo.DateTime)
		cc := complete_time.Time()
		complete_time_str := cc.Format("2006-01-02")
		if complete_time_str == "1970-01-01" {
			complete_time_str = ""
		}
		minsecdiff := ""
		if complete_time_str == "" {
			minsecdiff = ""
		}
		if src == dst {
			minsecdiff = ""
		}
		if send_time_str != "" && complete_time_str != "" {
			duration := p.Sub(cc)

			if duration < 0 {
				duration = -duration
			}
			totalSeconds := int(duration.Seconds())
			diffMinutes := totalSeconds / 60
			diffSeconds := totalSeconds % 60
			minsecdiff = fmt.Sprintf("%d分%d秒", diffMinutes, diffSeconds)
		}
		remark, _ := row["remark"].(string)
		creatorStr := ""
		sort_creatorStr := ""
		groupStr := ""
		if len(users) > 0 {
			creator, _ := row["creator"].(mo.ObjectID)
			sort_creator, _ := row["sort_creator"].(mo.ObjectID)
			creatorStr = users[creator]
			sort_creatorStr = users[sort_creator]
			if len(inventorys) > 0 {
				group := inventorys[wcs_sn]
				groupStr = users[group]
			}
		}

		f.SetCellValue(sheetName, fmt.Sprintf("A%d", rowNum), wcs_sn)
		f.SetCellValue(sheetName, fmt.Sprintf("B%d", rowNum), ss)
		f.SetCellValue(sheetName, fmt.Sprintf("C%d", rowNum), tt)
		f.SetCellValue(sheetName, fmt.Sprintf("D%d", rowNum), container_code)
		f.SetCellValue(sheetName, fmt.Sprintf("E%d", rowNum), src)
		f.SetCellValue(sheetName, fmt.Sprintf("F%d", rowNum), dst)
		f.SetCellValue(sheetName, fmt.Sprintf("G%d", rowNum), p)
		f.SetCellValue(sheetName, fmt.Sprintf("H%d", rowNum), cc)
		f.SetCellValue(sheetName, fmt.Sprintf("I%d", rowNum), minsecdiff)
		f.SetCellValue(sheetName, fmt.Sprintf("J%d", rowNum), remark)
		f.SetCellValue(sheetName, fmt.Sprintf("K%d", rowNum), groupStr)
		f.SetCellValue(sheetName, fmt.Sprintf("L%d", rowNum), creatorStr)
		f.SetCellValue(sheetName, fmt.Sprintf("M%d", rowNum), sort_creatorStr)
		f.SetCellValue(sheetName, fmt.Sprintf("N%d", rowNum), warehouseId)
	}

	// 7. 设置列宽等样式
	f.SetColWidth(sheetName, "A", "A", 10)
	f.SetColWidth(sheetName, "B", "B", 10)
	f.SetColWidth(sheetName, "C", "C", 10)
	f.SetColWidth(sheetName, "D", "D", 10)
	f.SetColWidth(sheetName, "E", "E", 10)
	f.SetColWidth(sheetName, "F", "F", 10)
	f.SetColWidth(sheetName, "G", "G", 10)
	f.SetColWidth(sheetName, "H", "H", 10)
	f.SetColWidth(sheetName, "I", "I", 10)
	f.SetColWidth(sheetName, "J", "J", 10)
	f.SetColWidth(sheetName, "K", "K", 10)
	f.SetColWidth(sheetName, "L", "L", 10)
	f.SetColWidth(sheetName, "M", "M", 10)
	f.SetColWidth(sheetName, "N", "N", 10)

	// 8. 输出文件
	filename := fmt.Sprintf("%s.xlsx", time.Now().Format("20060102_150405"))
	c.Header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
	c.Header("Content-Disposition", fmt.Sprintf("attachment; filename*=UTF-8''%s", filename))
	c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filename))

	if err := f.Write(c.Writer); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": 500, "msg": "生成文件失败"})
	}
}

2. 获取数据库数据

bash 复制代码
func queryAllTaskFromDB(wId string, u ii.User) ([]mo.M, error) {
	// 获取用户
	fil := mo.Matcher{}
	fil.Eq("warehouse_id", wId)
	fil.In("status", mo.A{"status_success", "status_delete", "status_cancel"})
	list, err := svc.Svc(u).Find(stocks.WmsTaskHistory, fil.Done())
	if err != nil {
		return nil, err
	}
	return list, nil
}

3.获取用户列表

bash 复制代码
func getUserAll(u ii.User) (map[mo.ObjectID]string, error) {
	users := make(map[mo.ObjectID]string)
	list, err := svc.Svc(u).Find(stocks.WmsUser, mo.D{})
	if err != nil {
		return nil, err
	}
	for _, row := range list {
		_id, _ := row[mo.ID.Key()].(mo.ObjectID)
		name, _ := row["name"].(string)
		users[_id] = name
	}
	return users, nil
}

4.获取入库单数据

bash 复制代码
func getInventoryAll(u ii.User) (map[string]mo.ObjectID, error) {
	data := make(map[string]mo.ObjectID)
	list, err := svc.Svc(u).Find(stocks.WmsGroupInventory, mo.D{})
	if err != nil {
		return nil, err
	}
	for _, row := range list {
		wcsSn, _ := row["wcs_sn"].(string)
		creator, _ := row["creator"].(mo.ObjectID)
		data[wcsSn] = creator
	}
	return data, nil
}