
比来尝试室作为自学测验的考场,需求在办事器上面为每个学天生立FTP帐号,我打算用Perl来完成的批措置成立。考虑到获得的考场先生名单是存储在Excel文件里面的,是以还需求让Perl去阐发Excel文件。经由过程google找到用Spreadsheet::ParseExcel和Spreadsheet::WriteExcel来读写Excel。在www.cpan.org高低载了呼应的Module并看了文档、典范后,毕竟写出了一个法度能够读考场先生名单,并天生暗码清单存到别的一个Excel文件中。
这还只是第一步,刚写出来的法度读Excel文件中的中文,也没法将中文写入Excel文件:单位格(Cell) 和任务簿(Worksheet) 中的汉字。
在找呼应的帮忙,得知能够用Spreadsheet::ParseExcel::FmtUnicode来措置Excel文件中的Unicode字符,其利用编制以下:use Spreadsheet::ParseExcel::FmtUnicode;my $oFmtJ = Spreadsheet::ParseExcel::FmtUnicode->new(Unicode_Map => CODE);my $oBook = Spreadsheet::ParseExcel::Workbook->Parse($ARGV[0], $oFmtJ);
晓得了完成的编制,可是这个CODE的值该当为多少还不晓得。刚起头我猜想是'GB2312',可是不晓得是哪里其他甚么处所错了导致不胜利;当时看到Manual里提到'GB2312-80',也试了一下,仍是不可。最初只好google,发觉别人用的是'CP936',此次就胜利了。当作功了今后再把CODE改回'GB2312'居然也能够或许了。
此刻读Excel文件已没有题目了,可是固然这些中文读出来了,可是在写Excel文件的时辰并没法写入中文。
处理计划就只要两种了:网上搜刮谜底;看ParseExcel的原文件逆向措置。
起首经由过程看WriteExcel的Manual得知它是支撑写Unicode字符的,此中就有一个Example说了然经由过程write_unicode()函数来向单位格写入日文Unicode字符。可是Example里面供应的日文字符串是经由过程pack来天生的,本身已经是Unicode格局的了,而我们但凡利用的GB2312的字符不属于Unicode字符串,所以没法间接写入。那末若何转换呢?
经由过程阐发Spreadsheet::ParseExcel.pm和Spreadsheet::ParseExcel::FmtUnicode.pm发觉:一切经由过程ParseExcel从Excel文件中阐发出来的花都网络公司字符都是颠末函数TextFmt()格局化过的,这个函数的定义在FmtUnicode.pm中。而TextFmt()核心是经由过程Unicode::Map的from_unicode()函数来将一个unicode字符串转换为非unicode的字符串,当然在转换之前还做了一个措置:s/(.)/x00$1/sg。
按照这个思路,就在WriteExcel之前,成立一个Unicode::Map对象,然后调用对象里的to_unicode函数停止字符串格局转换,最初调用write_unicode函数将中文写入单位格(Cell) 中。上面给出一个复杂的Example:use Unicode::Map();my $Map = new Unicode::Map("GB2312");$worksheet->write_unicode($iR, 2, $Map->to_unicode("考生姓名"))
单位格中的中文能够一般显现了,可是在写任务簿称号的时辰这个别例就不那末管用了,像$worksheet = $workbook->add_worksheet($Map->to_unicode($name)如许停止的话,就会发生任务簿称号不法的弊端而加入。一样的编制在set_header()是也不论用,固然不会犯错可是显现的倒是乱码。在措置单位格的时辰有分unicode的编制和非unicode的编制,为甚么add_worksheet的时辰没有呢?莫非要本身去写个函数或加个参数来扩展?
单位格中的中文能够一般显现了,可是在写任务簿称号的时辰这个别例就不那末管用了,像$worksheet = $workbook->add_worksheet($Map->to_unicode($name)如许停止的话,就会发生任务簿称号不法的弊端而加入。一样的编制在set_header()是也不论用,固然不会犯错可是显现的倒是乱码。在措置单位格的时辰有分unicode的编制和非unicode的编制,为甚么add_worksheet的时辰没有呢?莫非要本身去写个函数或加个参数来扩展?
再次进入源代码Spreadsheet::WriteExcel::Workbook.pm,发觉本来add_worksheet()函数还能够传送一个$encoding的参数的,可是这个参数仅用于判定输出的unicode字符是否是合适长度请求,编码转换哪里去了?若是说要本身去补齐的话该加甚么代码呢?比较Spreadsheet::WriteExcel::Worksheet.pm中的write()(实际上最初调用的是write_string)和write_unicode()发觉,后者比前者多了呼应的这么一段代码>(说呼应是因为一些变量名的差别,将此代码间接增加到前者是不克不及任务的):
# Check for a valid 2-byte char string.croak "Uneven number of bytes in Unicode string" if $num_bytes % 2;
# Change from UTF16 big-endian to little endian$str = pack "v*", unpack "n*", $str
那末也就是说将这段代码插手到add_workshe
