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

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

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

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

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

1回答

1785閲覧

pythonでフォルダ内のすべてのexcelブックの文字列を置換したい

sumop

総合スコア10

openpyxl

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

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2022/07/23 12:28

編集2022/07/24 09:52

前提

pythonの勉強中です。

フォルダ名「xchange」内にchange1~change3までの
3つのxlsx形式のファイルがあります。

実現したいこと

それぞれのブック内のセルの各所に「(ファイルパス)/Sheet1'!$A$1」という関数が入っており
全て「(ファイルパス)/Sheet1'!$A$2」に変換したい

https://qiita.com/AkioTakamoto/items/9d2ff4c7cc077d59d607
https://kirinote.com/python-char-replace/
上記2つのサイトを参考にしました

発生している問題・エラーメッセージ

実行すると

Traceback (most recent call last): File "<stdin>", line 17, in <module> AttributeError: 'NoneType' object has no attribute 'replace'

が出てしまい、うまくいきません。

該当のソースコード

import os import openpyxl import re #https://qiita.com/AkioTakamoto/items/9d2ff4c7cc077d59d607 for root, dirs, files in os.walk("xchange"): os.chdir('./xchange') for file in files: ext = os.path.splitext(file)[1] ext = ext.lower() if ".xls" in ext: if ".xlsx" in ext: wb = openpyxl.load_workbook(file) if ".xlsm" in ext: wb = openpyxl.load_workbook(file, keep_vba=True) sheetnames = wb.sheetnames for sheetname in sheetnames: sheet = wb[sheetname] for row in sheet.iter_rows(): for cell in row: if cell.col_idx == 1: new_text = cell.value.replace("$A$1", "$A$2") cell.value = new_text wb.save(file)

試したこと

下記のコード単体だとうまくいくのですが、
全てのブックを実行する処理に組み込むと、うまく動作しません。

import openpyxl #https://kirinote.com/python-char-replace/ wb = openpyxl.load_workbook('./xchange/change1.xlsx') ws = wb['Sheet1'] for row in ws.iter_rows(): for cell in row: if cell.col_idx == 1: new_text = cell.value.replace("$A$1", "$A$2") cell.value = new_text wb.save('./xchange/change1.xlsx')

勉強不足であることは承知しているのですが、
どなたか知恵を頂けないでしょうか。
よろしくお願いいたします。

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

anaconda3 4.13.0
VScode 1.69.2

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

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

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

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

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

meg_

2022/07/23 15:19

「ファイル名「xchange」内にchange1~change3までの3つのxlsx形式のファイルがあります。」とはどういう状態でしょうか?シート名の間違いでしょうか?
sumop

2022/07/23 19:54

大変失礼しました。 change1〜3はブック名で、 各ブックにはそれぞれsheet1、sheet2の名前のシートがあります。 xchangeは、これら3つのブックを入れているファイルの名前です。 デスクトップに置いてあります。 他、不足している情報等ありますでしょうか…?
meg_

2022/07/23 23:25

> xchangeは、これら3つのブックを入れているファイルの名前です。 もしかして”フォルダ”名ですか?
sumop

2022/07/24 00:26

フォルダ名ですね お恥ずかしい…失礼しました
meg_

2022/07/24 00:39

質問タイトルおよび本文を修正されて方が良いかと思います。(質問は編集できます) エラーが出るセルはどのような状態でしょうか?(どんな値や数式が入力されているか?) エラーが出るブックと出ないブックの差を調査されてはどうでしょうか?
sumop

2022/07/24 10:17

修正しました。ありがとうございます。 ご指摘の通り、色々と調査したところ、 A1セルのみに「=(ファイルパス)/Sheet1'!$A$1]」と入力して実行→変換できた A1、A2セルに「=(ファイルパス)/Sheet1'!$A$1]」と入力して実行→変換できた A1、A3セルに「=(ファイルパス)/Sheet1'!$A$1]」と入力して実行→エラー A3セルのみに「=(ファイルパス)/Sheet1'!$A$1]」と入力して実行→エラー となる事が分かりました。 空白セルがあることが原因の様なのですが、この場合はどの様に対処したらよいのでしょうか
sumop

2022/07/24 10:22

if not cell.value == None: をつけ足したらうまくいきました! 本当にありがとうございました
sumop

2022/07/24 11:47

と、思ったら、 PC再起動後にもう一度実行すると、今度は File "<stdin>", line 18, in <module> AttributeError: 'int' object has no attribute 'replace' と表示されてしまいました 本当はデバッグでステップ実行で確認したいのですが、 どの場所にブレークポイントを置いても for root, dirs, files in os.walk("xchange"): 以降は何故か止まらずに最後までいってしまうので、何処のセルが原因なのか分かりません。 もう少しだけアドバイスを頂けないでしょうか。
meg_

2022/07/24 15:09

> 何処のセルが原因なのか分かりません。 セル番地を出力してみたら分かるのではないでしょうか?
sumop

2022/07/24 23:37

シート内に数値があったことが原因でした。 if cell.value == str:で解決しました! ちなみに、replaceでは数値の置換はできないのであれば、 最初に質問させていただいたソースコード上でExcel上での数値の置換(例えば2021という数値を2022に置換する) といったことはどの様にしたらいいのでしょうか・・・ 自力で調べて、Excel上の数値の置換方法をうまく見つけられなかったので・・・ 新しくスレッドを立てた方が良ければ、そちらで質問し直します。
meg_

2022/07/25 11:21

> replaceでは数値の置換はできないのであれば 出来ませんか?試したところExcel側で「数値が文字列で保存されています」の警告は出ますが変換されましたよ。(new_text = str(cell.value).replace("123", "456") ※私の環境ではif文なしでエラーは出ません)
sumop

2022/07/25 22:08

(new_text = str(cell.value).replace("123", "456") ↑のやり方で、私もif文なしで上手くできました!ありがとうございます!! strを使用しているので、 セル上の数値は文字列に変換されて文字列として置換→保存されてしまうと認識しているのですが、 これを、数値→数値のまま置換→保存 といったことは難しいのでしょうか?
meg_

2022/07/26 11:09

数値を置き換えたいのであれば、単純にそのセルに新しい数値を代入するだけで良いのでは?
sumop

2022/07/26 23:32

あっ 仰る通りですね。replaceに囚われすぎていました。 これで、いったん締めようと思います。 meg_さん、とても勉強になりました! 無知な初心者に長々とおつきあいしてくださり、本当にありがとうございました!
guest

回答1

0

自己解決

if not cell.value == None:
で空白セルを回避して、
new_text = str(cell.value).replace("123", "456")
※meg_さんの解答例をコピペしました
で、文字列を置換して、無事に動作しました

meg_さんに、べストアンサーをつけたいのですが、
ボタンが見つけられないので、いったん自己解決扱いにします(涙)
meg_さん、本当にありがとうございました!

投稿2022/07/26 23:43

sumop

総合スコア10

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.30%

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

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

質問する

関連した質問