Автоматизация Excel на Python: библиотеки openpyxl и pandas, примеры кода | HATED
Размер шрифта
Цвет фона и шрифта
Изображения
Озвучивание текста
Обычная версия сайта
HATED.RU разработка и SEO продвижение сайтов, контекстная реклама в РФ
Разработка сайтов, контекстная реклама и привлечение трафика
SEO продвижение
+7 985 220-54-74
+7 985 220-54-74 mts.svg
+7 495 220-54-74 mts.svg
E-mail
info@hated.ru
Адрес
г. Тула, Московское шоссе , д.2в, офис № 3
Рязань, 2-й Школьный переулок, 1
Москва, МКАД 60й километр 4а
Режим работы
Ежедневно: с 9:00 до 20:00
Услуги
  • Разработка сайтов на CMS "1с Битрикс"
    • Информационный сайт на CMS 1с Битрикс
    • Лендинг на CMS 1с Битрикс
    • Доработка и модернизация сайта на 1С-Битрикс
    • Интернет-магазин на CMS 1с Битрикс
    • Корпоративный сайт на 1С‑Битрикс под ключ
    • Разработка маркетплейсов и агрегаторов на 1С-Битрикс
    • Разработка промо-сайта на 1С-Битрикс | Создание промо-сайтов под ключ
    • Сайт-визитка на CMS 1С Битрикс
    • Техническая поддержка сайта на 1С-Битрикс
  • Контекстная реклама
    • Настройка контекстной рекламы «Уверенный старт»
    • Настройка контекстной рекламы Яндекс Директ «Быстрый старт»
    • Сопровождение контекстной рекламы "+"
    • Сопровождение и ведение контекстной рекламы
    • Email-маркетинг и Email-Рассылка
    • Аудит Яндекс.Директ | Проверка контекстной рекламы
    • Медийная реклама
    • Мобильная реклама
    • Продвижение в Яндекс ПромоСтраницах
  • SEO продвижение сайтов
    • SEO‑аудит сайта: комплексный анализ для эффективного продвижения
    • Первичная SEO‑оптимизация сайта — залог эффективного продвижения!
    • SEO‑продвижение интернет‑магазина: рост продаж через поисковый трафик
    • SEO для «1С‑Битрикс»: выведем сайт в топ поиска за 3–6 месяцев
    • SEO-продвижение сайта в Google
    • Комплексное GEO-продвижение сайта в AI
    • Продвижение сайтов в ТОП Яндекс
    • Продвижение сайтов по трафику в России | Рост целевого SEO‑трафика
  • Дизайн "Брендинг"
    • Графический дизайн
    • Дизайн рекламных кампаний
    • Разработка брендбука — заказать создание брендбука для компании
    • Разработка логотипа — логотип, который работает на узнаваемость и продажи
    • Создание презентаций и каталогов на заказ | Дизайн, тексты, вёрстка
  • Разработка сайтов на CMS "Wordpress"
    • Доработка и модернизация сайтов на Wordpress
    • Разработка Landing page на WordPress
    • Разработка интернет-магазина на Wordpress
    • Разработка сайта-портфолио на Wordpress
    • Сайт-визитка на WordPress
  • Разработка сайтов на конструкторе "Tilda"
    • Одностраничный сайт на тильде
    • Доработка сайта на Tilda
    • Интернет-магазин на Тильде
    • Корпоративный сайт на Тильде
    • Промо-сайт на Тильде
    • Сайт-каталог на Тильде
    • Сайт-портфолио на Тильде
    • Создание сайта-визитки на Тильде
    • Сопровождение и техническая поддержка сайтов на Тильде
  • Создание быстрого сайта без CMS
    • Разработка базового лендинга без CMS в
  • DevOps
    • Внедрение CI/CD — автоматизация разработки под ключ
    • Настройка Яндекс Клауд и VK Cloud
    • Подбор и настройка инфраструктуры
  • SMM
    • Комплексное ведение социальных сетей под ключ
    • Контент-план для социальных сетей на месяц
    • Реклама у блогеров под ключ: подбор, ТЗ и сопровождение
    • Создание контента для социальных сетей
  • UI/UX разработка \ дизайн
    • Backend разработка на заказ
    • Frontend разработка сайтов и приложений
    • Разработка мобильных приложений для iOS и Android
  • Разработка под Telegram
    • Разработка Telegram Mini Apps
    • Разработка чат-ботов для Telegram
  • Таргетированная реклама
    • Авитолог — продвижение на Авито
    • Таргетированная реклама в Telegram \ Телеграмм ADS
    • Таргетированная реклама в VK (ВКонтакте)
    • Таргетированная реклама в Одноклассниках под ключ
Наши работы
  • Разработка сайтов на Drupal
  • Брендинг и айдентика
  • Портфолио: сайты на 1С‑Битрикс
  • Портфолио: сайты на CMS Tilda
  • Разработка сайта на "Чистом коде"
Магазин
  • Битрикс 24
  • Готовые шаблоны для cms 1c Bitrix
Компания
  • О компании
  • Лицензии
  • Реквизиты
  • Сотрудники
  • Отзывы
Статьи
Контакты
  • Отзывы
  • Лицензии
  • Новости
  • Вопрос-ответ
  • ...
    ...
    +7 985 220-54-74
    +7 985 220-54-74 mts.svg
    +7 495 220-54-74 mts.svg
    E-mail
    info@hated.ru
    Адрес
    г. Тула, Московское шоссе , д.2в, офис № 3
    Рязань, 2-й Школьный переулок, 1
    Москва, МКАД 60й километр 4а
    Режим работы
    Ежедневно: с 9:00 до 20:00
    HATED.RU разработка и SEO продвижение сайтов, контекстная реклама в РФ
    Разработка сайтов, контекстная реклама и привлечение трафика
    SEO продвижение
    Услуги
    Наши работы
    Магазин
    Компания
    Статьи
    Контакты
      HATED.RU разработка и SEO продвижение сайтов, контекстная реклама в РФ
      Услуги
      Наши работы
      Магазин
      Компания
      Статьи
      Контакты
        +7 985 220-54-74 mts.svg
        +7 495 220-54-74 mts.svg
        E-mail
        info@hated.ru
        Адрес
        г. Тула, Московское шоссе , д.2в, офис № 3
        Рязань, 2-й Школьный переулок, 1
        Москва, МКАД 60й километр 4а
        Режим работы
        Ежедневно: с 9:00 до 20:00
        HATED.RU разработка и SEO продвижение сайтов, контекстная реклама в РФ
        Телефоны
        +7 985 220-54-74 mts.svg
        +7 495 220-54-74 mts.svg
        E-mail
        info@hated.ru
        Адрес
        г. Тула, Московское шоссе , д.2в, офис № 3
        Рязань, 2-й Школьный переулок, 1
        Москва, МКАД 60й километр 4а
        Режим работы
        Ежедневно: с 9:00 до 20:00
        HATED.RU разработка и SEO продвижение сайтов, контекстная реклама в РФ
        • Услуги
          • Услуги
          • Разработка сайтов на CMS "1с Битрикс"
            • Разработка сайтов на CMS "1с Битрикс"
            • Информационный сайт на CMS 1с Битрикс
            • Лендинг на CMS 1с Битрикс
            • Доработка и модернизация сайта на 1С-Битрикс
            • Интернет-магазин на CMS 1с Битрикс
            • Корпоративный сайт на 1С‑Битрикс под ключ
            • Разработка маркетплейсов и агрегаторов на 1С-Битрикс
            • Разработка промо-сайта на 1С-Битрикс | Создание промо-сайтов под ключ
            • Сайт-визитка на CMS 1С Битрикс
            • Техническая поддержка сайта на 1С-Битрикс
          • Контекстная реклама
            • Контекстная реклама
            • Настройка контекстной рекламы «Уверенный старт»
            • Настройка контекстной рекламы Яндекс Директ «Быстрый старт»
            • Сопровождение контекстной рекламы "+"
            • Сопровождение и ведение контекстной рекламы
            • Email-маркетинг и Email-Рассылка
            • Аудит Яндекс.Директ | Проверка контекстной рекламы
            • Медийная реклама
            • Мобильная реклама
            • Продвижение в Яндекс ПромоСтраницах
          • SEO продвижение сайтов
            • SEO продвижение сайтов
            • SEO‑аудит сайта: комплексный анализ для эффективного продвижения
            • Первичная SEO‑оптимизация сайта — залог эффективного продвижения!
            • SEO‑продвижение интернет‑магазина: рост продаж через поисковый трафик
            • SEO для «1С‑Битрикс»: выведем сайт в топ поиска за 3–6 месяцев
            • SEO-продвижение сайта в Google
            • Комплексное GEO-продвижение сайта в AI
            • Продвижение сайтов в ТОП Яндекс
            • Продвижение сайтов по трафику в России | Рост целевого SEO‑трафика
          • Дизайн "Брендинг"
            • Дизайн "Брендинг"
            • Графический дизайн
            • Дизайн рекламных кампаний
            • Разработка брендбука — заказать создание брендбука для компании
            • Разработка логотипа — логотип, который работает на узнаваемость и продажи
            • Создание презентаций и каталогов на заказ | Дизайн, тексты, вёрстка
          • Разработка сайтов на CMS "Wordpress"
            • Разработка сайтов на CMS "Wordpress"
            • Доработка и модернизация сайтов на Wordpress
            • Разработка Landing page на WordPress
            • Разработка интернет-магазина на Wordpress
            • Разработка сайта-портфолио на Wordpress
            • Сайт-визитка на WordPress
          • Разработка сайтов на конструкторе "Tilda"
            • Разработка сайтов на конструкторе "Tilda"
            • Одностраничный сайт на тильде
            • Доработка сайта на Tilda
            • Интернет-магазин на Тильде
            • Корпоративный сайт на Тильде
            • Промо-сайт на Тильде
            • Сайт-каталог на Тильде
            • Сайт-портфолио на Тильде
            • Создание сайта-визитки на Тильде
            • Сопровождение и техническая поддержка сайтов на Тильде
          • Создание быстрого сайта без CMS
            • Создание быстрого сайта без CMS
            • Разработка базового лендинга без CMS в
          • DevOps
            • DevOps
            • Внедрение CI/CD — автоматизация разработки под ключ
            • Настройка Яндекс Клауд и VK Cloud
            • Подбор и настройка инфраструктуры
          • SMM
            • SMM
            • Комплексное ведение социальных сетей под ключ
            • Контент-план для социальных сетей на месяц
            • Реклама у блогеров под ключ: подбор, ТЗ и сопровождение
            • Создание контента для социальных сетей
          • UI/UX разработка \ дизайн
            • UI/UX разработка \ дизайн
            • Backend разработка на заказ
            • Frontend разработка сайтов и приложений
            • Разработка мобильных приложений для iOS и Android
          • Разработка под Telegram
            • Разработка под Telegram
            • Разработка Telegram Mini Apps
            • Разработка чат-ботов для Telegram
          • Таргетированная реклама
            • Таргетированная реклама
            • Авитолог — продвижение на Авито
            • Таргетированная реклама в Telegram \ Телеграмм ADS
            • Таргетированная реклама в VK (ВКонтакте)
            • Таргетированная реклама в Одноклассниках под ключ
        • Наши работы
          • Наши работы
          • Разработка сайтов на Drupal
          • Брендинг и айдентика
          • Портфолио: сайты на 1С‑Битрикс
          • Портфолио: сайты на CMS Tilda
          • Разработка сайта на "Чистом коде"
        • Магазин
          • Магазин
          • Битрикс 24
          • Готовые шаблоны для cms 1c Bitrix
        • Компания
          • Компания
          • О компании
          • Лицензии
          • Реквизиты
          • Сотрудники
          • Отзывы
        • Статьи
        • Контакты
        • +7 985 220-54-74
          • Телефоны
          • +7 985 220-54-74
            mts.svg
          • +7 495 220-54-74
            mts.svg
        • г. Тула, Московское шоссе , д.2в, офис № 3
          Рязань, 2-й Школьный переулок, 1
          Москва, МКАД 60й километр 4а
        • info@hated.ru
        • Ежедневно: с 9:00 до 20:00

        Как автоматизировать Excel с помощью Python: полная инструкция и библиотеки 2026

        Создание сайтов и SEO продвижение сайтов любой тематики в и по всей России. Индивидуальная разработка сайтов и комплексный подход к SEO продвижению.
        —
        Статьи о рекламе в интернете, разработке сайтов и их продвижению
        —
        Статьи на тему: Веб-дизайн, разработка сайтов
        Блог о 1С Битрикс
        Статьи о SEO продвижении сайтов
        Статьи о контекстной рекламе - Блог Hated.ru
        Полезное
        —Как автоматизировать Excel с помощью Python: полная инструкция и библиотеки 2026
        гайд по openpyxl, pandas и xlwings
        Статьи о разработки сайтов
        9 октября 2026
           Рутина и регулярная обработка больших таблиц в Excel отнимают у бизнеса сотни часов. В статье разбираем, как автоматизировать работу с Excel с помощью Python. Рассмотрим популярные библиотеки (openpyxl, pandas, xlwings), применим скрипты для отчетов и разберем способы избавления от ошибок. 
        Разработка · Python · Excel · 2026
        Автоматизация Excel на Python: отчёты, свод и диаграммы без ручной работы

        Разбираю, как разработчик автоматизирует таблицы: какие библиотеки брать, как читать и оформлять файлы, чистить выгрузки и собирать отчёты с диаграммами. Весь код запущен и проверен. Есть замеры скорости на 100 000 строк и калькулятор окупаемости.

        10 примеров кода с проверкой запуском замеры на 100 000 строк 10 частых ошибок калькулятор окупаемости 3 промпта для нейросети
        ...
        # из выгрузки в итоги по менеджерам
        import pandas as pd
        
        df = pd.read_excel("orders.xlsx")
        df = df.drop_duplicates()
        paid = df[df["Статус"] == "Оплачен"]
        paid.groupby("Менеджер")["Сумма"].sum()
        МенеджерСуммаВыполн.
        Иванова452 570 ₽113%
        Петров229 150 ₽92%
        Смирнова151 460 ₽84%

        Привет, я Дени, разработчик Hated.Ru. Пишу бэкенд на Python, работаю с PostgreSQL, Docker и Linux-серверами. Excel встречается в любом проекте: выгрузки заказов, отчёты по рекламе, прайсы, каталоги товаров. Файл приходит, его надо почистить, свести с другим, оформить и отправить дальше. Когда это повторяется каждую неделю, пора отдать работу скрипту.

        Я изучил курс по автоматизации Excel на Python, затем собрал примеры заново и прогнал их на свежих версиях библиотек. Ниже только то, что сработало, и ошибки, на которые я наткнулся по пути. К концу статьи у вас будет набор рабочих скриптов, понимание, чем openpyxl отличается от pandas и XlsxWriter, и расчёт, окупится ли автоматизация вашей задачи.

        Данные и версии проверены 7 октября 2026 года. Код запускался на Python 3.11 с openpyxl 3.1.5, pandas 3.0.2 и XlsxWriter 3.2.9. Все данные в примерах учебные, их создаёт скрипт из раздела 3.

        Коротко
        • Python читает и пишет Excel-файлы без запуска самого Excel. Хватает трёх библиотек: openpyxl правит и оформляет файлы, pandas чистит и считает, XlsxWriter создаёт отчёты с диаграммами.
        • Автоматизация окупается, когда одна и та же операция повторяется каждую неделю или строк слишком много для ручной проверки. Срок окупаемости покажет калькулятор в разделе 15.
        • Файл, который сохранил openpyxl, хранит формулы без результатов, пока его не откроют в Excel. Это самая частая причина пустых ячеек при чтении.
        • На 100 000 строк быстрее всего читает pandas с движком calamine: около 1,4 секунды против 6,5 секунды у стандартного пути.
        • Если в файле персональные данные клиентов, сначала сверьтесь с требованиями 152-ФЗ и только потом отправляйте файл в сторонние сервисы, включая нейросети.
        Содержание
        1. Когда Excel пора отдать Python
        2. Какая библиотека для чего
        3. Подготовка: окружение за десять минут
        4. Читаем файл: листы, ячейки, формулы
        5. Пишем, переименовываем, сохраняем
        6. Оформление: шрифты, границы, форматы
        7. pandas: чистим выгрузку
        8. Отчёт с диаграммами в XlsxWriter
        9. Условное форматирование: план и факт
        10. Свод из папки с выгрузками
        11. Скорость и память: замеры
        12. Десять частых ошибок
        13. Нейросеть как помощник и три промпта
        14. Безопасность и порядок
        15. Окупится ли автоматизация и ТЗ на скрипт
        16. Чек-лист перед запуском
        17. Что мы делаем в Hated.Ru
        Раздел 1

        Когда Excel пора отдать Python

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

        Мой порядок такой. Сначала смотрю, что даёт сам Excel: формулы, сводные таблицы, Power Query. Если их хватает, скрипт не нужен. Если файл надо забрать из почты или API, обработать по правилам и положить результат туда, где его увидит команда, подключаю Python.

        СитуацияЧто взятьКомментарий
        Разовая правка до сотни строкФормулы и рукиСкрипт писать и проверять дольше, чем править таблицу.
        Свод файлов одного формата раз в неделюPower Query или PythonPython удобнее, когда после свода нужны очистка, диаграммы и отправка.
        Кнопка внутри Excel для сотрудниковVBA-макросМакрос живёт в книге и запускается кнопкой, Python ставить не надо.
        Данные из API, CRM или почты, результат в файлPythonАвторизация, постраничная загрузка и обработка ошибок удобнее в скрипте.
        Подсветка отклонений в готовой таблицеУсловное форматирование ExcelPython нужен, если таблицу создаёт скрипт.
        Больше 1 048 576 строкБаза данных и pandasСтолько строк на одном листе Excel не помещается.

        Выберите свою задачу ниже, и я подскажу, что бы взял на вашем месте.

        Моя задача
        Раздел 2

        Какая библиотека для чего

        Новичку помогает простое правило. pandas берёт таблицу как данные: очистка, группировки, свод. openpyxl правит и оформляет готовые файлы. XlsxWriter создаёт новые отчёты с диаграммами. Остальное нужно реже.

        БиблиотекаЧитаетПишетМеняет готовый файлДля чего берут
        openpyxlxlsx, xlsmДаДа, с оговоркамиПравка, оформление, условное форматирование, формулы
        pandasЧерез движкиДаПишет новый файлОчистка, группировки, сводные таблицы, объединение файлов
        XlsxWriterНетДаНетНовые отчёты с диаграммами и аккуратным оформлением, быстрая запись
        python-calaminexlsx, xls, xlsb, odsНетНетБыстрое чтение больших файлов, подключается к pandas как движок
        pywin32Через настоящий ExcelДаДаУправление запущенным Excel через COM: макросы, сводные, экспорт в PDF
        Два ограничения из документации

        XlsxWriter умеет только создавать новые файлы. Если нужно дописать лист в чужую книгу, берите openpyxl.

        pywin32 работает только на Windows и только при установленном Excel, потому что управляет им через COM. Мои примеры запускались на стенде с Linux, где нет ни Windows, ни Excel, поэтому про pywin32 здесь обзор без кода.

        Отдельно стоит функция Microsoft 365 «Python в Excel». Код в ней выполняется в облаке Microsoft внутри таблицы и не имеет доступа к вашему компьютеру и сети. Для скриптов, которые собирают файлы из папок и отправляют отчёты, она не предназначена.

        Раздел 3

        Подготовка: окружение за десять минут

        Нужен Python 3.11 или новее, так как pandas 3 требует именно такую версию. Для каждого проекта я завожу отдельное виртуальное окружение. Версии библиотек остаются в нём, и обновление pandas в одном проекте не ломает скрипты в другом.

        1

        Папка проекта и окружение

        Создайте папку, например excel-auto, откройте в ней терминал и создайте окружение.

        Терминал
        python -m venv .venv
        .venv\Scripts\activate        # Windows
        source .venv/bin/activate      # macOS и Linux
        2

        Библиотеки

        Четыре пакета: три основные и calamine для быстрого чтения. Версии из моего прогона зафиксированы в файле requirements.

        Терминал
        pip install openpyxl==3.1.5 pandas==3.0.2 xlsxwriter==3.2.9 python-calamine==0.8.2
        pip freeze > requirements.txt
        3

        Тестовые данные

        Скрипт ниже создаёт файл orders.xlsx с типичным беспорядком: пропуски, дубли, лишние пробелы, даты текстом. Ещё он кладёт в папку exports три файла выгрузок для раздела 10. На этих данных построены все следующие примеры.

        Показать скрипт make_demo.py

        В итоге в папке проекта лежат файлы с понятными именами: orders.xlsx на входе, скрипты s01_read.py, s02_write.py и так далее, папка reports для готовых отчётов. Исходные файлы я держу отдельно от результатов, чтобы случайно не перезаписать данные.

        Раздел 4

        Читаем файл: листы, ячейки, формулы

        Начинаем с чтения через openpyxl. Откроем книгу, найдём лист, возьмём одну ячейку, пройдём по строкам и соберём столбец целиком.

        s01_read.py
        from openpyxl import load_workbook
        
        wb = load_workbook("orders.xlsx")          # открываем книгу
        print(wb.sheetnames)                        # ['Заказы']
        
        ws = wb["Заказы"]                           # нужный лист по имени
        print(ws.max_row, ws.max_column)            # 124 10
        print(ws["C2"].value)                       # одна ячейка: менеджер в строке 2
        
        # все строки, начиная со второй, сразу значениями
        total = 0
        for date, order, manager, city, good, qty, price, amount, *_ in ws.iter_rows(min_row=2, values_only=True):
            total += amount or 0
        print("Сумма всех заказов:", total)
        
        # один столбец целиком
        managers = [c.value for c in ws["C"][1:]]   # без заголовка
        print(len(managers), "значений в столбце «Менеджер»")
        Вывод
        ['Заказы']
        124 10
        Иванова
        Сумма всех заказов: 3395370
        123 значений в столбце «Менеджер»
        • ws["C2"].value возвращает содержимое одной ячейки. Адрес пишется так же, как в Excel.
        • iter_rows(min_row=2, values_only=True) отдаёт готовые значения без объектов ячеек. Цикл работает быстрее, а код короче.
        • ws["C"] возвращает все ячейки столбца C. Срез [1:] убирает заголовок.
        • Пустая ячейка приходит как None. Поэтому в сумме стоит amount or 0.
        Формулы и параметр data_only

        По умолчанию openpyxl возвращает формулу как текст. Параметр data_only=True просит вернуть значение, которое сохранил Excel при последнем открытии файла. Если файл создала сама библиотека, значений в нём нет, и вместо числа придёт None. Проверим на минимальном примере.

        s01b_formula.py
        from openpyxl import Workbook, load_workbook
        
        wb = Workbook()
        ws = wb.active
        ws["A1"], ws["A2"], ws["A3"] = 100, 250, "=SUM(A1:A2)"
        wb.save("formula_test.xlsx")
        
        print(load_workbook("formula_test.xlsx")["Sheet"]["A3"].value)                  # =SUM(A1:A2)
        print(load_workbook("formula_test.xlsx", data_only=True)["Sheet"]["A3"].value)  # None
        Вывод
        =SUM(A1:A2)
        None

        Если вам нужны итоги формул, откройте файл в Excel и сохраните его, либо считайте итоги в Python и записывайте числа.

        Раздел 5

        Пишем, переименовываем, сохраняем

        Задача: взять из выгрузки только оплаченные заказы, положить их на новый лист, добавить итог формулой и сохранить отчёт под именем с датой.

        s02_write.py
        from datetime import date
        from pathlib import Path
        from openpyxl import Workbook, load_workbook
        
        src = load_workbook("orders.xlsx")["Заказы"]
        
        wb = Workbook()
        ws = wb.active
        ws.title = "Оплаченные"                              # переименовали стандартный лист
        header = [c.value for c in src[1]]
        ws.append(header)
        for row in src.iter_rows(min_row=2, values_only=True):
            if row[8] == "Оплачен":                          # столбец «Статус»
                ws.append(row)
        
        ws["L1"] = "Всего оплачено"                          # запись в конкретную ячейку
        ws["L2"] = f"=SUM(H2:H{ws.max_row})"                 # формулу пишем строкой
        
        wb.create_sheet("Черновик")                          # лишний лист создали...
        del wb["Черновик"]                                   # ...и удалили
        
        out = Path("reports")
        out.mkdir(exist_ok=True)
        path = out / f"orders_paid_{date.today():%Y-%m-%d}.xlsx"   # исходник не перезаписываем
        wb.save(path)
        print("Сохранено:", path, "| листы:", wb.sheetnames, "| строк:", ws.max_row)
        Вывод
        Сохранено: reports/orders_paid_2026-10-07.xlsx | листы: ['Оплаченные'] | строк: 63
        • ws.title переименовывает лист. Стандартный лист новой книги называется Sheet, и оставлять его так в отчёте нехорошо.
        • ws.append(строка) дописывает строку в конец листа. Это самый короткий способ записи.
        • create_sheet и del wb["Черновик"] создают и удаляют листы.
        • Формулу записываем обычной строкой, которая начинается со знака равенства. Excel пересчитает её при открытии.
        Что говорит документация про сохранение

        Метод save перезаписывает существующий файл без предупреждения. Поэтому исходник остаётся нетронутым, а отчёт сохраняется под новым именем с датой.

        Ещё одна оговорка: openpyxl читает не все элементы файла, и фигуры из старой книги пропадут, если открыть её и сохранить под тем же именем. Для книги с макросами в формате xlsm нужен параметр keep_vba=True. Макросы тогда сохранятся, но редактировать их из Python нельзя.

        Раздел 6

        Оформление: шрифты, границы, форматы

        Сырая выгрузка в таком виде руководителю не уйдёт. Добавим заголовок отчёта с объединёнными ячейками, цветную шапку, границы, форматы денег и дат, ширину столбцов, закрепление шапки и фильтр.

        s03_format.py
        from openpyxl import load_workbook
        from openpyxl.styles import Alignment, Border, Font, PatternFill, Side
        from openpyxl.utils import get_column_letter
        
        wb = load_workbook("orders.xlsx")
        ws = wb["Заказы"]
        ws.insert_rows(1)                                    # строка под заголовок отчёта
        ws["A1"] = "Заказы за сентябрь 2026"
        ws.merge_cells("A1:J1")                              # объединили ячейки
        ws["A1"].font = Font(name="Calibri", size=16, bold=True)
        ws["A1"].alignment = Alignment(horizontal="center", vertical="center")
        ws.row_dimensions[1].height = 30                     # высота строки
        
        thin = Side(style="thin", color="BBBBBB")
        border = Border(left=thin, right=thin, top=thin, bottom=thin)
        head_fill = PatternFill("solid", fgColor="1F3864")
        
        for cell in ws[2]:                                   # шапка таблицы
            cell.font = Font(bold=True, color="FFFFFF")
            cell.fill = head_fill
            cell.alignment = Alignment(horizontal="center", vertical="center", wrap_text=True)
            cell.border = border
        
        for row in ws.iter_rows(min_row=3):
            for cell in row:
                cell.border = border
            row[0].number_format = "DD.MM.YYYY"              # дата
            row[6].number_format = '#,##0 "₽"'               # цена
            row[7].number_format = '#,##0 "₽"'               # сумма
            row[5].alignment = Alignment(horizontal="center")
        
        widths = {"A": 12, "B": 9, "C": 14, "D": 12, "E": 16, "F": 8, "G": 12, "H": 14, "I": 11, "J": 15}
        for col, w in widths.items():
            ws.column_dimensions[col].width = w              # ширина столбцов
        
        ws.freeze_panes = "A3"                               # шапка остаётся на экране
        ws.auto_filter.ref = f"A2:{get_column_letter(ws.max_column)}{ws.max_row}"
        
        wb.save("orders_formatted.xlsx")
        print("Готово: orders_formatted.xlsx")
        • merge_cells("A1:J1") объединяет ячейки. Значение и оформление берутся из верхней левой.
        • Font, PatternFill, Alignment и Border задают шрифт, заливку, выравнивание и рамку. Цвета пишутся шестнадцатеричным кодом без решётки.
        • number_format управляет тем, как число выглядит в ячейке, при этом значение остаётся числом. Формат '#,##0 "₽"' показывает 31900 как «31 900 ₽», разделитель разрядов зависит от региональных настроек.
        • Автоподбора ширины в openpyxl нет. Ширину столбцов задаёте числом в column_dimensions.
        • freeze_panes = "A3" закрепляет две верхние строки. Всё выше указанной ячейки остаётся на экране при прокрутке.
        • auto_filter.ref включает фильтр на заданном диапазоне.

        На картинке видны и проблемы самих данных: дата текстом у заказа 8017, лишний пробел перед названием товара, пустые менеджеры и города. Оформление их не лечит. Чистить данные будем в следующем разделе.

        Раздел 7

        pandas: чистим выгрузку

        В нашей выгрузке четыре типичные проблемы: пропуски в менеджерах и городах, дубли заказов, лишние пробелы в названиях и даты, часть которых записана текстом. pandas закрывает их несколькими строками. Читаем файл, чистим, считаем итоги и пишем результат сразу на три листа.

        s04_pandas.py
        import pandas as pd
        
        # телефон читаем строкой, иначе потеряются ведущие цифры у длинных номеров
        df = pd.read_excel("orders.xlsx", sheet_name="Заказы", dtype={"Телефон": str})
        
        print(df.shape)                      # (123, 10)
        print(df.isna().sum()[["Менеджер", "Город"]])
        
        df["Товар"] = df["Товар"].str.strip()                           # убрали пробелы
        df["Дата"] = pd.to_datetime(df["Дата"], format="mixed", dayfirst=True)  # даты текстом тоже
        df = df.drop_duplicates()                                       # дубли строк целиком
        df["Менеджер"] = df["Менеджер"].fillna("Не назначен")           # пропуски заполняем
        df = df.dropna(subset=["Город"])                                # без города заказ не нужен
        
        paid = df[df["Статус"] == "Оплачен"]
        by_manager = (paid.groupby("Менеджер", as_index=False)
                          .agg(Заказов=("Заказ", "count"), Сумма=("Сумма", "sum"))
                          .sort_values("Сумма", ascending=False))
        by_city = paid.pivot_table(index="Город", columns="Товар",
                                   values="Сумма", aggfunc="sum", fill_value=0)
        
        with pd.ExcelWriter("orders_clean.xlsx") as writer:             # несколько листов за раз
            df.to_excel(writer, sheet_name="Чистые данные", index=False)
            by_manager.to_excel(writer, sheet_name="По менеджерам", index=False)
            by_city.to_excel(writer, sheet_name="Город и товар")
        
        print(by_manager)
        print("Строк после очистки:", len(df))
        Вывод
        (123, 10)
        Менеджер    25
        Город       25
        dtype: int64
              Менеджер  Заказов   Сумма
        0      Иванова       10  452570
        1     Кузнецов       12  248270
        3       Петров        8  229150
        2  Не назначен       10  204740
        4     Смирнова        7  151460
        Строк после очистки: 97
        1. dtype={"Телефон": str} читает столбец строкой, чтобы номера не превратились в числа.
        2. str.strip() убирает пробелы по краям, и « Пылесос » становится «Пылесос».
        3. to_datetime(..., format="mixed", dayfirst=True) приводит к одному типу и настоящие даты, и текст вида 03.09.2026.
        4. drop_duplicates() убирает строки, полностью повторяющие другие. Здесь уходят три дубля.
        5. fillna заполняет пропуски значением, а dropna(subset=...) выбрасывает строки, где пусто в нужном столбце.
        6. groupby с именованными агрегатами считает заказы и сумму по менеджерам, pivot_table строит сводную по городам и товарам.
        7. ExcelWriter с несколькими вызовами to_excel складывает всё в одну книгу на разные листы.

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

        Ловушка

        Номера с хвостом .0

        Если в столбце с телефонами или ИНН есть пустые ячейки, pandas читает его как дробные числа. В моём тесте 79157135241 превратилось в 79157135241.0.

        Читайте такие столбцы строкой: dtype=str.

        Ловушка

        inplace на столбце молчит

        В pandas 3 запись df["a"].fillna(0, inplace=True) ничего не меняет и выдаёт предупреждение. Пропуски остаются на месте.

        Пишите df["a"] = df["a"].fillna(0).

        Ловушка

        Даты вперемешку

        В тестовой выгрузке 116 дат хранятся как даты и 7 как текст. Без приведения к одному типу сортировка и группировка по дате дадут странный результат.

        Решает to_datetime с форматом mixed.

        Раздел 8

        Отчёт с диаграммами в XlsxWriter

        Для отчёта с нуля я беру XlsxWriter. Он быстрый, умеет основные типы диаграмм Excel и оформляет файл прямо при создании. Построим таблицу по рекламным кампаниям, комбинированную диаграмму «расход и заявки» и круговую с долями расхода. Числа в таблице учебные.

        s05_chart.py
        import xlsxwriter
        
        rows = [
            ("Тула, поиск",      18400, 920, 36800, 31),
            ("Рязань, поиск",    12100, 610, 22400, 17),
            ("Москва, поиск",    30500, 1180, 71200, 44),
            ("РСЯ, ремаркетинг", 54000, 760, 15900, 12),
            ("Карты",             9800, 330, 11300, 14),
        ]
        
        wb = xlsxwriter.Workbook("ads_report.xlsx")
        ws = wb.add_worksheet("Реклама")
        
        head = wb.add_format({"bold": True, "bg_color": "#1F3864", "font_color": "white",
                              "align": "center", "valign": "vcenter", "border": 1})
        money = wb.add_format({"num_format": '#,##0 "₽"', "border": 1})
        num = wb.add_format({"num_format": "#,##0", "border": 1})
        pct = wb.add_format({"num_format": "0.0%", "border": 1})
        txt = wb.add_format({"border": 1})
        
        ws.write_row(0, 0, ["Кампания", "Показы", "Клики", "Расход", "Заявки", "CTR", "Цена заявки"], head)
        for r, (name, shows, clicks, cost, leads) in enumerate(rows, start=1):
            ws.write(r, 0, name, txt)
            ws.write(r, 1, shows, num)
            ws.write(r, 2, clicks, num)
            ws.write(r, 3, cost, money)
            ws.write(r, 4, leads, num)
            # формулы пишем вместе с результатом: просмотрщики без пересчёта покажут число вместо нуля
            ws.write_formula(r, 5, f"=C{r+1}/B{r+1}", pct, clicks / shows)
            ws.write_formula(r, 6, f"=D{r+1}/E{r+1}", money, cost / leads)
        ws.set_column("A:A", 20)
        ws.set_column("B:G", 13)
        ws.freeze_panes(1, 0)
        ws.set_landscape()                                     # печать на одну страницу
        ws.fit_to_pages(1, 1)
        
        last = len(rows)
        col = wb.add_chart({"type": "column"})                 # столбцы: расход
        col.add_series({"name": "Расход, ₽", "categories": ["Реклама", 1, 0, last, 0],
                        "values": ["Реклама", 1, 3, last, 3], "fill": {"color": "#F98318"}})
        line = wb.add_chart({"type": "line"})                  # линия: заявки
        line.add_series({"name": "Заявки", "categories": ["Реклама", 1, 0, last, 0],
                         "values": ["Реклама", 1, 4, last, 4], "y2_axis": True,
                         "marker": {"type": "circle", "size": 7}, "line": {"color": "#1F3864", "width": 2.5}})
        col.combine(line)
        col.set_title({"name": "Расход и заявки по кампаниям"})
        col.set_y_axis({"name": "Расход, ₽"})
        line.set_y2_axis({"name": "Заявки"})
        col.set_size({"width": 620, "height": 320})
        ws.insert_chart("A9", col)
        
        pie = wb.add_chart({"type": "pie"})                    # круг: доли расхода
        pie.add_series({"categories": ["Реклама", 1, 0, last, 0], "values": ["Реклама", 1, 3, last, 3],
                        "data_labels": {"percentage": True}})
        pie.set_title({"name": "Доли расхода"})
        pie.set_size({"width": 420, "height": 320})
        ws.insert_chart("H9", pie)
        
        wb.close()
        print("Готово: ads_report.xlsx")
        • Данные диаграммы задаются адресом [лист, строка_начала, столбец_начала, строка_конца, столбец_конца]. Нумерация идёт с нуля.
        • combine() накладывает линию на столбцы, а y2_axis выводит вторую шкалу для заявок.
        • set_landscape() и fit_to_pages(1, 1) настраивают печать: отчёт ложится на одну страницу.
        • На учебных числах сразу видно разницу: CTR у ремаркетинга в РСЯ 1,4% против 5,0% у поиска по Туле и Рязани.
        Формулы и нули в просмотрщиках

        XlsxWriter сам формулы не считает. Он записывает в файл ноль и просит Excel пересчитать всё при открытии. Excel так и делает. Но PDF-конвертеры, часть мобильных приложений и программы просмотра без пересчёта покажут нули. Я столкнулся с этим при подготовке картинки для статьи: без четвёртого параметра write_formula столбцы CTR и цены заявки выглядели как 0.

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

        Для очень больших файлов у XlsxWriter есть режим constant_memory. Он записывает данные построчно и держит в памяти одну строку, но тогда строки нужно писать строго по порядку. Сколько это даёт на практике, смотрите в замерах в разделе 11.

        Раздел 9

        Условное форматирование: план и факт

        Условное форматирование красит ячейки по правилам, и правила остаются в файле. Поменяете число в Excel, цвет пересчитается сам. Возьмём лист «По менеджерам» из раздела 7, добавим план и выполнение и раскрасим таблицу по уровню выполнения плана.

        s06_condfmt.py
        from openpyxl import load_workbook
        from openpyxl.formatting.rule import CellIsRule, DataBarRule, FormulaRule
        from openpyxl.styles import Font, PatternFill
        
        wb = load_workbook("orders_clean.xlsx")
        ws = wb["По менеджерам"]                              # лист из прошлого шага
        
        plans = {"Иванова": 400000, "Кузнецов": 300000, "Петров": 250000,
                 "Смирнова": 180000, "Не назначен": 100000}
        ws["D1"], ws["E1"] = "План", "Выполнение"
        for r in range(2, ws.max_row + 1):
            ws[f"D{r}"] = plans[ws[f"A{r}"].value]
            ws[f"E{r}"] = f"=C{r}/D{r}"
            ws[f"E{r}"].number_format = "0%"
            ws[f"C{r}"].number_format = ws[f"D{r}"].number_format = '#,##0 "₽"'
        for c in ws[1]:
            c.font = Font(bold=True)
        
        rng = f"E2:E{ws.max_row}"
        green = PatternFill(start_color="C6EFCE", end_color="C6EFCE", fill_type="solid")
        yellow = PatternFill(start_color="FFEB9C", end_color="FFEB9C", fill_type="solid")
        red = PatternFill(start_color="FFC7CE", end_color="FFC7CE", fill_type="solid")
        ws.conditional_formatting.add(rng, CellIsRule(operator="greaterThanOrEqual", formula=["1"], fill=green))
        ws.conditional_formatting.add(rng, CellIsRule(operator="between", formula=["0.8", "0.9999"], fill=yellow))
        ws.conditional_formatting.add(rng, CellIsRule(operator="lessThan", formula=["0.8"], fill=red))
        ws.conditional_formatting.add(f"C2:C{ws.max_row}", DataBarRule(start_type="num", start_value=0,
                                      end_type="max", color="F98318"))
        ws.conditional_formatting.add(f"A2:A{ws.max_row}", FormulaRule(formula=['$A2="Не назначен"'],
                                      font=Font(italic=True, color="9C0006")))
        
        for col, w in {"A": 16, "B": 10, "C": 16, "D": 14, "E": 13}.items():
            ws.column_dimensions[col].width = w
        wb.save("plan_fact.xlsx")
        print("Готово: plan_fact.xlsx")
        • CellIsRule сравнивает значение ячейки с порогом. Для жёлтой зоны я взял between с границами 0,8 и 0,9999, чтобы ровно 100% попало в зелёное правило.
        • DataBarRule рисует полосу внутри ячейки пропорционально сумме.
        • FormulaRule с формулой $A2="Не назначен" красит по условию на другую ячейку. Знак доллара фиксирует столбец, а номер строки сдвигается для каждой строки диапазона.
        • Заливка задаётся парой start_color и end_color. Для сплошного цвета они одинаковые.

        Пороги в примере такие: от 100% зелёный, от 80 до 99% жёлтый, ниже 80% красный. Свои числа поставьте исходя из плана вашего отдела. Подробный список правил есть в документации openpyxl, ссылка в источниках.

        Раздел 10

        Свод из папки с выгрузками

        Типичная задача: три филиала присылают выгрузки отдельными файлами, и раз в неделю их надо свести в один. Складываем файлы в папку exports. Скрипт читает все xlsx, добавляет столбец с именем файла, убирает повторы заказов и пишет свод.

        s07_folder.py
        from pathlib import Path
        import pandas as pd
        
        folder = Path("exports")                              # сюда складывают выгрузки
        frames = []
        for path in sorted(folder.glob("*.xlsx")):
            part = pd.read_excel(path, dtype={"Телефон": str})
            part["Источник"] = path.stem                      # из какого файла строка
            frames.append(part)
        
        if not frames:
            raise SystemExit("В папке exports нет файлов .xlsx")
        
        svod = pd.concat(frames, ignore_index=True)
        svod = svod.drop_duplicates(subset=["Заказ"])         # заказ не должен считаться дважды
        
        with pd.ExcelWriter("svod.xlsx", engine="xlsxwriter") as writer:   # движок указываем явно
            svod.to_excel(writer, sheet_name="Свод", index=False)
            ws = writer.sheets["Свод"]
            ws.freeze_panes(1, 0)                             # это уже API XlsxWriter
            ws.autofilter(0, 0, len(svod), len(svod.columns) - 1)
            ws.set_column("A:J", 14)
        
        print(f"Файлов: {len(frames)}, строк в своде: {len(svod)}")
        Вывод
        Файлов: 3, строк в своде: 120
        • Path.glob("*.xlsx") находит все файлы нужного типа, а sorted делает порядок стабильным.
        • Столбец «Источник» нужен, чтобы при ошибке в своде найти файл, из которого пришла строка.
        • drop_duplicates(subset=["Заказ"]) убирает повторы по ключу. В моих трёх тестовых файлах заказы пересекаются: из 133 прочитанных строк в своде остаётся 120.
        • Движок записи указан явно. По документации pandas для xlsx по умолчанию использует XlsxWriter и переключается на openpyxl, если XlsxWriter не установлен. Явный выбор избавляет от сюрпризов на чужом компьютере.
        • Раз движок XlsxWriter, закрепление и фильтр делаются его методами freeze_panes и autofilter, а ширина столбцов задаётся через set_column.
        Проверка свода за тридцать секунд

        Печатайте в консоль, сколько строк прочитано и сколько записано. Если разница не совпадает с числом дублей, которое вы ожидаете, смотрите столбец «Источник» и ищите файл с лишним форматом.

        Раздел 11

        Скорость и память: замеры на 100 000 строк

        На маленьких файлах разницы между библиотеками не заметно. На десятках тысяч строк она превращается в минуты. Я измерил запись и чтение файла в 100 000 строк и 8 столбцов: даты, числа, текст. Каждый вариант запускался в отдельном процессе пять раз, в таблице медиана.

        Запись 100 000 строк: время и пиковая память
        XlsxWriter, обычный режим4,2 с147 МБ
        XlsxWriter, constant_memory4,7 с53 МБ
        openpyxl, write_only7,1 с77 МБ
        openpyxl, обычный режим8,1 с344 МБ
        pandas to_excel, движок XlsxWriter8,4 с222 МБ
        pandas to_excel, движок openpyxl12,0 с434 МБ
        Чтение 100 000 строк: время и пиковая память
        pandas read_excel, движок calamine1,38 с236 МБ
        openpyxl, read_only5,0 с85 МБ
        pandas read_excel, движок openpyxl6,5 с159 МБ
        openpyxl, обычный режим9,4 с397 МБ
        Как мерили

        Стенд: 2 ядра Intel Xeon 2,1 ГГц, 8 ГБ памяти, Python 3.11, openpyxl 3.1.5, pandas 3.0.2, XlsxWriter 3.2.9, python-calamine 0.8.2. Память указана как пиковый размер процесса вместе с исходными данными в списке, а это около 42 МБ. Читали файл, который записал XlsxWriter. На вашем компьютере секунды будут другими, сравнивайте соотношения.

        Показать скрипт замеров bench.py
        bench/one.py
        import random
        import resource
        import sys
        import time
        from datetime import date, datetime, time as dtime, timedelta
        
        N = 100_000
        variant = sys.argv[1]
        random.seed(1)
        base = date(2026, 1, 1)
        rows = [(base + timedelta(days=i % 300), 1000 + i, f"Клиент {i % 500}",
                 random.choice(["Тула", "Рязань", "Москва"]), random.randint(1, 9),
                 round(random.random() * 1000, 2), random.randint(100, 99999), "Оплачен")
                for i in range(N)]
        head = ["Дата", "Заказ", "Клиент", "Город", "Кол-во", "Скидка", "Сумма", "Статус"]
        
        def write_xlsxwriter(path, **opts):
            import xlsxwriter
            wb = xlsxwriter.Workbook(path, opts)
            ws = wb.add_worksheet()
            date_fmt = wb.add_format({"num_format": "dd.mm.yyyy"})
            ws.write_row(0, 0, head)
            for i, r in enumerate(rows, 1):
                ws.write_datetime(i, 0, datetime.combine(r[0], dtime()), date_fmt)
                ws.write_row(i, 1, r[1:])
            wb.close()
        
        t0 = time.perf_counter()
        if variant == "baseline":
            pass
        elif variant == "w_openpyxl":
            from openpyxl import Workbook
            wb = Workbook(); ws = wb.active; ws.append(head)
            for r in rows: ws.append(r)
            wb.save("bench/o1.xlsx")
        elif variant == "w_openpyxl_wo":
            from openpyxl import Workbook
            wb = Workbook(write_only=True); ws = wb.create_sheet(); ws.append(head)
            for r in rows: ws.append(r)
            wb.save("bench/o2.xlsx")
        elif variant == "w_xlsxwriter":
            write_xlsxwriter("bench/o3.xlsx")
        elif variant == "w_xlsxwriter_cm":
            write_xlsxwriter("bench/o4.xlsx", constant_memory=True)
        elif variant in ("w_pandas_openpyxl", "w_pandas_xlsxwriter"):
            import pandas as pd
            df = pd.DataFrame(rows, columns=head)
            df["Дата"] = pd.to_datetime(df["Дата"])
            engine = variant.split("_")[-1]
            df.to_excel(f"bench/o5_{engine}.xlsx", index=False, engine=engine)
        elif variant == "r_openpyxl":
            from openpyxl import load_workbook
            ws = load_workbook("bench/o3.xlsx").active
            total = sum(r[6] for r in ws.iter_rows(min_row=2, values_only=True))
        elif variant == "r_openpyxl_ro":
            from openpyxl import load_workbook
            wb = load_workbook("bench/o3.xlsx", read_only=True)
            total = sum(r[6] for r in wb.active.iter_rows(min_row=2, values_only=True))
            wb.close()
        elif variant == "r_pandas":
            import pandas as pd
            total = pd.read_excel("bench/o3.xlsx")["Сумма"].sum()
        elif variant == "r_pandas_calamine":
            import pandas as pd
            total = pd.read_excel("bench/o3.xlsx", engine="calamine")["Сумма"].sum()
        elapsed = time.perf_counter() - t0
        peak_mb = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1024
        print(f"{variant};{elapsed:.2f};{peak_mb:.0f}")

        Что из замеров следует

        • Запись нового отчёта: XlsxWriter быстрее всех. Через pandas с движком openpyxl тот же файл пишется почти втрое дольше.
        • Память при записи: режимы write_only у openpyxl и constant_memory у XlsxWriter держат пик в разы ниже обычного. Платите за это ограничениями: строки только по порядку, правки ячеек задним числом невозможны.
        • Чтение: режим read_only у openpyxl почти вдвое быстрее обычного и держит память в разы ниже. Взамен недоступны диаграммы, картинки и часть других возможностей, это прямо сказано в документации.
        • Самое быстрое чтение: pandas с движком calamine. Он подключается одним словом engine="calamine" после установки пакета python-calamine. Память при этом выше, чем у read_only.
        • Лимит самого Excel: 1 048 576 строк и 16 384 столбца на листе, до 32 767 символов в ячейке. Если данных больше, храните их в базе, а в Excel отдавайте итоговую сводку.
        Раздел 12

        Десять частых ошибок

        Большинство этих ошибок я воспроизвёл на тестовых файлах, остальные описаны в документации библиотек. В последнем столбце указан раздел, где ошибка разобрана подробнее.

        №ОшибкаКак проявляетсяЧто делатьГде
        1Лист не найденВ openpyxl приходит KeyError, в pandas ValueError. Частая причина: лишний пробел в названии листаВывести wb.sheetnames и взять имя оттуда4
        2Сохранили поверх исходникаИсходные данные потеряны, предупреждения нетИсходники в отдельной папке, отчёт с датой в имени5
        3Формулы без значенийВ openpyxl с data_only=True приходит None, в pandas приходит NaNОткрыть и сохранить файл в Excel или считать итоги в Python4
        4Нули вместо результатовПросмотрщик показывает 0 на месте формул из XlsxWriterПередавать результат формулы параметром value8
        5Номера с хвостом .0Телефон превращается в 79157135241.0, если в столбце есть пустые ячейкиЧитать столбец строкой: dtype=str7
        6Даты вперемешкуЧасть строк не сортируется и не группируется по датеto_datetime с format="mixed" и dayfirst=True7
        7inplace на столбцеВ pandas 3 пропуски остаются на месте, в консоли предупреждениеПрисваивание df["a"] = df["a"].fillna(0)7
        8Старый формат xlsopenpyxl выдаёт InvalidFileException с просьбой взять xlrdПересохранить в xlsx или читать через pandas с xlrd либо calamine2
        9Пропали фигуры после сохраненияopenpyxl читает не все элементы файла, фигуры в старой книге теряютсяПравить копию, не сохранять поверх, проверять результат глазами5
        10Объединённые ячейки читаются пустымиЗначение лежит только в верхней левой ячейке, остальные дают NoneЧитать верхнюю левую или снять объединение до обработки6
        Раздел 13

        Нейросеть как помощник и три промпта

        Нейросеть быстро пишет скрипты для Excel. Ошибается она с тем же спокойствием. Поэтому её код я считаю черновиком: проверяю на копии, сверяю итоги и только потом запускаю на настоящих данных.

        1

        Обезличьте пример

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

        2

        Опишите вход, выход и правила

        Какие столбцы на входе, какой файл нужен на выходе, что делать с пропусками и дублями.

        3

        Назовите версии

        Python, pandas, openpyxl. Модель охотно пишет под старые версии, и такой код падает на свежих.

        4

        Просите код порциями

        Сорок строк с комментариями читать проще, чем двести без них.

        5

        Проверьте на копии

        Запустите на десяти строках и сверьте итог с ручным расчётом.

        6

        Запускайте на полном файле

        Только после сверки, и желательно с записью в журнал, сколько строк прочитано и сколько записано.

        Промпт 1. Написать скрипт
        Ты опытный Python-разработчик. Напиши скрипт автоматизации Excel. Окружение: Python 3.11, pandas 3.0, openpyxl 3.1. Вход: файл orders.xlsx, лист «Заказы». Столбцы: Дата, Заказ, Менеджер, Город, Товар, Кол-во, Цена, Сумма, Статус, Телефон. Пример данных, обезличенный, пять строк: [вставьте строки] Что сделать: 1. Убрать дубли по номеру заказа. 2. Пустого менеджера заменить на «Не назначен». 3. Посчитать сумму оплаченных заказов по менеджерам. 4. Сохранить результат в report.xlsx на двух листах: «Данные» и «Итоги». Правила: исходный файл не менять. Телефон читать строкой. Даты могут быть текстом вида дд.мм.гггг. Формат ответа: один файл с кодом, комментарии на русском. В конце список допущений и что проверить вручную.
        Промпт 2. Найти ошибку
        Мой скрипт для Excel падает с ошибкой. Окружение: Python 3.11, pandas 3.0, openpyxl 3.1. Код: [вставьте скрипт] Текст ошибки целиком: [вставьте traceback] Что должно было произойти: [одно предложение] Объясни причину простыми словами. Покажи только исправленный участок кода, весь скрипт не переписывай. Скажи, как проверить, что ошибка исчезла.
        Промпт 3. Ускорить скрипт
        Скрипт обрабатывает файл на [N] строк за [M] минут. Окружение: Python 3.11, pandas 3.0, openpyxl 3.1. Код: [вставьте скрипт] Найди узкие места. Рассмотри режимы read_only и write_only в openpyxl, constant_memory в XlsxWriter, движок calamine в pandas и замену циклов на операции pandas над целыми столбцами. Результат работы должен остаться прежним. Предложи, как это проверить: какие числа сравнить до и после.
        Что нейросети отправлять нельзя

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

        Раздел 14

        Безопасность и порядок

        Скрипт, который меняет файлы, должен быть аккуратнее человека. Человек заметит странный результат, скрипт отправит его дальше без раздумий. Шесть правил, которых я придерживаюсь.

        1

        Копии и версии

        Исходники лежат в отдельной папке, результат сохраняется под новым именем. Сами скрипты живут в Git, и любое изменение можно откатить.

        2

        Чужие файлы

        По документации openpyxl по умолчанию не защищает от атак через специально собранный XML. Для файлов от незнакомых отправителей установите пакет defusedxml.

        3

        Макросы

        Книги xlsm открывайте с keep_vba=True, если макросы нужно сохранить. Макросы из чужих файлов не запускайте.

        4

        Персональные данные

        Статья 18 закона 152-ФЗ требует хранить персональные данные граждан России в базах на территории России. Если скрипт складывает такие данные на сервер, берите российское облако. Детали для вашего случая уточните у юриста.

        5

        Секреты

        Пароли и ключи доступа к API не пишите в код. Берите их из переменных окружения и не коммитьте в Git.

        6

        Журнал

        Скрипт пишет, сколько строк прочитал, сколько записал и какие строки пропустил. По журналу видно, когда и почему отчёт разошёлся с ручным счётом.

        Раздел 15

        Окупится ли автоматизация и ТЗ на скрипт

        Скрипт стоит денег: часы разработки и немного поддержки. Экономит он часы сотрудников. Посчитайте оба числа на своих данных. В калькуляторе стоят учебные значения: ежедневный отчёт на полчаса, восемь часов на разработку и ставка разработчика 3 500 ₽, как на нашей странице про backend-разработку. Подставьте свои цифры.

        Минут на одну ручную обработкусколько занимает отчёт сейчас
        Сколько раз в месяц20 рабочих дней, если отчёт ежедневный
        Стоимость часа сотрудника, ₽с налогами, ваша оценка
        Часов на разработку скриптавключая проверку на копии
        Ставка разработчика, ₽ в часу нас от 3 500 ₽
        Часов поддержки в месяцправки и разбор сбоев
        Окупаемость 0 месяцев

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

        Шаблон ТЗ на скрипт

        Разработчику для старта нужны десять ответов. Нейросети они нужны не меньше. Скопируйте шаблон и заполните.

        Шаблон ТЗ на скрипт для Excel
        Название задачи: [например, еженедельный свод выгрузок заказов] Кто и как часто запускает: [менеджер, по понедельникам] Вход: [где лежат файлы, формат, пример строки] Выход: [какой файл, листы, столбцы, оформление, кому отправляется] Правила обработки: [дубли по какому ключу, что делать с пропусками, формат дат и номеров] Что считать ошибкой: [пустой файл, другой набор столбцов, неизвестный статус] Как проверить результат: [сверка итогов с ручным расчётом на 20 строках] Где живёт скрипт: [компьютер, сервер, расписание запуска] Персональные данные в файле: [есть или нет, какие именно] Срок и бюджет: [желаемая дата, рамки по стоимости]
        Раздел 16

        Чек-лист перед запуском

        Отметьте то, что у вас уже сделано. Внизу появится вердикт.

        Скрипт готов к настоящим данным?

        Отмечено: 0 из 12

        • Исходные файлы лежат в отдельной папке, скрипт их не перезаписывает
        • Есть резервная копия или Git
        • Скрипт запускался на копии из 10 или 20 строк
        • Итоги сверены с ручным расчётом
        • Телефоны, ИНН и артикулы читаются строкой
        • Даты приведены к одному формату
        • Дубли удаляются по ключу, например по номеру заказа
        • Правило для пустых значений записано в коде
        • Версии библиотек записаны в requirements.txt
        • Скрипт пишет в журнал, сколько строк прочитано и записано
        • Готовый файл открыт в Excel и просмотрен глазами
        • Понятно, кто запускает скрипт и что делать при ошибке
        Отмечайте пункты, и здесь появится вердикт.
        Раздел 17

        Что мы делаем в Hated.Ru

        Когда задача вырастает из одного скрипта в систему, подключаемся мы. Ниже то, что связано с темой статьи. Цены стартовые, со страниц услуг на 7 октября 2026 года. Точную смету считаем после разбора задачи.

        ЗадачаЧто делаемЦена
        Автоматизация и интеграцииСерверная часть на Python: обработка файлов, связь с 1С, CRM и другими сервисамиот 60 000 ₽, срок от 2 недель
        Небольшие задачи по часамДоработка вашего скрипта, разовая обработка файлов. Оценку объёма даём письменно до началаот 3 500 ₽/час
        Telegram-ботБот, который принимает файл или присылает отчёт в чат, интеграция с CRMот 30 000 ₽
        Сервер в российском облакеВиртуальная машина в Yandex Cloud или VK Cloud, где скрипт запускается по расписаниюбазовая настройка от 30 000 ₽
        Безопасность и 152-ФЗПрава доступа, шифрование дисков и бэкапов, размещение данных внутри страныот 40 000 ₽

        Про меня и мой стек есть отдельная страница. Если нужен совет до начала проекта, напишите на почту, ответим по существу.

        Частые вопросы

        Вопросы и ответы про автоматизацию Excel на Python

        Можно. openpyxl, XlsxWriter и pandas читают и пишут файлы формата xlsx напрямую, Excel для этого не нужен. Он понадобится только для pywin32, которая управляет запущенным Excel через COM на Windows.

        VBA живёт внутри книги и запускается кнопкой, поэтому удобен сотрудникам, которым нужна готовая кнопка. Python работает снаружи: ходит за данными в API, обрабатывает папки с файлами, отправляет результат и запускается по расписанию. Часто используют оба инструмента.

        pandas подходит для очистки и расчётов, openpyxl для правки и оформления готовых файлов, XlsxWriter для новых отчётов с диаграммами. В одном скрипте их спокойно сочетают: чистят в pandas, пишут через XlsxWriter, дорабатывают в openpyxl.

        Файл, который создала или сохранила библиотека, хранит формулы без результатов, пока его не пересчитает Excel. Параметр data_only=True возвращает значение, которое Excel сохранил при последнем открытии. Если его нет, придёт None. Откройте файл в Excel и сохраните, либо считайте итоги в Python.

        Самый быстрый вариант в моих замерах: pandas с движком calamine. На 100 000 строк он справился примерно за 1,4 секунды против 6,5 у обычного read_excel. Если нужен openpyxl, включите режим read_only, он быстрее и расходует в разы меньше памяти, но диаграммы и картинки в нём недоступны.

        Согласно документации Microsoft, 1 048 576 строк и 16 384 столбца на листе, в одной ячейке до 32 767 символов. Для больших массивов используйте базу данных, а в Excel выгружайте итоговую сводку.

        Нет. По документации XlsxWriter только создаёт новые файлы. Для правки готовой книги берите openpyxl.

        Открывайте книгу с параметром keep_vba=True и сохраняйте с расширением xlsm. Макросы сохранятся, но редактировать их из Python нельзя.

        Файлы с персональными данными клиентов, договорами и закупочными ценами отправлять нельзя. Для запроса хватает пяти обезличенных строк. Требования 152-ФЗ к хранению персональных данных граждан России в базах на территории России уточняйте у юриста.

        В Hated.Ru автоматизация и интеграции на Python стоят от 60 000 ₽, срок от двух недель. Небольшие задачи берём по часам от 3 500 ₽ в час, оценку объёма даём письменно до начала. Точную стоимость называем после разбора файла и правил обработки.

        Нужны основы Python: переменные, циклы, функции. Базовые примеры из статьи читаются без опыта, а остальное приходит с практикой. Если времени на это нет, задачу можно поручить разработчику и приложить ТЗ по шаблону из раздела 15.

        Источники

        Где проверить цифры и правила

        Данные проверены 7 октября 2026 года. Версии библиотек и правила меняются, перед внедрением сверяйте их с первоисточником.

        • Документация openpyxl 3.1: руководство, сохранение, data_only, keep_vba
        • Документация openpyxl: режимы read_only и write_only
        • Документация openpyxl: условное форматирование
        • Документация openpyxl: введение и раздел о безопасности
        • Документация XlsxWriter: введение и ограничения
        • Документация XlsxWriter: формулы и их результаты
        • Документация XlsxWriter: память и режим constant_memory
        • Документация pandas: read_excel и доступные движки
        • Документация pandas: выбор движка записи Excel
        • Документация pandas: Copy-on-Write и цепочечное присваивание
        • PyPI: python-calamine
        • PyPI: defusedxml
        • PyPI: pywin32
        • Microsoft: спецификации и лимиты листов и книг Excel
        • Microsoft: безопасность данных и Python в Excel
        • Гарант: локализация персональных данных, статья 18 закона 152-ФЗ
        • Hated.Ru: страница Дени Булатова
        Дени Булатов, разработчик Hated.Ru

        Дени Булатов

        Разработчик Hated.Ru. Учится в РТУ МИРЭА по направлению «Прикладная информатика». Делает фронтенд на React и Next.js, бэкенд на Python, работает с PostgreSQL, Docker и Linux-серверами.

        Страница Дени · Deni@hated.ru · +7 985 220-54-74

        Hated.Ru · Разработка
        Собираете таблицу руками? Оценим, что можно отдать скрипту

        Пришлите пример файла без персональных данных и опишите, что на входе и что нужно получить на выходе. Скажем, стоит ли автоматизировать задачу, назовём срок и стоимость до начала работ. Работаем по всей России, офисы в Москве, Туле и Рязани.

        Написать Дени +7 985 220-54-74
        Дополнительно

        Освоение 1С-Битрикс: Разбираемся в сложнох подготовки платформы к работе

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

        Первый и, пожалуй, самый важный этап – выбор и заказ хостинга. Для стабильной работы 1С-Битрикс требуется внимательно подойти к требованиям системы к серверу. Помимо стандартных параметров, таких как PHP и MySQL, стоит учитывать поддержку технологий, таких как memcached и поддержка отправки почты через SMTP.

        • Комментарии
        Загрузка комментариев...
        как автоматизировать excel python библиотека openpyxl pandas read_excel xlwings python excel автозаполнение excel python генерация отчетов python
        Назад к списку
        • Блог о 1С Битрикс 3
        • Полезное 6
        • Статьи о SEO продвижении сайтов 17
        • Статьи о контекстной рекламе - Блог Hated.ru 7
        • Статьи о разработки сайтов 13
        1с битрикс 1С‑Битрикс ai agent n8n claude code в vs code claude code для начинающих CMS 2026 css design engineer digital marketing services digital стратегия 2026 digital стратегия для оффлайн бизнеса Drupal E-E-A-T для сайта E-E-A-T что это EEAT EEAT SEO generative engine optimization GEO geo seo 2026 GEO продвижение geo продвижение GEO-оптимизация Яндекс gigachat api бесплатно Hated.ru hated.ru headless CMS html JavaScript Joomla js metrika n8n google calendar n8n openrouter n8n telegram бот n8n бесплатно n8n ии агент OpenCart pandas read_excel sape покупка ссылок Schema.org SEO SEO 2026 seo vs geo SEO аудит seo без накрутки пф SEO для AI 2026 SEO продвижение seo продвижение SEO продвижение Битрикс цена SEO продвижение интернет-магазина seo продвижение сайта seo услуги SEO услуги Битрикс seo-оптимизация Tilda ugc видео цена ugc креатор цена ugc под ключ ui аудит сайта ux ui аудит ux аудит сайта перед редизайном vk клипы для бизнеса WordPress xlwings python excel Yandex автозаполнение excel python автоматизация автоматизация поддержки нейросетью автоматический деплой сайта автостратегии яндекс директ Алиса AI аудит перед контекстной рекламой аудит сайта перед запуском рекламы аудит сайта перед редизайном безопасная покупка ссылок белое seo продвижение бесплатные ии агенты бесплатные ии платформы бесплатный ии агент для бизнеса библиотека openpyxl Бизнес бот с проверкой подписки бренд и seo брендовые запросы брендовый трафик бриф для ugc креатора веб-дизайн Веб-разработка видимость в ответах нейросетей визуал для ozon влияние искусственного интеллекта на бизнес внедрение ии в бизнес внедрение нейросети вордстат яндекс статистика воронка подписки max выбор CMS выкладка сайта без простоя где публиковать короткие видео генерация отчетов python генерация фото товара гео продвижение сайта геолокация деплой сайта деплой через symlink дизайн карточек wildberries дизайн-инженер дизайнер и нейросети дизайнер с ии доверие сайта Google доноры sape дорожная карта digital стратегии е е а т заказать SEO продвижение Битрикс заказать ugc видео запросы яндекс вордстат ии в бизнес-процессах ИИ-помощник Яндекс Карт ИКС инструкция claude code интеграция нейросети в crm интернет-маркетинг инфографика для маркетплейсов нейросеть информационная безопасность искусственный интеллект искусственный интеллект в маркетинге искусственный интеллект в рекламе ИТ-инфраструктура как автоматизировать excel python как внедрить E-E-A-T как задеплоить сайт как запустить рекламу как не попасть под минусинск как нейросеть выбирает компании как покупать ссылки в sape как пользоваться вордстатом как сделать сайт с claude code как улучшить дизайн сайта карточки товара нейросетью клипы без лица Лайфхаки Начинающим Обработка данных Персональные данные Продвижение сайта РКН Яндекс ИСК Яндекс нейро продвижение Яндекс Тег-менеджер Яндекс.Браузер бизнес ЯндексGPT оптимизация
        Проекты
        Разработка сайтов на Drupal
        Брендинг и айдентика
        Портфолио: сайты на 1С‑Битрикс
        Портфолио: сайты на CMS Tilda
        Разработка сайта на "Чистом коде"
        Фото компании
        Битрикс 24
        Готовые шаблоны для cms 1c Bitrix
        Услуги
        Разработка сайтов на CMS "1с Битрикс"
        Контекстная реклама
        SEO продвижение сайтов
        Дизайн "Брендинг"
        Разработка сайтов на CMS "Wordpress"
        Разработка сайтов на конструкторе "Tilda"
        Создание быстрого сайта без CMS
        DevOps
        SMM
        UI/UX разработка \ дизайн
        Разработка под Telegram
        Таргетированная реклама
        Статьи
        Новости
        О компании
        Сертификаты
        Реквизиты
        +7 985 220-54-74
        +7 985 220-54-74 mts.svg
        +7 495 220-54-74 mts.svg
        E-mail
        info@hated.ru
        Адрес
        г. Тула, Московское шоссе , д.2в, офис № 3
        Рязань, 2-й Школьный переулок, 1
        Москва, МКАД 60й километр 4а
        Режим работы
        Ежедневно: с 9:00 до 20:00
        info@hated.ru
        г. Тула, Московское шоссе , д.2в, офис № 3
        Рязань, 2-й Школьный переулок, 1
        Москва, МКАД 60й километр 4а
        © 2026 Разработка сайтов, контекстаная реклама,веб-дизайн hated
        ООО "ХАТЕД"
        ИНН/КПП 7100009120 / 710001001
        ОГРН: 1217100008960

        Политика конфиденциальности
        Версия для слабовидящих
        Карта сайта
        Главная Услуги Контакты Проекты Акции
        Регион сайта: Россия