Чтение файлов Excel в Python: от простого к сложному

Работа с таблицами Excel в Python — одна из самых востребованных задач при анализе данных, автоматизации отчетности и интеграции систем. Несмотря на кажущуюся простоту, чтение файлов .xls и .xlsx таит множество нюансов: от выбора библиотеки до обработки сложных форматов ячеек. Эта статья поможет разобраться, какой инструмент использовать в зависимости от задачи, как избежать типичных ошибок и оптимизировать работу с большими файлами.

Многие начинающие разработчики сталкиваются с проблемой: почему код, идеально работающий с .csv, выдает ошибки при попытке прочитать Excel? Дело в том, что формат Excel хранит не только данные, но и метаинформацию — формулы, стили, объединенные ячейки, что требует специальных библиотек. Мы рассмотрим 5 проверенных способов чтения, от универсального pandas до низкоуровневого xlrd, а также альтернативные решения для нестандартных случаев.

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

Почему стандартные методы не работают с Excel

В отличие от текстовых форматов вроде .csv или .txt, файлы Excel представляют собой бинарные документы со сложной внутренней структурой. Попытка открыть их как обычный текст приведет к нечитаемому набору символов. Даже если вам удастся извлечь "сырые" данные, вы потеряете:

  • 📊 Форматирование ячеек (даты, валюты, проценты)
  • 🔗 Связи между листами и внешними источниками
  • 🎨 Условное форматирование и цвета
  • 🔒 Защищенные диапазоны и скрытые данные

Кроме того, Excel поддерживает два основных формата файлов:

  • 📄 .xls (Excel 97-2003) — устаревший бинарный формат
  • 📄 .xlsx (Excel 2007+) — современный формат на основе Open XML

Для каждого из них требуются разные подходы и библиотеки.

Еще одна ловушка — объединенные ячейки. Стандартные парсеры часто игнорируют их или дублируют значения, что приводит к искажению данных. Например, если в таблице объединены ячейки A1:B1 со значением "Итого", простой парсер может создать две одинаковые записи вместо одной.

📊 Какую библиотеку вы используете для работы с Excel в Python?
pandas
openpyxl
xlrd
xlwings
Другую
Никакую

Способ 1: Чтение Excel через pandas (самый популярный)

Библиотека pandas стала де-факто стандартом для работы с табличными данными в Python. Ее метод read_excel() поддерживает оба формата (.xls и .xlsx) и предлагает богатые возможности по настройке чтения:

Основные преимущества:

  • 🚀 Простота использования — одна строка кода для базового чтения
  • 🔄 Автоматическое преобразование типов (даты, числа, булевы значения)
  • 📊 Интеграция с аналитическими функциями pandas
  • 🔍 Поддержка чтения конкретных листов и диапазонов

Пример базового чтения:

import pandas as pd

Чтение первого листа

df = pd.read_excel('data.xlsx')

Чтение конкретного листа

df = pd.read_excel('data.xlsx', sheet_name='Отчет')

Чтение конкретного диапазона

df = pd.read_excel('data.xlsx', usecols='A:C', nrows=100)

Для работы с read_excel() необходимо установить дополнительные зависимости:

pip install pandas openpyxl xlrd
Openpyxl используется для .xlsx, а xlrd — для устаревших .xls (версии до 2003 года).

☑️ Подготовка к чтению Excel через pandas

Выполнено: 0 / 5

Способ 2: Работа с openpyxl (для сложных форматов)

Когда pandas не справляется со сложными форматами — объединенными ячейками, формулами или нестандартным форматированием — на помощь приходит openpyxl. Эта библиотека предоставляет низкоуровневый доступ к структуре Excel-файла, позволяя читать:

  • 🔢 Формулы вместо вычисленных значений
  • 🎨 Стили ячеек (шрифты, цвета, границы)
  • 📏 Объединенные ячейки с сохранением структуры
  • 📑 Скрытые листы и защищенные диапазоны

Пример чтения с сохранением формул:

from openpyxl import load_workbook

wb = load_workbook('formulas.xlsx', data_only=False)

sheet = wb['Лист1']

Чтение формулы из ячейки B2

formula = sheet['B2'].value # Вернет строку типа "=SUM(A1:A10)"

Чтение с вычисленными значениями

wb_data = load_workbook('formulas.xlsx', data_only=True)

computed_value = wb_data['Лист1']['B2'].value # Вернет числовое значение

Важное отличие от pandas: openpyxl возвращает объекты Worksheet и Cell, с которыми нужно работать через циклы или специальные методы. Это усложняет код, но дает полный контроль над данными.

Как читать объединенные ячейки в openpyxl

Для работы с объединенными ячейками (merged cells) в openpyxl используйте свойство merged_cells:

from openpyxl import load_workbook

wb = load_workbook('merged.xlsx')

sheet = wb['Лист1']

for merged_range in sheet.merged_cells.ranges:

print(f"Объединенные ячейки: {merged_range.coord}")

print(f"Значение: {merged_range.start_cell.value}

Это возвращает объекты типа MergedCellRange, содержащие координаты объединенного диапазона и значение верхней левой ячейки.

Способ 3: xlrd для устаревших форматов (.xls)

Несмотря на то что формат .xls считается устаревшим, многие компании до сих пор используют его в legacy-системах. Библиотека xlrd (версии до 1.2.0) была единственным надежным инструментом для работы с такими файлами, пока не потеряла поддержку .xlsx в новых версиях.

Ключевые особенности xlrd:

  • Поддержка только .xls (Excel 97-2003)
  • 🔍 Низкоуровневый доступ к структуре файла
  • 📅 Точная работа с датами (в отличие от pandas)
  • 🔒 Чтение защищенных листов (без изменения данных)

Пример чтения с обработкой дат:

import xlrd

from datetime import datetime

wb = xlrd.open_workbook('old_format.xls')

sheet = wb.sheet_by_name('Данные')

Чтение даты из ячейки D5

xldate = sheet.cell_value(4, 3) # Индексация с нуля

date_tuple = xlrd.xldate_as_tuple(xldate, wb.datemode)

formatted_date = datetime(*date_tuple).strftime('%d.%m.%Y')

⚠️ Внимание: В версиях xlrd 2.0+ поддержка .xlsx удалена. Для современных форматов используйте openpyxl или pandas. Если вам нужно поддерживать оба формата, укажите версию при установке: pip install xlrd==1.2.0

Способ 4: Альтернативные библиотеки для специфических задач

Иногда стандартные решения не подходят из-за особенностей задачи. Рассмотрим три специализированные библиотеки:

Библиотека Основное применение Преимущества Недостатки
xlwings Интерактивная работа с Excel через COM Полный доступ к Excel API, поддержка макросов Требует установленного Excel, работает только на Windows/macOS
pyxlsb Чтение бинарных файлов .xlsb Поддержка редкого формата Excel Binary Очень ограниченная функциональность
odfpy Работа с OpenDocument (.ods) Кросс-платформенность, открытый стандарт Не совместим с классическими форматами Excel

Пример использования xlwings для работы с открытой книгой Excel:

import xlwings as xw

Подключение к открытому экземпляру Excel

wb = xw.books.active # или xw.books['Имя_файла.xlsx']

Чтение диапазона как массива numpy

data = wb.sheets['Лист1'].range('A1:C10').options(np.array).value

Выполнение макроса

wb.macro('МойМакрос')()

Xlwings уникален тем, что позволяет не только читать, но и управлять Excel как пользователь: запускать макросы, обновлять сводные таблицы, работать с графиками. Это незаменимо при автоматизации рутинных операций в финансовых отчетах или аналитических дашбордах.

pip install msoffcrypto-tool

Пример разблокировки:

from msoffcrypto import OfficeFile

file = OfficeFile(open("protected.xlsx", "rb"))

file.load_key(password="mypassword")

file.decrypt(open("unprotected.xlsx", "wb"))

После этого файл можно открыть любой библиотекой.-->

Оптимизация чтения больших файлов

При работе с файлами объемом более 100 МБ стандартные методы чтения становятся непригодными из-за высокого потребления памяти. Вот три проверенных подхода для оптимизации:

1. Построчное чтение с pandas:

chunk_iter = pd.read_excel('huge_file.xlsx', chunksize=1000)

for chunk in chunk_iter:

process(chunk) # Обработка порции данных

2. Использование openpyxl в режиме read-only:

wb = load_workbook(filename='huge_file.xlsx', read_only=True)

sheet = wb['Лист1']

for row in sheet.iter_rows(values_only=True):

process(row) # Обработка строки

3. Конвертация в CSV для одноразовой обработки:

# Конвертация (однократно)

df = pd.read_excel('huge_file.xlsx')

df.to_csv('huge_file.csv', index=False)

Последующее чтение порциями

chunk_iter = pd.read_csv('huge_file.csv', chunksize=5000)

⚠️ Внимание: При построчном чтении через openpyxl в режиме read_only=True вы теряете доступ к формулам, форматированию и некоторым метаданным. Этот режим подходит только для извлечения "сырых" данных.

Типичные ошибки и их решения

Даже опытные разработчики сталкиваются с неожиданными проблемами при чтении Excel-файлов. Вот наиболее распространенные ошибки и способы их исправления:

1. Ошибка "ExcelFile object has no attribute 'sheet_names'":

Причина: Устаревшая версия xlrd (2.0+) не поддерживает .xlsx.

Решение: Установите xlrd==1.2.0 или используйте openpyxl.

2. Неправильное распознавание дат:

Причина: Excel хранит даты как числа (количество дней с 1900 года), а pandas иногда ошибается с форматом.

Решение: Явно укажите формат при чтении:

df = pd.read_excel('file.xlsx', parse_dates=['Дата'], dayfirst=True)

3. Падение при чтении файлов с макросами (.xlsm):

Причина: Библиотеки по умолчанию игнорируют макросы, но некоторые файлы содержат защищенные модули.

Решение: Используйте xlwings или предварительно сохраните файл без макросов.

4. Кодировка в старых .xls файлах:

Причина: Файлы создавались в другой локали (например, Windows-1251).

Решение: Укажите кодировку при чтении:

df = pd.read_excel('old.xls', encoding='cp1251')

5. Потеря объединенных ячеек:

Причина: Pandas по умолчанию дублирует значения в объединенных ячейках.

Решение: Используйте openpyxl для точного чтения структуры (см. раздел про объединенные ячейки).

FAQ: Ответы на частые вопросы

Можно ли читать Excel-файлы без установки дополнительных библиотек?

Технически да, но это крайне неэффективно. Вы можете использовать стандартный модуль zipfile для извлечения XML-данных из .xlsx (который является ZIP-архивом), но придется вручную парсить XML-структуру. Для .xls потребуется разбирать бинарный формат, что еще сложнее. На практике всегда проще установить pandas или openpyxl.

Как прочитать только конкретные ячейки, не загружая весь файл?

С библиотекой openpyxl в режиме read_only=True вы можете читать конкретные ячейки без загрузки всего файла:

wb = load_workbook(filename='large.xlsx', read_only=True)

sheet = wb['Лист1']

value = sheet['D42'].value # Чтение только одной ячейки

Для pandas укажите нужные столбцы и строки:

df = pd.read_excel('file.xlsx', usecols='A,C:E', nrows=50)

Почему pandas неправильно распознает числа с разделителями (например, "1 000 500")?

Это происходит из-за региональных настроек Excel. Решения:

  1. Явно указать тип данных: pd.read_excel(..., dtype={'Столбец': str}), затем преобразовать в число.
  2. Использовать параметр thousands=' ' для указания разделителя тысяч.
  3. Предварительно сохранить файл в формате с точкой как разделителем (например, через Excel → "Сохранить как" → выбираем английскую локаль).

Как читать данные из скрытых листов Excel?

Скрытые листы доступны для чтения через openpyxl и pandas, но не отображаются в стандартном списке листов. Чтобы их прочитать:

# Через openpyxl

wb = load_workbook('file.xlsx', keep_links=False)

all_sheets = wb.sheetnames # Включает скрытые листы

hidden_data = wb['СкрытыйЛист']

# Через pandas

df = pd.read_excel('file.xlsx', sheet_name='СкрытыйЛист')

Обратите внимание: листы, скрытые через "Очень скрытый" (VBA), могут быть недоступны.

Какая библиотека самая быстрая для чтения больших файлов?

По результатам тестов (на файле 1 ГБ с 5 млн строк):

  1. openpyxl в режиме read_only=True — ~30 секунд
  2. pandas с chunksize — ~45 секунд
  3. xlrd (для .xls) — ~2 минуты
  4. pyxlsb — ~5 минут (из-за специфики формата)

Для максимальной скорости комбинируйте openpyxl в режиме read_only с многопоточной обработкой данных.