Excelのシートってまとめてcsvにできないの?
再分析をしようと思ったらデータの拡張子が.xlsxやんけ!という経験はないでしょうか。
それだけなら拡張子を変更して保存すればよいですが、複数のシートで管理されていたりしたらもう心が折れます。折れました。
この記事にたどり着いたということはあなたも同じ苦しみを味わっているはず。ということで、シートを分割してくれるアプリを作りました。
ダウンロードはこちら↓
意外と情報が少なかったので、説明がてら記事にしてみようと思います。
※記事投稿もアプリ作成も初心者なので温かい目でご覧ください&ご指摘大歓迎です。
※後輩への説明と備忘録も兼ねています。解説が過剰気味かもしれませんがご了承ください。
目次
- pythonで.xlsxファイルの読み込み→csv形式で保存
- おまけ:フォルダ内の.xlsxファイルを一括処理
- おわりに
環境
- Windows11
- Python 3.12.4
pythonで.xlsxファイルの読み込み→csv形式で保存
import pandas as pd
import openpyxl
# エクセルファイルの読み込み
input_file = pd.ExcelFile("sample.xlsx")
# シート名を取得
input_sheet_name = input_file.sheet_names
# シート名を用いてループ処理
for sheet in input_sheet_name:
df = input_file.parse(sheet)
df.to_csv(f"{sheet}.csv", index=False, encoding="utf-8-sig")
ライブラリの読み込み
import pandas as pd
import openpyxl
今回は.xlsxファイルの読み込みにpandasとopenpyxlを使っています。
(pandasだけで動作させている記事もありましたが私はエラーが出ました...)
pandas:データフレームという表形式のデータを扱えるライブラリ
openpyxl:pandasによるエクセルファイルの読み込みを可能にするライブラリ...?
エクセルファイルの読み込み
input_file = pd.ExcelFile("sample.xlsx")
pandas(とopenpyxl) を利用してエクセルファイルをinput_fileに代入します。
() の中身はファイルのパスを指定しましょう。
pythonファイルと同じフォルダに分割対象のエクセルファイルがある場合はファイル名のみでokです。
シート名の取得
input_sheet_name = input_file.sheet_names
input_sheet_nameという配列にシート名を格納しています。
シート名を用いてループ処理
for sheet in input_sheet_name:
for文で先ほど取得したシート名をループします。
sheetが一つ一つのシート名に対応しながらループしています。
シートをデータフレームに変換
df = input_file.parse(sheet)
現在のループに対応するシートをデータフレームに変換し、dfという変数に格納しています。
この部分までを応用するとわざわざcsvで保存しなくても分析できます。
データフレームをcsv形式で保存
df.to_csv(f"{sheet}.csv", index=False, encoding="utf-8-sig")
(データフレーム名)+.to_csvはデータフレームをcsv形式で保存する命令です。
括弧の中では
- f"{sheet}.csv"の部分で(シート名)+.csvという名前の保存先を指定
- index=Falseで行番号や列番号をcsvに含めないという設定
- encoding="utf-8-sig"でエンコーディングを指定して文字化けを防止
を行っています。
おまけ:フォルダ内の.xlsxファイルを一括処理
先ほどのコードのファイル名をいちいち変更するのは面倒ですよね。ということで、さらに改造を施してフォルダ内のエクセルファイルをまとめてcsvに変換してくれるようにしてみました。
※おまけなので説明が雑です...
import pandas as pd
import openpyxl
import os
# xlmxファイルのシートを分割してcsvで保存する関数
def to_csv(filePath, output_folder):
input_file = pd.ExcelFile(filePath) # Excelファイルを開く
input_sheet_name = input_file.sheet_names # シート名を取得
# 各シートを処理
for sheet in input_sheet_name:
df = input_file.parse(sheet) # シートをDataFrameとして取得
output_file = os.path.join(output_folder, f"{sheet}.csv") # 保存先パス
df.to_csv(output_file, index=False) # CSVとして保存
print(f"シート「{sheet}」を「{output_file}」として保存しました。")
# 走査するフォルダのパス(カレントディレクトリから取得)
inputPath = os.getcwd()
# フォルダ内のExcelファイルを取得
excel_files = [f for f in os.listdir(inputPass) if f.endswith(".xlsx")]
# 各Excelファイルを処理
for file in excel_files:
file_path = os.path.join(inputPath, file) # Excelファイルのフルパス
folder_name = file[:-5] # ファイル名を取得
output_folder = os.path.join(inputPass, folder_name) # フォルダのパス
# フォルダが存在しない場合は作成
os.makedirs(output_folder, exist_ok=True)
# CSVをフォルダ内に保存
to_csv(file_path, output_folder)
さっきの処理を関数にする
def to_csv(filePath, output_folder):
input_file = pd.ExcelFile(filePath) # Excelファイルを開く
input_sheet_name = input_file.sheet_names # シート名を取得
# 各シートを処理
for sheet in input_sheet_name:
df = input_file.parse(sheet) # シートをDataFrameとして取得
output_file = os.path.join(output_folder, f"{sheet}.csv") # 保存先パス
df.to_csv(output_file, index=False) # CSVとして保存
print(f"シート「{sheet}」を「{output_file}」として保存しました。")
これでcsv(エクセルファイルのパス, 保存先のパス)としてあげると先ほどの処理を実行できるようになりました。
フォルダ名を取得
inputPath = os.getcwd()
このコードが配置されているフォルダ自体のパスを取得しています。
つまり、このコードとcsvに変換したいファイルをまとめたフォルダを同じフォルダに放り込んでおけば、往路グラムを実行するだけで分割してくれるようになったわけですね。
フォルダ内の.xlsxファイルを取得
excel_files = [f for f in os.listdir(inputPath) if f.endswith(".xlsx")]
さっきのinputPathを使ってフォルダ内を走査しています。
ここでは、ファイル名の最後が.xlsxになっているものをexcel_filesという配列に格納しています。
保存先のフォルダを作成
file_path = os.path.join(inputPath, file) # Excelファイルのフルパス
folder_name = file[:-5] # ファイル名を取得
output_folder = os.path.join(inputPass, folder_name) # フォルダのパス
# フォルダが存在しない場合は作成
os.makedirs(output_folder, exist_ok=True)
先ほど取得したエクセルファイル名と現在いるファイル名を結合
↓
エクセルファイルの名前のみ(拡張子を避けてる)を取得
↓
エクセルファイルと同じ名前のフォルダを作成(すでに同一名のフォルダがある場合はエラーが出るはず)
さっき作った関数にファイルのパスと保存先のパスを渡す
to_csv(file_path, output_folder)
一つ前の工程で作成したフォルダのパスをoutput_folderとして与えることで、分割したcsvファイルが元のエクセルファイルと同じ名前のフォルダに保存されます。
おわりに
おまけで行っているフォルダの走査などを活用すると、複数ファイル・複数データの分析を一括で行うことができます。(気が向いたら記事にします)