🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
openpyxl

openpyxlは、Excel2007以降のファイル(xlsx/xlsm/xltx/xltm)を読み書きするためのPythonライブラリです。

Python

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

Q&A

解決済

2回答

1647閲覧

Python エクセル転記

amateur0

総合スコア1

openpyxl

openpyxlは、Excel2007以降のファイル(xlsx/xlsm/xltx/xltm)を読み書きするためのPythonライブラリです。

Python

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

0グッド

1クリップ

投稿2020/12/10 10:15

編集2020/12/11 07:55

前提・実現したいこと

プログラム初心者です。
pythonでエクセルの転記を行いたいです。

イメージ説明

イメージ説明

「Book1」が本店でコード100ならば,「結果」の本店で収入の箇所に4月~6月のデータをコピペしたいです。
ただし,7月~12月の数字はそのまま残したいです。
これを順次繰り返していきたいのですが,うまくいきません。
「Book1」は,毎月更新されていきます。

よろしくお願いいたします。

試したこと

import openpyxl as py wb = py.load_workbook('Book1.xlsx') ws = wb.active aaa = [] for row in ws.iter_rows(min_row=1): values = [] for c in row: values.append(c.value) aaa.append(tuple(values)) code = ['100','102'] bbb = [] for ccc in aaa:  if ccc[0] in code: bbb.append(ccc) wbwb = py.load_workbook("結果.xlsx") wsws = wbwb.active maxrow = wsws.max_row maxcol = wsws.max_column for ddd in bbb: #ここを追加 if ddd[2] in '本店': if ddd[0] in '100': wsws.cell(row=2,col=3).value = ddd[3] #試しに1セル転記できるか wbwb.save("結果.xlsx")

###エラー

エラーは出ないが,何も起きない

補足情報(FW/ツールのバージョンなど)

Google Colaboratory

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

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

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

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

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

meg_

2020/12/10 11:28

・コードは「コードの挿入」で記入してください。 ・> うまくいきません。 とは具体的にはどういうことでしょうか?
jbpb0

2020/12/10 15:06

pythonのコードの一番最初の行のすぐ上に ```python だけの行を追加してください また、pythonのコードの一番最後の行のすぐ下に ``` だけの行を追加してください
amateur0

2020/12/11 00:30 編集

>meg_ 様 御返信ありがとうございます。 IndexError Traceback (most recent call last) <ipython-input-15-ffb0b9744663> in <module>() 29 maxcol = wsws.max_column 30 ---> 31 if bbb[3] in '本店': 32 if bbb[0] in 100: 33 wsws.cell(row=2,min_col=3).value = bbb IndexError: list index out of range というエラーが表示されてどうしたらよいか行き詰まっています
meg_

2020/12/11 01:11

他の方にも伝わるように、エラーは質問に追記してください。
meg_

2020/12/11 01:14

---> 31 if bbb[3] in '本店':とありますが、質問のコードでは「if bbb[2] in '本店':」となってます。 どちらが正しいのか確認してください。
amateur0

2020/12/11 01:30

申し訳ありません,修正いたしました。
guest

回答2

0

aaa.append(tuple(values))にてaaaにタプルを格納しているので、bbb.append(ccc)でのcccもタプルのはずです。

TypeError: 'in <string>' requires string as left operand, not tuple

上記エラーを解消するためには、bbbの各要素のタプルから値を取り出してから文字列と比較すれば良いでしょう。

投稿2020/12/11 05:10

meg_

総合スコア10736

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

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

amateur0

2020/12/11 07:56

御回答ありがとうございます。 エラーは出なくなりました。 試しにひとつのセルだけ転記できるか試したところ,何も起きませんでした。 御教示お願いいたします。
meg_

2020/12/11 08:36

それは if ddd[0] in '100':の条件分岐でFalseになっているのでは? ddd[0]の値を確認してください。
amateur0

2020/12/11 09:46

print(ddd[0] ) → 100 となりました。
guest

0

ベストアンサー

そもそも元のコードは力業で無理やり操作しようとしているため、元のコードを生かしたまま希望の動作を行わせるように修正しようと思うと
かなり難しいと思いました。

下記のようにデータを構造的に読み取り、構造的に書き込む必要があると思います。
(ただし下記コードも、月の並びについては考慮していない(Book1と結果.xlsxで月の並びが同じであることが前提となっている)ため汎用性に乏しいスクリプトである点は否めません)

import openpyxl as py wb = py.load_workbook('Book1.xlsx') ws = wb.active def write_values(wsh, row, col, values): for val in values: wsh.cell(row=row, column=col, value=val) col+=1 def get_values(wsh, row, start, end): return tuple(x.value for r in wsh.iter_rows(min_row=row, max_row=row, min_col=start, max_col=end) for x in r) # 列の定義 c_code = 1 c_kamoku = 2 c_mise = 3 last_col = 1 # 修正 for cell in ws["2:2"]: # 修正 if cell.value is not None: last_col += 1 code_index = {} data = {} for row in range(2, ws.max_row+1): if ws.cell(row, c_code).value == 'コード': continue if ws.cell(row, c_code).value is None: continue ''' コードと科目の組み合わせを格納する。 ''' code_index.setdefault(ws.cell(row, c_kamoku).value, ws.cell(row, c_code).value) ''' 店ごとに科目の組み合わせを格納する。 ''' mise = ws.cell(row, c_mise).value code = ws.cell(row, c_code).value data.setdefault(mise, {}) data[mise].setdefault(code, []) ''' 科目に対する月次の数字を格納する。 ''' data[mise][code] = get_values(ws, row, 4, last_col-1) # 書き込む対象の勘定コード codes = [100,102] wbwb = py.load_workbook("結果.xlsx") wsws = wbwb.active maxrow = wsws.max_row ''' 取得したデータを書き込む ''' row = 1 while row <= maxrow: # 店を格納する mise = wsws.cell(row, 1).value row += 1 # データを書き込む while row <= maxrow: if not wsws.cell(row, 1).value: break # 勘定名から勘定コードを逆引きする。 code = code_index.get(wsws.cell(row, 1).value) # codesに含まれる勘定コードがある行にデータを書き込む if data.get(mise) and data[mise].get(code) and code in codes: # 修正 write_values(wsws, row, 2, data[mise][code]) row += 1 # 次の店が見つかるまで空の行を送る while (wsws.cell(row, 1).value is None) and (row <= maxrow): row += 1 wbwb.save("結果.xlsx")

※上のコードでは、Book1にデータがなく、かつ結果.xlsxに既にデータがある場合、「結果.xlsx」の当該データは上書き消去されません

投稿2020/12/11 08:35

編集2020/12/26 00:50
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

amateur0

2020/12/11 09:50

ありがとうございます。 なりました! 最初は,スマートにやりたかったのですが,どうもハードルが高く,とりあえず目的を達成しようとおっしゃるとおり力業な感じになっていました。 どのようなプログラムになっているのか,分かっていないので,1行ずつ解読して7月,8月・・・と応用できるよう勉強します。 ありがとうございました。
amateur0

2020/12/11 11:18

last_col = 0 for cell in ws["B:B"]: if cell.value is not None: last_col += 1 ここをなぜこのような取得の仕方にするのか教えていただけませんでしょうか・・ 一応↑を mmm = ws.max_column に置き換えて ''' 科目に対する月次の数字を格納する。 ''' data[mise][code] = get_values(ws, row, 4, mmm-1) という風にしたら,私がしたいことはできるようになったのですが,御回答いただいたコードだとBook1の7月や8月に数字が入っても6月分までしか数字が反映されませんでした。(B列はB7までしかないからだと思いますが)
退会済みユーザー

退会済みユーザー

2020/12/11 11:35

最後列を取得する部分を修正しました。 テスト不足でした。すみません。 last_col = 1 #<------ for cell in ws["2:2"]: #<------ if cell.value is not None: last_col += 1
amateur0

2020/12/11 11:57

修正いただいたコードでもなりました,すっきりしました。 勉強になりました,ありがとうございました。
amateur0

2020/12/23 10:21

応用がきかず申し訳ありませんが 例えば Book1の5行目 100,収入,A店,・・・ がない場合,エラーになってしまいます。 プログラムをいろいろと編集して試してみたのですが,うまくいきませんでした。 解決方法を教えていただけませんでしょうか。 よろしくお願いいたします。 ---- --------------------------------------------------------------------------- KeyError Traceback (most recent call last) <ipython-input-4-6030e2e929ef> in <module>() 80 # codesに含まれる勘定コードがある行にデータを書き込む 81 if code in codes: ---> 82 write_values(wsws, row, 2, data[mise][code]) # 2→5 にしてみた 83 row += 1 84 KeyError: 100
退会済みユーザー

退会済みユーザー

2020/12/26 00:50

修正しました。
amateur0

2020/12/28 01:39

修正ありがとうございました,なりました。 いまの自分の知識では到底無理でした。 非常に助かりました,ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問