`
wjm251
  • 浏览: 110044 次
  • 性别: Icon_minigender_1
  • 来自: 沈阳
社区版块
存档分类
最新评论

python 操作ms office 生成报告相关总结

阅读更多
python 操作ms office 生成报告相关总结
I. 项目中需要生成word和excel报告,通常有两种方法:基于字符串拼接以及COM调用。

1) 字符串拼接生成office文档的原理: office文档本身可以体现为xml文件格式,尤其是MS Excel
2003,我们可以自己将一个excel另存为xml格式,用文本编辑器打开它——很容易看懂。
因此只要程序中按照格式输出这样的xml文件,再保存成office文档即可。生成大量格式化字符串有一个非常重要的工具就是模板引擎
(比如jsp就是这样的东西),在生成office文档时,java语言常用的模板引擎就是velocity,python中有和velocity非常类似的Airspeed,
还有一些第三方的Cheetah,Mako等模板引擎项目。 2) COM调用
字符串拼接的好处是速度快,但缺点就是必须是文档的文本格式必须简单易懂,有复杂的格式就无能为力了,尤其是对MS Office这个似乎并没有完全
开放格式的办公软件更麻烦。而COM调用几乎可以做任何事情,只要人工操作Office可以完成的,它都可以做。体现在我们这里就是动态生成图,
调整表格居中,表头颜色等,往往一个调用就完成了(但它们生成的文档格式让人看得焦头烂额)。Java中进行COM调用的好像就是jacob了。
Python中使用win32com。我觉得Python中的这个组件更好用些,得益于动态语言的优势,它的变量类型都是动态赋予的,
因此可以写出的COM调用代码和excel宏录制的VB代码很相似,很多时候拿过来直接用就行。而java的COM调用代码到处是Dispatch。
II.
使用过一个叫snakelets(蛇蟒还是有渊源的)的第三方模板引擎。通常他的后缀名是y。y文件中用<%%>括起来的是python代码,
通过内置方法out.write输出字符串和上下文的普通字符串(literal text)拼接(看起来和jsp的想法很相似)。
由该y文件生成的一个普通的文本文件就是一个符合excel格式的xml文件,里头有一个excel表格。
这样我们就生成一个excel sheet的雏形,多个y文件生成的代表excel
sheet的字符串再拼起来就可以构成一个完整的excel文件。然后进行COM调用,给这个文件加上首页,适当调整超链接——excel报告就这么生成了。
Word报告要复杂许多,由于excel表格保存的xml文件更容易看懂,而word中的图,章节等结构很复杂,
在生成word中表格的时候借助前面提到的y文件先生成excel表格(有事使用该表格再调用COM接口生成图),
然后把表格或图从excel中拷贝到word中来,其余部分几乎全部使用COM调用。
首先一个问题是具体某个表格在word中的位置。我们用一个word文件作为模板。
先把模板复制到最终要输出报告的位置并修改成最终的报告名。
然后将里面批注部分换成相应的表或图(具体内容信息从批注中获得)
比如批注内容可以表达:此处要生成图,图的数据来自名为"testci"的检查项所输出的表格'testtable',
这个图要类似于"pie.xls"文件的样式(是个扇形图),使用数据的t1和t2两列作为图的系列。
这里值得介绍的是这个批注的使用和"pie.xls"表示的图的格式。批注的作用应该很容易体会出来不多讲了。
而"pie.xls"这个文件中存放了一个简单的表格(其中数据是随意写的)和扇形图。
先将这个图拷贝到上述y文件生成的excel中,然后将图的相关属性修改成对应的excel中真实数据表格。
这个图就变成我们需要的,并且数据也就是检查项生成的数据。然后再把他拷贝到word就完成了图的输出。

一个遗留问题:前面多次提到拷贝。使用的是COM接口copy和paste,效果等同于人工ctrl-c和ctrl-v。
因此报告输出的过程中如果操作人员正好也在拷贝粘贴其他东西,可能导致生成报告出现问题。
目前多次尝试锁定剪切板等手段都没有解决。
关于网络评估中报告输出的方法大概就是这些。
下面提几点使用python及python调用COM的体会。 III. python调用COM的体会 1)
按文本生成报告时必须严格符合文档的格式
Excel中每个sheet页有65535的行数限制,sheet页的名称有特殊字符限制等等,这些在生成文本的过程中如果
不注意的话都能成功,但用excel程序打开的时候就有问题了。这些由于不符合文档格式导致报告生成失败的情况
可用折半排查法解决。
2) 要常调用save
word报告生成过程中大量操作后,生成几十页的文件处于未保存状态,也占用大量内存,有时会抛出“服务器未响应”的异常而导致生成报告过程终止。 3)
防止程序使用的office和用户打开的office的干扰 使用新的进程(通常没有Ex的那个方法会附着在已经打开的进程):
DispatchEx('Excel.Application') DispatchEx('Word.Application')

Excel防止操作的文档间干扰: App.IgnoreRemoteRequests = 1

对于Word比较麻烦, 当程序运行到打开一个文档a的时候,用户手工双击打开一个不相干的word文档(会附着到最近一个已经打开的word进程)就可能出问题,
问题本质就是手工操作的word和程序操作的word使用了同一个进程,
http://support.microsoft.com/kb/188546/en-us/
参考MS网站上的建议,解决方法是先开启程序,然后启动几个临时的word进程来专门给程序外的用户文档用,
并保持临时word进程的数量,一旦发现有被关闭的,马上再启动一个新的补上。
4) 禁用临时文件
大量操作之后,如果不save,表格大了后续操作(比如表格居中等)会出错,如果save,后续为了可以undo,
word自动生成了临时文件。(实际碰到过这个问题,类似~WRL0003.tmp这样的临时文件多大500MB)
禁用临时文件也就是不使用undo功能,调用一个方法就可以了 doc.UndoClear() 5)
当用户打开不同的两个word进程,并都进行操作,关闭最后一个的时候可能会提示未保存normal.dot,
这个手工操作也会出现,暂无法解决,手工点取消不保存即可。
6) Makepy
碰到个问题,excel附件贴到word中的时候,有的同事机器上发现贴完后excel没有文字部分,
后面的操作可以解决这个问题,步骤附在后面,先说一下好处,, 这么做了之后我发现的好处至少有:
可以解决现在这个问题了(比较怪异的问题,我相信还会有其他的怪异的问题,,,,)
 可以在代码中直接使用com常量,就是vb宏里的那些常量
可以在dir(com对象)的时候给出com对象包含哪些属性(否则是不行的,不像普通的python对象可以dir)
操作:
在python包下有个Python25\Lib\site-packages\pythonwin\Pythonwin.exe 运行一下com makepy
utility,

我们现在经常用python操作word或excel,所以找到里头的microsoft word x.x object library
和excel的(可能要分两次运行),点ok 这个可能要等好久,.也可能会死掉,不知为啥,等会还没反应强制关了发现也起作用了。
其上操作可以调用makepy.py代替。
这就是makepy,后来看资料了解到,大意是早期绑定,就是用这个工具生成python源码以支持com调用,
对象的变量属性已经预先生成了,不是运行时才产生的。
关于python的com编程有一本书Oreilly - Python Programming on Win32.chm 网上可以下载到
7)前面提到过python调用COM的代码和word或excel录制宏生成的vb代码很相似,接口99%一样,
因此想实现啥功能如果不知道用什么方法,先手工操作然后录制宏,看宏代码,照猫画虎。
IV. python编程注意点
1) 语言层面的好像各种语言都差不多,只简略提一下。
要多次使用的语句或者循环中尽量不要做重复的计算,比如列表或数组的长度计算后保存在局部变量,
 减少不必要的循环,递归
如果有多层if条件判断,尽量让最先容易失败的放在最外层,则进入内层的机会就少了
避免字符串相加——可以使用列表的join(见过好几种语言都强调这个,并且差异确实很明显)
2) 多线程
这个方面网上也可以查到很多资料。不过有个特点,似乎python的多线程是个假多线程,
python内部由于一个全局锁的原因,即使多核的机器,python进程中的多个“线程”也不能真正并发执行。
不过我亲自实践表明,如果程序中不光是大量cpu计算,还有网络数据库等操作的话,
用用多线程对提升性能的效果也是很显著的。这个就不多讲了,我也是半吊子,
再说成熟的资料很多,随用随查就行了,思想和其他语言差不多。
3) pysco 这是一个第三方模块,计算密集型的程序使用它能提高性能。
下面是我进行过的两个测试
# -*- coding: cp936 -*-
#-------差不多提升一倍-------------------
import psyco #添加的第一行,导入psyco模块
psyco.full() #第二行定义,对全局作用,也可以自定义对某一个函数或类作用。
import time
def test():
    sum=0
    for x in xrange(1,1000000):
        sum=sum+x
        return sum
begin=time.time()
test()
usetime=time.time()-begin
print usetime

#-------这个居然提升200倍------
import time
import psyco
psyco.full()
def main():
    ta=time.clock()
    y=2
    for x in range(1000000):
        y=y+3*8/3+3-2
    print time.clock()-ta
main()

4) python中还有一些非常优秀的模块,方法,使用它们可以达到事半功倍的效果。
比如最近发现的操作xml的elementtree,持久化对象到文件的shelve等等。
这里只是侧重使用python语言本身以及调用com生成报告过程中的一些弯路或者心得的总结,
肯定还会有更多的东西可以挖掘以提高我们的效率,后续再总结。希望能对后续开发有一些帮助,
也期待大家能多指出不足以修正。
3Q




分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics