goalng导出excel(csv格式)
最近项目中有个小需求,需要将查询结果导出到excel。之间前java比较容易,使用POI很容易就能实现,查了下golang的文档,发现golang下边并没有导出excel的包,但是却有一个encoding/csv的包,看了下发现可以导出csv文件,大家都知道csv文件其实就是文本格式的excel文件,可以直接通过excel打开或是导入excel。
看起来挺好的,问题如愿解决,但是事实证明对已一个还不成熟的语言或是库最好还是先测一下的好。兴冲冲的卸了测试例子,成功导出了一个text.csv文件,一切看起来都挺好的,然而打开之后就傻眼了:中文乱码,这个问题其实比较好理解,golang只支持utf-8,而win中文版默认字符集是GB2312(gbk),这样看来直接转码就行了呗。
由于之前吃了亏,这次我们先直接报文件转下码试试:直接将之前导出的text.csv另存为ASCII格式,打开后发现回车换行符丢了,全部变成一行了。这下就郁闷了,先看下源码吧:
// Writer writes a single CSV record to w along with any necessary quoting.
// A record is a slice of strings with each string being one field.
func (w *Writer) Write(record []string) (err error) {
for n, field := range record {
if n > 0 {
if _, err = w.w.WriteRune(w.Comma); err != nil {
return
}
} // If we don't have to have a quoted field then just
// write out the field and continue to the next field.
if !w.fieldNeedsQuotes(field) {
if _, err = w.w.WriteString(field); err != nil {
return
}
continue
}
if err = w.w.WriteByte('"'); err != nil {
return
} for _, r1 := range field {
switch r1 {
case '"':
_, err = w.w.WriteString(`""`)
case '\r':
if !w.UseCRLF {
err = w.w.WriteByte('\r')
}
case '\n':
if w.UseCRLF {
_, err = w.w.WriteString("\r\n")
} else {
err = w.w.WriteByte('\n')
}
default:
_, err = w.w.WriteRune(r1)
}
if err != nil {
return
}
} if err = w.w.WriteByte('"'); err != nil {
return
}
}
if w.UseCRLF {
_, err = w.w.WriteString("\r\n")
} else {
err = w.w.WriteByte('\n')
}
return
}
可以看到代码十分简单,每行就是按照csv的格式写入文件而已。需要注意的是writer里边有一个UserCRLF来指定是否适应回车换行符,默认为false,问题应该就出在这里,但是将UserCRLF设置为true之后,问题依旧,看来是转码有问题。
既然代码这么简单,那么还不如直接自己实现,然后转码输出,这里使用iconv-go进行转码,实现如下:
package components import (
"bytes"
"errors"
iconv "github.com/djimenez/iconv-go"
) /**
* 导出处理
*/ const (
OUT_ENCODING = "gbk" //输出编码
) /**
* 导出csv格式文件,输出byte数组
* 输出编码通过OUT_ENCODING指定
*/
func ExportCsv(head []string, data [][]string) (out []byte, err error) {
if len(head) == 0 {
err = errors.New("ExportCsv Head is nil")
return
} columnCount := len(head)
dataStr := bytes.NewBufferString("")
//添加头
for index, headElem := range head {
separate := ","
if index == columnCount-1 {
separate = "\n"
}
dataStr.WriteString(headElem + separate)
} //添加数据行
for _, dataArray := range data {
if len(dataArray) != columnCount { //数据项数小于列数
err = errors.New("ExportCsv data format is error.")
}
for index, dataElem := range dataArray {
separate := ","
if index == columnCount-1 {
separate = "\n"
}
dataStr.WriteString(dataElem + separate)
}
} //处理编码
out = make([]byte, len(dataStr.Bytes()))
iconv.Convert(dataStr.Bytes(), out, "utf-8", OUT_ENCODING)
return
}
测试一下,导出成功,而且没有乱码问题。
对于目前这个项目而言,导出简单格式的csv就能满足,但是如果想导出复杂的excel文件就不行了。考虑了下大概想出了以下几种方法:
- 使用cgo,用c来实现导出,这是golang处理类似问题的一贯作风,然而就导出excel而言并不太好,因为c导出复杂格式的excel本身就挺麻烦的
- 调用其他语言实现的模块,至于怎么调就无所谓,如果对于大批量的导出,其实还挺好的,可以把生成excel这样费时费力的操作给分离出去
- 按照excel文件格式直接生成为对应二进制文件,这个实现起来可能比较费劲,但是确实一劳永逸的,这里附一个excel格式的链接,有兴趣的可以实现下。
goalng导出excel(csv格式)的更多相关文章
- (转载)DBGridEh导出Excel等格式文件
DBGridEh导出Excel等格式文件 uses DBGridEhImpExp; {--------------------------------------------------------- ...
- PHP 高效导入导出Excel(csv)方法之fgetcsv()和fputcsv()函数
CSV,是Comma Separated Value(逗号分隔值)的英文缩写,通常都是纯文本文件. 一.CSV数据导入函数fgetcsv() fgetcsv() 函数从文件指针中读入一行并解析 CSV ...
- Elasticsearch:如何把Elasticsearch中的数据导出为CSV格式的文件
本教程向您展示如何将数据从Elasticsearch导出到CSV文件. 想象一下,您想要在Excel中打开一些Elasticsearch中的数据,并根据这些数据创建数据透视表. 这只是一个用例,其中将 ...
- AX导出excel设置格式
今天在AX2009里面写一个导出EXCEL,没有模版,这是第一次碰到,之后写完之后发现导出的数据格式不对. 到处取经之后得到一下结果: 定义一个 Com range; SysExcelCells ...
- POI导入导出Excel(HSSF格式,User Model方式)
1.POI说明 Apache POI是Apache软件基金会的开源代码库, POI提供对Microsoft Office格式档案读和写的功能. POI支持的格式: HSSF - 提供读写Microso ...
- 将数据 导出excel表格式
我的考试完提交生成的数据 这是我的考试题类型 //导出调查评议的数据 public function diaocha(){ $xlsName = '表格形式 调查评议 信息'; $xlsTitle = ...
- Asp.net导出Excel/Csv文本格式数据
刚刚开始做Excel相关的项目,所以遇到的问题不管大小都给记录一下 偶然的机会在添加数据的时候全改成了数字,结果输出的时候全自动变成了科学计数法,这是excel的强大功能,能自动识别数字和字符串,太聪 ...
- mongodb导出数据csv格式
mongoexport -d test -c item --type=csv -f salary,city,workYear,companyShortName -o user.csvmongoexpo ...
- c# 导入导出excel表格式
c#使用代码导入excel时,当遇到纯数字且大于15位时会出现编码混乱(表现为科学计数法),要想呈现与excel表中纯数字格式和在数据库中呈现纯数字,操作如下: 完成即可. 导出取决于导入的内容排版.
随机推荐
- 使用CRA开发的基于React的UI组件发布到内网NPM上去
前言:构建的ES组件使用CNPM发布内网上过程 1. 使用Create-React-APP开的组件 如果直接上传到NPM,你引用的时候会报: You may need an appropriate l ...
- GDI绘制图形的使用_验证码
//创建GDI对象 Graphics g = this.CreateGraphics();// new Graphics(); //创建画笔对象 Pen pen = new Pen(Brushes.R ...
- 修改datatable列
var dt = dh.GetPageTable("tabelename"); dt.Columns["TBLNO"].ColumnName = "业 ...
- jvm 内存dump、gc查看、线程死锁,jmap、jstack、jstat
1. jstat 这个命令对于查看Jvm的堆栈信息很有用.能够查看eden,survivor,old,perm等heap的capacity,utility信息 对于查看系统是不是有能存泄漏以及 ...
- 实例——省市区三级联动 & 还可以输入字符统计
1 省市区三级联动 html代码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8" ...
- Myeclipse发布第一个jsp页面及web project部署到tomcat上的几种方法
菜鸟日记: 1:new web project: 2:fix the visiting path of the tomcat,打开在安装目录下conf目录中的server.xml,在</Hos ...
- iOS开发 - Protocol协议及委托代理(Delegate)
因为Object-C是不支持多继承的,所以很多时候都是用Protocol(协议)来代替.Protocol(协议)只能定义公用的一套接口,但不能提供具体的实现方法.也就是说,它只告诉你要做什么,但具体怎 ...
- 给VS2008 打补丁
vs2003到2008各版本如下: vs.net2003 Visual Studio .NET 2003 Enterprise Architect Visual Studio .NET 2003 En ...
- UVA 11552 Fewest Flops(区间dp)
一个区间一个区间的考虑,当前区间的决策只和上一次的末尾有关,考虑转移的时候先统计当前区间出现过的字母以及种数ct 枚举上一个区间的末尾标号j,规定小于INF为合法状态,确定j之后看j有没有在当前的区间 ...
- C# 获取Google Chrome的书签
其实这个很简单,就是读取一个在用户目录里面的一个Bookmarks文件就好了. 先建立几个实体类 public class GoogleChrome_bookMark_meta_info { publ ...