2018-07-02 17:44:13 licui94 阅读数 104

参照《Python核心编程》练习遇到问题3个。

1、增加#coding:utf-8

2、一直提示没有Cell对象。查看报错源文件,搜索Cell发现只有Cells,确定代码少敲了s.低级错误。

sh.Cells(1,1).Value = 'Python-to-%s Demo'%app

3、showwarning时,提示框未显示在屏幕最前端。(未解决)

#coding:utf-8
#!/usr/bin/env python

from Tkinter import Tk
from time import sleep
from tkMessageBox import showwarning
#from Tkinter import messagebox
import win32com.client as win32

warn = lambda app:showwarning(app,'Exit?')
#warn = lambda app:messagebox.askokcancel(app,'Exit?')
RANGE = range(3,8)

def excel():
	app ='Excel'
	x1 = win32.gencache.EnsureDispatch('%s.Application'%app) 
	ss = x1.Workbooks.Add()
	sh = ss.ActiveSheet
	x1.Visible = True
	sleep(1)

	sh.Cells(1,1).Value = 'Python-to-%s Demo'%app
	sleep(1)
	for i in RANGE:
		sh.Cells(i,1).Value = 'line %d' %i
		sleep(1)
	sh.Cells(i+2,1).Value="Th-th-th-that's all folks!"

	warn(app)
#    print "warning",showwarning("Excel","exit?")
	ss.Close(False)
	x1.Application.Quit()

if __name__=='__main__':
	Tk().withdraw()
	excel()


2018-12-12 11:00:52 stone0823 阅读数 2624

微软 Office 提供基于 COM 接口的编程。Python 通过 pywin32 可以方便地调用各组件。如果下载和安装 pywin32 有困难,可以到 Sourceforge 的镜像网摘查找合适的版本。

单一账号

import win32com.client as win32

def send_mail():
    outlook = win32.Dispatch('Outlook.Application')

    mail_item = outlook.CreateItem(0) # 0: olMailItem

    mail_item.Recipients.Add('someone@qq.com')
    mail_item.Subject = 'Mail Test'

    mail_item.BodyFormat = 2          # 2: Html format
    mail_item.HTMLBody  = '''
        <H2>Hello, This is a test mail.</H2>
        Hello Guys. 
        '''
    mail_item.Send()

if __name__ == '__main__':
    send_mail()

多账号发送邮件

如果 Outlook 有多个账号,需要选择账号发送邮件,需要在代码中对账号进行判断,代码如下:

def send_mail():
    outlook_app = win32.Dispatch('Outlook.Application')

    # choose sender account
    send_account = None
    for account in outlook_app.Session.Accounts:
        if account.DisplayName == 'sender@hotmail.com':
            send_account = account
            break

    mail_item = outlook_app.CreateItem(0)   # 0: olMailItem

    # mail_item.SendUsingAccount = send_account not working
    # the following statement performs the function instead
    mail_item._oleobj_.Invoke(*(64209, 0, 8, 0, send_account))

    mail_item.Recipients.Add('receipient@qq.com')
    mail_item.Subject = 'Test sending using particular account'
    mail_item.BodyFormat = 2   # 2: Html format
    mail_item.HTMLBody = '''
        <H2>Hello, This is a test mail.</H2>
        Hello Guys. 
        '''

    mail_item.Send()


if __name__ == '__main__':
    send_mail()

这里有点黑魔法,直接设置 mail_item.SendUsingAccount 不会起作用,返回值是 None, 永远从第一个邮箱账号发送邮件,我使用的是 Office 365 版。需要调用 _oleobj_.Invoke() 方法。后面列出了参考链接。

本质上,这种方法是调用 COM 组件,可以查询微软的开发帮助了解相关对象的属性和方法,比如我想知道 Account 的细节,就特意参考了下面这篇帮助:https://docs.microsoft.com/zh-cn/office/vba/api/outlook.account 。COM 编程与语言无关。另外可以在 Outlook 中 ALT + F11,进入 VBE 环境,然后 F2 进入对象浏览器界面查看比如下面的界面显示了 Account 的属性和方法:

关于调试

python 作为动态语言,通过 Debug 获取 COM 对象信息并不是很方便,比如下面代码:

import win32com.client as win32

def print_outlook_accounts():
    outlook_app = win32.Dispatch('Outlook.Application')

    for account in outlook_app.Session.Accounts:
        print (account.DeliveryStore.DisplayName)

if __name__ == '__main__':
    send_mail()

设置断点的调试界面:

我们只知道 account 是一个 COM Object,account 包含的信息很多都是 unknown 的。碰到这种情况,我一般用 C# 或者 VBA 编写代码进行调试。如果我需要详细了解 account 的属性和方法,在 Office 的任何组件中,比如 Excel,写一段下面的代码:

Public Sub Print_Outlook_Accounts()

    ' 工具 -> 引用:添加 Microsoft Outook Object Library 引用
    
    Dim outlookApp As New Outlook.Application
    Dim accounts As Outlook.accounts
    
    Set accounts = outlookApp.Session.accounts
    
    Dim account As Outlook.account
    For Each account In accounts
        Debug.Print account.DisplayName
    Next
End Sub

显示出监视窗口,设置断点,获取 accounts 信息:

在监视窗口添加变量 accounts:

展开:


Item 1 和 Item 2 表示有两个账号,现在我们想看到 Item 2 的账号信息,将 Item 2 展开:


DeliveryStore 属性也包含 account 的信息,可以展开查看。

参考

2012-12-05 14:22:20 scmsgxz 阅读数 9
这里测试的环境是:windows xp,office 2007,python 2.5.2,pywin32 build 213,原理是利用win32com接口直接调用office API,好处是简单、兼容性好,只要office能处理的,python都可以处理,处理出来的结果和office word里面“另存为”一致。

#!/usr/bin/env python

#coding=utf-8

from win32com import client as wc

word = wc.Dispatch('Word.Application')

doc = word.Documents.Open('d:/labs/math.doc')

doc.SaveAs('d:/labs/math.html', 8 )

doc.Close()

word.Quit()

关键的就是doc.SaveAs(‘d:/labs/math.html’, 8 )这一行,网上很多文章写成:doc.SaveAs(‘d:/labs/math.html’, win32com.client.constants.wdFormatHTML),直接报错:

AttributeError: class Constants has no attribute ‘wdFormatHTML’

当然你也可以用上面的代码将word文件转换成任意格式文件(只要office 2007支持,比如将word文件转换成PDF文件,把8改成17即可),下面是office 2007支持的全部文件格式对应表:

wdFormatDocument = 0
wdFormatDocument97 = 0
wdFormatDocumentDefault = 16
wdFormatDOSText = 4
wdFormatDOSTextLineBreaks = 5
wdFormatEncodedText = 7
wdFormatFilteredHTML = 10
wdFormatFlatXML = 19
wdFormatFlatXMLMacroEnabled = 20
wdFormatFlatXMLTemplate = 21
wdFormatFlatXMLTemplateMacroEnabled = 22
wdFormatHTML = 8
wdFormatPDF = 17
wdFormatRTF = 6
wdFormatTemplate = 1
wdFormatTemplate97 = 1
wdFormatText = 2
wdFormatTextLineBreaks = 3
wdFormatUnicodeText = 7
wdFormatWebArchive = 9
wdFormatXML = 11
wdFormatXMLDocument = 12
wdFormatXMLDocumentMacroEnabled = 13
wdFormatXMLTemplate = 14
wdFormatXMLTemplateMacroEnabled = 15
wdFormatXPS = 18

照着字面意思应该能对应到相应的文件格式,如果你是office 2003可能支持不了这么多格式。word文件转html有两种格式可选wdFormatHTML、wdFormatFilteredHTML(对应数字8、10),区别是如果是wdFormatHTML格式的话,word文件里面的公式等ole对象将会存储成wmf格式,而选用wdFormatFilteredHTML的话公式图片将存储为gif格式,而且目测可以看出用wdFormatFilteredHTML生成的HTML明显比wdFormatHTML要干净许多。

当然你也可以用任意一种语言通过com来调用office API,比如PHP.

原文链接 : [url]http://www.fuchaoqun.com/2009/03/use-python-convert-word-to-html-with-win32com/[/url]
2010-05-14 12:54:00 binger819623 阅读数 1955

Python转换office word文件为HTML

这里测试的环境是:windows xp,office 2007,python 2.5.2,pywin32 build 213,原理是利用win32com接口直接调用office API,好处是简单、兼容性好,只要office能处理的,python都可以处理,处理出来的结果和office word里面“另存为”一致。

#!/usr/bin/env python

 
#coding=utf-8
 
from win32com import client as wc
 
word = wc.Dispatch ( 'Word.Application' )
 
doc = word.Documents .Open ( 'd:/labs/math.doc' )
 
doc.SaveAs ( 'd:/labs/math.html' , 8 )
 
doc.Close ( )
 
word.Quit ( )

关键的就是doc.SaveAs(‘d:/labs/math.html’, 8)这一行,网上很多文章写成:doc.SaveAs(‘d:/labs/math.html’, win32com.client.constants.wdFormatHTML),直接报错:

AttributeError: class Constants has no attribute ‘wdFormatHTML’

当然你也可以用上面的代码将word文件转换成任意格式文件(只要office 2007支持,比如将word文件转换成PDF文件,把8改成17即可),下面是office 2007支持的全部文件格式对应表:

wdFormatDocument                    =  0
wdFormatDocument97 = 0
wdFormatDocumentDefault = 16
wdFormatDOSText = 4
wdFormatDOSTextLineBreaks = 5
wdFormatEncodedText = 7
wdFormatFilteredHTML = 10
wdFormatFlatXML = 19
wdFormatFlatXMLMacroEnabled = 20
wdFormatFlatXMLTemplate = 21
wdFormatFlatXMLTemplateMacroEnabled = 22
wdFormatHTML = 8
wdFormatPDF = 17
wdFormatRTF = 6
wdFormatTemplate = 1
wdFormatTemplate97 = 1
wdFormatText = 2
wdFormatTextLineBreaks = 3
wdFormatUnicodeText = 7
wdFormatWebArchive = 9
wdFormatXML = 11
wdFormatXMLDocument = 12
wdFormatXMLDocumentMacroEnabled = 13
wdFormatXMLTemplate = 14
wdFormatXMLTemplateMacroEnabled = 15
wdFormatXPS = 18

照着字面意思应该能对应到相应的文件格式,如果你是office 2003可能支持不了这么多格式。word文件转html有两种格式可选wdFormatHTML、wdFormatFilteredHTML(对应数字 8、10),区别是如果是wdFormatHTML格式的话,word文件里面的公式等ole对象将会存储成wmf格式,而选用 wdFormatFilteredHTML的话公式图片将存储为gif格式,而且目测可以看出用wdFormatFilteredHTML生成的HTML 明显比wdFormatHTML要干净许多。

当然你也可以用任意一种语言通过com来调用office API,比如PHP.

 

=========================================

使用 python 写 COM

 

2009年09月03日 星期四 下午 07:01

from : http://www.cppblog.com/bigsml/archive/2008/08/14/58851.html

Python 支持Com调用(client com) 以及撰写COM 组件(server com).
1. com 调用示例(使用Windows Media Player 播放音乐)

from win32com.client import Dispatch
mp
= Dispatch( " WMPlayer.OCX " )
tune
= mp.newMedia( " C:/WINDOWS/system32/oobe/images/title.wma " )
mp.currentPlaylist.appendItem(tune)
mp.controls.play()


2. com server 的编写
主要可以参考 <<Python Programming on Win32 之 Chapter 12 Advanced Python and COM http://oreilly.com/catalog/pythonwin32/chapter/ch12.html >>
示例(分割字符串)
- 代码

class PythonUtilities:
     _public_methods_
= [ ' SplitString ' ]
     _reg_progid_
= " PythonDemos.Utilities "
    
# NEVER copy the following ID
     # Use "print pythoncom.CreateGuid()" to make a new one.
     _reg_clsid_ = " {41E24E95-D45A-11D2-852C-204C4F4F5020} "
    
    
def SplitString(self, val, item = None):
        
import string
        
if item != None: item = str(item)
        
return string.split(str(val), item)

# Add code so that when this script is run by
#
Python.exe, it self-registers.
if __name__ == ' __main__ ' :
    
print " Registering COM server "
    
import win32com.server.register
     win32com.server.register.UseCommandLine(PythonUtilities)


- 注册/注销Com

Command-Line Option

Description

 

The default is to register the COM objects.

--unregister

Unregisters the objects. This removes all references to the objects from the Windows registry.

--debug

Registers the COM servers in debug mode. We discuss debugging COM servers later in this chapter.

--quiet

Register (or unregister) the object quietly (i.e., don't report success).


- 使用COM
可以在python 命令行下运行

>>> import win32com.client
>>> s = win32com.client.Dispatch( " PythonDemos.Utilities " )
>>> s.SplitString( " a,b,c " , " , " )
((u
' a ' , u ' a,b,c ' ),)
>>>


3. python server com 原理
其实在注册表中查找到python com 的实现内幕

Windows Registry Editor Version 5.00

[ HKEY_CLASSES_ROOT/CLSID/{41E24E95-D45A-11D2-852C-204C4F4F5020} ]
@
= " PythonDemos.Utilities "

[ HKEY_CLASSES_ROOT/CLSID/{41E24E95-D45A-11D2-852C-204C4F4F5020}/Debugging ]
@
= " 0 "

[ HKEY_CLASSES_ROOT/CLSID/{41E24E95-D45A-11D2-852C-204C4F4F5020}/Implemented Categories ]

[ HKEY_CLASSES_ROOT/CLSID/{41E24E95-D45A-11D2-852C-204C4F4F5020}/Implemented Categories/{B3EF80D0-68E2-11D0-A689-00C04FD658FF} ]

[ HKEY_CLASSES_ROOT/CLSID/{41E24E95-D45A-11D2-852C-204C4F4F5020}/InprocServer32 ]
@
= " pythoncom25.dll "
" ThreadingModel " = " both "

[ HKEY_CLASSES_ROOT/CLSID/{41E24E95-D45A-11D2-852C-204C4F4F5020}/LocalServer32 ]
@
= " D://usr//Python//pythonw.exe / " D://usr//Python//lib//site-packages//win32com//server//localserver.py/ " {41E24E95-D45A-11D2-852C-204C4F4F5020} "

[ HKEY_CLASSES_ROOT/CLSID/{41E24E95-D45A-11D2-852C-204C4F4F5020}/ProgID ]
@
= " PythonDemos.Utilities "

[ HKEY_CLASSES_ROOT/CLSID/{41E24E95-D45A-11D2-852C-204C4F4F5020}/PythonCOM ]
@
= " PythonDemos.PythonUtilities "

[ HKEY_CLASSES_ROOT/CLSID/{41E24E95-D45A-11D2-852C-204C4F4F5020}/PythonCOMPath ]
@
= " D:// "

inproc server 是通过pythoncom25.dll 实现
local server 通过localserver.py 实现
com 对应的python 源文件信息在 PythonCOMPath & PythonCOM

4. 使用问题
用PHP 或者 c 调用com 的时候

<? php
$com = new COM( " PythonDemos.Utilities " );
$rs = $com -> SplitString( " a b c " );
foreach ( $rs as $r )
    
echo $r . " /n " ;
?>

会碰到下面的一些错误.
pythoncom error: PythonCOM Server - The 'win32com.server.policy' module could not be loaded.
<type 'exceptions.ImportError'>: No module named server.policy pythoncom error: CPyFactory::CreateInstance failed to create instance. (80004005)


可以通过2种方式解决:
a. 设置环境 PYTHONHOME = D:/usr/Python
另外在c ++ 使用python 的时候, 如果import module 出现错误 'import site' failed; use -v for traceback 的话, 也可以通过设置这个变量解决.

b. 为com 生产exe, dll 可执行文件, setup.py 代码如下 :

from distutils.core import setup
import py2exe

import sys
import shutil

# Remove the build tree ALWAYS do that!
shutil.rmtree( " build " , ignore_errors = True)

# List of modules to exclude from the executable
excludes = [ " pywin " , " pywin.debugger " , " pywin.debugger.dbgcon " , " pywin.dialogs " , " pywin.dialogs.list " ]

# List of modules to include in the executable
includes = [ " win32com.server " ]

# ModuleFinder can't handle runtime changes to __path__, but win32com uses them
try :
    
# if this doesn't work, try import modulefinder
     import py2exe.mf as modulefinder
    
import win32com
    
    
for p in win32com. __path__ [ 1 :]:
         modulefinder.AddPackagePath(
" win32com " , p)
    
    
for extra in [ " win32com.shell " , " win32com.server " ]: # ,"win32com.mapi"
         __import__ (extra)
         m
= sys.modules[extra]
        
for p in m. __path__ [ 1 :]:
             modulefinder.AddPackagePath(extra, p)

except ImportError:
    
# no build path setup, no worries.
     pass

# Set up py2exe with all the options
setup(
     options
= { " py2exe " : { " compressed " : 2 ,
                          
" optimize " : 2 ,
                          
# "bundle_files": 1,
                           " dist_dir " : " COMDist " ,
                          
" excludes " : excludes,
                          
" includes " : includes}},
    
# The lib directory contains everything except the executables and the python dll.
     # Can include a subdirectory name.
     zipfile = None,
     com_server
= [ 'PythonDemos ' ], # 文件名!!
     )



ref:
http://oreilly.com/catalog/pythonwin32/chapter/ch12.html
http://blog.donews.com/limodou/archive/2005/09/02/537571.aspx

 


2013-09-09 15:42:51 yangjianli868 阅读数 816

本文为自己亲自测试通过在office2007上。
#coding:utf-8

import win32com.client as win32
RANGE = range(3,8)

def outlook():
    app= 'Outlook'
    olook = win32.gencache.EnsureDispatch("%s.Application" % app)   
    mail=olook.CreateItem(win32.constants.olMailItem)
    mail.Recipients.Add('jianl@163.com')
    mail.Recipients.Add('jianliy@sina.com')   
    subj = mail.Subject = '21112Python -to - %s ' %app
    body = ["line %d" % i for i in RANGE]
#  body.insert(0,"%s\r\n" %subj)
    body.append("\r\nThat's all folks!")
    mail.Body = '\r\n'.join(body)
    mail.Send()
    print "send ok"
#============================================================================================   
    #以下为对收件箱、已发送、发件箱、草稿箱、已删除、任务进行的操作
(目前我还没找到垃圾邮件获取的方法)。
    ns = olook.GetNamespace("MAPI")
   
    #收件箱
    inbox = ns.GetDefaultFolder(win32.constants.olFolderInbox)
    messages1 = inbox.Items
    print u"收件箱邮件数量 :",messages1.Count
   
    #已发送邮件数量
    sentmail = ns.GetDefaultFolder(win32.constants.olFolderSentMail)
    messages2 = sentmail.Items
    print u"已发送邮件数量 :",messages2.Count
   
    #已删除邮件数量
    DeletedItems = ns.GetDefaultFolder(win32.constants.olFolderDeletedItems)
    messages3 = DeletedItems.Items
    print u"已删除邮件数量 :",messages3.Count
   
    #草稿数量
    drafts = ns.GetDefaultFolder(win32.constants.olFolderDrafts)
    messages4 = drafts.Items
    print u"草稿邮件数量 :",messages4.Count
   
    #发件箱   
    outbox = ns.GetDefaultFolder(win32.constants.olFolderOutbox)
    messages5 = outbox.Items
    print u"发件箱邮件数量 :",messages5.Count
#    obox.Display() #打开发件箱
#    obox.Items.Item(1).Display()#打开发件箱中第一封邮件
   
    #任务操作
    task_list = ns.GetDefaultFolder(win32.constants.olFolderTasks)
    tasks = task_list.Items
    print u"任务数量:", tasks.Count
           
if __name__ =="__main__":
    outlook()
   
参考内容如下:
#http://mail.python.org/pipermail//python-win32/2011-August/011754.html
# http://www.java2s.com/Tutorial/Python/0460__Windows/OutlookExample.htm
# http://www.outlookcode.com/
没有更多推荐了,返回首页