目次
『問題内容』
「オプション 1」
『プラン2』
ホームページ バックエンド開発 Python チュートリアル Python は Excel ファイルをどのように処理しますか?

Python は Excel ファイルをどのように処理しますか?

May 08, 2023 pm 05:58 PM
excel python

『問題内容』

今回処理するExcelはシートが2枚あり、一方のシートのデータを元にもう一方のシートの値を計算する必要があります。問題は、計算対象のシートに数値だけでなく数式も含まれていることです。見てみましょう:

Python は Excel ファイルをどのように処理しますか?

上の図に示すように、この Excel には CP と DS の合計 2 つのシートがあります。特定のビジネス ルールに従い、 CP のデータ DS の該当セルのデータを計算します。画像の青いボックスには数式が含まれており、他の領域には数値が含まれています。

見てみましょう。前述の処理ロジックに従い、Excel を一度にバッチでデータフレームに読み込み、それを一度にバッチで書き戻すと、何が問題になるでしょうか。コードのこの部分は次のとおりです。

import pandas as pd
import xlwings as xw
 
#要处理的文件路径
fpath = "data/DS_format.xlsm"
 
#把CP和DS两个sheet的数据分别读入pandas的dataframe
cp_df = pd.read_excel(fpath,sheet_name="CP",header=[0])
ds_df = pd.read_excel(fpath,sheet_name="DS",header=[0,1])
 
#计算过程省略......
 
#保存结果到excel       
app = xw.App(visible=False,add_book=False)
ds_format_workbook = app.books.open(fpath)
ds_worksheet = ds_format_workbook.sheets["DS"]
ds_worksheet.range("A1").expand().options(index=False).value = ds_df 
ds_format_workbook.save()
ds_format_workbook.close()
app.quit()
ログイン後にコピー

上記のコードの問題は、pd.read_excel() メソッドが Excel からデータフレームにデータを読み取るときに、数式が含まれるセルの場合、数式が直接読み取られることです。結果 (結果がない場合は Nan が返されます)、Excel に書き込むときは、データフレームを一度にバッチで直接書き戻すので、以前に数式が含まれていたセルは計算された値または計算値で書き戻されます。ナン、と捨てられる式。

さて、問題が発生しました。どう解決すればよいでしょうか?ここで 2 つのアイデアが思い浮かびます:

  • データフレームを Excel に書き戻すとき、一度にバッチで書き戻すのではなく、行と列を繰り返して計算されたデータのみを書き戻す。 . 数式が入ったセルが動かない;

  • エクセルを読んでいるときに、数式の計算結果を読むのではなく、数式が入っているセルの数式を読み取る方法はありますか?

上記の 2 つのアイデアをそれぞれ試してみました。見てみましょう。

「オプション 1」

次のコードは、データフレームを走査し、セルに従って対応する値を書き込もうとします。数式が含まれるセルは移動しません

#根据ds_df来写excel,只写该写的单元格
for row_idx,row in ds_df.iterrows():
    total_capabity_val = row[('Total','Capabity')].strip()
    total_capabity1_val = row[('Total','Capabity.1')].strip()
    #Total和1Gb  Eqv.所在的行不写
    if total_capabity_val!= 'Total' and total_capabity_val != '1Gb  Eqv.':
        #给Delta和LOI赋值
        if total_capabity1_val == 'LOI' or total_capabity1_val == 'Delta':
            ds_worksheet.range((row_idx + 3 ,3)).value = row[('Current week','BOH')]
            print(f"ds_sheet的第{row_idx + 3}行第3列被设置为{row[('Current week','BOH')]}") 
        #给Demand和Supply赋值
        if total_capabity1_val == 'Demand' or total_capabity1_val == 'Supply':
            cp_datetime_columns = cp_df.columns[53:]
            for col_idx in range(4,len(ds_df.columns)):
                ds_datetime = ds_df.columns.get_level_values(1)[col_idx]
                ds_month = ds_df.columns.get_level_values(0)[col_idx]
                if type(ds_datetime) == str and ds_datetime != 'TTL' and ds_datetime != 'Total' and (ds_datetime in cp_datetime_columns):
                    ds_worksheet.range((row_idx + 3,col_idx + 1)).value = row[(f'{ds_month}',f'{ds_datetime}')]
                    print(f"ds_sheet的第{row_idx + 3}行第{col_idx + 1}列被设置为{row[(f'{ds_month}',f'{ds_datetime}')]}") 
                elif type(ds_datetime) == datetime.datetime and (ds_datetime in cp_datetime_columns):
                    ds_worksheet.range((row_idx + 3,col_idx + 1)).value = row[(f'{ds_month}',ds_datetime)]     
                    print(f"ds_sheet的第{row_idx + 3}行第{col_idx + 1}列被设置为{row[(f'{ds_month}',ds_datetime)]}")
ログイン後にコピー

上記のコードは問題を解決します。問題は解決されます。つまり、数式が含まれるセルの数式は保持されます。ただし、記事の冒頭で述べた Python による Excel 処理に関するアドバイスによると、このコードは API を介して Excel のセルを頻繁に操作するため、パフォーマンスに重大な問題があり、書き込みが非常に遅くなります。私の古い Mac で実行するには時間がかかりました。 40 分という時間は到底受け入れられないため、計画は断念せざるを得ませんでした。

『プラン2』

このプランは、Excelで数式値が含まれるセルを読み込む際に、数式値を保持したいと考えています。これは、各 Python Excel ライブラリの API から、対応するメソッドがあるかどうかを確認するだけです。 Pandas の read_excel() メソッドを注意深く調べてみましたが、対応するパラメーターのサポートはありませんでした。 Openpyxl をサポートできる API を見つけました:

import openpyxl
ds_format_workbook = openpyxl.load_workbook(fpath,data_only=False)
ds_wooksheet = ds_format_workbook['DS']
ds_df =  pd.DataFrame(ds_wooksheet.values)
ログイン後にコピー

ここでのキーは data_only パラメータです。True の場合はデータが返され、False の場合は数式の値が保持されます。

見つかったと思い、対応する解決策を見つけて大喜びしましたが、openpyxl で読み取られたデータフレーム内のデータ構造を見てショックを受けました。 Excel テーブルのヘッダーは比較的複雑な 2 レベルのヘッダーであるため、ヘッダー内でセルがマージされたり分割されたりする状況があり、そのようなヘッダーが openpyxl によってデータフレームに読み込まれた後、マルチレベルのヘッダーには従いません。パンダのヘッダー インデックスは処理されますが、単に数値インデックス 0123...

に処理されるだけですが、データフレームの計算はマルチレベル インデックスに依存するため、openpyxl のこの処理方法により、後続の計算を処理できません。

openpyxl は機能しません。xlwings はどうですか? xlwings API ドキュメントを検索した結果、以下に示すように実際に見つかりました。

Python は Excel ファイルをどのように処理しますか?

Range クラスには、formula を取得および設定できる Formula というプロパティが用意されています。

これを見たとき、宝物を見つけたような気分になり、すぐにコードを練習し始めました。おそらく惰性からか、あるいは過去に Excel を行、列、セルごとに操作する効率性に恐怖を感じていたのかもしれませんが、私が最初に思いついた解決策は、それを一度にバッチで実行する、つまりすべての数式を読み取ることでした。戻って、私の最初のコードは次のようなものでした:

#使用xlwings来读取formula
app = xw.App(visible=False,add_book=False)
ds_format_workbook = app.books.open(fpath)
ds_worksheet = ds_format_workbook.sheets["DS"]
#先把所有公式一次性读取并保存下来
formulas = ds_worksheet.used_range.formula
 
#中间计算过程省略...
 
#一次性把所有公式写回去
ds_worksheet.used_range.formula = formulas
ログイン後にコピー

しかし私の考えは間違っており、ds_worksheet.used_range.formula によって数式は返されるだけであると誤解しました。 Excel で数式が含まれるセルですが、実際にはすべてのセルが返され、数式が含まれるセルについては数式のみが保持されます。したがって、数式を書き直すと、データフレームを通じて計算して Excel に書き込んだ他の値が上書きされます。

この場合、数式を含むセルは一度にすべて処理するのではなく個別に処理することしかできないため、コードは次のように記述する必要があります。

#使用xlwings来读取formula
app = xw.App(visible=False,add_book=False)
ds_format_workbook = app.books.open(fpath)
ds_worksheet = ds_format_workbook.sheets["DS"]
 
#保留excel中的formula
#找到DS中Total所在的行,Total之后的行都是formula
row = ds_df.loc[ds_df[('Total','Capabity')]=='Total ']
total_row_index = row.index.values[0]
#获取对应excel的行号(dataframe把两层表头当做索引,从数据行开始计数,而且从0开始计数。excel从表头就开始计数,而且从1开始计数)
excel_total_row_idx = int(total_row_index+2)
#获取excel最后一行的索引
excel_last_row_idx = ds_worksheet.used_range.rows.count
#保留按日期计算的各列的formula
I_col_formula = ds_worksheet.range(f'I3:I{excel_total_row_idx}').formula
N_col_formula = ds_worksheet.range(f'N3:N{excel_total_row_idx}').formula
T_col_formula = ds_worksheet.range(f'T3:T{excel_total_row_idx}').formula
U_col_formula = ds_worksheet.range(f'U3:U{excel_total_row_idx}').formula
Z_col_formula = ds_worksheet.range(f'Z3:Z{excel_total_row_idx}').formula
AE_col_formula = ds_worksheet.range(f'AE3:AE{excel_total_row_idx}').formula
AK_col_formula = ds_worksheet.range(f'AK3:AK{excel_total_row_idx}').formula
AL_col_formula = ds_worksheet.range(f'AL3:AL{excel_total_row_idx}').formula
#保留Total行开始一直到末尾所有行的formula
total_to_last_formula = ds_worksheet.range(f'A{excel_total_row_idx+1}:AL{excel_last_row_idx}').formula
 
#中间计算过程省略...
 
#保存结果到excel                 
#直接把ds_df完整赋值给excel,会导致excel原有的公式被值覆盖
ds_worksheet.range("A1").expand().options(index=False).value = ds_df 
#用之前保留的formulas,重置公式
ds_worksheet.range(f'I3:I{excel_total_row_idx}').formula = I_col_formula
ds_worksheet.range(f'N3:N{excel_total_row_idx}').formula = N_col_formula
ds_worksheet.range(f'T3:T{excel_total_row_idx}').formula = T_col_formula
ds_worksheet.range(f'U3:U{excel_total_row_idx}').formula = U_col_formula
ds_worksheet.range(f'Z3:Z{excel_total_row_idx}').formula = Z_col_formula
ds_worksheet.range(f'AE3:AE{excel_total_row_idx}').formula = AE_col_formula
ds_worksheet.range(f'AK3:AK{excel_total_row_idx}').formula = AK_col_formula
ds_worksheet.range(f'AL3:AL{excel_total_row_idx}').formula = AL_col_formula
ds_worksheet.range(f'A{excel_total_row_idx+1}:AL{excel_last_row_idx}').formula = total_to_last_formula
 
ds_format_workbook.save()
ds_format_workbook.close()
app.quit()
ログイン後にコピー

テスト後、上記のコードで問題は解決しました。完璧に私のニーズを満たしており、パフォーマンスはまったく問題ありません。

以上がPython は Excel ファイルをどのように処理しますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

hadidb:pythonの軽量で水平方向にスケーラブルなデータベース hadidb:pythonの軽量で水平方向にスケーラブルなデータベース Apr 08, 2025 pm 06:12 PM

hadidb:軽量で高レベルのスケーラブルなPythonデータベースHadIDB(HadIDB)は、Pythonで記述された軽量データベースで、スケーラビリティが高くなっています。 PIPインストールを使用してHADIDBをインストールする:PIPINSTALLHADIDBユーザー管理CREATEユーザー:CREATEUSER()メソッド新しいユーザーを作成します。 Authentication()メソッドは、ユーザーのIDを認証します。 fromhadidb.operationimportuseruser_obj = user( "admin"、 "admin")user_obj。

MongoDBデータベースパスワードを表示するNAVICATの方法 MongoDBデータベースパスワードを表示するNAVICATの方法 Apr 08, 2025 pm 09:39 PM

Hash値として保存されているため、Navicatを介してMongoDBパスワードを直接表示することは不可能です。紛失したパスワードを取得する方法:1。パスワードのリセット。 2。構成ファイルを確認します(ハッシュ値が含まれる場合があります)。 3.コードを確認します(パスワードをハードコードできます)。

2時間のPython計画:現実的なアプローチ 2時間のPython計画:現実的なアプローチ Apr 11, 2025 am 12:04 AM

2時間以内にPythonの基本的なプログラミングの概念とスキルを学ぶことができます。 1.変数とデータ型、2。マスターコントロールフロー(条件付きステートメントとループ)、3。機能の定義と使用を理解する4。

高負荷アプリケーションのMySQLパフォーマンスを最適化する方法は? 高負荷アプリケーションのMySQLパフォーマンスを最適化する方法は? Apr 08, 2025 pm 06:03 PM

MySQLデータベースパフォーマンス最適化ガイドリソース集約型アプリケーションでは、MySQLデータベースが重要な役割を果たし、大規模なトランザクションの管理を担当しています。ただし、アプリケーションのスケールが拡大すると、データベースパフォーマンスのボトルネックが制約になることがよくあります。この記事では、一連の効果的なMySQLパフォーマンス最適化戦略を検討して、アプリケーションが高負荷の下で効率的で応答性の高いままであることを保証します。実際のケースを組み合わせて、インデックス作成、クエリ最適化、データベース設計、キャッシュなどの詳細な主要なテクノロジーを説明します。 1.データベースアーキテクチャの設計と最適化されたデータベースアーキテクチャは、MySQLパフォーマンスの最適化の基礎です。いくつかのコア原則は次のとおりです。適切なデータ型を選択し、ニーズを満たす最小のデータ型を選択すると、ストレージスペースを節約するだけでなく、データ処理速度を向上させることもできます。

Python:主要なアプリケーションの調査 Python:主要なアプリケーションの調査 Apr 10, 2025 am 09:41 AM

Pythonは、Web開発、データサイエンス、機械学習、自動化、スクリプトの分野で広く使用されています。 1)Web開発では、DjangoおよびFlask Frameworksが開発プロセスを簡素化します。 2)データサイエンスと機械学習の分野では、Numpy、Pandas、Scikit-Learn、Tensorflowライブラリが強力なサポートを提供します。 3)自動化とスクリプトの観点から、Pythonは自動テストやシステム管理などのタスクに適しています。

Amazon AthenaでAWS接着クローラーの使用方法 Amazon AthenaでAWS接着クローラーの使用方法 Apr 09, 2025 pm 03:09 PM

データの専門家として、さまざまなソースから大量のデータを処理する必要があります。これは、データ管理と分析に課題をもたらす可能性があります。幸いなことに、AWS GlueとAmazon Athenaの2つのAWSサービスが役立ちます。

MySQLはSQLサーバーに接続できますか MySQLはSQLサーバーに接続できますか Apr 08, 2025 pm 05:54 PM

いいえ、MySQLはSQL Serverに直接接続できません。ただし、次のメソッドを使用してデータ相互作用を実装できます。ミドルウェア:MySQLから中間形式にデータをエクスポートしてから、ミドルウェアを介してSQL Serverにインポートします。データベースリンカーの使用:ビジネスツールは、よりフレンドリーなインターフェイスと高度な機能を提供しますが、本質的にはミドルウェアを通じて実装されています。

Redisでサーバーを開始する方法 Redisでサーバーを開始する方法 Apr 10, 2025 pm 08:12 PM

Redisサーバーを起動する手順には、以下が含まれます。オペレーティングシステムに従ってRedisをインストールします。 Redis-Server(Linux/Macos)またはRedis-Server.exe(Windows)を介してRedisサービスを開始します。 Redis-Cli ping(Linux/macos)またはRedis-Cli.exePing(Windows)コマンドを使用して、サービスステータスを確認します。 Redis-Cli、Python、node.jsなどのRedisクライアントを使用して、サーバーにアクセスします。

See all articles