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表中纯数字格式和在数据库中呈现纯数字,操作如下: 完成即可. 导出取决于导入的内容排版.
随机推荐
- null、undefined和NaN的区别
未定义的值和定义未赋值的值是undefined: null是一种特殊的Object,可以给变量赋一个值null,来清除变量的值: NaN是一种特殊的number:
- Android自定义可拖动的悬浮按钮
在页面上随意拖动的按钮 public class MoveScaleRotateView extends RelativeLayout { private Context mContext; //默认 ...
- 中国区 Azure 服务和定价模式概述
由世纪互联运营的 Microsoft Azure 是第一个在中国正式商用,符合中国政府相关法规要求的国际化公有云服务.本文剖析了由世纪互联运营的 Microsoft Azure 的运营模式.采购模式. ...
- vijos 1320 清点人数
背景 NK中学组织同学们去五云山寨参加社会实践活动,按惯例要乘坐火车去.由于NK中学的学生很多,在火车开之前必须清点好人数. 描述 初始时,火车上没有学生:当同学们开始上火车时,年级主任从第一节车厢出 ...
- LibreOJ #107. 维护全序集
内存限制:256 MiB 时间限制:1000 ms 标准输入输出 题目类型:传统 评测方式:文本比较 上传者: 匿名 splay模板题 屠龙宝刀点击就送 #include <cstdio&g ...
- WPF中,DataGrid最左边多出一行的解决方案
这种情况下,请在DataGrid的属性里加上这个属性: RowHeaderWidth="0" 必须赋值为0,不能不赋值,也不能赋其他值. 问题解决.
- java面试题(杨晓峰)---第四讲强引用、软引用、弱引用、幻想引用有什么区别?
在java语言中,除了原始数据类型的变量,其他所有都是所谓的引用类型,指向各种不同的对象,理解引用对于掌握java对象生命周期和JVM内部相关机制非常有帮助. 今天问题:强引用.软引用.弱引用.幻想引 ...
- [机器视觉] SIFT特征-尺度不变特征理解
SIFT特征-尺度不变特征理解 简介 SIFT,即尺度不变特征变换(Scale-invariant feature transform,SIFT),是用于图像处理领域的一种描述.这种描述具有尺度不变性 ...
- 《剑指offer》39题—数组中出现次数超过一半的数字
题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2. ...
- Mybatis中关于OGNL表达式冲突
注意设计表字段不能用bor xor and band eq neq lt gt lte gte shl shr ushr