Как переписать лист Excel в Python: от чтения до сохранения

Введение: зачем переписывать Excel в Python?

Работа с таблицами Excel через Python стала неотъемлемой частью автоматизации бизнес-процессов. Представьте: у вас есть отчёт с тысячами строк, которые нужно отфильтровать, преобразовать или перенести в другую систему. Вручную это займёт часы, а с помощью скрипта — несколько секунд. Но как правильно прочитать данные, изменить их и записать обратно без потери форматирования?

Эта статья поможет разобраться в нюансах работы с Excel-файлами через pandas, openpyxl и другие библиотеки. Мы рассмотрим не только базовые операции, но и распространённые ошибки, которые могут испортить ваши данные. Например, знали ли вы, что при неправильном сохранении формулы в ячейках могут превратиться в статичные значения? Или что даты в Excel и Python хранятся по-разному?

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

1. Подготовка: какие библиотеки понадобятся?

Прежде чем переписывать данные, нужно выбрать инструмент. В Python есть несколько популярных библиотек для работы с Excel:

  • 📊 pandas — универсальный инструмент для анализа данных, поддерживает чтение/запись Excel через openpyxl или xlrd.
  • 📑 openpyxl — специализированная библиотека для работы с форматом .xlsx (не поддерживает .xls).
  • 📈 xlwings — позволяет взаимодействовать с Excel как с приложением (например, обновлять графики в реальном времени).
  • 🔄 pyxlsb — для работы с бинарными файлами .xlsb (реже используется).

Для большинства задач хватит pandas + openpyxl. Установите их через pip:

pip install pandas openpyxl

Важно: если вы работаете с файлами .xls (старый формат Excel), дополнительно установите xlrd версии ниже 2.0:

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

2. Чтение данных из Excel: базовые методы

Начнём с самого простого — чтения данных. Предположим, у вас есть файл data.xlsx с листом "Sales". Вот как его открыть:

import pandas as pd

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

df = pd.read_excel("data.xlsx", sheet_name="Sales")

Чтение конкретных колонок

df = pd.read_excel("data.xlsx", sheet_name="Sales", usecols=["Date", "Amount"])

Чтение с пропуском первых 3 строк (например, если есть заголовки)

df = pd.read_excel("data.xlsx", sheet_name="Sales", skiprows=3)

Если нужно прочитать несколько листов сразу, используйте sheet_name=None — результат будет словарём, где ключи — названия листов:

all_sheets = pd.read_excel("data.xlsx", sheet_name=None)

sales_df = all_sheets["Sales"]

inventory_df = all_sheets["Inventory"]

Обратите внимание: по умолчанию pandas преобразует даты в формат Timestamp, а пустые ячейки — в NaN. Если вам нужно сохранить оригинальные типы данных, используйте параметр dtype=str:

df = pd.read_excel("data.xlsx", dtype=str)

3. Изменение данных: фильтрация и преобразования

После чтения данные обычно требуется обработать. Вот несколько типичных операций:

  • 🔍 Фильтрация: оставить только строки, где сумма продаж > 1000.
    filtered_df = df[df["Amount"] > 1000]
  • 🔄 Замена значений: заменить все NaN на ноль.
    df.fillna(0, inplace=True)
  • 📅 Работа с датами: добавить новый столбец с номером месяца.
    df["Month"] = pd.to_datetime(df["Date"]).dt.month
  • 📊 Агрегация: посчитать сумму продаж по категориям.
    grouped_df = df.groupby("Category")["Amount"].sum()

Критическая особенность: если вы планируете сохранить данные обратно в Excel, избегайте операций, которые преобразуют DataFrame в Series (например, groupby().sum()). В таком случае перед сохранением преобразуйте результат обратно в DataFrame:

grouped_df = df.groupby("Category")["Amount"].sum().reset_index()

Также помните, что Excel не поддерживает некоторые типы данных Python, например, dict или set. Перед сохранением преобразуйте их в строки:

df["Metadata"] = df["Metadata"].apply(str)

4. Сохранение данных обратно в Excel

Теперь разберёмся, как записать изменённые данные в новый (или существующий) файл. Базовый синтаксис:

df.to_excel("output.xlsx", sheet_name="Updated_Sales", index=False)

Ключевые параметры:

ПараметрОписаниеПример
indexСохранять ли индексы строкindex=False
sheet_nameНазвание листа (макс. 31 символ)sheet_name="Data"
startrowСтрока, с которой начнётся записьstartrow=5
engineДвижок для записи ('openpyxl' или 'xlsxwriter')engine='openpyxl'

Внимание: если вы сохраняете данные в существующий файл, pandas по умолчанию перезапишет его полностью. Чтобы добавить лист в существующий файл, используйте ExcelWriter с параметром mode='a':

from openpyxl import load_workbook

with pd.ExcelWriter("output.xlsx", engine='openpyxl', mode='a') as writer:

df.to_excel(writer, sheet_name="New_Sheet", index=False)

Что делать, если при сохранении пропадает форматирование?

При использовании pandas оригинальное форматирование (цвета, шрифты, объединённые ячейки) не сохраняется. Чтобы его сохранить, придётся работать напрямую с openpyxl:

1. Откройте файл через load_workbook().

2. Найдите нужный лист по имени.

3. Запишите данные в ячейки вручную, сохраняя стили.

4. Сохраните файл через save().

5. Работа с формулами и специальными форматами

Одна из самых сложных задач — сохранение формул и пользовательских форматов (например, процентов или валют). По умолчанию pandas вычисляет формулы и сохраняет только результаты. Чтобы этого избежать, используйте openpyxl напрямую:

from openpyxl import load_workbook

Открываем файл

wb = load_workbook("formulas.xlsx")

ws = wb["Calculations"]

Записываем формулу в ячейку B2 (например, сумма A1:A10)

ws["B2"] = "=SUM(A1:A10)"

Сохраняем файл

wb.save("formulas_updated.xlsx")

Для работы с датами и временем важно помнить:

  • 📅 Excel хранит даты как количество дней с 1 января 1900 года.
  • Python использует объект datetime.
  • 🔄 При чтении/записи дат используйте pd.to_datetime() для преобразований.

Пример: преобразование столбца с датами из Excel в нормальный формат:

df["Date"] = pd.to_datetime(df["Date"], unit='D', origin='1899-12-30')

6. Оптимизация работы с большими файлами

Если ваш файл весит сотни мегабайт, стандартные методы могут не сработать. Вот несколько советов для ускорения:

  • Читайте только нужные столбцы: usecols=["Column1", "Column2"].
  • 🗃️ Используйте chunksize: обрабатывайте файл порциями по 10 000 строк.
    for chunk in pd.read_excel("huge_file.xlsx", chunksize=10000):
    

    process(chunk)

  • 📉 Отключите автоматическое определение типов: dtype=str ускорит чтение, но данные придётся преобразовывать вручную.
  • 💾 Сохраняйте в .csv: если форматирование не важно, df.to_csv() работает в 5–10 раз быстрее.

Внимание: при работе с chunksize нельзя использовать sheet_name=None — нужно обрабатывать листы по одному.

Для максимальной производительности рассмотрите использование dask или modin — библиотек, оптимизированных для работы с большими данными:

import modin.pandas as pd  # Замена стандартного pandas

df = pd.read_excel("huge_file.xlsx") # Работает быстрее на многопроцессорных системах

7. Типичные ошибки и как их избежать

Даже опытные разработчики сталкиваются с проблемами при работе с Excel в Python. Вот самые распространённые:

⚠️ Ошибка: ValueError: Excel file format cannot be determined, you must specify an engine manually.
Решение: Укажите движок явно: pd.read_excel("file.xlsx", engine='openpyxl').
⚠️ Ошибка: Формулы сохраняются как текст, а не как вычисляемые выражения.
Решение: Используйте openpyxl для записи формул (см. раздел 5).

Другие частые проблемы:

ОшибкаПричинаРешение
Пустые ячейки становятся NaNpandas автоматически преобразует пустотыИспользуйте keep_default_na=False
Русские буквы отображаются как ????Некорректная кодировкаУкажите encoding='utf-8' при сохранении в .csv
Файл не открывается после сохраненияЗакрыт доступ к файлу или не хватает правЗакройте файл в Excel перед записью

Убедитесь, что файл не открыт в Excel|Проверьте названия листов (макс. 31 символ)|Преобразуйте несовместимые типы данных (dict, set) в строки|Сохраните резервную копию оригинального файла|Укажите явный движок (engine='openpyxl')

-->

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

Можно ли переписать только часть листа, не затрагивая остальные данные?

Да, но для этого придётся использовать openpyxl напрямую. Пример:

from openpyxl import load_workbook

wb = load_workbook("data.xlsx")

ws = wb["Sheet1"]

Записываем данные в диапазон B2:D10

for row in dataframe_to_rows(df, index=False, header=False):

ws.append(row)

wb.save("data_updated.xlsx")

Обратите внимание: dataframe_to_rows — это функция из pandas, которая преобразует DataFrame в список строк.

Как сохранить несколько DataFrame на разных листах одного файла?

Используйте ExcelWriter:

with pd.ExcelWriter("multi_sheet.xlsx", engine='openpyxl') as writer:

df1.to_excel(writer, sheet_name="Sheet1", index=False)

df2.to_excel(writer, sheet_name="Sheet2", index=False)

df3.to_excel(writer, sheet_name="Sheet3", index=False)

Почему после сохранения пропадают цвета и объединённые ячейки?

Pandas не сохраняет форматирование. Чтобы его сохранить, нужно:

  1. Открыть исходный файл через openpyxl.
  2. Скопировать стили из оригинальных ячеек.
  3. Применить их к новым данным.
  4. Сохранить файл.

Это трудоёмкий процесс, поэтому для сложных таблиц лучше использовать Excel как источник данных, а визуализацию делать в Python (например, через matplotlib).

Как переписать данные в Excel онлайн (Google Sheets)?

Для работы с Google Sheets используйте библиотеку gspread:

import gspread

from oauth2client.service_account import ServiceAccountCredentials

Авторизация

scope = ["https://spreadsheets.google.com/feeds", "https://www.googleapis.com/auth/drive"]

creds = ServiceAccountCredentials.from_json_keyfile_name("credentials.json", scope)

client = gspread.authorize(creds)

Открываем таблицу

sheet = client.open("My Sheet").sheet1

Записываем данные (например, обновляем ячейку A1)

sheet.update_acell("A1", "New Value")

Подробнее о настройке авторизации читайте в документации gspread.

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

Технически да, но это крайне неудобно. Python в стандартной библиотеке имеет модуль csv, но он не поддерживает формат .xlsx. Для работы с .xls можно использовать xlrd (только чтение) и xlwt (только запись), но они устарели и не поддерживают современные форматы.

Рекомендуем установить pandas и openpyxl — это займёт пару минут и сэкономит часы времени.