Skip to content

Instantly share code, notes, and snippets.

@gologius
Last active November 13, 2022 07:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gologius/79f793e0f2a1fe7b321e9bdf2fc8f10c to your computer and use it in GitHub Desktop.
Save gologius/79f793e0f2a1fe7b321e9bdf2fc8f10c to your computer and use it in GitHub Desktop.
CSVファイルをシンプルなExcelに変換する
# -*- 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