当前位置:   article > 正文

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

golang csv

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

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

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

xy1.csv文件

  1. 日期 最高温度 最低温度 天气 风力风向 空气质量
  2. 2023-01-01 周日 4° 0° 多云~阴 东北风1256 重度
  3. 2023-01-02 周一 6° -4° 多云~晴 东风1285 重度
  4. 2023-01-03 周二 7° -3° 多云~阴 东北风1296 重度
  5. 2023-01-04 周三 6° -2° 多云~阴 东风1361 严重
  6. 2023-01-05 周四 8° -2° 多云~晴 东南风1368 严重
  7. 2023-01-06 周五 14° -2° 晴 西南风2174 中度
  8. 2023-01-07 周六 14° -2° 晴 东北风1163 中度
  9. 2023-01-08 周日 12° -3° 晴 东风1224 重度

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

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

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

一、问题版本

解决的难题,

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

2.自动化事项

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

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

  1. package main
  2. import (
  3. "bytes"
  4. "encoding/csv"
  5. "fmt"
  6. "github.com/xuri/excelize/v2"
  7. "golang.org/x/text/encoding/simplifiedchinese"
  8. "golang.org/x/text/transform"
  9. "io"
  10. "io/ioutil"
  11. "strings"
  12. )
  13. // 生成表格数据
  14. func creatxlsx(lists [][]string) {
  15. //f, err := excelize.OpenFile("施工日志模版.xlsx", excelize.Options{Password: "password"})
  16. f, err := excelize.OpenFile("施工日志模版.xlsx")
  17. if err != nil {
  18. return
  19. }
  20. for num, item := range lists {
  21. year_xq := item[0]
  22. year_xq_slices := strings.Split(year_xq, " ")
  23. year := year_xq_slices[0]
  24. //需要把2016-4-23修改年的格式为 2016423
  25. year_lists := strings.Split(year, "-")
  26. newyea := year_lists[0]
  27. newmon := year_lists[1]
  28. newday := year_lists[2]
  29. newyear_fomat := fmt.Sprintf("%s年%s月%s日", newyea, newmon, newday)
  30. xq := year_xq_slices[1]
  31. //xq := year_xq_slices[1]
  32. //=====================================
  33. zg := item[1]
  34. zd := item[2]
  35. tq := item[3]
  36. fengli := item[4]
  37. //sheetname 201302
  38. //fmt.Println("year===>", year)
  39. index, err := f.NewSheet(year)
  40. if err != nil {
  41. fmt.Println(err)
  42. return
  43. }
  44. err = f.CopySheet(num, index)
  45. if err != nil {
  46. return
  47. }
  48. //获取每个单元表
  49. evesheet := f.GetSheetName(num)
  50. f.SetCellValue(evesheet, "I7", tq)
  51. f.SetCellValue(evesheet, "I8", fengli)
  52. f.SetCellValue(evesheet, "I9", zg)
  53. f.SetCellValue(evesheet, "I10", zd)
  54. //表格中 年的位置 星期的位置
  55. f.SetCellValue(evesheet, "P6", newyear_fomat)
  56. f.SetCellValue(evesheet, "X6", xq)
  57. //if err := f.SaveAs("Book1.xlsx"); err != nil {
  58. // fmt.Println(err)
  59. //}
  60. }
  61. if err := f.SaveAs("Book1.xlsx"); err != nil {
  62. fmt.Println(err)
  63. }
  64. }
  65. func readcsvline2() [][]string {
  66. lists := make([][]string, 0)
  67. //file, err := os.Open("xy1.csv")
  68. file, err := ioutil.ReadFile("xy1.csv")
  69. if err != nil {
  70. fmt.Println(err)
  71. }
  72. //解决读取csv中文乱码的问题
  73. reader := csv.NewReader(transform.NewReader(bytes.NewReader(file), simplifiedchinese.GBK.NewDecoder()))
  74. reader.FieldsPerRecord = -1
  75. // csvdata, err := reader.ReadAll()
  76. for {
  77. csvdata, err := reader.Read() // 按行读取数据,可控制读取部分
  78. if err != nil && err != io.EOF {
  79. fmt.Println("Error:", err)
  80. break
  81. }
  82. if err == io.EOF {
  83. break
  84. }
  85. lists = append(lists, csvdata)
  86. //fmt.Println(csvdata)
  87. }
  88. //去掉csv文件头的那行
  89. return lists[1:]
  90. }
  91. func main() {
  92. lists := readcsvline2()
  93. creatxlsx(lists)
  94. }

代码与python项目相似:

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


二、修正版本

修正版本:

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

可以使用了 

  1. package main
  2. import (
  3. "bytes"
  4. "encoding/csv"
  5. "fmt"
  6. excelize "github.com/xuri/excelize/v2"
  7. "golang.org/x/text/encoding/simplifiedchinese"
  8. "golang.org/x/text/transform"
  9. "io"
  10. "io/ioutil"
  11. "strings"
  12. )
  13. // 生成表格数据
  14. func creatxlsx(lists [][]string) {
  15. //f, err := excelize.OpenFile("施工日志模版.xlsx", excelize.Options{Password: "password"})
  16. f, err := excelize.OpenFile("施工日志魔板.xlsx")
  17. if err != nil {
  18. return
  19. }
  20. for num, item := range lists {
  21. year_xq := item[0]
  22. year_xq_slices := strings.Split(year_xq, " ")
  23. year := year_xq_slices[0]
  24. //需要把2016-4-23修改年的格式为 2016423
  25. year_lists := strings.Split(year, "-")
  26. newyea := year_lists[0]
  27. newmon := year_lists[1]
  28. newday := year_lists[2]
  29. newyear_fomat := fmt.Sprintf("%s年%s月%s日", newyea, newmon, newday)
  30. xq := year_xq_slices[1]
  31. //xq := year_xq_slices[1]
  32. //=====================================
  33. zg := item[1]
  34. zd := item[2]
  35. tq := item[3]
  36. fengli := item[4]
  37. //sheetname 201302
  38. //fmt.Println("year===>", year)
  39. index, err := f.NewSheet(year)
  40. if err != nil {
  41. fmt.Println(err)
  42. return
  43. }
  44. err = f.CopySheet(num, index)
  45. if err != nil {
  46. return
  47. }
  48. //获取每个单元表
  49. evesheet := f.GetSheetName(index)
  50. //evesheet := f.GetSheetName(num) //错误的地方,应该是上面的index
  51. f.SetCellValue(evesheet, "I7", tq)
  52. f.SetCellValue(evesheet, "I8", fengli)
  53. f.SetCellValue(evesheet, "I9", zg)
  54. f.SetCellValue(evesheet, "I10", zd)
  55. //表格中 年的位置 星期的位置
  56. f.SetCellValue(evesheet, "P6", newyear_fomat)
  57. f.SetCellValue(evesheet, "X6", xq)
  58. //if err := f.SaveAs("Book1.xlsx"); err != nil {
  59. // fmt.Println(err)
  60. //}
  61. }
  62. if err := f.SaveAs("Book1.xlsx"); err != nil {
  63. fmt.Println(err)
  64. }
  65. }
  66. func readcsvline2() [][]string {
  67. lists := make([][]string, 0)
  68. //file, err := os.Open("xy1.csv")
  69. file, err := ioutil.ReadFile("xy1.csv")
  70. if err != nil {
  71. fmt.Println(err)
  72. }
  73. //解决读取csv中文乱码的问题
  74. reader := csv.NewReader(transform.NewReader(bytes.NewReader(file), simplifiedchinese.GBK.NewDecoder()))
  75. reader.FieldsPerRecord = -1
  76. // csvdata, err := reader.ReadAll()
  77. for {
  78. csvdata, err := reader.Read() // 按行读取数据,可控制读取部分
  79. if err != nil && err != io.EOF {
  80. fmt.Println("Error:", err)
  81. break
  82. }
  83. if err == io.EOF {
  84. break
  85. }
  86. lists = append(lists, csvdata)
  87. //fmt.Println(csvdata)
  88. }
  89. //去掉csv文件头的那行
  90. return lists[1:]
  91. }
  92. func main() {
  93. lists := readcsvline2()
  94. creatxlsx(lists)
  95. }

修正的地方 :

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

  1. package main
  2. import (
  3. "bytes"
  4. "encoding/csv"
  5. "fmt"
  6. "github.com/xuri/excelize/v2"
  7. "golang.org/x/text/encoding/simplifiedchinese"
  8. "golang.org/x/text/transform"
  9. "io"
  10. "io/ioutil"
  11. "strings"
  12. )
  13. // 生成表格数据
  14. func creatxlsx(lists [][]string) {
  15. //f, err := excelize.OpenFile("施工日志模版.xlsx", excelize.Options{Password: "password"})
  16. f, err := excelize.OpenFile("conf/施工日志模版.xlsx")
  17. if err != nil {
  18. return
  19. }
  20. for _, item := range lists {
  21. year_xq := item[0]
  22. year_xq_slices := strings.Split(year_xq, " ")
  23. //2016-4-23
  24. year := year_xq_slices[0]
  25. // 星期三
  26. xq := year_xq_slices[1]
  27. //==================================
  28. //需要把2016-4-23修改年的格式为 2016423
  29. year_lists := strings.Split(year, "-")
  30. newyea := year_lists[0]
  31. newmon := year_lists[1]
  32. newday := year_lists[2]
  33. newyear_fomat := fmt.Sprintf("%s年%s月%s日", newyea, newmon, newday)
  34. //xq := year_xq_slices[1]
  35. //=====================================
  36. //最高温度,最低温度,天气,风力
  37. zg := item[1]
  38. zd := item[2]
  39. tq := item[3]
  40. fengli := item[4]
  41. //sheetname 201302
  42. //fmt.Println("year===>", year)
  43. //创建sheet表的名称为 2016-4-23 的表名
  44. index, err := f.NewSheet(year)
  45. if err != nil {
  46. fmt.Println(err)
  47. return
  48. }
  49. //复制序列号 0 的索引[需要的模版]到新的索引的位置
  50. err = f.CopySheet(0, index)
  51. //err = f.CopySheet(num, index)
  52. if err != nil {
  53. return
  54. }
  55. //获取每个单元表,获取新建sheet表的index,在这里获取每个单元格的sheet
  56. evesheet := f.GetSheetName(index)
  57. //设置单元格的值
  58. f.SetCellValue(evesheet, "I7", tq)
  59. f.SetCellValue(evesheet, "I8", fengli)
  60. f.SetCellValue(evesheet, "I9", zg)
  61. f.SetCellValue(evesheet, "I10", zd)
  62. //表格中 年的位置 星期的位置
  63. f.SetCellValue(evesheet, "P6", newyear_fomat)
  64. f.SetCellValue(evesheet, "X6", xq)
  65. //if err := f.SaveAs("Book1.xlsx"); err != nil {
  66. // fmt.Println(err)
  67. //}
  68. }
  69. if err := f.SaveAs("Book1.xlsx"); err != nil {
  70. fmt.Println(err)
  71. }
  72. fmt.Println("数据处理完毕。")
  73. }
  74. func readcsvline2(csvname string) [][]string {
  75. lists := make([][]string, 0)
  76. //file, err := os.Open("xy1.csv")
  77. //打开csv文件的内容
  78. file, err := ioutil.ReadFile(csvname)
  79. //file, err := ioutil.ReadFile("xy1.csv")
  80. if err != nil {
  81. fmt.Println(err)
  82. }
  83. //解决读取csv中文乱码的问题
  84. reader := csv.NewReader(transform.NewReader(bytes.NewReader(file), simplifiedchinese.GBK.NewDecoder()))
  85. reader.FieldsPerRecord = -1
  86. // csvdata, err := reader.ReadAll()
  87. for {
  88. csvdata, err := reader.Read() // 按行读取数据,可控制读取部分
  89. if err != nil && err != io.EOF {
  90. fmt.Println("Error:", err)
  91. break
  92. }
  93. if err == io.EOF {
  94. break
  95. }
  96. lists = append(lists, csvdata)
  97. //fmt.Println(csvdata)
  98. }
  99. //去掉csv文件头的那行
  100. return lists[1:]
  101. }
  102. func main() {
  103. for {
  104. var csvname string
  105. fmt.Println("请输入城市的天气csv表名称[q :退出]:")
  106. fmt.Scan(&csvname)
  107. if !strings.HasSuffix(csvname, ".csv") {
  108. fmt.Println("输入文件后缀错误,必须是*.CSV文件")
  109. break
  110. }
  111. //判断输出的是Q 还是 q ,都是通过字符串转换后都是小写进行判断
  112. newcsvnamne := strings.ToLower(csvname)
  113. if newcsvnamne == "q" {
  114. break
  115. }
  116. lists := readcsvline2(csvname)
  117. creatxlsx(lists)
  118. }
  119. }

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

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

  1. package main
  2. import (
  3. "bytes"
  4. "encoding/csv"
  5. "fmt"
  6. "github.com/xuri/excelize/v2"
  7. "golang.org/x/text/encoding/simplifiedchinese"
  8. "golang.org/x/text/transform"
  9. "io"
  10. "io/ioutil"
  11. "strings"
  12. "time"
  13. )
  14. // 定义读取的csv文件的字段信息
  15. type Csvfield struct {
  16. Yead_week string
  17. Zg string
  18. Zd string
  19. Tq string
  20. Fengli string
  21. Zhiliang string
  22. }
  23. // 生成表格数据,升级版本,对应readcsvline2Dic的未文件
  24. func creatxlsxU1(lists []Csvfield) {
  25. //f, err := excelize.OpenFile("施工日志模版.xlsx", excelize.Options{Password: "password"})
  26. f, err := excelize.OpenFile("conf/施工日志模版.xlsx")
  27. if err != nil {
  28. return
  29. }
  30. for _, item := range lists {
  31. year_xq := item.Yead_week
  32. year_xq_slices := strings.Split(year_xq, " ")
  33. //2016-4-23
  34. year := year_xq_slices[0]
  35. // 星期三
  36. xq := year_xq_slices[1]
  37. //==================================
  38. //需要把2016-4-23修改年的格式为 2016423
  39. year_lists := strings.Split(year, "-")
  40. newyea := year_lists[0]
  41. newmon := year_lists[1]
  42. newday := year_lists[2]
  43. newyear_fomat := fmt.Sprintf("%s年%s月%s日", newyea, newmon, newday)
  44. //xq := year_xq_slices[1]
  45. //=====================================
  46. //最高温度,最低温度,天气,风力
  47. zg := item.Zg
  48. zd := item.Zd
  49. tq := item.Tq
  50. fengli := item.Fengli
  51. //sheetname 201302
  52. //fmt.Println("year===>", year)
  53. //创建sheet表的名称为 2016-4-23 的表名
  54. index, err := f.NewSheet(year)
  55. if err != nil {
  56. fmt.Println(err)
  57. return
  58. }
  59. //复制序列号 0 的索引[需要的模版]到新的索引的位置
  60. err = f.CopySheet(0, index)
  61. //err = f.CopySheet(num, index)
  62. if err != nil {
  63. return
  64. }
  65. //获取每个单元表,获取新建sheet表的index,在这里获取每个单元格的sheet
  66. evesheet := f.GetSheetName(index)
  67. //设置单元格的值
  68. f.SetCellValue(evesheet, "I7", tq)
  69. f.SetCellValue(evesheet, "I8", fengli)
  70. f.SetCellValue(evesheet, "I9", zg)
  71. f.SetCellValue(evesheet, "I10", zd)
  72. //表格中 年的位置 星期的位置
  73. f.SetCellValue(evesheet, "P6", newyear_fomat)
  74. f.SetCellValue(evesheet, "X6", xq)
  75. }
  76. //文件名的组成方式target_36.xlsx文件名
  77. inttime := time.Now().Second()
  78. timestr := fmt.Sprintf("%02d", inttime)
  79. saveExcelname := "target_" + timestr + ".xlsx"
  80. if err := f.SaveAs(saveExcelname); err != nil {
  81. fmt.Println(err)
  82. }
  83. fmt.Println("数据处理完毕。")
  84. }
  85. // 返回[]Csvfield 方式 ,升级版本,以结构体方式进行
  86. func readcsvline2Dic(csvname string) []Csvfield {
  87. lists := make([]Csvfield, 0)
  88. //file, err := os.Open("xy1.csv")
  89. //打开csv文件的内容
  90. file, err := ioutil.ReadFile(csvname)
  91. //file, err := ioutil.ReadFile("xy1.csv")
  92. if err != nil {
  93. fmt.Println(err)
  94. }
  95. //解决读取csv中文乱码的问题
  96. reader := csv.NewReader(transform.NewReader(bytes.NewReader(file), simplifiedchinese.GBK.NewDecoder()))
  97. reader.FieldsPerRecord = -1
  98. // csvdata, err := reader.ReadAll()
  99. for {
  100. csvdata, err := reader.Read() // 按行读取数据,可控制读取部分
  101. if err != nil && err != io.EOF {
  102. fmt.Println("Error:", err)
  103. break
  104. }
  105. if err == io.EOF {
  106. break
  107. }
  108. //数据组装到结构体中
  109. stc1 := Csvfield{Yead_week: csvdata[0],
  110. Zg: csvdata[1],
  111. Zd: csvdata[2],
  112. Tq: csvdata[3],
  113. Fengli: csvdata[4],
  114. Zhiliang: csvdata[5],
  115. }
  116. lists = append(lists, stc1)
  117. //fmt.Println(csvdata)
  118. }
  119. //跳过csv首行 字段头部分
  120. return lists[1:]
  121. }
  122. // 测试代码
  123. func creatxlsxU2(lists []Csvfield) {
  124. for i, item := range lists {
  125. //fmt.Println(i, "====>", item)xy5
  126. fmt.Printf("%T%T", i, item)
  127. fmt.Println(item.Yead_week)
  128. }
  129. }
  130. func main() {
  131. //struct版本---->新的内容
  132. for {
  133. var csvname string
  134. fmt.Println("请输入城市的天气csv表名称[q :退出]:")
  135. fmt.Scan(&csvname)
  136. if !strings.HasSuffix(csvname, ".csv") {
  137. fmt.Println("输入文件后缀错误,必须是*.CSV文件")
  138. break
  139. }
  140. //判断输出的是Q 还是 q ,都是通过字符串转换后都是小写进行判断
  141. newcsvnamne := strings.ToLower(csvname)
  142. if newcsvnamne == "q" {
  143. break
  144. }
  145. lists := readcsvline2Dic(csvname)
  146. //fmt.Println(lists)
  147. creatxlsxU1(lists)
  148. }
  149. }

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

编译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

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/624876
推荐阅读
相关标签
  

闽ICP备14008679号