Поиск по таблице excel python

поиск в Excel-файле

Привет всем! Интересный вопрос был задан мне в Telegram несколько дней назад. В целом, он сводился к задаче, которая звучала как: поиск в Excel-файле. Давайте попробуем ее решить? 🙂

Собственно, любой Excel-файл — это некоторое количество строк и колонок. Работаем, как всегда — с помощью библиотеки Openpyxl, а для работы с каждой отдельной ячейкой — используем цикл while.

В целом, алгоритм работы кода сводится к:
1. Открываем файл (об этом я писал ранее)
2. Читаем первую ячейку в строке
3. Переходим к следующей строке в этом столбце
4. После того, как достигли максимума по количеству ячеек в столбце — переходим к следующему столбцу.
5. И так до полной обработки файла.

Важно: для того, что бы цикл работал — нам нужно знать количество ячеек в строках и в столбцах. Для этого используем конструкции в виде:

  1. row_max = sheet_active.max_row  # Получаем количество столбцов

и

  1. column_max = sheet_active.max_column  # Получаем количество строк

Сам код с комментариями — доступен ниже.

  1. import openpyxl
  2. from openpyxl.utils import get_column_letter
  3. import re
  4.  
  5. path_to_file = 'base_to_search.xlsx'
  6.  
  7. search_text = input(str('Какой текст ищем: '))
  8. search_text = search_text.lower()
  9. print('Ищем:', search_text)
  10.  
  11. wb = openpyxl.load_workbook(path_to_file)  # Грузим наш прайс-лист
  12. sheets_list = wb.sheetnames  # Получаем список всех листов в файле
  13. sheet_active = wb[sheets_list[0]]  # Начинаем работать с самым первым
  14. row_max = sheet_active.max_row  # Получаем количество столбцов
  15. #print(type(row_max))
  16. column_max = sheet_active.max_column  # Получаем количество строк
  17.  
  18. print('В файле:', path_to_file, 'n Cтолбцов:', row_max, 'n Колонок:', column_max)
  19.  
  20. row_min = 1 #Переменная, отвечающая за номер строки
  21. column_min = 1 #Переменная, отвечающая за номер столбца
  22.  
  23. while column_min <= column_max:
  24.     row_min_min = row_min
  25.     row_max_max = row_max
  26.     while row_min_min <= row_max_max:
  27.         row_min_min = str(row_min_min)
  28.  
  29.         word_column = get_column_letter(column_min)
  30.         word_column = str(word_column)
  31.         word_cell = word_column + row_min_min
  32.  
  33.         data_from_cell = sheet_active[word_cell].value
  34.         data_from_cell = str(data_from_cell)
  35.         #print(data_from_cell)
  36.         regular = search_text
  37.         result = re.findall(regular, data_from_cell)
  38.         if len(result) > 0:
  39.             print('Нашли в ячейке:', word_cell)
  40.         row_min_min = int(row_min_min)
  41.         row_min_min = row_min_min + 1
  42.     column_min = column_min + 1

Конечно, я буду рад любым комментариям и вопросам. Для этого используйте почту или Telegram.

Больше …

Самое основное, с чего начинается изучение языка — с фраз…

Устали фильтровать данные в excel?

Есть решение, как с помощью Python осуществить поиск строк в файле по ключевым словам в столбцах.

Несомненно, многие из нас в своей работе не раз сталкивались с необходимостью фильтрации данных в файле excel, обычно мы делаем это через встроенный в программу фильтр, но бывают ситуации, когда нужно осуществить отбор строк по большому количеству условий (в нашем случае – по ключевым словам) сразу по нескольким столбцам.

Рассмотрим задачу более подробно. Например, у нас есть файл excel с обращениями клиентов в банк (тысячи строк), который содержит следующие колонки: «ИНН клиента», «Дата обращения», «Обращение», «Решение». В столбце «Обращение» содержится текст обращения клиента, в столбце «Решение» — ответ банка на обращение. Суть обращений может быть абсолютно любой (кредитование, страхование, эквайринг и т.д).

Требуется с помощью поиска ключевых слов/сочетаний слов (например, «КАСКО», «ОСАГО», «автострахов», «залог…авто» и т.п.) в колонках «Обращение» и «Решение» выбрать обращения клиентов, которые относятся к страхованию автотранспорта. Нужные слова могут содержаться как в обоих столбцах, так и в одном из них.

Конечно, можно начать фильтровать данные колонки в excel, но это будет долго и трудоёмко, особенно, если слов для поиска подходящих обращений много (или столбцов, в которых необходимо найти ключевые слова). Поэтому для решения нашей задачи требуется более удобный инструмент – Python.

Ниже представлен код, с помощью которого мы отберем необходимые обращения клиентов:

# Импорт библиотек.
import pandas as pd
import numpy as np
import re
#Чтение исходного файла с данными.
df = pd.read_excel(r’ПУТЬ К ФАЙЛУНазвание исходного файла с данными.xlsx’, dtype=’str’)
# Регулярные выражения.
# Шаблон (слова/сочетания слов, которые необходимо найти в столбцах).
r = r'(каско)|(осаго)|(страх.*?транспорт)|(транспорт.*?страх)|(страх.*?авто)|(авто.*?страх)|(залог.*?транспорт)|(транспорт.*?залог)|(залог.*?авто)|(авто.*?залог)|(автострахов)’

Поясним, что «.*?» в выражении (страх.*?транспорт) ищет между «страх» и «транспорт» любое количество символов, вопросительный знак отключает жадность алгоритма поиска (поиск заканчивается как только находится первый «транспорт»).

#Для каждой строки ищем шаблон в столбце «Обращение».
obr = df[‘Обращение’].apply(lambda x: re.search(r, str(x).lower())) #другой вариант: obr = df[‘ Обращение ‘].str.lower().str.contains(r)
#Для каждой строки ищем шаблон в столбце «Решение».
otvet = df[‘Решение’].apply(lambda x: re.search(r, str(x).lower())) #другой вариант: otvet = df[‘Решение’].str.lower().str.contains(r)
#Для каждой строки проверяем наличие шаблона хотя бы в одном из столбцов «Обращение» и «Решение» (результат — True/False).
itog = np.any(np.array([~obr.isnull(), ~otvet.isnull()]), axis=0)
#Результат (оставляем только те строки в таблице, по которым получен результат True).
new_df = df[itog]
#Запись результата в excel.
new_df.to_excel(‘Название итогового файла.xlsx’, index=False)

В результате получаем новый файл excel, в который полностью скопированы нужные нам обращения клиентов:

— в обращении клиента с ИНН 1111111111 в столбцах «Обращение» и «Решение» содержится слово «КАСКО»;

— в обращении клиента с ИНН 333333333333 в столбце «Решение» содержатся сочетания слов «залог…транспорт», «транспорт…страх», «залог…авто», «страх…авто»;

— в обращении клиента с ИНН 444444444444 в столбце «Обращение» содержатся сочетания слов «страх…транспорт»; «транспорт…залог».

Количество столбцов, в которых можно производить поиск ключевых слов, не ограничен – в приведенном примере их два, но у вас может быть больше.

При необходимости для каждого столбца можно задать свой шаблон для поиска слов:

#Шаблон 1 для столбца «Обращение».
r1= r'(каско)|(осаго)|(страх.*?транспорт)|(транспорт.*?страх)|(страх.*?авто)|(авто.*?страх)’
#Шаблон 2 для столбца «Решение».
r2= r'(залог.*?транспорт)|(транспорт.*?залог)|(залог.*?авто)|(авто.*?залог)|(автострахов)’
#Поиск шаблонов 1 и 2 в столбцах «Обращение» и «Решение» соответственно.
obr = df[‘Обращение’].apply(lambda x: re.search(r1, str(x).lower()))
otvet = df[‘Решение’].apply(lambda x: re.search(r2, str(x).lower()))

Если требуется выбрать строки, в которых ключевые слова содержатся и в том, и в другом столбце, то нужно заменить функцию any() на all():

itog = np.all(np.array([~obr.isnull(), ~otvet.isnull()]), axis=0)

Теперь рассмотрим ситуацию, когда у нас имеется несколько файлов excel с обращениями клиентов (с аналогичной структурой столбцов), и необходимо в каждом выбрать подходящие обращения.

Тогда код, с помощью которого мы отберем нужные строки, будет выглядеть так:

#Импорт библиотек.
import pandas as pd
import numpy as np
import os
import re
import warnings
#Игнорирование всех предупреждений.
warnings.filterwarnings(‘ignore’)
#Путь к папке с исходными файлами.
path = r’ПУТЬ К ПАПКЕ С ФАЙЛАМИ ‘
#Регулярные выражения.
#Шаблон (слова/сочетания слов, которые необходимо найти в столбцах).
r= r'(каско)|(осаго)|(страх.*?транспорт)|(транспорт.*?страх)|(страх.*?авто)|(авто.*?страх)|(залог.*?транспорт)|(транспорт.*?залог)|(залог.*?авто)|(авто.*?залог)|(автострахов)’
#Создание папки, в которую будут сохраняться файлы с нужными обращениями.
os.makedirs(‘Нужные обращения’, exist_ok=True)
#Получение списка полных имён для всех файлов xlsx в папке с исходными файлами.
docs = []
for root, _, files in os.walk(path):
for file in files:
if file.split(‘.’)[-1] == ‘xlsx’:
docs.append(os.path.join(root, file))
print(f’В директории {path} nобнаружено {len(docs)} файлов’)
#Для каждого файла из списка производим его чтение, поиск шаблона в столбцах «Обращение» и «Решение», проверяем наличие шаблона хотя бы в одном из данных столбцов, оставляем только те строки в таблице, по которым получен результат True, записываем результат в excel в папку «Нужные обращения».
%%time
for i, doc in enumerate(docs):
df = pd.read_excel(doc)
print(f'{i+1} файл из {len(docs)} прочитан’, end=’ ‘)
obr = df[‘Обращение’].apply(lambda x: re.search(r, str(x).lower()))
otvet = df[‘Решение’].apply(lambda x: re.search(r, str(x).lower()))
itog = np.any(np.array([~obr.isnull(), ~otvet.isnull()]), axis=0)
df = df[itog]
df.to_excel(os.path.join(‘Нужные обращения’, doc.split(‘\’)[-1]), index=False)
print(‘и обработан’)

В результате создается папка «Нужные обращения», в которой содержатся новые файлы excel с полностью скопированными нужными обращениями клиентов. По количеству и названию данные файлы соответствуют исходным.

Таким образом, благодаря Python поиск строк в файлах по ключевым словам в столбцах становится быстрым и несложным делом. Приведенный код значительно ускоряет и упрощает работу аналитика в части фильтрации строк по большому количеству условий по нескольким столбцам.

I have an excel sheet (data.xlxs) with the following pattern of data with more than 200 rows.

NS71282379_67698209    123456001
NS71282379_56698765    123456002
NS71282379_67698209    123456003
.
.
.

Now in my script, I am trying to find the corresponding value for 123456003 as NS71282379_67698209. In my script, I want to replace 123456003 with its value from the excel sheet.
I used xlrd to import the sheet but haven’t found any method which easily allows me to find the corresponding value.
How can I do this smartly?

ballade4op52's user avatar

ballade4op52

2,2374 gold badges25 silver badges41 bronze badges

asked Apr 20, 2016 at 20:51

learnningprogramming's user avatar

2

you can iterate the Excel sheet by range(sheet.nrows) and get row values based on the row number. The script below iterates the Excel sheet row by row and prints out the row that matches value 123456003. You can modify it to meet your requirement

$cat test.py

import xlrd

def open_file(path):
    wb = xlrd.open_workbook(path)
    sheet = wb.sheet_by_index(0)


    for row_num in range(sheet.nrows):
        row_value = sheet.row_values(row_num)
        if row_value[1] == 123456003:
            print row_value

if __name__ == "__main__":
    path = "data.xlsx"
    open_file(path)

$python test.py

[u'NS71282379_67698209', 123456003.0]

ballade4op52's user avatar

ballade4op52

2,2374 gold badges25 silver badges41 bronze badges

answered Apr 20, 2016 at 21:20

Haifeng Zhang's user avatar

Haifeng ZhangHaifeng Zhang

29.5k19 gold badges77 silver badges124 bronze badges

You will have to iterate over the rows and find the one you’re interested in changing. Something like this:

for r in xrange(sheet.nrows):
  row = sheet.row(r)
  if row[0].value == "NS71282379_67698209":
    row[1].value = "new value"
    break

If you need to do this repeatedly, you could instead build a map from the first column values to the second column cells:

cells = dict((row[0].value, row[1])
             for row in (sheet.row(r) for r in xrange(sheet.nrows)))
cells["NS71282379_67698209"].value = "new value"

answered Apr 20, 2016 at 21:25

johndburger's user avatar

Last updated on 
Feb 10, 2022

Do you need to search and replace a list of values in a big Excel file with many sheets?

If so, I’ll show you the steps to search in Excel file — list of words and replace them. In this article you can find the exact cell(with packages like xlrd, xlwt and openpyxl) and partial cell match. At the end a new Excel file is generated with the replaced values.

Let’s check the example data:

A B C
4321 3210 2100
1 0 0
2 1 0
3 2 1
4 3 2

we are going to search for 0 and 1 — and replace them with False and True.

A B C
4321 3210 2100
True False False
2 True False
3 2 True
4 3 2

You can check also this video:
Easily extract information from Excel with Python and Pandas

Python and Excel — search and replace with xlrd and xlwt

In this example we are going to use two Python packages: xlrd and xlwt.

Step 1: Read Excel file

The first package reads the Excel file and a given sheet by name or index:

import xlwt
import xlrd

# read Excel file and sheet by name
workbook = xlrd.open_workbook('/home/vanx/Documents/example1.xlsx')
sheet = workbook.sheet_by_name('Test')
sheet2 = workbook.sheet_by_index(2)

Step 2: Create new Excel file

The second package — xlwt — will be used to write the data into new Excel file:

new_workbook = xlwt.Workbook()
new_sheet = new_workbook.add_sheet('Test')

Step 3: Search and replace a cell in xlsx file

The next step is to define replacement pairs like: {1:True, 0:False}:

replacement = {1:True, 0:False}

Step 4: Search and replace a cell in xlsx file

Finally the code iterates over the rows and columns is controlled by:

  • ncols — number of columns in the selected sheet
  • nrows — number of rows in the selected sheet

This is the final part of the code:

# iterate over the rows
for i in range(sheet.nrows):
    print(i)

    data = [sheet.cell_value(i, col) for col in range(sheet.ncols)]

    for index, value in enumerate(data):

        if value in replacement.keys():
            new_sheet.write(i, index, str(replacement.get(value)))
        else:
            new_sheet.write(i, index, value)

new_workbook.save('example.xls')

where new_workbook.save('example.xlsx') saves the data into file — example.xlsx

Python and Excel — search and replace with openpyxl

Another Python package exists and can be used — openpyxl. It can do the same as the previous example. Difference is that only one module is used for reading and writing new Excel file:

import openpyxl
from openpyxl.utils.cell import get_column_letter

wb = openpyxl.load_workbook('/home/vanx/Documents/example1.xlsx')
wb.sheetnames
sheet = wb["Test"]
number_rows = sheet.max_row
number_columns = sheet.max_column

replacement = {'1':True, '0':False}


for i in range(number_columns):
    for k in range(number_rows):
        cell = str(sheet[get_column_letter(i+1)+str(k+1)].value)
        for key in replacement.keys():
            if str(cell) == key:
                newCell = replacement.get(key)
                sheet[get_column_letter(i+1)+str(k+1)] = str(newCell)

wb.save('example1.xlsx')

The code above reads file: example1.xlsx from folder ~/Documents and then produces a new Excel file in the current working directory. In the file there are several sheets — we are interested in the one named — Test.

Getting the number of rows and columns is done by:

  • sheet.max_row
  • sheet.max_column

Finally we iterate and search for the values. In case of a match then we will replace the cell with the new values.

Python and Excel — partial match

The previous examples work with exact text matches for the cell value. If you need to perform partial match than you can try with Python code like:

if str(cell[0]) == key:

This will search only the first character of the cell if it’s exactly the searched value.

Or if the cell contains the key:

 if key in str(cell[0]):

Regex can be used as well. The problem for such partial matches is performance — it might take resources and time for large Excel files.

Working with Python and Excel together is really fun for a VBA Developer! It somehow shows you what all these years of coding with VBA have taught you! Today, I was thinking how to implement the .Find() method of searching in Excel values.


At first, I have tought about going old school and simply loop through all the cells in a given Excel range, check their values and thus implement a “manual” search. For this, I have generated an Excel file with the xlswriter library and I have read it with the xlrd library. Both are quite easy to be used, if you are aware how the Excel object model is built.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

import xlsxwriter

from xlsxwriter.utility import xl_rowcol_to_cell

import xlrd    

#First part of the code, used only to create some Excel file with data

wbk = xlsxwriter.Workbook(‘hello.xlsx’)

wks = wbk.add_worksheet()

i = 1

for x in range(1, 1000, 11):

    i+=1

    cella = xl_rowcol_to_cell(i, 0) #0,0 is A1!

    cellb = xl_rowcol_to_cell(i, 1)

    cellc = xl_rowcol_to_cell(i, 2)

    #print (cella)

    wks.write(cella,x)

    wks.write(cellb,x*3)

    wks.write(cellc,x*4.5)

myPath= r‘C:Desktophello.xlsx’

wbk.close()

#SecondPart of the code

for sh in xlrd.open_workbook(myPath).sheets():  

    for row in range(sh.nrows):

        for col in range(sh.ncols):

            myCell = sh.cell(row, col)

            print(myCell)

            if myCell.value == 300.0:

                print(‘————‘)

                print(‘Found!’)

                print(xl_rowcol_to_cell(row,col))

                quit()

This is the generated excel file from the first part of the code. (Does it remind something from here?):

This is what Python prints, which is actually quite nice:


SecondlyI remembered that I have actually learnt programming in Python some years ago and this is a programming blog, thus I should probably not code as a first year student (or so). Thus, I have decided to introduce at least one function. So, the function was named findCell and I have rewritten my code to this:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

import xlsxwriter

import os

import xlrd    

import time

from xlsxwriter.utility import xl_rowcol_to_cell

def findCell(sh, searchedValue):

    for row in range(sh.nrows):

        for col in range(sh.ncols):

            myCell = sh.cell(row, col)

            if myCell.value == searchedValue:

                return xl_rowcol_to_cell(row, col)

    return 1

myName = ‘hello.xlsx’

wbk = xlsxwriter.Workbook(myName)

wks = wbk.add_worksheet()

i = 1

for x in range(1, 1000, 11):

    i+=1

    cella = xl_rowcol_to_cell(i, 0) #0,0 is A1!

    cellb = xl_rowcol_to_cell(i, 1)

    cellc = xl_rowcol_to_cell(i, 2)

    wks.write(cella,x)

    wks.write(cellb,x*3)

    wks.write(cellc,x*4.5)

myPath= os.getcwd()+«\»+myName

searchedValue = 300

for sh in xlrd.open_workbook(myPath).sheets():  

    print(findCell(sh, searchedValue))

input(‘Press ENTER to exit’)

Now, it is a bit fancier, as the code could be executed with a click. On the previous one, I have written quit() , thus one should execute it from the console. Still, B10 is found:


Thirdly, I have read a comment from @ashleedawg, that one should be able to use the Excel API and thus use the Find() method from it. The whole programming becomes quite easy this way, using the xlwings library:

import xlwings as xw

bookName = r‘C:somePathhello.xlsx’

sheetName = ‘Sheet1’

wb = xw.Book(bookName)

sht = wb.sheets[sheetName]

myCell = wb.sheets[sheetName].api.UsedRange.Find(‘test’)

print(‘—————‘)

print (myCell.address)

input()

Thus, from an imput like this:

I was still able to get the A10:


That’s all folks! All the code is in GitHub here – Python Find.

  • xlrd documentation

  • xlswriter documentation

  • xlwings documentation

Like this post? Please share to your friends:
  • Поиск по строке первого ненулевого значения excel
  • Поиск по строкам или столбцам в excel
  • Поиск по страницам word
  • Поиск по стилю в word
  • Поиск по ссылкам word