記事
· 2022年7月4日 7m read

Embedded Python:ExcelからPDFに変換する方法(Windows環境のみ)

開発者の皆さん、こんにちは!

PythonでExcelからPDFへ変換を行うには、pywinを使うとできるらしいので、IRISにあるデータをDataframeに設定した後Excelに出力し、ExcelからPDFに変換する流れを、Embedded Pythonで試してみました。

メモ:pywinはWindows環境下で動くモジュールのようです。

Excelに出力するデータですが、例では、SELECTの結果をDataframeに格納する方法を利用しています。グローバル変数の情報をDataframeに格納する方法については、以下の記事で詳しくご紹介しています。ぜひご参照ください。
Embedded Python で IRIS グローバル($LB) を Pandas Dataframe に変換する方法

 

まずは、必要なモジュールをインストールする必要があるので、pywin32 モジュールを irispipを使ってインストールします。

以下の例では、IRIS for Health が c:\InterSystems\IRISHealth にインストールされている状態で実行しています。

Embedded Pythonは、IRIS/IRIS for Health どちらでも利用できます。​​​​

c:\InterSystems\IRISHealth\bin>irispip install --target c:\InterSystems\IRISHealth\mgr\python pywin32
Collecting pywin32
  Using cached pywin32-304-cp39-cp39-win_amd64.whl (12.2 MB)
Installing collected packages: pywin32
Successfully installed pywin32-304
// 以下省略

 

pywin32モジュールインストール後、以下の作業を行うことで、Embedded Python でExcelからPDFへの変換を実行できるようになりました。

  1. 専用DLL(pythoncom39.dll とpywintypes39.dll)を c:\windows\system32以下にコピー
  2. pywin32のパス2種(<IRISインストールディレクトリ>\mgr\python\win32\lib と <IRISインストールディレクトリ>\mgr\python\win32)を sys.pathに追加
  3. IRISのサービスアカウントを管理者ユーザに変更:ご参考「サービスアカウントの変更について【IRIS】

 

それぞれの手続きをご紹介します。

1. 専用DLL(pythoncom39.dll とpywintypes39.dll)を c:\windows\system32以下にコピー

インストール後、さっそく import win32com.client を実行したいところですが、IRISターミナルから起動するPythonシェルで実行すると以下のエラーが出てしまいます。

>>> import win32com.client
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "c:\intersystems\irishealth\mgr\python\win32com\__init__.py", line 5, in <module>
    import win32api, sys, os
ModuleNotFoundError: No module named 'win32api

このエラーをググりますと、以下の投稿に辿り着き、

How to fix "ImportError: DLL load failed" while importing win32api

👆52番の回答を試してみると、インポートできるようになりました。

具体的な手続きは以下の通りです。

irispipでインストールしたpywin32の2種類のDLL(pythoncom39.dll とpywintypes39.dll)を c:\windows\system32にコピーします。

irispipでインストールされる場所:<IRISインストールディレクトリ>\mgr\python\pywin32_system32

例)C:\InterSystems\IRISHealth\mgr\python\pywin32_system32

 

2. pywin32のパス2種を sys.pathに追加

import win32com.client を行うため、sys.pathにpywin32のインストールで用意される以下2つのディレクトリを追加する必要がありました。

参考記事:http://blog.livedoor.jp/blackcode/archives/python-win32api-import-error....

  • <IRISインストールディレクトリ>\mgr\python\win32\lib
  • <IRISインストールディレクトリ>\mgr\python\win32

例は以下の通りです。

import sys
sys.path += ['C:\InterSystems\IRISHealth\mgr\python\win32\lib','C:\InterSystems\IRISHealth\mgr\python\win32']

 

3. IRISのサービスアカウントを管理者ユーザに変更

1、2までで、import win32com.client  は成功しますが、肝心のExcelからPDFへ変換する流れでエラーが出ます😢。

どうやら、ExcelからPDF変換の流れを管理者権限で実行する必要があり、IRISのサービスアカウントが規定(SYSTEMアカウント)である場合に失敗します。

IRISのサービスアカウントを管理者に変更します(管理者権限でコマンドプロンプトを起動した後、以下のコマンドを実行します)。

例)<IRISインストールディレクトリ>\bin> irisinstall setserviceusername 構成名 ユーザ名 パスワード

c:\InterSystems\IRISHealth\bin>irisinstall setserviceusername IRISHealth userx passwordx

サービスアカウント変更後、IRISの再起動が必要となります。

サービスアカウントの変更について【IRIS】

※サービスアカウントを変更した場合の注意点

サービスアカウントを LOCAL_SYSTEM から変更すると、権限が不足するため、IRIS開始時の共有メモリの取得に Large Page (※)が使用できなくなります。
Windows上でのCaché共有メモリの割り当てについて

Large Pageを使用するためには、変更したアカウントに対して"メモリ内のページのロック" 特権を付与する必要があります。
“メモリ内のページのロック” 特権の付与は、ローカルセキュリティポリシー(secpol.msc)より実施します。

 

1~3までの手続きを行った後、以下のPythonスクリプトファイルを実行できるようになります。

スクリプト例では、2つ関数を用意しています。以下それぞれの概要です。

 

関数:CreateExcel(ファイルフルパス) では、Test.Personテーブルを作成し、テストデータを4件登録し、Excel出力しています。(関数最後にTest.PersonをDropしています)

Excel出力の為、openpyxlとpandasのインストールが必要です。irispipでインストールしてから実行してください。

例)
c:\InterSystems\IRISHealth\bin\irispip install --target c:\InterSystems\IRISHealth\mgr\python openpyxl
c:\InterSystems\IRISHealth\bin\irispip install --target c:\InterSystems\IRISHealth\mgr\python pandas

 関数:Output(エクセルファイルフルパス,PDFファイルフルパス) では、関数CreateExcel()を呼び出し、Excelファイルを準備してから、PDF変換を行っています。

第1引数:出力したいエクセルファイル名をフルパスで指定します。例)c:\\temp\\Book4.xlsx

第2引数:Excelから変換するPDF保存名でフルパスで指定します。 例)c:\\temp\\Book4.pdf

サンプルコードは以下の通りです。

import sys
sys.path += ['C:\InterSystems\IRISHealth\mgr\python\win32\lib','C:\InterSystems\IRISHealth\mgr\python\win32']

# 以下 python.exeから実行する時のパス
sys.path+=['c:\intersystems\irishealth\mgr\python','c:\intersystems\irishealth\lib\python']
import iris

#--------------------------------------------
import win32com.client
import pandas as pd
import openpyxl
from openpyxl.utils.dataframe import dataframe_to_rows


def CreateExcel(filename):
    sql="create table Test.Person (Name VARCHAR(50),Email VARCHAR(50))"
    rs=iris.sql.exec(sql)
    rs=iris.sql.exec("insert into Test.Person (Name,Email) VALUES('テスト1','test1@mail.com')")
    rs=iris.sql.exec("insert into Test.Person (Name,Email) VALUES('テスト2','test2@mail.com')")
    rs=iris.sql.exec("insert into Test.Person (Name,Email) VALUES('テスト3','test3@mail.com')")
    rs=iris.sql.exec("insert into Test.Person (Name,Email) VALUES('テスト4','test4@mail.com')")

    df=iris.sql.exec("select Name,Email from Test.Person").dataframe()
    #df.to_excel(filename)
    wb=openpyxl.Workbook()
    ws = wb.create_sheet(title="シート1")
    ws.append(['行番号', '名前', 'メール'])

    for i,row in enumerate(dataframe_to_rows(df,header=False)):
        if i==0:
            continue
        ws.append(row)
    wb.save(filename)
    wb.close()
    rs=iris.sql.exec("drop table Test.Person")

def Output(filename,pdfname):
    CreateExcel(filename)

    excel = win32com.client.Dispatch("Excel.Application")
    wb=excel.WorkBooks.Open(filename)
    wb.WorkSheets("シート1").Select()
    wb.ActiveSheet.ExportAsFixedFormat(0,pdfname)
    excel.quit()

 

上記コードを c:\WorkSpace\TryPython\ExcelToPDF.py に配置した状態とします。

ObjectScritpからの実行例は以下の通りです。

set sys=##class(%SYS.Python).Import("sys")
do sys.path.append("c:\WorkSpace\TryPython")
set e=##class(%SYS.Python).Import("ExcelToPDF")
do e.Output("c:\\temp\\Book5.xlsx","c:\\temp\\Book5.pdf")

 

Pythonシェルからの実行例は以下の通りです。

C:\WorkSpace\TryPython> python
Python 3.9.10 (tags/v3.9.10:f2f3f53, Jan 17 2022, 15:14:21) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path+=['C:\WorkSpace\TryPython']
>>> import ExcelToPDF as e
>>> e.Output("c:\\temp\\Book6.xlsx","c:\\temp\\Book6.pdf") 

 

少し前準備が多いですが、Pythonの機能を活用してIRISにあるデータをExcel出力+PDF変換までできました🐍

Pythonとても便利ですね!

ディスカッション (0)1
続けるにはログインするか新規登録を行ってください