年賀状作成で困ったことについて書き留める(続き)
前回、年賀状作成で困ったことを書いたがその続き。
郵便番号がゼロサプレス問題で0から始まるものが7桁ではなく6桁になってしまった件。その後確認してみたら出力したCSVファイルの郵便番号はちゃんと0から始まる7桁で出力されていたので問題ははがき印刷ソフトの住所録インポート機能が正しく読み込んでくれないことに問題があった模様。
そこで正しく読み込ませるには郵便番号を「012-3456」とハイフン付きで行えば良いことが分かったので以下のようにreplaceで正規表現で数字を3桁と4桁で分けてハイフンを追加することで対応。簡単に説明すると0から9の数字3桁が最初の括弧の中でマッチし、次の括弧内で同じく0から9の数字4桁がマッチする。括弧の中でマッチした部分はそれぞれ順番に'\1'と'\2'で参照することが出来るのでそれを'-'(ハイフン)で繋いだ文字にすることで
「0123456」 が 「012-3456」 と変換される。
import pandas as pd
df = pd.read_excel('address_from_202112.xlsx')
df['自宅 〒'] = df['自宅 〒'].replace('([0-9]{3})([0-9]{4})',
r'\1-\2', regex=True)
しかしこれがなぜかうまく行かない。なぜだろうといろいろ確認してみたら郵便番号の部分が数値としてpandasに読み込まれていることが原因であることがわかり、それならと以下のように「str」を指定して文字列型に。
df['自宅 〒'] = df['自宅 〒'].str.replace('([0-9]{3})([0-9]{4})',
r'\1-\2', regex=True)
しかしこれもうまく行かず。最終的にはpandasのDataFrameに読み込む時点でconvertersにて以下のように指定することで文字列型に変換。
df = pd.read_excel('address_from_202112.xlsx', converters={'自宅 〒':str})
df['自宅 〒'] = df['自宅 〒'].replace('([0-9]{3})([0-9]{4})',
r'\1-\2', regex=True)
これで解決できた… と思ったら、今度は元のExcelシートのセルに
"012-3456"
とダブルクォーテーション付きで入力しているものが一部あったようでそれを削除するべく以下のようにダブルクォーテーションを削除するようにした。
df = pd.read_excel('address_from_202112.xlsx', converters={'自宅 〒':str})
df['自宅 〒'] = df['自宅 〒'].str.replace('"*([0-9]{3})([0-9]{4})"*',
r'\1-\2', regex=True)
しかしまだ、
”012-3456
というのが1つだけなぜか残ってしまった。これはいったいなんだろうと思って調べてみたら
文字コードが0x22(")と0x201D(”)の似て非なるダブルクォーテーションが存在していてことが原因だった。
よって、最終的に以下のように両方の文字コードのダブルクォーテーションを削除するようにした。
df = pd.read_excel('address_from_202112.xlsx', converters={'自宅 〒':str})
df['自宅 〒'] = df['自宅 〒'].replace('["”]*([0-9]{3})([0-9]{4})["”]*'
, r'\1-\2', regex=True)
これでようやく7桁のハイフン付きの郵便番号をCSVファイルに出力できるようになった。ふう。
おまけ - アドレス帳を変換
某所の「はがきデザインキットWeb版」は指定されたテンプレートのCSVファイルに住所を入力してアップロードすることで住所録を読み込ませて印刷することが出来るということでそのテンプレートに流し込むコードを書いてみた。
まずは、テンプレートのヘッダを確認。
df = pd.read_csv('UserAddress.csv', encoding='shift-jis')
print(df.columns.tolist())
以下がその出力。
['名前(姓)', '名前(名)', 'ふりがな(姓)', 'ふりがな(名)', '敬称', '郵便番号(数字7桁)', '都道府県', '市区町村(最大23文字)', '番地・号(12文字)', '建物名(最大25文字)', '会社名(20文字)', '部署名(最大20文字)', '役職名(最大20文字)', '連名1(姓)', '連名1(名)', '連名1(敬称)', '連名1(役職名:最大20文字)', '連名2(姓)', '連名2(名)', '連名2(敬称)', '連名2(役職名:最大20文字)', '連名3(姓)', '連名3(名)', '連名3(敬称)', '連名3(役職名:最大20文字)', '連名4(姓)', '連名4(名)', '連名4(敬称)', '連名4(役職名:最大20文字)']
データの項目が分かったので、
上記に合うように自分のExcelの列ヘッダの情報をmy_headersに並べる。
敬称は全部「様」で良かったのでそのように入力。
最後に出力の再、デフォルトでは余計なインデックスが含まれてしまうのでindex=Falseを指定。
として以下のようにした。
df = pd.read_csv('UserAddress.csv', encoding='shift-jis')
df2022 = pd.read_excel('address_from_202112.xlsx', converters={'自宅 〒':str})
my_headers = {
'名前(姓)': '氏名(性)',
'名前(名)': '氏名(名)',
'敬称': '敬称',
'連名1(名)': '連名1',
'連名2(名)': '連名2',
'連名3(名)': '連名3',
'郵便番号(数字7桁)': '自宅 〒',
'都道府県': '自宅 住所1',
'市区町村(最大23文字)': '自宅 住所2',
'番地・号(12文字)': '自宅 住所3' }
for k, v in my_headers.items():
df[k] = df2022[v]
df['連名1(敬称)'] = '様'
df['連名2(敬称)'] = '様'
df['連名3(敬称)'] = '様'
df.to_csv('convertedAddress.csv',encoding="shift-jis",index=False)
これではがきデザインキットに住所録を流し込むことが出来るCSVファイルの作成に成功した。
その後の顛末
これではがきデザインキットWeb版には住所録を流し込んだので年賀状を出していない相手から年賀状が届いたら、はがきデザインキットWeb版から直接住所を入力し印刷面も用意していたものを使って年賀はがきを買わずに直接そこから相手に年賀状を出せる…。
と
思っていたのだが、今年からはなぜかデザインキットWeb版からは
自宅でプリントする
コンビニでプリントする
プリントしたものを自宅に郵送する
の選択肢しかなっていた。去年まではネットで住所を入力して注文すると直接年賀状を相手先に届けることが出来ていたのに今年から出来なくなってしまったようでがっかり。
というわけで、いろいろ仕様の改悪もあり来年の年賀状はもうやめようかなと思っている次第。