您现在的位置是:首页 >技术教程 >golang 读取csv文件到excel--推荐使用【不同实现方式】网站首页技术教程

golang 读取csv文件到excel--推荐使用【不同实现方式】

雨师@ 2024-09-26 00:01:02
简介golang 读取csv文件到excel--推荐使用【不同实现方式】

 需求:把下面的csv文件,自动写入到excel模版中,

1.自动按照csv的行数,以日期时间名问sheet名成写入到excel表的sheet名称中

2.自动复制excel的第一个sheet的所有内容,同时用csv文件的内容填充特定区域内容

xy1.csv文件

日期	最高温度	最低温度	天气	风力风向	空气质量
2023-01-01 周日	4°	0°	多云~阴	东北风1级	256 重度
2023-01-02 周一	6°	-4°	多云~晴	东风1级	285 重度
2023-01-03 周二	7°	-3°	多云~阴	东北风1级	296 重度
2023-01-04 周三	6°	-2°	多云~阴	东风1级	361 严重
2023-01-05 周四	8°	-2°	多云~晴	东南风1级	368 严重
2023-01-06 周五	14°	-2°	晴	西南风2级	174 中度
2023-01-07 周六	14°	-2°	晴	东北风1级	163 中度
2023-01-08 周日	12°	-3°	晴	东风1级	224 重度

 xx.xlsx文件[模版文件],需要依托这个excel模版进行复制N个sheet表格,把上面的csv文件填充进去

=================

不同版本,不同方式测试,建议参看结构体方式

一、问题版本

解决的难题,

1.解决读取中文乱码的问题;

2.自动化事项

读取csv文件到excel文件中,批量自动化设置

待解决的问题,文件名称的时间与表里时间不一致的问题

package main

import (
	"bytes"
	"encoding/csv"
	"fmt"
	"github.com/xuri/excelize/v2"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"
	"io"
	"io/ioutil"
	"strings"
)

// 生成表格数据
func creatxlsx(lists [][]string) {

	//f, err := excelize.OpenFile("施工日志模版.xlsx", excelize.Options{Password: "password"})
	f, err := excelize.OpenFile("施工日志模版.xlsx")
	if err != nil {
		return
	}

	for num, item := range lists {
		year_xq := item[0]
		year_xq_slices := strings.Split(year_xq, " ")

		year := year_xq_slices[0]

		//需要把2016-4-23修改年的格式为 2016年4月23日

		year_lists := strings.Split(year, "-")
		newyea := year_lists[0]
		newmon := year_lists[1]
		newday := year_lists[2]

		newyear_fomat := fmt.Sprintf("%s年%s月%s日", newyea, newmon, newday)
		xq := year_xq_slices[1]
		//xq := year_xq_slices[1]
		//=====================================
		zg := item[1]
		zd := item[2]
		tq := item[3]
		fengli := item[4]

		//sheetname  201302
		//fmt.Println("year===>", year)
		index, err := f.NewSheet(year)
		if err != nil {
			fmt.Println(err)
			return
		}
		err = f.CopySheet(num, index)
		if err != nil {
			return
		}
		//获取每个单元表
		evesheet := f.GetSheetName(num)
		f.SetCellValue(evesheet, "I7", tq)
		f.SetCellValue(evesheet, "I8", fengli)
		f.SetCellValue(evesheet, "I9", zg)
		f.SetCellValue(evesheet, "I10", zd)

		//表格中  年的位置    星期的位置
		f.SetCellValue(evesheet, "P6", newyear_fomat)
		f.SetCellValue(evesheet, "X6", xq)

		//if err := f.SaveAs("Book1.xlsx"); err != nil {
		//	fmt.Println(err)
		//}

	}
	if err := f.SaveAs("Book1.xlsx"); err != nil {
		fmt.Println(err)
	}

}

func readcsvline2() [][]string {
	lists := make([][]string, 0)

	//file, err := os.Open("xy1.csv")
	file, err := ioutil.ReadFile("xy1.csv")
	if err != nil {
		fmt.Println(err)
	}
	//解决读取csv中文乱码的问题
	reader := csv.NewReader(transform.NewReader(bytes.NewReader(file), simplifiedchinese.GBK.NewDecoder()))
	reader.FieldsPerRecord = -1
	// csvdata, err := reader.ReadAll()

	for {
		csvdata, err := reader.Read() // 按行读取数据,可控制读取部分

		if err != nil && err != io.EOF {
			fmt.Println("Error:", err)
			break
		}

		if err == io.EOF {
			break
		}
		lists = append(lists, csvdata)
		//fmt.Println(csvdata)
	}
	//去掉csv文件头的那行
	return lists[1:]

}

func main() {

	lists := readcsvline2()

	creatxlsx(lists)

}

代码与python项目相似:

https://ht666666.blog.csdn.net/article/details/130973792?spm=1001.2014.3001.5502


二、修正版本

修正版本:

下面的版本完全可以使用了

可以使用了 

package main

import (
	"bytes"
	"encoding/csv"
	"fmt"
	excelize "github.com/xuri/excelize/v2"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"
	"io"
	"io/ioutil"
	"strings"
)

// 生成表格数据
func creatxlsx(lists [][]string) {

	//f, err := excelize.OpenFile("施工日志模版.xlsx", excelize.Options{Password: "password"})
	f, err := excelize.OpenFile("施工日志魔板.xlsx")
	if err != nil {
		return
	}

	for num, item := range lists {
		year_xq := item[0]
		year_xq_slices := strings.Split(year_xq, " ")

		year := year_xq_slices[0]

		//需要把2016-4-23修改年的格式为 2016年4月23日

		year_lists := strings.Split(year, "-")
		newyea := year_lists[0]
		newmon := year_lists[1]
		newday := year_lists[2]

		newyear_fomat := fmt.Sprintf("%s年%s月%s日", newyea, newmon, newday)
		xq := year_xq_slices[1]
		//xq := year_xq_slices[1]
		//=====================================
		zg := item[1]
		zd := item[2]
		tq := item[3]
		fengli := item[4]

		//sheetname  201302
		//fmt.Println("year===>", year)
		index, err := f.NewSheet(year)
		if err != nil {
			fmt.Println(err)
			return
		}
		err = f.CopySheet(num, index)
		if err != nil {
			return
		}
		//获取每个单元表
		evesheet := f.GetSheetName(index)
		//evesheet := f.GetSheetName(num)   //错误的地方,应该是上面的index
		f.SetCellValue(evesheet, "I7", tq)
		f.SetCellValue(evesheet, "I8", fengli)
		f.SetCellValue(evesheet, "I9", zg)
		f.SetCellValue(evesheet, "I10", zd)

		//表格中  年的位置    星期的位置
		f.SetCellValue(evesheet, "P6", newyear_fomat)
		f.SetCellValue(evesheet, "X6", xq)

		//if err := f.SaveAs("Book1.xlsx"); err != nil {
		//	fmt.Println(err)
		//}

	}
	if err := f.SaveAs("Book1.xlsx"); err != nil {
		fmt.Println(err)
	}

}

func readcsvline2() [][]string {
	lists := make([][]string, 0)

	//file, err := os.Open("xy1.csv")
	file, err := ioutil.ReadFile("xy1.csv")
	if err != nil {
		fmt.Println(err)
	}
	//解决读取csv中文乱码的问题
	reader := csv.NewReader(transform.NewReader(bytes.NewReader(file), simplifiedchinese.GBK.NewDecoder()))
	reader.FieldsPerRecord = -1
	// csvdata, err := reader.ReadAll()

	for {
		csvdata, err := reader.Read() // 按行读取数据,可控制读取部分

		if err != nil && err != io.EOF {
			fmt.Println("Error:", err)
			break
		}

		if err == io.EOF {
			break
		}
		lists = append(lists, csvdata)
		//fmt.Println(csvdata)
	}
	//去掉csv文件头的那行
	return lists[1:]

}

func main() {

	lists := readcsvline2()

	creatxlsx(lists)

}

修正的地方 :

三、优化版本【可以使用了--推荐】

package main

import (
	"bytes"
	"encoding/csv"
	"fmt"
	"github.com/xuri/excelize/v2"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"
	"io"
	"io/ioutil"
	"strings"
)

// 生成表格数据
func creatxlsx(lists [][]string) {

	//f, err := excelize.OpenFile("施工日志模版.xlsx", excelize.Options{Password: "password"})
	f, err := excelize.OpenFile("conf/施工日志模版.xlsx")
	if err != nil {
		return
	}

	for _, item := range lists {
		year_xq := item[0]
		year_xq_slices := strings.Split(year_xq, " ")

		//2016-4-23
		year := year_xq_slices[0]
		//  星期三
		xq := year_xq_slices[1]
		//==================================
		//需要把2016-4-23修改年的格式为 2016年4月23日

		year_lists := strings.Split(year, "-")
		newyea := year_lists[0]
		newmon := year_lists[1]
		newday := year_lists[2]

		newyear_fomat := fmt.Sprintf("%s年%s月%s日", newyea, newmon, newday)

		//xq := year_xq_slices[1]
		//=====================================
		//最高温度,最低温度,天气,风力
		zg := item[1]
		zd := item[2]
		tq := item[3]
		fengli := item[4]

		//sheetname  201302
		//fmt.Println("year===>", year)

		//创建sheet表的名称为 2016-4-23 的表名
		index, err := f.NewSheet(year)
		if err != nil {
			fmt.Println(err)
			return
		}
		//复制序列号 0 的索引[需要的模版]到新的索引的位置
		err = f.CopySheet(0, index)
		//err = f.CopySheet(num, index)
		if err != nil {
			return
		}
		//获取每个单元表,获取新建sheet表的index,在这里获取每个单元格的sheet
		evesheet := f.GetSheetName(index)

		//设置单元格的值

		f.SetCellValue(evesheet, "I7", tq)
		f.SetCellValue(evesheet, "I8", fengli)
		f.SetCellValue(evesheet, "I9", zg)
		f.SetCellValue(evesheet, "I10", zd)

		//表格中  年的位置    星期的位置
		f.SetCellValue(evesheet, "P6", newyear_fomat)
		f.SetCellValue(evesheet, "X6", xq)

		//if err := f.SaveAs("Book1.xlsx"); err != nil {
		//	fmt.Println(err)
		//}

	}
	if err := f.SaveAs("Book1.xlsx"); err != nil {
		fmt.Println(err)
	}
	fmt.Println("数据处理完毕。")

}

func readcsvline2(csvname string) [][]string {

	lists := make([][]string, 0)

	//file, err := os.Open("xy1.csv")
	//打开csv文件的内容
	file, err := ioutil.ReadFile(csvname)
	//file, err := ioutil.ReadFile("xy1.csv")
	if err != nil {
		fmt.Println(err)
	}
	//解决读取csv中文乱码的问题
	reader := csv.NewReader(transform.NewReader(bytes.NewReader(file), simplifiedchinese.GBK.NewDecoder()))
	reader.FieldsPerRecord = -1
	// csvdata, err := reader.ReadAll()

	for {
		csvdata, err := reader.Read() // 按行读取数据,可控制读取部分

		if err != nil && err != io.EOF {
			fmt.Println("Error:", err)
			break
		}

		if err == io.EOF {
			break
		}
		lists = append(lists, csvdata)
		//fmt.Println(csvdata)
	}
	//去掉csv文件头的那行
	return lists[1:]

}

func main() {

	for {
		var csvname string
		fmt.Println("请输入城市的天气csv表名称[q :退出]:")
		fmt.Scan(&csvname)

		if !strings.HasSuffix(csvname, ".csv") {
			fmt.Println("输入文件后缀错误,必须是*.CSV文件")
			break
		}

		//判断输出的是Q 还是	q ,都是通过字符串转换后都是小写进行判断
		newcsvnamne := strings.ToLower(csvname)
		if newcsvnamne == "q" {
			break
		}
		lists := readcsvline2(csvname)

		creatxlsx(lists)

	}

}

四、针对上面的代码优化,采用结构体方式进行重构,代码大部分重写【结构体方式】

采用结构体方式:重构了一下代码;

package main

import (
	"bytes"
	"encoding/csv"
	"fmt"
	"github.com/xuri/excelize/v2"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"
	"io"
	"io/ioutil"
	"strings"
	"time"
)

// 定义读取的csv文件的字段信息
type Csvfield struct {
	Yead_week string
	Zg        string
	Zd        string
	Tq        string
	Fengli    string
	Zhiliang  string
}

// 生成表格数据,升级版本,对应readcsvline2Dic的未文件
func creatxlsxU1(lists []Csvfield) {

	//f, err := excelize.OpenFile("施工日志模版.xlsx", excelize.Options{Password: "password"})
	f, err := excelize.OpenFile("conf/施工日志模版.xlsx")
	if err != nil {
		return
	}

	for _, item := range lists {
		year_xq := item.Yead_week
		year_xq_slices := strings.Split(year_xq, " ")

		//2016-4-23
		year := year_xq_slices[0]
		//  星期三
		xq := year_xq_slices[1]
		//==================================
		//需要把2016-4-23修改年的格式为 2016年4月23日

		year_lists := strings.Split(year, "-")
		newyea := year_lists[0]
		newmon := year_lists[1]
		newday := year_lists[2]

		newyear_fomat := fmt.Sprintf("%s年%s月%s日", newyea, newmon, newday)

		//xq := year_xq_slices[1]
		//=====================================
		//最高温度,最低温度,天气,风力
		zg := item.Zg
		zd := item.Zd
		tq := item.Tq
		fengli := item.Fengli

		//sheetname  201302
		//fmt.Println("year===>", year)

		//创建sheet表的名称为 2016-4-23 的表名
		index, err := f.NewSheet(year)
		if err != nil {
			fmt.Println(err)
			return
		}
		//复制序列号 0 的索引[需要的模版]到新的索引的位置
		err = f.CopySheet(0, index)
		//err = f.CopySheet(num, index)
		if err != nil {
			return
		}
		//获取每个单元表,获取新建sheet表的index,在这里获取每个单元格的sheet
		evesheet := f.GetSheetName(index)

		//设置单元格的值

		f.SetCellValue(evesheet, "I7", tq)
		f.SetCellValue(evesheet, "I8", fengli)
		f.SetCellValue(evesheet, "I9", zg)
		f.SetCellValue(evesheet, "I10", zd)

		//表格中  年的位置    星期的位置
		f.SetCellValue(evesheet, "P6", newyear_fomat)
		f.SetCellValue(evesheet, "X6", xq)

	}

	//文件名的组成方式target_36.xlsx文件名
	inttime := time.Now().Second()
	timestr := fmt.Sprintf("%02d", inttime)
	saveExcelname := "target_" + timestr + ".xlsx"
	if err := f.SaveAs(saveExcelname); err != nil {
		fmt.Println(err)
	}
	fmt.Println("数据处理完毕。")

}

// 返回[]Csvfield   方式 ,升级版本,以结构体方式进行
func readcsvline2Dic(csvname string) []Csvfield {

	lists := make([]Csvfield, 0)

	//file, err := os.Open("xy1.csv")
	//打开csv文件的内容
	file, err := ioutil.ReadFile(csvname)
	//file, err := ioutil.ReadFile("xy1.csv")
	if err != nil {
		fmt.Println(err)
	}
	//解决读取csv中文乱码的问题
	reader := csv.NewReader(transform.NewReader(bytes.NewReader(file), simplifiedchinese.GBK.NewDecoder()))
	reader.FieldsPerRecord = -1
	// csvdata, err := reader.ReadAll()

	for {
		csvdata, err := reader.Read() // 按行读取数据,可控制读取部分

		if err != nil && err != io.EOF {
			fmt.Println("Error:", err)
			break
		}

		if err == io.EOF {
			break
		}

		//数据组装到结构体中
		stc1 := Csvfield{Yead_week: csvdata[0],
			Zg:       csvdata[1],
			Zd:       csvdata[2],
			Tq:       csvdata[3],
			Fengli:   csvdata[4],
			Zhiliang: csvdata[5],
		}

		lists = append(lists, stc1)
		//fmt.Println(csvdata)
	}
	//跳过csv首行  字段头部分
	return lists[1:]

}

// 测试代码
func creatxlsxU2(lists []Csvfield) {
	for i, item := range lists {
		//fmt.Println(i, "====>", item)xy5
		fmt.Printf("%T%T", i, item)

		fmt.Println(item.Yead_week)
	}
}

func main() {

	//struct版本---->新的内容
	for {
		var csvname string
		fmt.Println("请输入城市的天气csv表名称[q :退出]:")
		fmt.Scan(&csvname)

		if !strings.HasSuffix(csvname, ".csv") {
			fmt.Println("输入文件后缀错误,必须是*.CSV文件")
			break

		}

		//判断输出的是Q 还是	q ,都是通过字符串转换后都是小写进行判断
		newcsvnamne := strings.ToLower(csvname)
		if newcsvnamne == "q" {
			break
		}
		lists := readcsvline2Dic(csvname)

		//fmt.Println(lists)

		creatxlsxU1(lists)

	}

}

五、编译,参加我以前写的内容;

编译exe文件+图标的链接地址:

https://ht666666.blog.csdn.net/article/details/124512392

 重点关注 :

如果打包命令不成功,需要安装mingw-w64这个软件【绿色版本解压即可使用】,关注我我的上个编译图标的链接

1.下载地址

https://sourceforge.net/projects/mingw-w64/

2.编译命令:
 

windres -o readcsvtoxlsxv2.1.syso readcsvtoxlsxv2.1.rc

windres -o  这个就是编译命令;

后面的两个

readcsvtoxlsxv2.1.syso  需要生成的文件[readcsvtoxlsxv2.1---》修改为你的程序名称]

readcsvtoxlsxv2.1.rc  ;你的第一次生成的文件

总结:

编译的时候的文件名基本都是一样的  只是后缀不一样的!

编译局题目内容见

Go在Window平台下编译出来的exe如何添加一个图标--推荐使用_雨师@的博客-CSDN博客

https://ht666666.blog.csdn.net/article/details/124512392

 

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。