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

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

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

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

Python

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

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

Q&A

解決済

2回答

377閲覧

for文中に変数の変化を加えても変わらない

nanoko

総合スコア10

openpyxl

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

Python

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

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

0グッド

0クリップ

投稿2023/08/29 08:38

前提

質問としてはpython基礎についてとなります。

openpyxlとpandasを利用してExcelファイルの編集を行っています。
とあるExcelの表をopenpyxlで開き、一列目(実際の表では社員番号が表記されている列)に"重複"と記載されていた場合は、その行を削除するという操作をfor文で行っています。
行が削除されることで、それ以降の行番号が一つずつずれてしまうため、下記コードのように"c=c-1"とし、行を飛ばすことなく操作することが目的だったのですが、cの値は変わることなく処理が行われてしまいます。
そのため、実行結果としては"重複"と記載されていた行が2行続いていた場合は、2行目の処理が行われず表に残ったままです。
どうすればすべての行に処理を行えるようにできるでしょうか?
また、代替案等ございましたらご教授お願い致します。

ソースコードは問題部分だけ記載しております。

該当のソースコード

python

1#iは最大行数です 2 3c = 4 4for c in range(c,i): 5 print('for中のcの値:'+str(c)) 6 if ws_new.cell(row=c,column=1).value == '重複': 7 ws_new.delete_rows(c) 8 c = c - 1 9 print('-1を加えたcの値:'+str(c))

実行結果

for中のcの値:4 for中のcの値:5 for中のcの値:6 for中のcの値:7 for中のcの値:8 for中のcの値:9 -1を加えたcの値:8 for中のcの値:10 -1を加えたcの値:9 for中のcの値:11 for中のcの値:12

試したこと

元々、社員番号の重複がある場合は一つの行にまとめるという操作を行うための処理なのですが、pandasのduplicatedなどを試してみても、表の装飾や入力をopenpyxlを使って操作していたためか、どう修正しても上手く実行されなかったため、崩しに崩してこのような処理に至りました。

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

ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答2

0

forではそういうことはできません。安易な方法としては、whileに書き直すとか。

Python

1c = 4 2while c < i: 3 print('for中のcの値:'+str(c)) 4 if ws_new.cell(row=c,column=1).value == '重複': 5 ws_new.delete_rows(c) 6 c = c - 1 7 print('-1を加えたcの値:'+str(c)) 8 c = c + 1

機械的に書き直しただけで動作確認はしていません。
また、ループ終了後のcの値がforの場合とは異なります。

投稿2023/08/29 09:14

otn

総合スコア85654

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

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

nanoko

2023/08/29 09:18

ご回答ありがとうございます。 仕様についていまいち理解していなかったため、大変参考になりました。
guest

0

ベストアンサー

for c in range(c, i) というのは、range関数(ジェネレータ)が生成する c, c+1, c+2, ... という列を順番に取り出して処理をするという意味なので、ブロックの中で c を変更しても、次のループでは range が生成する次の値をとってくるだけで変化することはありません。

ブロックの中でcを変更したいなら、whileで書き直せばいいです。
(最大行の数値も変更する必要があると思います)

python

1c = 4 2while c < i: 3 print('for中のcの値:'+str(c)) 4 if ws_new.cell(row=c,column=1).value == '重複': 5 ws_new.delete_rows(c) 6 c = c - 1 7 print('-1を加えたcの値:'+str(c)) 8 # i = i - 1 # 行を削除したら最大行も減るはず 9 c += 1

参考までに、こういう削除していくみたいなやつは、後ろから処理していくと簡単になる場合が多いです。

python

1c = 4 2for c in range(i-1, c-1, -1): 3 print('for中のcの値:'+str(c)) 4 if ws_new.cell(row=c,column=1).value == '重複': 5 ws_new.delete_rows(c)

投稿2023/08/29 09:06

bsdfan

総合スコア4749

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

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

nanoko

2023/08/29 09:18

ご回答ありがとうございます。 ご説明を踏まえ考えてみると、確かにこの処理でcの値が変わる方が不自然だと思えました。 非常に分かりやすく、大変助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.38%

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

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

質問する

関連した質問