Операции с Excel документами
Создание, редактирование и анализ Excel-файлов через Python в песочнице: формулы, сводные таблицы, форматирование, диаграммы, объединение листов и выгрузка готовых отчётов в формате .xlsx.
Excel (v4.5)
Маршрутизация
XML-справочник: ooxml_cheatsheet.md
Таблица для человека
- Шапка: слова человека по-русски, с единицей: «Выручка, ₽», «Комиссия, %», «Продано, шт». Ни ключей ответа API (
offer_id,nmID,cogs_basis), ни snake_case. Отчёт о сохранении называет такие колонки: переименуй и сохрани заново. - Ячейки: нет UUID, href,
True/False(пиши «да»/«нет»), кодов вендора (SHIPMENT_TYPE_GENERAL) и служебных пометок на английском. Как считали: отдельный лист «Как считали» обычными словами. - Строка = сущность человека (товар, документ, операция): название рядом с артикулом. Пустая колонка, ради которой файл делали (название, себестоимость), это недоделанный расчёт: дозаполни или скажи, чего не хватает.
- Одинаковые сущности разных площадок: один лист с колонкой «Площадка» или листы с одним набором и порядком колонок.
- Журнал своей проверки (сверка позиций, доказательства) человеку не отдаётся как отчёт: в отчёт идут выводы, журнал остаётся в рабочих файлах.
- Исправленный файл сохрани под прежним именем и отдай полученный путь через
exit(filepaths=[path]): в том же чате запишется новая текущая версия файла.save_outputсохраняет черновик;artifact_idsвыбирает уже сохранённую версию и не перечитывает изменённый файл на диске. Новое имя («…_исправленная») оставляет прежний файл отдельным живым результатом. - Просьба прислать таблицу с изменением («только с себестоимостью», «за октябрь»): это пересчёт от источника, а не выборка из файла, отданного раньше: прежний файл мог быть исправлен или собран из старых данных.
.agg() и .rename(): имена результирующих колонок
Кварг-имя в .agg(name=('col','func')) обязано быть валидным Python-идентификатором: латиница/кириллица + цифры + _. Дефис ломает парсер: Кол-во= читается как Кол - во=, и интерпретатор валится с SyntaxError: expression cannot contain assignment, perhaps you meant "=="?.
Английский snake_case в .agg(), человекочитаемые имена через .rename():
Альтернатива: дикт-распак, принимает любые символы сразу:
ASCII-операторы в исходнике
Сравнения и форматирование внутри Python-кода пишутся только ASCII: >=, <=, !=. Юникод ≥ ≤ ≠ ловится парсером как SyntaxError, особенно в f-string'ах для красивого вывода. Юникод-символы идут в финальный markdown/текст для пользователя, не в исходник.
Чтение таблиц
Имена колонок бери точно из df.columns: [repr(c) for c in df.columns] показывает переносы строк (\n), табуляцию и пробелы внутри заголовка. Например, Добавления в\nкорзину всего и Добавления в корзину всего разные имена. Для расчёта можно явно переименовать проверенную колонку через rename(columns={исходное_имя: новое_имя}), убедившись, что новое имя не занято. Массовая замена пробелов и переносов может слить разные колонки; пропущенную обязательную колонку не создавай с нулями.
Для иерархического отчёта без единой шапки читай все строки с header=None. Числа преобразуй точечно:
1С: иерархические отчёты («История по заказ-нарядам» и аналоги)
Структура: клиент → VIN → заказ-наряд → строки работ/запчастей. Все четыре уровня живут в col[0], числовые суммы в правых колонках, индекс зависит от шаблона отчёта. Колонки Работ / Запчастей / Всего обычно в индексах 5 / 6 / 7, проверяй на образце.
Алгоритм: один проход, state-machine с тремя переменными cur_vin / cur_zn / cur_customer. Порядок проверок: skip-заголовки → VIN → ЗН → детальная строка → клиент. Клиент проверяется последним, иначе VIN или ЗН-строка попадает в клиенты.
Контрольная сумма: zn_df['works_sum'].sum() должна сходиться с суммой work_cost по it_df[it_df.kind=='work'] (±ровные комплексные строки: норма). Расходится в 2-3 раза: индексы WORK_COL / PARTS_COL / TOTAL_COL не те, проверь образец строки рядом с первым ЗН.
Умные таблицы (Excel Tables)
Заголовок таблицы: только явные строки; ref начинается со строки текстовых заголовков. Если header-ячейка содержит формулу или дату, Excel открывает файл только через «восстановление», и для пользователя это «файл повреждён». openpyxl при этом лишь warning'ует (column headings must be strings) и сохраняет битый XML.
Имена листов
Excel запрещает в именах листов символы: \ * ? : / [ ]
Ремонт структуры (битый файл)
xlsx не открывается / BadZipFile / XMLSyntaxError / Excel сообщает о повреждении: сначала структурный ремонт, потом обычные операции. Это другой класс, чем починка формул (fix_guide.md): тут разорваны сами XML-теги.
- Первый вызов без output: диагностика, файл не трогаем; второй: ремонт в output.
- Output ≠ input по имени (
fixed.xlsx). - Битые теги (zip цел) чинятся; битый zip-контейнер (обрыв/CRC) даёт exit 2, нерекаверабелен.
- После ремонта дальнейшие правки идут на
*_fixed.xlsxчерез unpack→edit→pack.
RU-форматы
| Формат | numFmt |
|---|---|
| 1 234 567 | #,##0 |
| 1 234,56 | #,##0.00 |
| 1 234 руб. | #,##0\ "руб." |
| 12,5% | 0.0% |
| 05.04.2026 | DD.MM.YYYY |
Разделитель разрядов в формате всегда ,: файл хранит место разряда, а пробел и десятичную запятую ставит русский Excel. #\ ##0 ставит буквальный пробел в одной позиции: 1234567 читается «1234 567».
1С-экспорт: encoding="utf-8-sig", sep=";", decimal=",".
Пути
| Что | Путь |
|---|---|
| Входные файлы | /tmp/ |
| Результат | $OUTPUT_ROOT/ |
Похожие навыки
Попробуйте этот навык
Зарегистрируйтесь и используйте навык «Операции с Excel документами» неделю на Pro без карты.