目次
1. はじめに
2. 環境
3. インストールするライブラリ
4. サンプルコード
5. 補足
6. 参考にしたサイト
1. はじめに
PythonでExcel
、Word
、PowerPoint
の図形処理をしたら嵌ったお話
- Googleで検索だと
python-docx
、python-pptx
のライブラリが出てくるが、このライブラリだと図形で操作できない機能があるので嵌る(結局、pywin32
になる) -
Excel
、Word
、PowerPoint
でパスワード(読み取り、書き込み)を設定されてるとダイアログが表示されて処理が停止して嵌る(Googleで検索するとパスワード解析ばかりで、スキップするだけの内容が出てこない) - ネットワークドライブ経由のファイルサーバ操作で大量処理すると
win32com
でネットワークエラーになり嵌る(win32com
エラーはあまり情報がなくて探すのが大変)
2. 環境
- Windows10 Pro:21H2
- Microsoft Office 2019
- Python:3.10.4
3. インストールするライブラリ
- pywin32:WindowsのAPIを呼び出すライブラリ
pip install pywin32
4. サンプルコード
import win32com.client
import pythoncom
from abc import ABCMeta, abstractmethod
#main処理
def main():
#Excel図形操作
excel = Excel(r"Excelファイルのフルパス")
excel.shape_control()
#Word図形操作
word = Word(r"Wordファイルのフルパス")
word.shape_control()
#PowerPoint図形操作
powerpoint = PowerPoint(r"PowerPointファイルのフルパス")
powerpoint.shape_control()
#-----------------------------------------------------
# Documentクラス(インターフェース)
#-----------------------------------------------------
class Document(metaclass=ABCMeta):
@abstractmethod
def shape_control(self):
pass
#-----------------------------------------------------
# Excelクラス
#-----------------------------------------------------
class Excel(Document):
def __init__(self, file_name):
self.file_name = file_name
# Excel図形操作
def shape_control(self):
pythoncom.CoInitialize() #win32com開始前にこれを呼び出す
excel = win32com.client.DispatchEx("Excel.Application") #ファイルサーバなどのリモートの大量処理ではDispatchではなくDispatchExを使う
excel.Visible = True
try:
excel.DisplayAlerts = False
doc = excel.Workbooks.Open(self.file_name,False ,False ,None ,"dummy@password" ,"dummy@password" ,True) #パスワード有りはダミーパスワードで無視
sheet = doc.Worksheets(1) #1シート目を対象
#シート内の図形を全て処理
for shape in sheet.Shapes:
try:
print(shape.TextFrame.Characters().Text.strip())
except:
print("Error")
doc.Close(False) #閉じる
except:
print("Error")
finally:
excel.DisplayAlerts = True
excel.Quit()
del excel
pythoncom.CoUninitialize() #終了した後はこれを呼び出す
#-----------------------------------------------------
# Wordクラス
#-----------------------------------------------------
class Word(Document):
def __init__(self, file_name):
self.file_name = file_name
# Word図形操作
def shape_control(self):
pythoncom.CoInitialize() #win32com開始前にこれを呼び出す
word = win32com.client.DispatchEx("Word.Application") #ファイルサーバなどのリモートの大量処理ではDispatchではなくDispatchExを使う
word.Visible = True
try:
word.DisplayAlerts = False
doc = word.Documents.Open(self.file_name, False, False, None,"dummy@password", "dummy@password", False, "dummy@password", "dummy@password") #パスワード有りはダミーパスワードで無視する
#ドキュメント内の図形を全て処理
for shape in doc.Shapes:
try:
print(shape.TextFrame.TextRange.Text.strip())
except:
print("Error")
doc.Close(False) #閉じる
except:
print("Error")
finally:
word.DisplayAlerts =True
word.Quit()
del word
pythoncom.CoUninitialize() #win32com終了時にこれを呼び出す
#-----------------------------------------------------
# PowerPointクラス
#-----------------------------------------------------
class PowerPoint(Document):
def __init__(self, file_name):
self.file_name = file_name
# PowerPoint図形操作
def shape_control(self):
pythoncom.CoInitialize() #win32com開始前にこれを呼び出す
powerpoint =win32com.client.DispatchEx("PowerPoint.Application") #ファイルサーバなどのリモートの大量処理ではDispatchではなくDispatchExを使う
powerpoint.Visible = True
try:
doc = powerpoint.Presentations.Open(self.file_name +"::dummy@password::dummy@password") #パスワード有りはダミーパスワードで無視する
slide = doc.slides[0] #1スライド目を対象
#ドキュメント内の図形を全て処理
for shape in slide.shapes:
try:
print(shape.TextFrame.TextRange.Text.strip())
except:
print("Error")
doc.Close() #閉じる
except:
print("Error")
finally:
powerpoint.Quit()
del powerpoint
pythoncom.CoUninitialize() #win32com終了時にこれを呼び出す
#main呼び出し
if __name__ == "__main__":
main()
5. 補足
-
【情報少なめの嵌まりポイント】
pywin32(win32com)で頻発するエラー
Traceback (most recent call last):
File "C:\Python39\lib\site-packages\win32com\client\dynamic.py", line 86, in _GetGoodDispatch
IDispatch = pythoncom.connect(IDispatch)
pywintypes.com_error: (-2147221021, '操作を利用できません', None, None)
IDispatch = pythoncom.CoCreateInstance(
pywintypes.com_error: (-2146959355, 'サーバーの実行に失敗しました', None, None)
Traceback (most recent call last):
File "C:\Python39\lib\site-packages\win32com\client\dynamic.py", line 707, in setattr
raise AttributeError(
AttributeError: Property 'Excel.Application.Visible' can not be set.
- 上記エラーは、下記2つのリンク先のあわせ技で解消
-
Dispatch
をDispatchEx
にする
ファイルサーバとかリモートのファイルを大量処理する場合にプロセスを殺しきれない時があるのでDispatchEx
した方が良い
pywin32 を使用すると、Dispatch と DispatchEx の違いは何ですか? -
CoInitialize
とCoUninitialize
を追加する
上記1.だけでも問題ないと思われるが、それでもwin32com
を使いエラーになる時はおまじない的に呼んでおいた方が良い
com_error at / (-2147221008, 'CoInitialize は呼び出されていません。', None, None)
-