【Python】csvをExcelに変換するコード

仕事柄、csvファイルとExcelをよく扱います。
一日の業務はcsvに始まりExcelに終わると言っても過言ではありません。

PCに慣れていない頃、csvファイルをダブルクリックしたら文字化けしたExcelが出てきた経験を持っている方は多いと思います。
csvを文字化けせずにExcelで読み込む方法はいくつかありますが、いずれにせよ少し手間です。
そこで、csvファイルを一気にExcelに変換するコードをPythonで書きました。

import datetime
import pathlib
from tkinter import filedialog

import openpyxl
import pandas as pd


def main():
    """csvファイルの一覧を取得するメイン関数"""

    # csvファイルの選択画面を開く
    csv_files = filedialog.askopenfilenames(
        title="csvファイルを選択する", filetypes=[("csvファイル", ".csv")]
    )

    # 選択されたcsvファイルの一覧を取得し、csv用とExcel用のファイルパスを生成する
    for file in csv_files:
        csv_path = pathlib.Path(file)
        excel_path = csv_path.with_suffix(".xlsx")

        # 既に同名のExcelファイルが存在する場合、上書きを防ぐためファイル名にタイムスタンプをつける
        if pathlib.Path.exists(excel_path) is True:

            # タイムスタンプを生成する
            now = datetime.datetime.now()
            time_num = now.strftime("%Y%m%d%H%M%S")

            # ファイルパスにタイムスタンプをつける
            excel_path = (
                str(excel_path.parent)
                + "\\"
                + str(excel_path.stem)
                + "_"
                + time_num
                + ".xlsx"
            )

        conversion_to_excel(csv_path, excel_path)


def conversion_to_excel(csv_path, excel_path):
    """csvファイルをExcelに変換する関数

    Args:
        csv_path (pathlib.WindowsPath): csv用のファイルパス
        excel_path (pathlib.WindowsPath): Excel用のファイルパス

    Todo:
        現状では文字コードがutf-8とSJISの場合しか対応していないので、
        より柔軟に多数の文字コードに対応できるよう改善したい
    """

    # pandasでcsvを読み込む
    # ヘッダーがないcsvも扱うので、header=Noneを指定する
    try:
        df = pd.read_csv(csv_path, header=None, encoding="utf-8")  # 最初はutf-8で読み込み、
    except UnicodeDecodeError:
        df = pd.read_csv(
            csv_path, header=None, encoding="cp932"
        )  # 文字コードでエラーが発生したら、SJISで読み込む

    # データフレームをExcelとして保存する
    # Excelには既に行番号があるので、index=Falseを指定する
    df.to_excel(excel_path, index=False)

    # csvをpandasで読み込むとき、header=Noneを指定すると1行目に列番号が生成される
    # Excelで扱う上では不要な行なので、1行目を削除する
    wb = openpyxl.load_workbook(excel_path)
    ws = wb["Sheet1"]
    ws.delete_rows(1)
    wb.save(excel_path)


if __name__ == "__main__":
    main()

例えばこんな感じのcsvデータがあったとします。

ID Name Score
001 Alice 80
002 Bob 75
003 Carol 20
004 堂林 50
005 Elin 未測定

これをExcelでそのまま開くと文字化けしますが、当記事のコードで変換すると、
こんな感じにExcelにしてくれます。

コメントにも書いた通り、現在はutf-8SJISというメジャーな2つの文字コードのみの対応となっており、それ以外は未対応なのが課題です。
一応、chardetというライブラリを使えばファイルの文字コードを自動で判別できますが、chardetはたまに文字コードを誤認識するらしく、実際に自分の環境で試したところ文字コードを上手く認識してくれないケース*1があったので、今回は断念しました。
対応する文字コードを増やすだけなら比較的楽なので、もしutf-8SJIS以外の文字コードを扱う機会があれば、随時追加する方針で考えます。

ここまで読んでいただき、ありがとうございます。

*1:特に、サイズが小さいファイルで誤認識が起こりやすい傾向でした