实例解说:用Perl来分析并生成中文Excel文件

2016-01-29 13:22 79 1 收藏

实例解说:用Perl来分析并生成中文Excel文件,实例解说:用Perl来分析并生成中文Excel文件

【 tulaoshi.com - PHP 】

    最近实验室作为自学考试的考场,需要在服务器上面为每个学生创建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的原文件逆向处理。

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com/php/)

    首先通过看WriteExcel的Manual得知它是支持写Unicode字符的,其中就有一个Example说明了通过write_unicode()函数来向单元格写入日文Unicode字符。可是Example里面提供的日文字符串是通过pack来生成的,本身已经是Unicode格式的了,而我们通常使用的GB2312的字符不属于Unicode字符串,所以没法直接写入。那么如何转换呢?

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com/php/)

    通过分析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

来源:https://www.tulaoshi.com/n/20160129/1489947.html

延伸阅读
标签: 办公软件
   1.考试混合编,成绩统一理——老方法遇到新问题     关于使用Excel进行学生成绩处理,已经是老话题了。但在实际工作中还是会有很多新问题,例如,现在很多学校都是全年级各班混在一起考试,以防考试改卷中的不正当竞争。而统计成绩时,则是将已判分但未拆封的考卷统一交到教务处,先按座位号顺序(每本考卷的自然...
标签: 电脑入门
实例 某溶液浓度正比对应于色谱仪器中的峰面积,现欲建立不同浓度下对应峰面积的标准曲线以供测试未知样品的实际浓度。已知8组对应数据,建立标准曲线,并且对此曲线进行评价,给出残差等分析数据。 这是一个很典型的线性拟合问题,手工计算就是采用最小二乘法求出拟合直线的待定参数,同时可以得出R的值,也就是相关系数的大小。在Excel中,...
学习Java的朋友应该都知道Java从刚开始的时候就打着平台无关性的旗号,说“一次编写,到处运行”,其实说到无关性,Java平台还有另外一个无关 性那就是语言无关性,要实现语言无关性,那么Java体系中的class的文件结构或者说是字节码就显得相当重要了,其实Java从刚开始的时候就有两套 规范,一个是Java语言规范,另外一个是Java虚拟机规范,Ja...
Adobe PDF格式已经变成很多机构和公司进行跨平台制表的通用媒体格式。尽管我不是这个产品的狂热痴迷者,却不得不接受这样一个事实:用这个格式产生一个协定可能会比用Word还要好。 PDF的全称为Portable document.nbspFormat,即可移植文档格式,由广泛应用于专业打印领域的Postscript解释语言演化而来。为了使PDF迅速得到推广,Adobe...
标签: Web开发
如果你的服务器不容许你读他的LOG文件,那你只好停下来分析你的访问者?做你自己的LOG文件吧! 你仅需做的事情是用PHP计算实际的点击次数,没有错误,没有象'304 Not Modified' 和 'Internal Server Error' 一样的错误。你的代码将生成自己的LOG文件。 ?php /* 用户定义变量 */ $logfile = "clf.log"; /*LOG文件写到那里 */ $timezone ...

经验教程

429

收藏

60
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部