io.BytesIO()にデータフレームで作成したExcelを保存して、openpyxlで列の幅を変更してメールに添付する方法


業務でio.BytesIO()にデータフレームから作成したExcelファイルを保存した後に
openpyxlで列の幅を修正する際につまづいたのでここにメモを残します。

クソコードですが、業務終了後自宅で6時間かけてやっとうまく動いたので許してください;;;;
多分よろしくない書き方しているので動きますけどコピペはやめた方が良いです。ごめんなさい。

from csv import writer
from tkinter import W
import pandas as pd
import io
import openpyxl
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
import smtplib
from os.path import basename
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
import smtplib
from os.path import basename

output = io.BytesIO()
writer = pd.ExcelWriter

df = pd.DataFrame([['2022/03/28','hoge','hige','fuge','fege','foge','0.0'],['2022/03/29','hoge1','hige1','fuge1','fege1','foge1','1.0']]\
    , columns=['DATE', "HOGE", 'HIGE', 'FUGE', 'FEGE', 'FOGE', 'SU-ZI'])

file_name = 'sample.xlsx'
sheet_name = 'sheet1'

# index=Falseにすると不要なインデックスがつかない
df.to_excel(output,index=False,sheet_name=sheet_name)

writer.save
output.seek(0)

wb = openpyxl.load_workbook(output)
ws = wb[sheet_name]

# 列の幅を修正する
for col in ws.columns:
  max_length = 0
   column = col[0].column
 
  for cell in col:
       if len(str(cell.value)) > max_length:
           max_length = len(str(cell.value))

       adjusted_width = (max_length + 2) * 1.5
       ws.column_dimensions[col[0].column_letter].width = adjusted_width

wb.save(output)
writer.save
output.seek(0)
 
# SMTP認証情報
account = "接続先のアカウント"
password = "接続先のパスワード"
 
# 送受信先
to_email = "送信先のアドレス"
from_email = "送信元のアドレス"
 
# MIMEの作成
subject = "件名"
message = "本文"
# バイナリデータを添付する場合はMultipart、テキストのみの場合はMIMETextだけで大丈夫です
msg = MIMEMultipart()
msg["Subject"] = subject
msg["To"] = to_email
msg["From"] = from_email
msg.attach(MIMEText(message))

part = MIMEApplication(output.read(),Name=basename(file_name))
 
part['Content-Disposition'] = 'attachment; filename="%s"' % basename(file_name)
msg.attach(part)
 
# メール送信処理
# Gmailでテストする場合
server = smtplib.SMTP("smtp.gmail.com", 587)
server.starttls()
server.login(account, password)
server.send_message(msg)
server.quit()
writer.close