Last active
November 13, 2022 07:29
-
-
Save gologius/79f793e0f2a1fe7b321e9bdf2fc8f10c to your computer and use it in GitHub Desktop.
CSVファイルをシンプルなExcelに変換する
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
""" | |
Created on Tue Apr 30 10:58:53 2019 | |
""" | |
import logging | |
import os | |
import openpyxl | |
from openpyxl.styles import Alignment | |
from openpyxl.utils import get_column_letter, column_index_from_string | |
import pandas as pd | |
import sys | |
import unicodedata | |
logging.basicConfig(level=logging.DEBUG) | |
logger = logging.getLogger(__name__) | |
#設定 ※CSVのヘッダはあることが前提のスクリプトなので注意 | |
ZENKAKU_WIDTH = 2 | |
HANKAKU_WIDTH = 1.2 | |
ADD_WIDTH = 3 #最終的に列幅を決める際に加算するサイズ数 | |
INPUT_CSV_ENCODING = "cp932" | |
OUTPUT_CSV_ENCODING = "cp932" | |
def calc_text_width(text): | |
width = 0 | |
for char in text: | |
if unicodedata.east_asian_width(char) in 'FWA': | |
# 全角かな(W)、全角英数(A)、特殊文字(F) | |
width += ZENKAKU_WIDTH | |
else: | |
width += HANKAKU_WIDTH | |
return width | |
def main (): | |
#引数からCSVロード | |
logger.info(f"引数 {sys.argv}") | |
if len(sys.argv) <= 1: | |
logger.error("引数エラー: ファイルが指定されていません") | |
return | |
for idx, path in enumerate(sys.argv): | |
if idx == 0: | |
continue #引数一つ目は実行ファイル名なのでスキップする | |
#事前に再出力先のファイルパスを組み立てておく | |
p, ext = os.path.splitext(path) | |
new_path = f"{p}.xlsx" | |
if os.path.exists(new_path): | |
logger.warning(f"ファイルが既に存在しています。処理をスキップします{new_path}") | |
continue | |
#csvロード | |
logger.info(f"pandasでのファイル変換処理開始:{path}") | |
data = pd.read_csv(path, encoding=INPUT_CSV_ENCODING, dtype="str", header=0) | |
data.fillna("") | |
#Excel形式で再出力 | |
data.to_excel(new_path, encoding=OUTPUT_CSV_ENCODING, index=False) | |
#Excelの書式修正 | |
logger.info(f"openpyxlでの書式処理開始:{new_path}") | |
book = openpyxl.load_workbook(new_path) | |
sheet = book.active #シートが一つしかないことしか想定してないので注意 | |
for columns in sheet.columns: | |
max_column_size = calc_text_width(columns[0].value) | |
for cell in columns: | |
cell.alignment = Alignment(horizontal='right') | |
cell.alignment = Alignment(vertical='center') | |
cell.style = "Normal" #標準スタイル(装飾なし・罫線なし) | |
cell.number_format = openpyxl.styles.numbers.FORMAT_TEXT #書式変更 | |
#最大列幅の更新 | |
if cell.value is None: | |
pass | |
elif max_column_size < calc_text_width(cell.value): | |
max_column_size = calc_text_width(cell.value) | |
#半角全角を考慮して列幅計算 | |
column_name = columns[0].column | |
sheet.column_dimensions[column_name].width = max_column_size + ADD_WIDTH | |
#その他全体設定の適用 | |
sheet.auto_filter.ref = f"A1:{get_column_letter(sheet.max_column)}1048576" #filter | |
sheet.freeze_panes = "A2" #ウインドウ固定 | |
book.save(new_path) | |
logger.info(f"openpyxl処理終了:{new_path}") | |
return | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment