PythonでExcelを操作する

# はじめに
とりあえず急ぎで作成したため、後でゆっくり整理する...予定

# 参考サイト
## 環境構築関連
◆Seleniumをオフラインで動かす
　https://qiita.com/wakasama_pcmaster/items/73c8e71fde81ed6336bb
　　※Pythonインストール関連はこちらに記載していたので...

◆# openpyxl と xlwings の比較
　https://qiita.com/m5knt/items/ab56f1d0a783f3422ee3
◆ExcelにPythonが搭載？その後 - xlwings を使おう
　https://qiita.com/yniji/items/b38bc312e860027108ac

◆PythonでExcelマクロ実行！VBAを起動する方法
　https://fastclassinfo.com/entry/run_excelvba_from_python/#xlwingsPythonExcelVBA
◆Python×Excel自動化できること28！読み込み書き込みグラフ作成の事例紹介
　https://fastclassinfo.com/entry/python_excel_operation/
◆マスターしよう！PythonでのCSVファイル操作方法を徹底解説！
　https://www.tech-teacher.jp/blog/python-csv/
◆xlwings · PyPI
　https://pypi.org/project/xlwings/#files
　　※xlwings-0.21.4.tar.gz
◆pywin32 · PyPI
　https://pypi.org/project/pywin32/#files
　　※pywin32-300-cp37-cp37m-win_amd64.whl
　
◆Python API — xlwings dev ドキュメント
　https://docs.xlwings.org/ja/latest/api.html
◆xlwings入門
　https://jimaru.blog/programming/python/xlwings/
　　※デバッグのやり方書いてある...重要!!

◆意外と知らない？pipコマンド
　https://qiita.com/tmurakami1234/items/b407dc4cc558564882bf

# TODO
- [x]  環境構築
- [x]  基本操作
- [x]  セルの数式とその結果値の取得/設定
　◆python xlwings: 最終行のセルを求める
　　https://qiita.com/Mihiraghi/items/f234d2679ad8905dee27
- [x]  CSV操作
- [ ]  R1C1参照方式<br>
　◆xlwingsでR1C1参照形式を使う<br>
　　https://qiita.com/k_maki/items/150213d2e64699e0e704
- [ ]  引数処理<br>
　◆Pythonのコマンドライン引数がわかる！渡し方・取得方法を分かりやすく解説<br>
　　https://www.tech-teacher.jp/blog/python-commandline/
- [ ]  例外処理
　◆Pythonで例外を投げるときのベストプラクティス
　　https://qiita.com/hasoya/items/05d4e49d492869875cca
- [ ]  ログ処理
- [ ]  おまじない<br>
　◆[Python]おまじないif __name__ == '__main__'の挙動<br>
　　https://qiita.com/nal_dal_dere/items/a138522230a413ec75ad
- [ ]  リスト処理<br>
　◆Pythonで奇数・偶数を判定する<br>
　　https://www.relief.jp/docs/python-is-odd-is-even.html<br>
　◆［Python入門］リストと繰り返し処理<br>
　　https://www.atmarkit.co.jp/ait/articles/1906/11/news007.html
- [ ]  フォルダ/ファイル構成<br>
　◆Pythonでよく使うExcel操作集めた
　　https://qiita.com/code2545Light/items/c8f84ddc70281eee670e


# Memo
- Pythonの文字コード：UTF-8 

# コードサンプル
## 事前準備＆環境構築
```python:enviroment.py
# バージョン確認
> python --version
Python 3.7.1

# インストール パッケージ確認
> pip list

# xlwingsダウンロード
> pip download -d src --no-binary :all: xlwings
#  ※一部はwhlしかないので、実際は下記で取得
> pip download -d package xlwings

# xlwingsインストール
> pip install --no-index --find-links=package xlwings
```
## Excel操作
```python:excel2.py
import csv
import datetime as dt
import os
import time
import xlwings as xw


def isDictionary(dicRange, cellPosition):
    for column in dicRange.columns:
        cells = column[0].value.split(';')
        if cellPosition in cells:
            return True


def createDictionary(dicRange, cellPosition):
    cindex = -1
    dic = {}
    for column in dicRange.columns:
        cindex = cindex + 1
        cells = column[0].value.split(';')
        if cellPosition in cells:
            # print(dicRange.value[cindex])
            # print(column.value)
            rindex = -1
            for r in column:
                rindex = rindex + 1
                # print(dicRange.value[rindex][cindex],
                #      dicRange.value[rindex][cindex+1])
                dic1 = {dicRange.value[rindex][cindex]: dicRange.value[rindex][cindex+1]}
                dic.update(dic1)
                # print(dic)
    return dic


def searchDictionary(dicRange, cellPosition, key):

    # 指定セル情報の値検索
    # cindex = -1
    rindex = -1
    keyFlag = False
    for column in dicRange.columns:
        # if isDictionary(dicRange, cellPosition):
        #     keyFlag = key in column.value
        #     if keyFlag:
        #         rindex = column.value.index(key)
        #         #print(key, rindex)
        # else:
        #     if keyFlag:
        #         return column[rindex].value
        # cindex = cindex + 1
        cells = column[0].value.split(';')
        if cellPosition in cells:
            keyFlag = key in column.value
            if keyFlag:
                rindex = column.value.index(key)
                # print(key, rindex)
            # else:
            #     continue
            # for r in column:
            #     rindex = rindex + 1
            #     if key == r.value:
            #         keyFlag = True
            #         break
            #     else:
            #         continue
        else:
            # if keyFlag == True:
            if keyFlag:
                # print(cindex, rindex)
                # print(column[cindex].value)
                return column[rindex].value
            # else:
            #     continue


start2 = time.time()

# メイン処理
try:
    # 新規Excelインスタンスでブックを開く
    app = xw.App(visible=False)
    wb = app.books.open('テスト_InputData_TYPE.xlsx')

    # シートを得る
    wss = wb.sheets
    ws1 = wss['InputCsvData']
    # ws.activate()

    # 処理開始
    start = time.time()

    # Dictionary情報取得
    ws2 = wss['Dictionary']
    # ws2.activate()
    u = ws2.api.UsedRange
    r = u.Row + u.Rows.Count - 1
    c = u.Column + u.Columns.Count - 1
    dicRange = ws2.range((1, 1), (r, c))

    # InputCsvData情報取得
    ws1.activate()
    u = ws1.api.UsedRange
    r = u.Row + u.Rows.Count - 1
    c = u.Column + u.Columns.Count - 1
    csvRange = ws1.range((1, 1), (r, c))

    for column in csvRange.columns:
        cellPosition = column[1].value

        # if isDictionary(dicRange, cellPosition):
        #     for r in column:
        #         r.value = searchDictionary(dicRange, cellPosition, r.value)

        dictionary = createDictionary(dicRange, cellPosition)
        if(len(dictionary) > 0):
            index = 0
            for r in column:
                if(index < 2):
                    index = index + 1
                else:
                    # if(r.value == 'R11C3'):
                    #    print(column.value)
                    r.value = dictionary[r.value]

        # print(dicRange.value[0][0])

    # 列毎の範囲操作
    # svalue = searchDictionary(dicRange, 'R10C4', '休日')
    # print(svalue)
    # svalue = searchDictionary(dicRange, 'R11C5', '木曜日')
    # print(svalue)
    # svalue = searchDictionary(dicRange, 'R20C4', '管理職')
    # print(svalue)
    # index = 0
    # for column in dicRange.columns:
    #     if index % 2 == 0:
    #         print('セル情報')
    #         key1 = column[index].value
    #         print(key1)
    #         dkey = column.value
    #     else:
    #         print('不要')
    #         dvalue = column.value
    #     index = index + 1
    #     # for r in column:
    #     print(column.value)

    # 処理終了
    stop = time.time()
    print(stop-start)

    # 使用範囲の値(list)を取得して出力
    # print(rng.value)

    # 行毎の範囲を得て値を出力 (値のみなら rng.value が速い)
    # for row in rng.rows:
    #    print([c.value for c in row])

    # 列毎の範囲を得て値を出力
    # for column in rng.columns:
    #    #print([r.value for r in column])
    #    for r in column:
    #        print(r.value)

    saveFile = r"D:\Python\Excel\OutputData.csv"
    # ファイル存在確認
    isFileExist = os.path.isfile(saveFile)
    if isFileExist:
        os.remove(saveFile)
    # else:
    #     pass  # パスが存在しないかファイルではない

    # csvファイルとして保存
    # ◆XlFileFormat 列挙体 (Excel)
    # 　https://docs.microsoft.com/ja-jp/office/vba/api/excel.xlfileformat
    wb.api.SaveAs(saveFile, 6)

finally:
    # ブックを閉じる
    wb.close()
    # Excelインスタンスを閉じる
    app.quit()


# 処理終了
stop2 = time.time()
print(stop2-start2)

```

```python:excel.py
import csv
import datetime as dt
import xlwings as xw

# CSVファイル読込
with open('data.csv', encoding="utf_8") as file:
    reader = csv.reader(file)
    # ラベルデータをスキップする
    header = next(reader)

    for row in reader:
        print(row)


# 新規Excelインスタンスでブックを開く
app = xw.App(visible=False)
wb = app.books.open('work.xlsx')

# シートを得る
wss = wb.sheets
ws = wss['202101']

# データ表示
print(ws.range('A5').value)
dt1 = ws.range('A5').value
strdt1 = dt1.strftime('%Y/%m/%d(%a)')
print(strdt1)

print(ws.range('B5').value)
print(ws.range('C5').value)


def day_to_time(D):
    # hh:mm:ss
    #    T = str(dt.timedelta(days=D))
    #    return T
    # hh:mm
    return ':'.join(str(dt.timedelta(days=D)).split(':')[:2])


d = day_to_time(ws.range('D5').value)
print(d)
# 数式
print(ws.range('E5').formula)
# 数式の結果
print(day_to_time(ws.range('E5').value))
dt3 = dt.datetime.strptime(
    str(dt.timedelta(days=ws.range('E5').value)), "%H:%M:%S")
print(dt3)
print(dt3.strftime('%H:%M'))

# 使用範囲
# u = ws.api.UsedRange
# r = u.Row + u.Rows.Count - 1
# c = u.Column + u.Columns.Count - 1
# rng = ws.range((1, 1), (r, c))

# 使用範囲の値(list)を取得して出力
# print(rng.value)

# 行毎の範囲を得て値を出力 (値のみなら rng.value が速い)
# for row in rng.rows:
#    print([c.value for c in row])

# テーブル内容の範囲
# rng = ws['テーブル']
# テーブルタイトルを取得して出力
# print(rng.rows[0].offset(-1, 0).value)
#　テーブル内容を取得して出力
# print(rng.value)

# マクロVBAを呼び出して実行
# App = xw.App()
# wb = App.books.open(filename)
# macro=wb.macro('keisan')
# macro()

# エクセルファイルを保存
# newfilename = 'Macro_' + filename
# wb.save(newfilename)

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

# Excelインスタンスを閉じる
app.quit()
```