老有人问我 excel 中文乱码的问题,
我平时很少接触这一块,
每次都得从头研究,
现在把结论记录在这里,以做备忘。
读:
- use?strict; ?
- use?warnings; ?
- ?
- use?Spreadsheet::ParseExcel; ?
- use?MyExcelFormatter; ?
- ?
-
my?$file?=?'foo.xls'; ?
- ?
- my?$fmt?=?new?MyExcelFormatter(); ?
- ?
- my?$xls?=?Spreadsheet::ParseExcel::Workbook->Parse(?$file,?$fmt?); ?
- my?@workSheet?=?@{?$xls->{Worksheet}?}; ?
- foreach?my?$sheet?(?@workSheet?){ ?
- ????my?$sheetName?=?$sheet->get_name(); ?
-
????print?"工作表:?$sheetNamen"; ?
- ?
- ????my?(?$minRow,?$maxRow?)?=?$sheet->row_range(); ?
- ????my?(?$minCol,?$maxCol?)?=?$sheet->col_range(); ?
- ?
- ????foreach?my?$row?(?$minRow?..?$maxRow?){ ?
- ????????foreach?my?$col?(?$minCol?..?$maxCol?){ ?
- ????????????my?$cell?=?$sheet->get_cell(?$row,?$col?); ?
-
????????????next?unless?$cell; ?
-
????????????print?"?($row,$col)?",?$cell->value; ?
- ????????} ?
-
????????print?"n"; ?
- ????} ?
- }?
?基本上上面这段代码就是从 Spreadsheet::ParseExcel 的文档里抄来的。
除了 my $fmt = new MyExcelFormatter(); 这一行之外。
这一行生成了一个文档内容的转换器(格式化工具),
转换器代码如下:
- package?MyExcelFormatter; ?
- ?
- use?strict; ?
- use?warnings; ?
- ?
- use?base?qw(Spreadsheet::ParseExcel::FmtDefault); ?
- ?
- use?Encode::CN; ?
- use?Encode?qw(from_to); ?
- ?
- sub?new()?{ ?
-
????return?bless?{}; ?
- } ?
- ?
- sub?TextFmt(?$;$?)?{ ?
- ????my?$this?=?shift; ?
- ????my?($value,?$code)?=?@_; ?
- ?
-
????if?(?defined?$code?and?$code?eq?'ucs2'?){ ?
-
????????from_to(?$value,?'ucs2',?'gb2312'?); ?
- ????} ?
-
????return?$value; ?
- } ?
-
??
如法炮制以此类推,可以处理所有本地语言编码。
写 excel,这个就更简单了:
- use?strict; ?
- use?warnings; ?
- ?
- use?Spreadsheet::WriteExcel; ?
- ?
-
my?$workbook?=?new?Spreadsheet::WriteExcel(?'foo.xls'?); ?
-
my?$worksheet?=?$workbook->add_worksheet(?T('世界你好')?); ?
- ?
-
$worksheet->write(?0,?0,?T('干啥呢')?);?
大家可以看到,完全就是抄 perldoc 文档里的例子的。
只不过,T( '世界你好' ) 看上去有点怪怪的罢了。
其实这是一个自定义函数:
- use?Encode?qw(decode); ?
- ?
- sub?T?{ ?
- ????my?$text?=?shift; ?
- ?
-
????return?decode(?'gb2312',?$text?); ?
- }?
名字当然也可以不叫 T,叫别的也行。
完整的代码如下:
- use?strict; ?
- use?warnings; ?
- ?
- use?Spreadsheet::WriteExcel; ?
- use?Encode?qw(decode); ?
- ?
-
my?$workbook?=?new?Spreadsheet::WriteExcel(?'foo.xls'?); ?
-
my?$worksheet?=?$workbook->add_worksheet(?T('世界你好')?); ?
- ?
-
$worksheet->write(?0,?T('干啥呢')?); ?
- ?
- sub?T?{ ?
- ????my?$text?=?shift; ?
- ?
-
????return?decode(?'gb2312',?$text?); ?
- }?
最后再来个总结: 要点只有一个:excel 里保存的是且只能是 utf8 编码,而简体中文版的 windows 控制台和其它一些软件缺省显示的是 gb2312 编码 有些朋友在 tk 应用或者 mysql 应用中用了上面的代码,仍然看到乱码,那是因为你没有搞明白 tk 和 mysql 的编码,所以上面的办法也不是万能的。 万能的办法就是搞清楚每个信息流的编码方案,彻底把思路搞明白了。