设为首页 收藏本站
查看: 1214|回复: 0

[经验分享] [经验总结]Perl读取Excel数据并调用MSXML接口操作XML数据

[复制链接]
累计签到:2 天
连续签到:1 天
发表于 2017-5-19 13:19:54 | 显示全部楼层 |阅读模式
  #################################################################################################################################
#File: excel.pl
#Desscription: Perl读取Excel文件
#Create: Thinkhy
#Date: 2010.05.04
#History:
#2010.05.04确定转换规则
#2010.05.05确定技术方案(Excel、XML操作库)
#2010.05.07完成编码
#2010.05.10根据确认意见,修改:
# 1> 输出XML保持有序(sequence)
#
#Q: 1. 暂只支持"绝对路径"的中文文件名? A: 暂无解决办法
# 2. 怎么确认Excel文件共有多少行? A: 已解决,参考:http://blog.csdn.net/lanman/archive/2007/07/10/1684191.aspx
# 3. 输出XML添加GBK的编码声明? A: 已解决,调用接口:createProcessingInstruction appendChild
#################################################################################################################################
##!/usr/local/bin/perl

use strict;

use Tie::IxHash; # 使用CPAN包 IxHash 使哈希值保持原有顺序

use Win32::OLE qw(in with);
use Win32::OLE::Const 'Microsoft Excel';

use constant MSXMLDOM => "MSXML2.DOMDOCUMENT.4.0";

$Win32::OLE::Warn= 3;#die on errors


# 文件名中须包括绝对路径
my$filename= $ARGV[0]; # 必须用绝对路径
my$output_file= $ARGV[1]; # 可以用相对路径

die"[Usage: excel.pl inputfile outputfile]"if(!$filename);

my$excel= Win32::OLE->GetActiveObject('Excel.Application')
||Win32::OLE->new('Excel.Application', 'Quit');

my$book0= $excel->Workbooks->Open($filename);

my$sheet0= $book0->Worksheets(1);

# 获得Excel文件的行数
# 参考: http://blog.csdn.net/lanman/archive/2007/07/10/1684191.aspx
my$row_num= $sheet0->{UsedRange}->{Rows}->{Count};

my@collection;
my@array;

# 生成
if($row_num> 0) {
# 生成头结点

my$doc= Win32::OLE->new(MSXMLDOM) ordie
"Couldn't create @{[MSXMLDOM]}";

$doc->{async} = "False";
$doc->{validateOnParse} = "True";

# 新建PI结点 默认编码为GBK
my$pi_node= $doc->createProcessingInstruction("xml", "version='1.0' encoding='GBK'");
$doc->appendChild($pi_node);# 记得创建PI结点后要手动append到doc结点

# 新建根结点
my$root= $doc->createElement("root");
$doc->appendChild($root);
$doc->{documentElement} = $root;

my$head= $doc->createElement("head");
$root->appendChild($head);

# 新建头结点
my%head_info;
tie(%head_info, 'Tie::IxHash');
%head_info= (# 哈希要用小括号包起来?
"class" => "条目",
"identity"=> "",
"copyright" => "",
"publishtime"=> "2002-04-10",# [TODO] 这里需要取当前时间
"state" => "中国",
"area"=> "北京",
);

foreachmy$key(keys%head_info) {
my$value= $head_info{$key};
my$node= $doc->createElement($key);
$node->{Text} = $value;
$head->appendChild($node);
}

# 新建main结点
my$main= $doc->createElement("main");
$root->appendChild($main);

my@tmp_array= (1..156);
my$cnt_item= 1;

for(my$num= 1; $num< $row_num; $num++) {
my$item_name=getcell($sheet0, $num, 'A'); # 地名
my$pinyin=getcell($sheet0, $num, 'B');# 拼音
my$abbr=getcell($sheet0, $num, 'C');# 简称
my$zoneid=getcell($sheet0, $num, 'D');# 区号
my$zipcode=getcell($sheet0, $num, 'E'); # 邮编
my$author=getcell($sheet0, $num, 'M');# 作者

my$writetime=getcell($sheet0, $num, 'K'); # 时间
$writetime=~ s//./-/ig;

my$trace=getcell($sheet0, $num, 'L'); # 来源

# 首列(条目名)或拼音 为空则过滤此行
# print $item_name, $pinyin, $abbr, $zoneid, $zipcode , "/n";

nextif(!$item_name|| (!$pinyin&& !$abbr&& !$zoneid&& !$zipcode));

# 过滤首列 内容为 “地名” 的行
nextif($item_name=~//s*地名/s*/);

# 新建 item 结点
my$item= $doc->createElement("item");
$main->appendChild($item);
$item->setAttribute("id",$cnt_item++);
$item->setAttribute("fatherid",0);

my%main_info;
tie(%main_info, 'Tie::IxHash');
%main_info= (# 哈希要用小括号包起来?
"type"=> "",
"name"=> $item_name,
"ename" => "",
"spell" => $pinyin,
"volume"=> "",
"subclass"=> "",
"author"=> $author,
"writetime"=> $writetime,
"referitem"=> $item_name,
"trace" => $trace,
"links" => "",
"elementfiles"=> "",
);


# 构建item下一级内容
foreachmy$key(keys%main_info) {
my$value= $main_info{$key};
my$node= $doc->createElement($key);
$node->{Text} = $value;
$item->appendChild($node);

if($keyeq"elementfiles") {
my$sourcetype= $doc->createElement("sourcetype");
my$count= $doc->createElement("count");

$node->appendChild($sourcetype);
$node->appendChild($count);
}
}

# 省级、市级元素按HOTLINK处理
my$province=getcell($sheet0, $num, 'I'); # 省级
my$city=getcell($sheet0, $num, 'J'); # 市级

my$links= $item->selectSingleNode("links");
$links|| die"未创建links结点";

my($hotlink1, $hotlink2);

# 省级元素不为空则创建HOTLINK
if($province) {
my$hotlink_pro= $doc->createElement("HOTLINK");
$hotlink_pro->{Text} = $province;

$hotlink1= $hotlink_pro->cloneNode(1);
$links->appendChild($hotlink_pro);
}

if($city) {
my$hotlink_city= $doc->createElement("HOTLINK");
$hotlink_city->{Text} = $city;

$hotlink2= $hotlink_city->cloneNode(1);
$links->appendChild($hotlink_city);
}

my$body= $doc->createElement("body");
$item->appendChild($body);

my$body_cdata= $doc->createElement("body_cdata");

my$province=getcell($sheet0, $num, 'I');&nbsp;# 省级
my$city=getcell($sheet0, $num, 'J');# 市级

my$population= getcell($sheet0, $num, 'F'); # 人口
my$area= getcell($sheet0, $num, 'G'); # 面积
my$summary= getcell($sheet0, $num, 'H');# 概况

my%cdata_info;
tie(%cdata_info, 'Tie::IxHash');
%cdata_info= (
"简称"=> "$abbr",
"区号"=> "$zoneid",
"邮编"=> "$zipcode",
"人口(万人)"=> "$population",
"面积(平方千米)"=> "$area",
"概况"=> "$summary",
"省级"=> "$hotlink1->{Text}",
"市级"=> "$hotlink2->{Text}",
);

# 构建CDATA内容
foreachmy$key(keys%cdata_info) {
my$value= $cdata_info{$key};
nextif(!$value); # 值为空则忽略

# 每个项目一行(<p>)
my$p_node= $doc->createElement("p");
$body_cdata->appendChild($p_node);

# 字段名称加粗(<bold>)
my$bold_node= $doc->createElement("bold");
$bold_node->{Text} = $key."";
$p_node->appendChild($bold_node);

if($keyeq"省级"|| $keyeq"市级") { # 省级、市级直接添加HOTLINK结点
my$hotlink_node= $doc->createElement("HOTLINK");
$hotlink_node->{Text} = $value;
$p_node->appendChild($hotlink_node);
}
else{
my$text_node= $doc->createTextNode($value);
$p_node->appendChild($text_node);
}
}

my$cdata_text= $body_cdata->{xml};
$cdata_text=~ s/(<body_cdata>)|(<//body_cdata>)//ig;# 清除body_cdata结点


# 新建CDATA结点
my$cdata_node= $doc->createCDATASection($cdata_text);

# 将CDATA结点添加到 /root/main/item/body
$body->appendChild($cdata_node);
} # for

# 保存输出XML
my($dirpath,$basename,$extname) = ($filename=~/^((?:.*[:////])?)(.*)(/.[^.]*$)/s); # 获取文件名 代码来源于basename.pm
$output_file= $output_file? $output_file: $basename.".xml";

$doc->save($output_file);
print"Excel文件".'"'.$filename.'"'."转换成功!/n输出文件:$output_file/n";
}

$book0->Close;

# 获得Excel表格中的一个元素
subgetcell{
my($sheet, $x, $y, $cellvalue);
($sheet, $x, $y) = @_;

$cellvalue= $sheet->cells($x, $y)->{'Value'};
chomp($cellvalue); # 注意chomp的返回值为数字

$cellvalue;
}

__END__



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-379135-1-1.html 上篇帖子: Perl实现Websocket-76的TCP并发连接服务器端 下篇帖子: 日文网站搜索时,关键字在url地址栏里有一个编码的过程,perl怎么获得这个编码后的结果?
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表