python从word中提取信息导入excel_使用python模块win32com提取word表格到excel

由于工作的要求,需要将word文档里的表格提取出来放到excel里面。表格结构比较复杂,且一篇word里面有多个表格。对于一个word文档来说提取很简单,只要选中表格,然后复制黏贴到excel里面就可以了。但是word文档有上百个,手工操作不现实,最直接的想法就是使用VBA编程实现批量操作。可是VBA又不能直接嵌入已有的python项目,所幸python是有直接操作office的库的,如:python-docx、xlrd、xlwt等。但是如果需要把word 里面的表格copy到excel里面就需要进行使用python-docx读取word的表格—>解析表格—>使用xlwd创建excel表格这样一个蛋疼的过程。我只是想简单的拷贝一个表格过去而已啊(摔)。于是我通过万能的百度搜索到了win32com这个可以直接操作COM的python模块,本来以为可以顺利把问题解决了,没想到是一个神坑。

坑1、win32com的文档非常少,唯一能找到的只有下面这个地址的文档,这个文档也仅仅是介绍了win32com模块的基本使用而已,基本没有具体的例子。http://docs.activestate.com/activepython/2.4/pywin32/html/com/win32com/HTML/docindex.html​docs.activestate.com

坑2、VBA例子需要做改动转化为Python的语句。API文档要查MSDN,win32com模块调用了word或者excel的com接口,com接口的对象、接口、函数等都要通过MSDN查询,并且MSDN查询到的都是VBA写的程序,还要转化为python。这里面有几点要注意:1、所有的方法后面都需要接括号,比如Copy,写到python里面就要变成Copy()。2、VBA的WITH用法要改,很多MSDN上面的例子都用了WITH语句,Python上面没有类似的语句,没办法只好用还原成“对象.变量”或者“对象.方法”这样的形式。还有就是要注意万恶的大小写了,一定要完全对应才可以。

坑3、COM常量(Constants)。VBA方法的参数照道理来说应该是对应COM里面的常量,但是,它不管用啊。比如用word的Documents的Close()方法,里面有个参数SaveChanges用来确定关闭文档时是否保存,MSDN说关闭不保存的情况SaveChanges=wdDoNotSaveChanges(一个COM常量)。到了PYTHON 里面这个wdDoNotSaveChanges应该表示为constants.wdDoNotSaveChanges吧,可是不行。查了一下文档,文档里是这么说的:

Using COM Constants

Makepy automatically installs all generated constants from a type library in an object called win32com.clients.constants. You do not need to do anything special to make these constants work, other than create the object itself (ie, in the example above, the constants relating to Word would automatically be available after the w=win32com.client.Dispatch("Word.Application") statement.

For example, immediately after executing the code above, you could execute the following:

>>> w.WindowState = win32com.client.constants.wdWindowStateMinimize

and Word will Minimize.

好吧,加上win32com.client.constants.wdDoNotSaveChanges,还是不行(摔)

w.constants.wdDoNotSaveChanges?不行。。。

再仔细看看文档,原来还要先Makepy,怎么这么难用(摔)文档如下(以Office97为例.....这文档有多老):

Example using Microsoft Office 97.

Either:Run 'win32com\client\makepy.py' (eg, run it from the command window, or double-click on it) and a list will be presented. Select the Type Library 'Microsoft Word 8.0 Object Library'

From a command prompt, run the command 'makepy.py "Microsoft Word 8.0 Object Library"' (include the double quotes). This simply avoids the selection process.

If you desire, you can also use explicit code to generate it just before you need to use it at runtime. Run 'makepy.py -i "Microsoft Word 8.0 Object Library"' (include the double quotes) to see how to do this.

And that is it! Nothing more needed. No special import statements needed! Now, you simply need say

>>> import win32com.client

>>> w=win32com.client.Dispatch("Word.Application")

>>> w.Visible=1

>>> w

Note that now Python knows the explicit type of the object.

用了Makepy了还是不行,再仔细看。。原来要用-i参数。。。用了以后结果如下:

PS C:\python\Anaconda3\Lib\site-packages\win32com\client> python makepy.py -i

Microsoft Word 16.0 Object Library

{00020905-0000-0000-C000-000000000046}, lcid=0, major=8, minor=7

>>> # Use these commands in Python code to auto generate .py support

>>> from win32com.client import gencache

>>> gencache.EnsureModule('{00020905-0000-0000-C000-000000000046}', 0, 8, 7)

PS C:\python\Anaconda3\Lib\site-packages\win32com\client> python makepy.py -i

Microsoft Excel 16.0 Object Library

{00020813-0000-0000-C000-000000000046}, lcid=0, major=1, minor=9

>>> # Use these commands in Python code to auto generate .py support

>>> from win32com.client import gencache

>>> gencache.EnsureModule('{00020813-0000-0000-C000-000000000046}', 0, 1, 9)

PS C:\python\Anaconda3\Lib\site-packages\win32com\client>

导入gencache 模块

from win32com.client import gencache

然后

gencache.EnsureModule('{00020905-0000-0000-C000-000000000046}', 0, 8, 7)

word的constants就加入进来了。使用方法是constants.常量名,这样的话SaveChanges=wdDoNotSaveChanges,用python就写成SaveChanges=constants.wdDoNotSaveChanges。

如果上述方法都失效的话,只能去MSDN查枚举了,通过枚举查到常量对应的数值,然后直接等于数值,比如:SaveChanges=wdDoNotSaveChanges等效于SaveChanges=0

坑4、word的剪贴板。如果剪贴板有大量的数据word在退出的时候会询问是否保留数据,这对于自动化执行来说简直就是灾难,需要手动确认的算什么自动化呢?excel里面很好处理,使用Application.CutCopyMode = False 就可以了,但是word 没有这个方法啊!(摔)

网上搜了很久都没有办法,无奈只好用笨办法了:

word = win32com.client.Dispatch('Word.Application')

word.Selection.HomeKey(Unit=6)

word.Selection.MoveRight(Unit=1,Count=1,Extend=1)

word.Selection.Copy()

上面的代码是选择文档第一个字,然后复制,因为只有一个字所以退出时候不会提示有大量数据在剪贴板。为啥要选一个字,因为不选一个字word不让复制啊!(摔)

坑5、excel的最后一行。网上查到找到EXCEL的最后一行有各种方法,比如:

方法1、x = range("A65536").end(xlup).row,这个方法要求每一列的长度相同,这样只要A列的最后一个选择了就可以确定最后一行的行号了。也不会因为中间有空行而导致没有选中。注意excel比较新的版本是1048576行,因此最后一行x = range("A1048576").end(xlup).row。

方法2、x = ActiveSheet.UsedRange.Rows.Count,这个方法会把已用的格式也算作一行,在最后的行里面没有数据但是有格式的情况下会选到空行。

似乎没有完美的解决方法,只有用方法1循环每列,然后取最大值了。好在现在的word里面的表格每列都一样长,就用方法1执行了,然后实际执行的时候发现,每次取到的不是最后一行,而是倒数第二行!?WTF!检查EXCEL 表格发现。。。:

合并单元格是什么鬼!!我只是要选个17行,excel你为什么要这样对我!获取合并单元格的行数

If range("A%d")%x.MergeCells == True

m = range("A%d")%x.MergeArea.Count

x = x+m+1 #x表示最后一行的下一行行号

坑6、word替换。只能说网上搜索到的包括MSDN上写的方法都不管用,因为他们方法的参数没有写全,唯一找到能用的是

word.Selection.Find.Execute("^l", False, False, False, False, False, True, 0, True, "", 2)

你可能感兴趣的:(python从word中提取信息导入excel_使用python模块win32com提取word表格到excel)