python 3.13+pywin32でExcelを操作してみる

# 目的
python 3.13,0 がリリースされて動作確認ということで
[pywin32でExcelを操作してみる](https://qiita.com/tabizou/items/8e8b03e9b5415e3319c9)
を実行してみたらサンプルコードの xlc.xlLeft が参照不可をいうエラーメッセージが発生
これを解決するためには、パッケージの追加後の処理の項目にあるように
以下を実行する必要がある
<pre>
PS C:\> python Python313\Lib\site-packages\win32com\client\makepy.py
</pre>
既存のメモを修正するか迷ったのだけど、修正版を書くことにする
pywin32+Excelの調べものついでに少しだけ触って気がついたことをメモっておく

## 気が付いたこと
軽く検索したときに
```python
import win32com.client
xl = win32com.client.Dispatch("Excel.Application")
```
を見て以下を連想したんだけど
```vb
Dim myExcel As Object
Set myExcel = CreateObject("Excel.Application")
```
つまるところはそういうことなんですね
Object受けと同様なのでIntelliSenseが効かないのが残念！
Listが普通に使えるのはやはりうれしい

## パッケージの追加
[Installation](https://brian3johnson.github.io/pywin32/installation.html) より
<pre>
PS C:\> python -m pip install --upgrade pywin32
Collecting pywin32
  Downloading pywin32-307-cp313-cp313-win_amd64.whl.metadata (8.3 kB)
Downloading pywin32-307-cp313-cp313-win_amd64.whl (6.5 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 6.5/6.5 MB 592.6 kB/s eta 0:00:00
Installing collected packages: pywin32
Successfully installed pywin32-307
</pre>

## パッケージの追加後の処理
以下を実行しないとサンプルコードの xlc.xlLeft が参照不可になる
※以前試した時は、この手順を実行しないで動作が確認できたと思うのだが（謎
※バージョン指定のインストールは不可？のようなので当時のバージョンで試せない。
※実行した場合はメモに残しているはずなのに・・
[win32comで、makepyを使って COM(AcitveX)の定数をロードさせる手順について](https://wacky.hatenadiary.com/entry/20091011/1255240572) より
<pre>
PS C:\> python \path\to\Python313\Lib\site-packages\win32com\client\makepy.py
を実行後に「Microsoft Excel ver Object Library」を選択後 OKボタンを押下する。

Generating to C:\path\to\Python313\Lib\site-packages\win32com\gen_py\00020813-0000-0000-C000-000000000046x0x1x9.py
Building definitions from type library...
Generating...
Importing module
</pre>

## サンプルコード
VBAでCSVファイルを取り込んでWorksheetに書き込んでいるコードを書き直してみる
・対象データは[郵便番号検索](http://www.post.japanpost.jp/zipcode/)の17ISHIKA.CSV 
・コメントにもあるように、VBAで使用する定数はオブジェクトブラウザで確認できるようにExcel.Constantsに定義されている
```python
from win32com.client import constants as xlc
```
　の宣言により xlc.定数名で使用可能となる
・csv.readerで取り込んだ結果をそのままws.Range.Valueで書き込めるのは楽
※VBAだとRangeにVariantの配列に代入したデータを書き込む感じ
・よく使う機能以外(Worksheetの書式とかグラフの作成等)はマクロの記録で生成されたコードを修正することが多いから、定数の前に xlc. を追加することはひと手間だけど数が多いとなんとも言いがたい
・ユーザー定義型(Type)やWithステートメントは使用できないだろうけど、使えないと面倒な気も
　ユーザー定義型(Type)はDBの読み書き前後に１レコード分づつReDim Preserve Type型の配列を追加 しながらデータまとめるんだけど、美しくない実装になりそうだ
　Python的発想がもう少し強くなると考え方も違ってくるんだろうな
　Withステートメントだめだと、コード見づらくなるし、省略形として短く定義するという事かな？
・スペルの大文字、小文字あたりは元々VBAは無視しているのでしょうがないと思うしかない気も
　オブジェクトブラウザで見えるスペルが正しいスペルではと

```python
# coding:utf-8
# Windows Add env PYTHONIOENCODING = UTF-8 & restart vscode

import win32com.client
# 定数はExcel.Constantsに定義されている
from win32com.client import constants as xlc
import os.path
import csv

xlfile = os.path.abspath(".") +  "/samp.xlsx"
# csvfile = "17ISHIKA.CSV"
csvfile =  os.path.abspath(".") + "/17ISHIKA.CSV"
addsheet = "KENCODE"

xl = win32com.client.Dispatch("Excel.Application")

xl.Visible = True

#ブックを開く
wb = xl.Workbooks.Open(xlfile)

# Worksheetの一覧を作成
lstws = []
for sh in wb.Worksheets:
    lstws.insert(len(lstws), sh.Name)

# Worksheet一覧の表示
print(lstws)

# シート名[KENCODE]が存在すれば削除する
if addsheet in lstws:
    xl.Application.DisplayAlerts = False
    wb.Worksheets(addsheet).Delete()
    xl.Application.DisplayAlerts = True

# ワークシートを追加後に名前を[KENCODE]とする
wb.Worksheets.Add()
xl.ActiveSheet.Name = addsheet
ws = wb.Worksheets(addsheet)

# 書式を先に付けた後にデータを貼り付ける
ws.Columns("A:Q").NumberFormatLocal = "@"
ws.Columns("A:Q").HorizontalAlignment = xlc.xlLeft
ws.Range("A1").Select()

rows = 1
with open(csvfile, newline='') as csvfile:
    spamreader = csv.reader(csvfile, delimiter=',', quotechar='"')
    for line in spamreader:
        rows = rows + 1
        # 書き込み対象Range単位で書式を付けても構わない
        # 事前に定義してある領域からの書式のコピペはよくある(帳票用とか)
        ws.Range(ws.Cells(rows, 1), ws.Cells(rows, 15)).NumberFormatLocal = "@"
        ws.Range(ws.Cells(rows, 1), ws.Cells(rows, 15)).HorizontalAlignment = xlc.xlLeft
        ws.Range(ws.Cells(rows, 2), ws.Cells(rows, 16)).Value = line

# 保存する場合
# xl.Save()

# 今回は何もしない
xl.Quit()
```

# 参考にしたのは以下のサイト
[pywin32 · PyPI](https://pypi.org/project/pywin32/)
[Python for Windows Extensions](https://brian3johnson.github.io/pywin32/index.html)
[win32comで、makepyを使って COM(AcitveX)の定数をロードさせる手順について](https://wacky.hatenadiary.com/entry/20091011/1255240572) 
[mhammond/pywin32](https://www.moug.net/tech/acvba/0090016.html)
[Python pywin32(win32com) Excel 操作備忘録](https://qiita.com/feo52/items/150745ae0cc17cb5c866)
[PythonからExcelをwin32comで操作する](https://qiita.com/kumarstack55/items/9ae3432446afca06497f)
[第24回.エクセルを操作する（pywin32:win32com）](https://www.excel-ubara.com/python/python025.html)
[Excelを起動する（オートメーション）｜Access VBA](https://www.moug.net/tech/acvba/0090016.html)