go可以通过excelize
包实现对excel的操作
"github.com/xuri/excelize/v2"
导出示例
service层
批量导出数据的,我们可以在dao层中返回一个切片。在service中新建一个excelize对象,单独设置表头。遍历切片往excelize上修改即可。
func (s *Service) ExcelDown(req model.ReleaseRecordRequest) (*excelize.File, error) {// 从数据库拿到自己想要的数据data, err := s.dao.QueryData(req)if err != nil {return nil, err}if len(data) == 0 {return nil, errors.New("数据为空")}// 设置模版f := excelize.NewFile() // 新建一个.xlsx文件f.SetCellValue("Sheet1", "A1", "project_name") // 设置Sheet1中对应位置的值f.SetCellValue("Sheet1", "B1", "env_name")f.SetCellValue("Sheet1", "C1", "cluster_name")f.SetCellValue("Sheet1", "D1", "mode")f.SetCellValue("Sheet1", "E1", "remark")f.SetCellValue("Sheet1", "F1", "status")f.SetCellValue("Sheet1", "G1", "username")f.SetCellValue("Sheet1", "H1", "start_time")for i, datum := range data {f.SetCellValue("Sheet1", fmt.Sprintf("A%d", i+2), datum.ProjectName)f.SetCellValue("Sheet1", fmt.Sprintf("B%d", i+2), datum.EnvName)f.SetCellValue("Sheet1", fmt.Sprintf("C%d", i+2), datum.ClusterName)f.SetCellValue("Sheet1", fmt.Sprintf("D%d", i+2), datum.Mode)f.SetCellValue("Sheet1", fmt.Sprintf("E%d", i+2), datum.Remark)f.SetCellValue("Sheet1", fmt.Sprintf("F%d", i+2), datum.Status)f.SetCellValue("Sheet1", fmt.Sprintf("G%d", i+2), datum.Username)f.SetCellValue("Sheet1", fmt.Sprintf("H%d", i+2), datum.StartTime)}return f, err
}
controller层
这里跟普通的返回有点区别,需要给响应头添加参数
func export(ctx *gin.Context) {file, err := s.ExportDown(req)if err != nil {...return}buffer := new(bytes.Buffer)if err := file.Write(buffer); err != nil {...return}excelData := buffer.Bytes()ctx.Header("Content-Disposition", "attachment;filename="+"xxx.xlsx")ctx.Data(http.StatusOK, "application/octet-stream", excelData)
}
cvs
如果一切顺利的话,导出到这里结束了,但我今天偏偏就遇到了不正常的。
在本地、测试环境下载文件均正常,在生产环境下载文件无法打开。
中间我查了很多资料,但是都没解决(我怀疑是生产环境的问题,但是由于是生产环境,也没有办法)
条条大陆通罗马,我们的目的是导出,至于具体是什么类型的文件,并没有要求
终于我找到了 cvs
文件
CSV(逗号分隔值)文件是一种特殊的文件类型,可在 Excel 中创建或编辑。 CSV 文件不是采用多列的形式存储信息,而是使用逗号分隔的形式存储信息。 将文本和数字保存在 CSV 文件中时,可轻松将它们从一个程序移动至另一个程序。
简直一摸一样,操作也十分简单,只需要对上面代码简单修改即可
server层
func (s *Service) ExcelDown(req model.ReleaseRecordRequest) (string, error) {// 查data, err := s.dao.QueryData(req)if err != nil {return "", err}if len(data) == 0 {return "", errors.New("数据为空")}var b strings.Builderwriter := csv.NewWriter(&b)// 写入标题行err = writer.Write([]string{"project_name", "env_name", "cluster_name", "mode", "remark", "status", "username", "start_time"})if err != nil {return "", err}// 写入数据for _, datum := range data {err = writer.Write([]string{datum.ProjectName, datum.EnvName, datum.ClusterName, datum.Mode, datum.Remark, datum.Status, datum.Username, datum.StartTime})if err != nil {return "", err}}writer.Flush()return b.String(), nil
}
controller层
func export(ctx *gin.Context) {data, err := s.ExportDown(req)if err != nil {...return}c.Header("Content-Type", "text/csv")c.Header("Content-Disposition", "attachment;filename=export.csv")c.String(http.StatusOK, "\xEF\xBB\xBF"+data) // "\xEF\xBB\xBF 解决乱码问题"
}
最后成功导出,打开和excel一摸一样(公司的数据,这里我就不打开演示了)