Perl的Excel读写问题

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

读:

  
  
  
  
  1. use strict;  
  2. use warnings;  
  3.  
  4. use Spreadsheet::ParseExcel;  
  5. use MyExcelFormatter;  
  6.  
  7. my $file = 'foo.xls';  
  8.  
  9. my $fmt = new MyExcelFormatter();  
  10.  
  11. my $xls = Spreadsheet::ParseExcel::Workbook->Parse( $file, $fmt );  
  12. my @workSheet = @{ $xls->{Worksheet} };  
  13. foreach my $sheet ( @workSheet ){  
  14.     my $sheetName = $sheet->get_name();  
  15.     print "工作表: $sheetName\n";  
  16.  
  17.     my ( $minRow, $maxRow ) = $sheet->row_range();  
  18.     my ( $minCol, $maxCol ) = $sheet->col_range();  
  19.  
  20.     foreach my $row ( $minRow .. $maxRow ){  
  21.         foreach my $col ( $minCol .. $maxCol ){  
  22.             my $cell = $sheet->get_cell( $row, $col );  
  23.             next unless $cell;  
  24.             print " ($row,$col) ", $cell->value;  
  25.         }  
  26.         print "\n";  
  27.     }  

 基本上上面这段代码就是从 Spreadsheet::ParseExcel 的文档里抄来的。
除了 my $fmt = new MyExcelFormatter(); 这一行之外。
这一行生成了一个文档内容的转换器(格式化工具),
转换器代码如下:

  
  
  
  
  1. package MyExcelFormatter;  
  2.  
  3. use strict;  
  4. use warnings;  
  5.  
  6. use base qw(Spreadsheet::ParseExcel::FmtDefault);  
  7.  
  8. use Encode::CN;  
  9. use Encode qw(from_to);  
  10.  
  11. sub new() {  
  12.     return bless {};  
  13. }  
  14.  
  15. sub TextFmt( $;$ ) {  
  16.     my $this = shift;  
  17.     my ($value, $code) = @_;  
  18.  
  19.     if ( defined $code and $code eq 'ucs2' ){  
  20.         from_to( $value, 'ucs2''gb2312' );  
  21.     }  
  22.     return $value;  
  23. }  
  24.   

如法炮制以此类推,可以处理所有本地语言编码。

写 excel,这个就更简单了:

  
  
  
  
  1. use strict;  
  2. use warnings;  
  3.  
  4. use Spreadsheet::WriteExcel;  
  5.  
  6. my $workbook = new Spreadsheet::WriteExcel( 'foo.xls' );  
  7. my $worksheet = $workbook->add_worksheet( T('世界你好') );  
  8.  
  9. $worksheet->write( 0, 0, T('干啥呢') ); 

大家可以看到,完全就是抄 perldoc 文档里的例子的。
只不过,T( '世界你好' ) 看上去有点怪怪的罢了。
其实这是一个自定义函数:

  
  
  
  
  1. use Encode qw(decode);  
  2.  
  3. sub T {  
  4.     my $text = shift;  
  5.  
  6.     return decode( 'gb2312', $text );  

名字当然也可以不叫 T,叫别的也行。
完整的代码如下:

  
  
  
  
  1. use strict;  
  2. use warnings;  
  3.  
  4. use Spreadsheet::WriteExcel;  
  5. use Encode qw(decode);  
  6.  
  7. my $workbook = new Spreadsheet::WriteExcel( 'foo.xls' );  
  8. my $worksheet = $workbook->add_worksheet( T('世界你好') );  
  9.  
  10. $worksheet->write( 0, 0, T('干啥呢') );  
  11.  
  12. sub T {  
  13.     my $text = shift;  
  14.  
  15.     return decode( 'gb2312', $text );  

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

你可能感兴趣的:(Excel,中文,Excel,perl,write,read,休闲)