Извлечение непрерывных значений ячеек из нескольких файлов Excel с помощью Python

Цель моей задачи — во-первых, извлечь значения из непрерывных ячеек одного файла Excel. Затем тот же метод извлечения будет применен к остальным файлам Excel в той же папке, пока цикл не завершится

Например,
Я хочу извлечь значения из строки «A283:A9000» в файле Excel 1. После завершения извлечения в файле Excel 1 будет извлечено значение из строки «A283:A9000» в файле Excel 2, а затем извлечение в том же файле. строки «A283:A9000» будут продолжены в файле Excel 3, файле Excel 4, файле Excel 5 и так далее.

Я узнаю, как извлекать значения из нескольких файлов Excel из https://thewikihow.com/video_M7YkQpcB4fg Код работает хорошо, когда извлекаются значения из прерывистых ячеек. Однако, когда я пытаюсь использовать код для извлечения значения из непрерывных ячеек ('A283:A9000') одного и того же листа, код терпит неудачу.

Я знаю, что проблема возникает, когда я пытаюсь использовать код для извлечения значений из непрерывных ячеек одного и того же листа, но я не уверен, как исправить код в моем случае. Я думаю, что проблема заключается в строке (ячейки = ['C11', 'C15', 'D15', 'C16', 'A283:A9000']).

Может ли кто-нибудь помочь мне?

Ваше здоровье

Вот код, который я пробовал.

import os
import openpyxl 

folder = r'C:\PhD study\GIS\Wind_Downscale\test_one'
output_file = 'C:\PhD study\GIS\Wind_Downscale\Wind_data_forecast_time.xlsx'

output_wb = openpyxl.Workbook()
output_sheet = output_wb.active
output_sheet.title = 'Wind Data for Forecast Time'

cells = ['C11', 'C15', 'D15', 'C16', 'A283:A9000']

for filename in os.listdir(folder):
    if filename.endswith('.xlsx'):
        
        file = os.path.join(folder, filename)
        
        workbook = openpyxl.load_workbook(file)
       
   
        values = [workbook.active[cell].value for cell in cells]

        
        output_sheet.append(values)
        
output_wb.save(output_file)

Вот сообщение об ошибке:

Traceback (most recent call last):

File C:\\Conda5\\lib\\site-packages\\spyder_kernels\\py3compat.py:356 in compat_exec
exec(code, globals, locals)

File c:\\users\\kxz237.spyder-py3\\temp.py:29
values = \[workbook.active\[cell\].value for cell in cells\]

File c:\\users\\kxz237.spyder-py3\\temp.py:29 in \<listcomp\>
values = \[workbook.active\[cell\].value for cell in cells\]

AttributeError: 'tuple' object has no attribute 'value'

Возможность использования адресации ячеек предусмотрена для удобства в интерактивных сеансах. Для одиночных ячеек Openpyxl возвращает одну ячейку, для каждого другого диапазона — генератор кортежей. Для программного доступа всегда следует использовать ws.iter_rows(), здесь с values_only=True и, возможно, режим только для чтения.

Charlie Clark 21.08.2024 10:43
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
1
71
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я не знаю, есть ли в openpyxl метод чтения из диапазонов ячеек (то, что вы называете непрерывными ячейками), который может быть быстрее. Однако обратите внимание, что ваш диапазон ячеек также может быть представлен списком адресов отдельных ячеек. Поэтому, если вы сначала используете понимание списка для создания списка этих отдельных адресов ячеек, это должно сработать.

Попробуйте заменить эту строку в своем коде:

cells = [f"A{i}" for i in range(283, 9000+1)]

Это создаст список типа ['A283', 'A284'... 'A9000']

Итак, все в вашем примере (при условии, что вам на самом деле не нужны эти начальные ячейки «C11», «C15», «D15», «C16» в вашем списке) будет...

import os
import openpyxl 

folder = r'C:\PhD study\GIS\Wind_Downscale\test_one'
output_file = 'C:\PhD study\GIS\Wind_Downscale\Wind_data_forecast_time.xlsx'

output_wb = openpyxl.Workbook()
output_sheet = output_wb.active
output_sheet.title = 'Wind Data for Forecast Time'

cells = [f"A{i}" for i in range(283, 9000+1)]

for filename in os.listdir(folder):
    if filename.endswith('.xlsx'):
        
        file = os.path.join(folder, filename)
        
        workbook = openpyxl.load_workbook(file)
       
   
        values = [workbook.active[cell].value for cell in cells]

        
        output_sheet.append(values)
        
output_wb.save(output_file)

Вы можете просто объединить понимание списка с дополнительными ячейками cells = ['C11', 'C15', 'D15', 'C16'] + [f"A{i}" for i in range(283, 9000 + 1)]

moken 21.08.2024 01:52

Если вы не знаете, на что способна библиотека, вам не следует делать никаких предложений по этому поводу.

Charlie Clark 21.08.2024 10:41

Спасибо Мэтту и Мокену, на самом деле оба метода на странице работают очень хорошо. Однако stackoverflow позволяет мне принять только один ответ, поэтому мне нужно выбрать только один из них.

Kaiyuan Zheng 21.08.2024 11:08

@CharlieClark Я не думаю, что в данном случае это очень конструктивное замечание. Очевидно, что я знаю достаточно, чтобы решить проблему ОП в точности так, как описано, и только упомянул о своем незнании потенциальных методов диапазона в openpyxl, чтобы признать, что они здесь не нужны, но, возможно, стоит посмотреть, если производительность неудовлетворительна при обработке большого количества строк/листов.

Matt Smith 21.08.2024 11:13
Ответ принят как подходящий

Да, вы пытаетесь использовать «A283: A9000» в качестве координаты одной ячейки, отсюда и ошибка атрибута.

Альтернативой является то, что вы можете рассматривать каждый элемент списка ячеек как диапазон
cells = ['C11', 'C15', 'D15', 'C16', 'A283:A9000']
поэтому для каждого элемента код извлекает все ячейки, которые охватывает диапазон;
для «C11» это будет просто «C11»
для «A283:A9000» это будет «A283», «A284», «A285», «A286», ...

Используйте утилиту Openpyxl openpyxl.utils.cell.cols_from_range(<cells element>) для каждого элемента в списке ячеек.

import os
import openpyxl 

folder = r'C:\PhD study\GIS\Wind_Downscale\test_one'
output_file = 'C:\PhD study\GIS\Wind_Downscale\Wind_data_forecast_time.xlsx'

output_wb = openpyxl.Workbook()
output_sheet = output_wb.active
output_sheet.title = 'Wind Data for Forecast Time'

cells = ['C11', 'C15', 'D15', 'C16', 'A283:A9000']

for filename in os.listdir(folder):
    if filename.endswith('.xlsx'):
        file = os.path.join(folder, filename)

        workbook = openpyxl.load_workbook(file)

        #values = [workbook.active[cell].value for cell in cells]

        for rng in cells:  # Each element in 'cells' list 
            ### Get all cells in the elements range
            for allcells in openpyxl.utils.cell.cols_from_range(rng):
                ### allcells is a tuple of all individual cells in the range rng
                for cell in allcells:  # Extract each cell
                    values = workbook.active[cell].value

                    output_sheet.append([values])

output_wb.save(output_file)

Дополнительная информация к вашему сведению
Существует две утилиты Openpyxl, которые возвращают отдельные ячейки диапазона
openpyxl.utils.cell.cols_from_range(range_string) и
openpyxl.utils.cell.rows_from_range(range_string)

В этом сценарии можно использовать любой из них, учитывая, что указанный диапазон составляет всего один столбец.
Однако, если ваш диапазон охватывает два или более столбцов, каждый из них будет возвращать отдельные ячейки;
cols_from_range, ячейка из каждой строки вниз по первому столбцу, затем то же самое вниз по следующему столбцу и т. д. rows_from_range, ячейки во всех столбцах первой строки, затем все ячейки во всех столбцах второй строки и т. д.

то есть вернется диапазон «C3:D4»
cols_from_range, 'C3', 'C4', 'D3', 'D4'
rows_from_range, 'C3', 'D3', 'C4', 'D4'

Вчера я увидел, что кто-то использовал этот подход, и подумал о том, чтобы принять решение, но не знал, как адаптировать его для своего случая. Спасибо за очень подробное объяснение, оно действительно помогло мне понять подход и сэкономить мое время.

Kaiyuan Zheng 21.08.2024 11:17

Другие вопросы по теме