前提
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
「ファイル名「xchange」内にchange1~change3までの3つのxlsx形式のファイルがあります。」とはどういう状態でしょうか?シート名の間違いでしょうか?
大変失礼しました。
change1〜3はブック名で、
各ブックにはそれぞれsheet1、sheet2の名前のシートがあります。
xchangeは、これら3つのブックを入れているファイルの名前です。
デスクトップに置いてあります。
他、不足している情報等ありますでしょうか…?
> xchangeは、これら3つのブックを入れているファイルの名前です。
もしかして”フォルダ”名ですか?
フォルダ名ですね
お恥ずかしい…失礼しました
質問タイトルおよび本文を修正されて方が良いかと思います。(質問は編集できます)
エラーが出るセルはどのような状態でしょうか?(どんな値や数式が入力されているか?)
エラーが出るブックと出ないブックの差を調査されてはどうでしょうか?
修正しました。ありがとうございます。
ご指摘の通り、色々と調査したところ、
A1セルのみに「=(ファイルパス)/Sheet1'!$A$1]」と入力して実行→変換できた
A1、A2セルに「=(ファイルパス)/Sheet1'!$A$1]」と入力して実行→変換できた
A1、A3セルに「=(ファイルパス)/Sheet1'!$A$1]」と入力して実行→エラー
A3セルのみに「=(ファイルパス)/Sheet1'!$A$1]」と入力して実行→エラー
となる事が分かりました。
空白セルがあることが原因の様なのですが、この場合はどの様に対処したらよいのでしょうか
if not cell.value == None:
をつけ足したらうまくいきました!
本当にありがとうございました
と、思ったら、
PC再起動後にもう一度実行すると、今度は
File "<stdin>", line 18, in <module>
AttributeError: 'int' object has no attribute 'replace'
と表示されてしまいました
本当はデバッグでステップ実行で確認したいのですが、
どの場所にブレークポイントを置いても
for root, dirs, files in os.walk("xchange"):
以降は何故か止まらずに最後までいってしまうので、何処のセルが原因なのか分かりません。
もう少しだけアドバイスを頂けないでしょうか。
> 何処のセルが原因なのか分かりません。
セル番地を出力してみたら分かるのではないでしょうか?
シート内に数値があったことが原因でした。
if cell.value == str:で解決しました!
ちなみに、replaceでは数値の置換はできないのであれば、
最初に質問させていただいたソースコード上でExcel上での数値の置換(例えば2021という数値を2022に置換する)
といったことはどの様にしたらいいのでしょうか・・・
自力で調べて、Excel上の数値の置換方法をうまく見つけられなかったので・・・
新しくスレッドを立てた方が良ければ、そちらで質問し直します。
> replaceでは数値の置換はできないのであれば
出来ませんか?試したところExcel側で「数値が文字列で保存されています」の警告は出ますが変換されましたよ。(new_text = str(cell.value).replace("123", "456") ※私の環境ではif文なしでエラーは出ません)
(new_text = str(cell.value).replace("123", "456")
↑のやり方で、私もif文なしで上手くできました!ありがとうございます!!
strを使用しているので、
セル上の数値は文字列に変換されて文字列として置換→保存されてしまうと認識しているのですが、
これを、数値→数値のまま置換→保存
といったことは難しいのでしょうか?
数値を置き換えたいのであれば、単純にそのセルに新しい数値を代入するだけで良いのでは?
あっ
仰る通りですね。replaceに囚われすぎていました。
これで、いったん締めようと思います。
meg_さん、とても勉強になりました!
無知な初心者に長々とおつきあいしてくださり、本当にありがとうございました!

回答1件
あなたの回答
tips
プレビュー