golang读取excel文件(个人经验)

v1,v2版本访问地址
**注:本篇使用的工具包为下列v2版本

github.com/xuri/excelize/v2

之前的 工具包为下列v1版本**

github.com/360EntSecGroup-Skylar/excelize~~

其中

v2与v1的区别

日期
v2:默认为日期格式的字符串
v1:以到excel日期的浮点数(如果要使用需要转换,转换方法参考v2版本里面date文件中的timeFromExcelTime 方法)

我的公共工具方法

导入方法一,读取本地Excel文件(文件类型为.xlsx格式)

(根据表格名称获取指定表格数据)(返回的二维数据均为字符串格式,错误情况)

//filename:指定文件路径名称,例如:"D:/aa.xlsx"
//tablename: (可变参数)指定Excel中的某个表格名,不传默认第一个表格
func ReadExcel(filename string, tablename ... string) ([][]string,error) {
	f, err := excelize.OpenFile(filename)  //
	if err != nil {
		return nil,err
	}
	firstSheet := ""
	if len(tableau) > 0 {
		firstSheet = tableau[0]
	} else {
		firstSheet = f.GetSheetName(0)
	}
	rows, err := f.GetRows(firstSheet)
	return rows,err
	//以下为遍历数据(我个人禁用掉了)
	/*for _, row := range rows {
		for _, colCell := range row {
			fmt.Print(colCell, "\t")
		}
		fmt.Println()
	}*/
}

导入方法二 读取Excel文件流(文件类型为.xlsx格式)

//直接传入整个文件
type File interface {
	io.Reader
	io.ReaderAt
	io.Seeker
	io.Closer
}
func ReadExcelFile(file File,tableName ... string) ([][]string,error) {
	f, err := excelize.OpenReader(file)
	if err != nil {
		return nil,err
	}
	//默认读取第一个
	firstSheet := ""
	if len(tableName) > 0 {
		firstSheet = tableName[0]
	} else {
		firstSheet = f.GetSheetName(0)
	}
	rows, err := f.GetRows(firstSheet)
	return rows,err
}

导出方法一 ,限制工作簿每页条数,避免数据过多导致导出出现问题

func WriteExcel(filename string, value [][]string, tableName ...string) error {
	f := excelize.NewFile()
	//默认Excel每个页面保存500条数据,超出500条就新建一个页面保存,page为每页最多保存条数
	page := 500
	//默认保存开始名称
	firstSheet := "Sheet"
	if len(tableName) > 0 {
		firstSheet = tableName[0]
	}
	// Create a new sheet.
	sheetRow := int(math.Floor(float64(len(value)/page)) + 1)
	for j := 0; j < sheetRow; j++ {
		index := f.NewSheet(firstSheet + gconv.String(j+1))
		if j > 0 {
			for k, v := range value[0] { //列
				path, err := excelize.ColumnNumberToName(k + 1)
				if err != nil {
					return err
				}
				err = f.SetCellValue(firstSheet+gconv.String(j+1), path+gconv.String(1), v)
				if err != nil {
					return err
				}
			}
			for i := 0 + j*page; i < (j+1)*page; i++ { //行
				if len(value) < i+1 {
					break
				}
				for k, v := range value[i] { //列
					path, err := excelize.ColumnNumberToName(k + 1)
					if err != nil {
						return err
					}
					err = f.SetCellValue(firstSheet+gconv.String(j+1), path+gconv.String(i+2-j*page), v)
					if err != nil {
						return err
					}
				}
			}
		} else {
			for i := 0 + j*page; i < (j+1)*page; i++ { //行
				if len(value) < i+1 {
					break
				}
				for k, v := range value[i] { //列
					path, err := excelize.ColumnNumberToName(k + 1)
					if err != nil {
						return err
					}
					err = f.SetCellValue(firstSheet+gconv.String(j+1), path+gconv.String(i+1-j*page), v)
					if err != nil {
						return err
					}
				}
			}
		}
		f.SetActiveSheet(index - 1)
	}
	if err := f.SaveAs(filename); err != nil {
		return err
	}
	return nil
}

导入示例

controller中,我是使用的goframe框架

func import(r *ghttp.Request) {
	//首先,获取form-data传过来的excel文件数据
	file := r.GetUploadFile("file")
	if file == nil {
		fmt.Println("上传文件不能为空")
	}
	/*if file.Size > maxSize {
		fmt.Println("上传文件不能超过1G")
	}*/
	//验证文件类型
	filesuffix := path.Ext(file.Filename)   // 文件类型
	if filesuffix != ".xlsx" {
		fmt.Println("文件类型错误")
	}
	open, err := file.Open()
	if err != nil {
		fmt.Println("打开文件失败")
	}
	//我个人使用的方法二,默认打开一个,所以不传表格名了
	res, err := utils.ReadExcelFile(open)
	if err != nil {
		fmt.Println("打开文件第一个表格失败")
	}
	//已获取到excel的sheet1表的数据,然后传到service处理就行了(处理方法就不贴出来了)
	if result, err := service.file.DealExcelSave(r.Context(), res); err != nil {
		response.JsonExit(r, 400, err.Error())
	} else {
		response.JsonExitOK(r, result)
	}
}

导出示例

func (s *Api) Export(r *ghttp.Request) {
	//获取数据
	var detailReq *Req
	if err := r.Parse(&detailReq); err != nil {
		response.JsonExit(r, 400, err.Error())
	}
	list, err := service.Data.Data(detailReq)
	if err != nil {
		response.JsonExit(r, 400, err.Error())
	}
	//创建临时目录,并在结束后删除
	tempDir, err := ioutil.TempDir("", "excel-")
	if err != nil {
		response.JsonExit(r, 400, err.Error())
	}
	defer os.RemoveAll(tempDir)
	file, err := ioutil.TempFile(tempDir, "excel-*.xlsx")
	if err != nil {
		response.JsonExit(r, 400, err.Error())
	}
	defer os.Remove(file.Name())
	writer := r.Response.ResponseWriter
	req := r.Request
	path := file.Name() //放置在临时文件夹
	err = service.Report.DealExport(path, list, detailReq)
	if err != nil {
		response.JsonExit(r, 400, err.Error())
	}
	//utils.WriteExcel(path,[][]string{{"A1","A2"},{"B1","B2"}})
	http.ServeFile(writer, req, path)
}

func (s *reportService) DealBillchargeDetailReportExport(path string, data []Data, req *Req) error {
	var result [][]string //二位数组,里面的一维数组按照excle排列
	//中间过程胜率,按业务需求给result添加数据就行了
	//最后,使用工具包,导出excle文件
	err = utils.WriteExcel(path, result)
	if err != nil {
		return err
	}
	return nil
}