質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

1087閲覧

Pythonで複数のCSVファイルのデータをテンプレートに差し込みたい

hhh-ds

総合スコア2

CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/10/14 02:46

編集2021/10/14 06:01

実現したいこと

Pythonで、csvファイルからデータを抽出し、テンプレートに差し込んだうえでtxtファイルとして保存するコードを作成しました。
応用として、今度は2つのcsvファイルからデータを抽出してテンプレートに差し込むコードを作りたいです。

元のコードはこんな感じです。

import csv csv_file = open("meisai_data.csv", "r", encoding="utf-8", errors="", newline="" ) #辞書形式 f = csv.DictReader(csv_file, delimiter=",", doublequote=True, lineterminator="\r\n", quotechar='"', skipinitialspace=True) items = {} template = ''' {姓} {名}様 株式会社〇〇の××です。 {振込月日}に振り込ませていただく給与について 明細(毎月末日締 翌月25日払)をお送りします。 以下略 ''' for items in f: filename = '{姓}{名}様.txt'.format(**items) f = open(filename, 'x') f.write(template.format(**items)) f.close() csv_file.close()

このコードのテンプレート部分の、「株式会社〇〇の××です。」など、基本の文章になる部分を2つめのcsvファイルにカラム付きのデータとして保存して、差し込めるようにしたいです。
理想のテンプレートは以下のような形になります。

template = ''' {姓} {名}様 {1行目} {振込月日}{2行目} {3行目} 以下略 '''

どうぞ知恵をお貸しください。よろしくお願いいたします。

###2つのcsvデータ
1.顧客データの入ったcsv(meisai_data.csv)

姓,名,振込月日 田中,太郎,6月24日 山田,花子,6月24日 佐藤,次郎,6月24日

2.明細の本文をcsv形式にしたもの(hinagata.csv)

1行目,2行目,3行目 株式会社〇〇の××です。,に振り込ませていただく給与について,明細(毎月末日締 翌月25日払)をお送りします。

試したこと

素人考えですが、globを使うと良いのかと思い、以下のようにコードを書き換えました。

import csv import glob file = glob.glob('./*csv') csv_file = open(file, "r", encoding="utf-8", errors="", newline="" ) #辞書形式 f = csv.DictReader(csv_file, delimiter=",", doublequote=True, lineterminator="\r\n", quotechar='"', skipinitialspace=True)

実行すると以下のようなエラーが出ました。

TypeError (note: full exception trace is shown but execution is paused at: <module>) expected str, bytes or os.PathLike object, not list

このエラーが解消されれば上手くいくのでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TakaiY

2021/10/14 04:13

1つめのCSV(客のデータ?)と2つめのCSV(こちらのデータ?)の関係がよくわかりません。 具体的な例を示してください。 1つめのCSVのデータの1行目と 2つめのCSVのデータの1行目が対応しているとかですか?
hhh-ds

2021/10/14 06:03

2つのCSVデータは対応関係にありません。 質問内容を修正しましたのでご確認ください。
guest

回答1

0

ベストアンサー

globは、撮り貯めた写真を日付ごとに整理したいなど、不特定多数のファイルがそれらのファイル名を一覧で取得したい場合などに使います。
今回のようにファイル名が決まっているのであれば不使いません。将来顧客データのファイルが複数になったりしたら使えるかもしれません)

ファイルの中身のデータは、現状のように読込みながら処理する(with openの中でforで回す)こともできますが、リストに読み込んでしまうこともできます。
hinagata.csvの方は読み込んでしまうのが扱いやすそうです。

python

1with open('hinagata.csv', encoding='utf-8') as h: 2 reader = csv.DictReader(h) 3 hinagata = list(reader)

これで、hinagata.csvの内容が取得できます。
ここで、hinagata変数がdictのリストであることに注意してください。
printで表示してみるといいでしょう。
1行目を取り出したければ、

python

1hinagata_1 = hinagata[0]

などとします。リストの扱いに慣れているのであれば、ここで置き換える必要はありません。

取得できたので、出力に使うことができます。
ここで作ったhitagata_1をformatの引数に追加してあげればOKです。

python

1template = ''' 2{姓} {名}様 3 4{1行目} 5{振込月日}{2行目} 6{3行目} 7''' 8 9for items in f: 10 filename = '{姓}{名}様.txt'.format(**items) 11 f = open(filename, 'w') 12 f.write(template.format(**items, **hinagata_1)) 13 f.close() 14 15csv_file.close()

★ f.close()の場所が間違えています。 元のコードだと最後のファイルしかクローズできません。 close漏れなど防ぐためには、with構文を使いましょう。

投稿2021/10/15 01:57

TakaiY

総合スコア12765

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hhh-ds

2021/10/20 06:24 編集

回答ありがとうございます。 printで表示するところまでは成功しました。 f.close()の件もありがとうございました。 以下のようなコードを書いたところ、エラーが発生しました。hinagata_1が上手く読み込めていない(関連付けられていない?)ような気がしています。検索もしましたが解決方法がわかりません。お力を貸していただけないでしょうか。 -------------------------- import csv csv_file = open("meisai_data.csv", "r", encoding="utf-8", errors="", newline="" ) #辞書形式 f = csv.DictReader(csv_file, delimiter=",", doublequote=True, lineterminator="\r\n", quotechar='"', skipinitialspace=True) with open('hinagata.csv', encoding='utf-8') as h: reader = csv.DictReader(h) hinagata = list(reader) items = {} hinagata_1 = hinagata[0] template = ''' {姓} {名}様 {1行目} {振込月日}{2行目} {3行目} 以下略 ''' for items in f: filename = '{姓}{名}様.txt'.format(**items) f = open(filename, 'w') f.write(template.format(**items, **hinagata_1)) f.close() csv_file.close() --------------------------- KeyError (note: full exception trace is shown but execution is paused at: <module>) '1行目' f.write(template.format(**items, **hinagata_1))
TakaiY

2021/10/20 07:31

KeyErrorというのは、辞書にキーでアクセスしようとしたときに、そのキーが無いのが原因です。 templateの中で使っているkey ('姓'とか'1行目'とか)が正しくitemsやhinagata_1に入っているかどうか確認してください。 直前でそれらをprintしてみるのがいいと思いますよ。
hhh-ds

2021/10/21 06:10

ありがとうございます! printしてみた結果、'1行目'の頭に'\ufeff'がついていたのが原因でした。encodingを'utf-8-sig'にしたら解決しました。 無事にtxtファイルを出力することができました。本当に感謝です!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問