90051


### 目的

あるexcelファイルにおいて特定の文字列を含むセルの情報（行，列情報）が欲しいです。  
走査方法は100列を行ごとに走査し，それを100行分繰り返します。  
走査部分のコードは次のとおりです。  
（worksheetはactiveにしていること前提です。またopenpyxlライブラリを使用しています。）

[code]

    for r in range(1, 100):
         for c in range(1, 100):
                if ws.cell(row=r, column=c).value != None:
                    if "パソコン" in ws.cell(row=r, column=c).value:
                #search_cells.append(ws.cell(row=r, column=c).value)
                        print(r,c)
    
[/code]

正しい出力結果は得られましたが，もっと簡単で速度の速い取得方法はありますでしょうか？


CC BY-SA 4.0
2022-07-17T11:01:29.087
90037
2022-07-18T03:59:30.327
2022-07-18T03:59:30.327
3060
52517
question
python
Excelファイルの走査にかかる時間を改善したい


エクセル無い (Google スプレッドシート派とも言う) ので, 速度の確認できないけど  
それなり速い かもしれない処理

pandasの `pd.read_excel()` で一括読み取り・検索する方法  
(テスト用コードでは CSV読み込み)

[code]

    import pandas as pd
    import io
    csvf = io.StringIO('''
    ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
    ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
    ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
    ''')
    df = pd.read_csv(csvf, header=None, keep_default_na=False, dtype=str)   # read_excel(dtype=str)
    df.loc[2,3] = 'パソコン1'
    df.loc[1,1] = 'aパソコン2'
    
    def fn(v):
        r = v.str.contains('パソコン')
        if r.any():
            print(f'row: {v.name}, cols: {list(v.index[r])}')
    
    dmy = df.apply(fn, axis=1)
    # row: 1, cols: [1]
    # row: 2, cols: [3]
    
[/code]

NumPyでの文字列検索。`pd.read_excel()` での読み込みまでは同じで, 検索は更に速いはず

[code]

    import numpy as np
    
    r = np.core.defchararray.find(df.to_numpy().astype('U'), 'パソコン') != -1
    np.nonzero(r)
    # (array([1, 2]), array([1, 3]))
    
[/code]


CC BY-SA 4.0
2022-07-17T23:34:44.763
90049
2022-07-17T23:34:44.763
43025
90037
answer


`openpyxl`を使う場合、二重ループで座標を指定しながら毎回セルを読み直すと耐えがたいほど(n分オーダー)遅くなります。  
[`iter_rows`](https://openpyxl.readthedocs.io/en/stable/api/openpyxl.worksheet.worksheet.html?highlight=iter_rows#openpyxl.worksheet.worksheet.Worksheet.iter_rows)などを使ってシートをまとめて読み込み、イテレータに対して処理をすることで劇的に速くなります。(コンマ秒～)

[code]

    import openpyxl
    import time
    
    start = time.time() # 時間計測
    
    fname = r"hoge.xlsx"
    wb = openpyxl.load_workbook(fname, read_only=True)
    ws = wb[wb.sheetnames[0]]
    for row in ws.iter_rows(max_row=100, max_col=100):
        for cell in row:
            if cell.value == 'パソコン':
                print(cell.row, cell.column)
    
    print(time.time() - start) # 処理時間表示(手元の環境では0.22秒)
    
[/code]

参考資料:

  * [Accessing many cells](https://openpyxl.readthedocs.io/en/stable/tutorial.html#accessing-many-cells)
  * [【Python】Excelのデータをすべて取得する方法](https://pg-chain.com/python-excel-data)


CC BY-SA 4.0
2022-07-18T00:13:53.897
90051
2022-07-18T00:13:53.897
9820
90037
answer