【Python】win32comでExcel操作する方法

  • URLをコピーしました!

Pythonのwin32comライブラリーでExcel操作する方法をまとめた記事です。

前半は基本的なコードの書き方、後半は実践的なサンプルコードを紹介します。

なお、win32comはWindows環境かつExcelインストール済み環境でのみ動作します。

mac OSだとwin32comは動作しないので、xlwingsやopenpyxlを使いましょう。

【基本編】コードの書き方

win32comでExcel操作をするための基本的なコードを紹介します。

なお、win32comでは大文字・小文字を区別するのでご注意ください。

win32comライブラリのインストール

一般的なライブラリ同様、win32comもpip installでインストールできます。

pip install pywin32

コマンドプロンプト上で上記のコードを実行することで、Outlook操作に必要なwin32comライブラリのインストールができます。

なお、冒頭でもご説明の通りwin32comはWindowsのみ対応です。MacOS等をお使いの場合はxlwingsやopenpyxlなどを使います。

import/Excel Appのインスタンス化

import win32com.client

# ExcelAppのインスタンス化
excel = win32com.client.Dispatch("Excel.Application")
# バックグラウンド
excel.Visible = False
# 警告非表示
excel.DisplayAlerts = False

VisibleFalseにするとExcelの画面を表示されなくなるため、誤作動を防ぎたい場合に有効です。逆に挙動を確認したい場合はTrueにします。

また、「ブックを保存しますか?」などの警告を出したくない場合はDisplayAlertsFalseにします。

ブックを開く

# ブックを開く
wb = excel.Workbooks.Open(book_path)

既存のブックを操作する場合には、まずブックを開きます。

ここで作成した変数wbは、シートをセットする際に使います。

シートをセット

# シートをセット
ws = wb.Worksheets(sheet_name)

sheet_nameには操作したいシート名を文字列で渡せばOKです。

セル番地で値を取得・入力

# 値を入力
ws.Range("A1").Value = "A1に入力"
# 値を取得
var = ws.Range("A1").Value

セル番地を指定して値を出し入れする場合はRangeメソッドを使います。

行・列番号で値を取得・入力

# 値を入力
ws.Cells(1, 1).Value = "A1に入力"
# 値を取得: A2セル
var = ws.Cells(2, 1).Value

変数で操作するセルを可変的にしたい場合はCellsの方が扱いやすいです。

関数の入力

# 関数を入力
ws.Range("A1").Formula = "=SUM(A2:A10)"

Valueを使ってしまうと文字列が入ってしまうのでFormulaを使います。

最終行の取得

# 最終行を取得(1列目)
endRow = ws.Cells(ws.Rows.Count, 1).End(-4162).Row

Cellsの第二引数(列番号)を1としているので、1列目の最終行を取得します。

なお-4162は何かというと、Ctrlを押したままキーを押す挙動を表します。(VBAでいうところのxlUp

今回は最終行の取得なのでキーにしましたが、他の番号が知りたい方はWindowsの公式ドキュメントを参照してみてください。

【参考】公式ドキュメント

セル範囲をリストに格納

# 空のリストを用意
array = []
# A1からB4セルをリストとして取得
array = ws.Range("A1:B4").Value

# リスト化
array = [list(map(int, row)) for row in array]

リストの中身はタプルになるので、純粋なリストに直す場合はリスト内包表記などで対応します。

最終行の取得と組み合わせるのも有効です。

すべてのセルをリストに格納

# すべてのセルをリストに格納
array = ws.UsedRange.Value

セル範囲を指定せずにすべてのセルを取得する場合は、UseRangeが使えます。

とはいえこの方法はごっそりと取得してきてしまって使いづらいので、Pandasのread_excelの方が扱いやすいです。

すべてのシートをA1セル選択状態にする

### すべてのシートをA1セル選択状態にする
# シート数を取得
sheet_num = wb.Worksheets.Count
# 後ろのシートから順に開く
for i in range(sheet_num, 0, -1):
    ws = wb.Worksheets(i)
    # シートをアクティブにする
    ws.Activate
    # A1セルをアクティブにする
    ws.Cells(1, 1).Activate

列幅を自動調整

# 列幅を自動調整
ws.Columns("A:G").AutoFit()

列を隠す

# 列を隠す
ws.Columns("A:G").EntireColumn.Hidden = False

シートを追加

# 新しいシートを追加する
wb.Sheets.Add()

指定したシートの前にシートを追加

# wsの前に新規シートを追加
excel.Sheets.Add(Before=ws)

指定したシートの後にシートを追加

# wsの後に新規シートを追加
excel.Sheets.Add(Before=None, After=ws)

余談ですが、excel.Sheets.Add(After=ws)のようにBeforeを省略すると動作しません。

このようにwin32comでは名前つき引数が正常に動作しないことがあります。

シートの削除

# wsを削除
ws.Delete()

シート名の変更

# wsのシート名を変更
ws.Name = "new_name"

ブックを上書き保存する

# 上書き保存
wb.Save()

ブックを名前をつけて保存

# 名前をつけて保存
wb.SaveAs(output_path)

ブックを閉じる

# ブックを閉じる
wb.Close()

シートをPDF化する

# wsをPDF化する
ws.ExportAsFixedFormat(0, output_path)

複数シートをPDF化する

# sheet1,sheet2を選択する
wb.Worksheets(["sheet1", "sheet2"]).Select()
# 選択したシートをPDF化する
wb.ActiveSheet.ExportAsFixedFormat(0, output_path)

PDF化したいシートを選択した状態でExportAsFixedFormatを使います。

全シートをPDF化する

# 空のリストを準備
array = []
# 全シートをsheet_listに格納
for sheet_name in wb.Sheets:
    array.append(sheet_name)

# 全シートを選択
wb.Worksheets(array).Select()
# 選択されたシートをPDF化
wb.ActiveSheet.ExportAsFixedFormat(0, output_path)

すべてのシートをPDF化する場合も考え方は同じです。

全シートを個別にPDFにする

# Sheetの数を取得
sheet_count = wb.Workbook.Count

# 左のシートから順次PDF化
for i in range(sheet_count):
    # i+1番目のシートを選択(iはゼロ始まりのため、+1する)
    wb.Worksheets(i+1).Select()
    # 選択されたシートをPDF化
    wb.ActiveSheet.ExportAsFixedFormat(0, output_path)

ご質問いただき加筆いたしました!

シート番号は1から始まるので、イテレーターのiに+1するのを忘れないでください。

【実践編】サンプルコード

【基本編】で紹介したコードを使ったサンプルコードを公開します。

サンプルコード掲載の要望はコメント欄より受け付けております!

ブック内の全シートをPDF化する

import getpass
import win32com.client
import os

user_name = getpass.getuser()

base_path = rf"C:\Users\{user_name}\Desktop"
book_path = os.path.join(base_path, "excel.xlsx")
sheet_name = r"sheet1"

output_path = os.path.join(base_path, "output.pdf")

# ExcelAppのインスタンス化
excel = win32com.client.Dispatch("Excel.Application")
excel.Visible = False
excel.DisplayAlerts = False

# ブック、シートのセット
wb = excel.Workbooks.Open(book_path)
ws = wb.Worksheets(sheet_name)

# 空のリストを準備
array = []
# 全シートをsheet_listに格納
for sheet_name in wb.Sheets:
    array.append(sheet_name.Name)

# 全シートを選択
wb.Sheets(array).Select()
# 選択されたシートをPDF化
wb.ActiveSheet.ExportAsFixedFormat(0, output_path)

# ブックを閉じる
wb.Close()
# Excel Appを終了
excel.Quit()

まとめ

Windows以外のOSでは使えないというデメリットはあるものの、動作の安定性としてはwin32comが一番だと思います。

より高速な動作を求めるならopenpyxlを、Macで安定した動作を求めるならxlwingsの導入も検討してみてください。

この記事が気に入ったら
フォローしてね!

シェアしてもらえると喜びます!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

Pythonを使ってプログラムを書くお仕事をしています。
業務自動化プログラムの作成が得意で、物販のお仕事をされている方や士業事務所様に業務効率化のツールをご提供させていただいております。
現在自力でWebサービスを作れるようになるべくDjangoを学習中。
お仕事のご相談はお気軽にご連絡ください。

コメント

コメント一覧 (6件)

  • ブック内の全シートを個別にPDFにしたい場合にはどうすればいいのでしょうか。

    • 佐藤様、初めまして!ご質問ありがとうございます。
      1シートに対して1つのPDFを出力するということでよろしいでしょうか?
      手順としては次の流れになります。
      ・ブック内にあるシート数を取得
      ・シート番号をループする
      ・Select→PDF出力を繰り返す
      本記事の【全シートを個別にPDFにする】という見出しをつけてサンプルコードを掲載させていただきましたので、よろしければ参考にしてみてください!

        • ぜひ試してみてください^^
          もしうまく動かないようでしたらまたメッセージいただければと思います!

  • ブック内の全シートをPDF化するの
    user_name = getpass.getuser()
    book_path = rf”/Users/{user_name}/Desktop/excel.xlsx”
    sheet_name = r”sheet1″
    コードは何を意味しますでしょうか。

    raise AttributeError(“%s.%s” % (self._username_, attr))というエラーが出ており対処に困っております。

    お時間ございますときに、ご教授いただけましたら幸いです。

    • 佐藤様
      ご質問ありがとうございます!
      すみません、コードにおかしな点がありましたので修正させていただきました。一度新しいコードで実行いただけますと幸いです!

      なお、user_nameの部分ではパソコンのユーザー名を取得しています。
      通常Windows PCは”C:\Users\ユーザー名\Desktop”という風に表されるので、getpass.getuser()を使ってプログラム上からユーザー名を取得すれば、動作させるPCが変わってもパスを修正せずに動作させることができます。

コメントする