免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 34714 | 回复: 25
打印 上一主题 下一主题

中文 Excel 读写终级解决方案 [复制链接]

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-12-10 11:10 |只看该作者 |倒序浏览
本帖最后由 flw 于 2011-11-06 16:34 编辑

老有人问我 excel 中文乱码的问题,
我平时很少接触这一块,
每次都得从头研究,
现在把结论记录在这里,以做备忘。


读:
  1. use strict;
  2. use warnings;

  3. use Spreadsheet::ParseExcel;
  4. use MyExcelFormatter;

  5. my $file = 'foo.xls';

  6. my $fmt = new MyExcelFormatter();

  7. my $xls = Spreadsheet::ParseExcel::Workbook->Parse( $file, $fmt );
  8. my @workSheet = @{ $xls->{Worksheet} };
  9. foreach my $sheet ( @workSheet ){
  10.     my $sheetName = $sheet->get_name();
  11.     print "工作表: $sheetName\n";

  12.     my ( $minRow, $maxRow ) = $sheet->row_range();
  13.     my ( $minCol, $maxCol ) = $sheet->col_range();

  14.     foreach my $row ( $minRow .. $maxRow ){
  15.         foreach my $col ( $minCol .. $maxCol ){
  16.             my $cell = $sheet->get_cell( $row, $col );
  17.             next unless $cell;
  18.             print " ($row,$col) ", $cell->value;
  19.         }
  20.         print "\n";
  21.     }
  22. }
复制代码
基本上上面这段代码就是从 Spreadsheet:arseExcel 的文档里抄来的。
除了 my $fmt = new MyExcelFormatter(); 这一行之外。
这一行生成了一个文档内容的转换器(格式化工具),
转换器代码如下:
  1. package MyExcelFormatter;

  2. use strict;
  3. use warnings;

  4. use base qw(Spreadsheet::ParseExcel::FmtDefault);

  5. use Encode::CN;
  6. use Encode qw(from_to);

  7. sub new() {
  8.     return bless {};
  9. }

  10. sub TextFmt( $;$ ) {
  11.     my $this = shift;
  12.     my ($value, $code) = @_;

  13.     if ( defined $code and $code eq 'ucs2' ){
  14.         from_to( $value, 'ucs2', 'gb2312' );
  15.     }
  16.     return $value;
  17. }

  18. 1;
复制代码
如法炮制以此类推,可以处理所有本地语言编码。

==================== 华丽的分割线 ====================================

写 excel,这个就更简单了:
  1. use strict;
  2. use warnings;

  3. use Spreadsheet::WriteExcel;

  4. my $workbook = new Spreadsheet::WriteExcel( 'foo.xls' );
  5. my $worksheet = $workbook->add_worksheet( T('世界你好') );

  6. $worksheet->write( 0, 0, T('干啥呢') );
复制代码
大家可以看到,完全就是抄 perldoc 文档里的例子的。
只不过,T( '世界你好' ) 看上去有点乖乖地罢了。
其实这是一个自定义函数:
  1. use Encode qw(decode);

  2. sub T {
  3.     my $text = shift;

  4.     return decode( 'gb2312', $text );
  5. }
复制代码
名字当然也可以不叫 T,叫别的也行。
完整的代码如下:
  1. use strict;
  2. use warnings;

  3. use Spreadsheet::WriteExcel;
  4. use Encode qw(decode);

  5. my $workbook = new Spreadsheet::WriteExcel( 'foo.xls' );
  6. my $worksheet = $workbook->add_worksheet( T('世界你好') );

  7. $worksheet->write( 0, 0, T('干啥呢') );

  8. sub T {
  9.     my $text = shift;

  10.     return decode( 'gb2312', $text );
  11. }
复制代码
================= 倒霉的分割线 =============================
最后再来个总结:
要点只有一个:excel 里保存的是且只能是 utf8 编码,而简体中文版的 windows 控制台和其它一些软件缺省显示的是 gb2312 编码
有些朋友在 tk 应用或者 mysql 应用中用了上面的代码,仍然看到乱码,
那是因为你没有搞明白 tk 和 mysql 的编码,所以上面的办法也不是万能的。
万能的办法就是搞清楚每个信息流的编码方案,彻底把思路搞明白了。

2011.11.06 增补:
Spreadsheet::WriteExcel 已死,Excel::Writer::XLSX 当立
http://perlbuzz.com/2011/10/spre ... xcelwriterxlsx.html

论坛徽章:
0
2 [报告]
发表于 2009-12-10 11:20 |只看该作者
good

论坛徽章:
78
双子座
日期:2013-10-15 08:50:09天秤座
日期:2013-10-16 18:02:08白羊座
日期:2013-10-18 13:35:33天蝎座
日期:2013-10-18 13:37:06狮子座
日期:2013-10-18 13:40:31双子座
日期:2013-10-22 13:58:42戌狗
日期:2013-10-22 18:50:04CU十二周年纪念徽章
日期:2013-10-24 15:41:34巨蟹座
日期:2013-10-24 17:14:56处女座
日期:2013-10-24 17:15:30双子座
日期:2013-10-25 13:49:39午马
日期:2013-10-28 15:02:15
3 [报告]
发表于 2009-12-10 11:20 |只看该作者
哇  老大出马啊  中文确实很烦人

论坛徽章:
0
4 [报告]
发表于 2009-12-10 11:22 |只看该作者
老大的示例都是精品~赞一个

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
5 [报告]
发表于 2009-12-10 11:24 |只看该作者
原帖由 yybmsrs 于 2009-12-10 11:20 发表
哇  老大出马啊  中文确实很烦人

我一点都不觉得烦人,
我觉得这是检验自己知识的一个机会。

论坛徽章:
0
6 [报告]
发表于 2009-12-10 11:28 |只看该作者
顶一个。

论坛徽章:
1
狮子座
日期:2013-12-16 16:09:24
7 [报告]
发表于 2009-12-10 12:13 |只看该作者
见老大mark

中文确实"烦人"啊,上个世纪gb2312和big5车不清楚,现在还有utf-8和gbk各占半边天,这段恩怨已经跨过10个年头了

[ 本帖最后由 ttcn_cu 于 2009-12-10 12:14 编辑 ]

论坛徽章:
1
2015亚冠之塔什干火车头
日期:2015-07-13 12:36:28
8 [报告]
发表于 2009-12-10 12:25 |只看该作者
very Good,收藏啦~

论坛徽章:
0
9 [报告]
发表于 2009-12-10 14:00 |只看该作者
收藏,学习!

论坛徽章:
1
丑牛
日期:2015-01-07 15:25:00
10 [报告]
发表于 2009-12-10 14:31 |只看该作者
好,好好学习一下~
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP