第24回.エクセルを操作する(pywin32:win32com)
PythonでExcelファイルを扱ってみましょう。
前回は外部ライブラリのopenpyxlを使いました。
今回は外部ライブラリのpywin32を使います。
pywin32は、PythonからWindowsAPIへのアクセスを提供してくれます。
実際にエクセルを操作する部分はVBAになります。
したがって、VBAの知識が無ければ全く使う事はできないことは理解しておいてください。
VBAについては以下を参照にしてください。
pywin32を使ったエクセル操作はVBAの説明になってしまいます。
ここではVBAの説明は一切せずに、実際のpywin32を使ったサンプルコードを掲載します。
サプルコードは、基本的な操作については網羅するように各種パターンで作成しました。
目次
pywin32のインストール
Visual Studio
ここに「pywin32」これを入れてください。
文字を入れた後にEnterするとそのままインストールされます。
コマンド プロンプト
詳しくは以下を参照してください。
公式URL
ただし、そもそもpywin32は、PythonからWindowsAPIへのアクセスを提供しているだけなので、使い方そのものに困ることは無いと思います。
pywin32:win32comのエクセル操作サンプル
モジュールは、from win32com.client になります。
使う場合は以下のように記述します。
import win32com.client
xl = win32com.client.Dispatch("Excel.Application")
from win32com.client import Dispatch
xl = Dispatch("Excel.Application")
xl = win32com.client.GetObject(Class="Excel.Application")
import win32com.client
#すでにExcelが起動されている場合はそのタスクが使われる
#エラー終了するとタスクは残ります
xl = win32com.client.Dispatch("Excel.Application")
#動いている様子を見てみる
xl.Visible = True
#ブック追加
wb = xl.Workbooks.Add()
#シート追加
ws = wb.Worksheets.Add()
#シート名変更
ws.Name = "練習1"
#不要シート削除
xl.DisplayAlerts = False #無くても良いようだが
for sh in wb.Worksheets:
if sh.Name != ws.Name:
sh.Delete()
# セルに値を設定
for i, cell in enumerate(ws.Range("A1:B5")):
cell.Value = i
#セル値を2次元配列で取得:タプルで取得される
ary1 = ws.Range("A1:B5").Value
print(f"{ary1=}")
#セルに入れるために2次元タプルを2次元リストに変換
ary2 = [[c for c in r] for r in ary1]
print(f"{ary2=}")
#2次元配列の値を2倍
for r, row in enumerate(ary2):
for c, col in enumerate(row):
ary2[r][c] = col * 2
#2次元配列をセルに入れる
ws.Range("A1:B5").Value = ary2
#Rangeのコピー
ws.Range("A1:B5").Copy(Destination=ws.Range("D1"))
#セルの削除
ws.Columns(5).Delete()
#セルの削除
ws.Range(ws.Cells(2,4),ws.Cells(4,4)).Delete(Shift=-4162) #-4162=xlUp
#罫線設定
ws.Range("A1:B5").Borders.LineStyle = 1
#表示形式
ws.Range("B1").NumberformatLocal = "0.0%"
#フォント
ws.Range("A1").CurrentRegion.Font.Bold = True
ws.Range("A1").CurrentRegion.Font.Size = 14
ws.Range("A1").CurrentRegion.Font.Color = 0x0000FF #赤
#その他のRangeのプロパティ・メソッドの確認
ws.Rows(3).Hidden = True
ws.Range("A1:B5").EntireColumn.AutoFit()
#これ以降は出力シートを変更
ws = wb.Worksheets.Add()
ws.Name = "練習2"
#以降の結果をセルに出力するので:セル出力には2次元配列が必要
titles = (("Sum",),
("CountIf",),
("Match",),
("VLookup",),
("Range(""A1"")",),
("Range(""A1:B5"")",),
("Range(Cells,Cells)",),
("UsedRange",),
("CurrentRegion",),
("SpecialCells",),
("End(xlUp)",),
("Offset(1, 1)",),
("Offset(2, 2)",),
("Offset(3, 3)",),
("Resize(2, 2)",),
("Resize(3, 3)",),
("Address(0, 0)",),
("InputBox",))
ws.Range("A1:A18").Value = titles
#WorksheetFunction
ws.Range("B1").Value = xl.WorksheetFunction.Sum(ws.Range("A1:A5"), ws.Range("B1:B5"))
ws.Range("B2").Value = xl.WorksheetFunction.CountIf(ws.Range("A1:B5"),">10")
try: #検索値が無い場合はエラーになるので
ws.Range("B3").Value = xl.WorksheetFunction.Match("Match", ws.Range("A:A"), 0)
except Exception as e:
#タプルの入れ子かつ数値文字混在なのでちょっと面倒です。
ws.Range("B3").Value = ",".join([str(x) for x in e.args[2]])
try:
ws.Range("B4").Value = xl.WorksheetFunction.VLookup("VLookup", ws.Range("A:A"), 1, False)
except Exception as e:
ws.Range("B4").Value = ",".join([str(x) for x in e.args[2]])
#Offset:1ずれている?、承知して使うのは怖い気がする
ws.Range("B12").Value = ws.Range("A1").Offset(1, 1).Address
ws.Range("B13").Value = ws.Range("A1").Offset(2, 2).Address
ws.Range("B14").Value = ws.Range("A1").Offset(3, 3).Address
#Resize:これはおかしいので使えない
ws.Range("B15").Value = ws.Range("A1").Resize(2, 2).Address
ws.Range("B16").Value = ws.Range("A1").Resize(3, 3).Address
#Addressに引数が指定できない?:'str' object is not callable
try:
ws.Range("B17").Value = ws.Range("A1").Address(False, False)
except Exception as e:
ws.Range("B17").Value = str(e)
#InputBox:
ws.Range("B18").Value = xl.InputBox("入力してください。")
#ブックを保存:相対パスはExcel.Applicationから見た位置になります。
import os
wb.SaveAs(os.getcwd() + "/test.xlsx") #.pyと同ディレクトリ
wb.Close(SaveChanges=True)
#他のブックが開いていなければExcelを終了
if xl.Workbooks.Count == 0:
xl.quit()
後日追加・修正
#Offset:1ずれてしまう?、GetOffsetで正しく動作する。
ws.Range("B12").Value = ws.Range("A1").GetOffset(1, 1).Address
ws.Range("B13").Value = ws.Range("A1").GetOffset(2, 2).Address
ws.Range("B14").Value = ws.Range("A1").GetOffset(3, 3).Address
#Resize:これはおかしい?、GetResizeで正しく動作する。
ws.Range("B15").Value = ws.Range("A1").GetResize(2, 2).Address
ws.Range("B16").Value = ws.Range("A1").GetResize(3, 3).Address
#Addressに引数を指定する場合はGetAddressを使う
try:
ws.Range("B17").Value = ws.Range("A1").GetAddress(False, False)
except Exception as e:
ws.Range("B17").Value = str(e)
エクセルのマクロを起動する
import win32com.client
import os
xl = win32com.client.Dispatch("Excel.Application")
xl.Visible = True
wb = xl.Workbooks.Open(Filename=os.getcwd() + "/Book1.xlsm", ReadOnly=1)
xl.Run("Book1.xlsm!SampleMacro")
wb.Close(SaveChanges=False)
if xl.Workbooks.Count == 0:
xl.quit()
Runメソッドの詳細については以下を参照してください。
pywin32の問題点
・大文字小文字が区別される
・プロパティの名前付き引数が機能しない
・正しく機能しないプロパティがある
大きく分けるとこの3点だと思います。
もしかすると、僅かな記述の乱れから全て発生しているのかもしれませんが、詳細は不明なままです。
また、これは当然のことですが、Excelがインストールされていないと動作しませ。
大文字小文字が区別される
VBAでは大文字小文字を区別しないので、通常はこれを意識することはありません。
VBAが相当出来る人でも、識別子のスペルを大文字小文字まで含めて正しく記憶している人は少ないでしょう。
VBA定数およびxl定数は使えないので、VBEのイミディエイトなりで調べる必要があるのは、かなり面倒です。
プロパティの名前付き引数が機能しない
あまり多くの確認は出来ていませんが、メソッドの引数は機能しているようです。
残念ながら現在のところは、プロパティの引数を正しく機能させる方法は見つけることが出来ませんでした。
これがエラーになってしまうのでは、他に指定方法があったとしても使う事は難しくなります。
したがって、何らかの代替え手段は見つかると思います。
正しく機能しないプロパティがある
いずれにしても、本来とは違う挙動をするものがある以上、使う上ではかなり注意が必要です。
VBAには代替方法がいくらでもあるのでそんなに困ることは無いと思います。
同じテーマ「Python入門」の記事
第16回.Pythonの引数は参照渡しだが・・・
第17回.リスト内包表記
第18回.例外処理(try文)とexception一覧
第19回.import文(パッケージ・モジュールのインポート)
第20回.フォルダとファイルの一覧を取得(os,glob,pathlib)
第21回.CSV読み込みとopen()関数とwith文
第22回.CSV読み書き(csvモジュール)
第23回.pipコマンド(外部ライブラリのインストール)
第24回.エクセルを操作する(openpyxl)
第24回.エクセルを操作する(pywin32:win32com)
第26回.WEBスクレイピング(selenium)
新着記事NEW ・・・新着記事一覧を見る
TRIMRANGE関数(セル範囲をトリム:端の空白セルを除外)|エクセル入門(2024-08-30)
正規表現関数(REGEXTEST,REGEXREPLACE,REGEXEXTRACT)|エクセル入門(2024-07-02)
エクセルが起動しない、Excelが立ち上がらない|エクセル雑感(2024-04-11)
ブール型(Boolean)のis変数・フラグについて|VBA技術解説(2024-04-05)
テキストの内容によって図形を削除する|VBA技術解説(2024-04-02)
ExcelマクロVBA入門目次|エクセルの神髄(2024-03-20)
VBA10大躓きポイント(初心者が躓きやすいポイント)|VBA技術解説(2024-03-05)
テンキーのスクリーンキーボード作成|ユーザーフォーム入門(2024-02-26)
無効な前方参照か、コンパイルされていない種類への参照です。|エクセル雑感(2024-02-17)
初級脱出10問パック|VBA練習問題(2024-01-24)
アクセスランキング ・・・ ランキング一覧を見る
1.最終行の取得(End,Rows.Count)|VBA入門
2.繰り返し処理(For Next)|VBA入門
3.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
4.変数宣言のDimとデータ型|VBA入門
5.RangeとCellsの使い方|VBA入門
6.ブックを閉じる・保存(Close,Save,SaveAs)|VBA入門
7.セルのクリア(Clear,ClearContents)|VBA入門
8.メッセージボックス(MsgBox関数)|VBA入門
9.条件分岐(Select Case)|VBA入門
10.ブック・シートの選択(Select,Activate)|VBA入門
このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
記述には細心の注意をしたつもりですが、
間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。
掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。