Из Excel в pandas: сохраняем коды, даты и деньги для рабочего отчёта

После импорта Excel артикул 00123 стал числом 123, дата прочиталась неоднозначно, а сумма с пробелом не складывается. Для рабочего отчёта важно сохранить смысл полей ещё до расчёта метрик. Соберём небольшой .xlsx в памяти, прочитаем его через pandas и подготовим принятую часть и карантин ошибок.

Договор о типах важнее автоматического угадывания

Код товара или клиента — идентификатор, даже когда он состоит только из цифр. Арифметика к нему не применяется, а ведущие нули могут быть значимы. Поэтому читаем код как строку. Но если исходная ячейка уже хранит число 123 и только отображает его форматом 00000, dtype="string" не восстановит утраченную текстовую запись. Экспорт должен передавать код текстом либо отдельно задавать согласованную ширину.

Дату в примере источник передаёт строкой день.месяц.год. Указываем формат явно и используем errors="coerce": неверная дата попадёт в NaT. Так 03.04.2026 не зависит от предположения о порядке месяца и дня. Если источник смешивает настоящие Excel-даты и текст, обработку лучше разделить по типу входной ячейки, сохранив исходное значение.

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

Сначала проверяем форму, потом преобразуем

Вместо молчаливого округления третьего знака отклоняем строку 20,005. Иначе импорт сам выберет финансовое правило, которое никто не согласовал. Для принятой суммы используем Decimal и переводим рубли в целые копейки. В результате дальнейшее суммирование не зависит от двоичного представления дробей.

Для запуска нужны pandas и openpyxl. Пример создаёт настоящий Excel-файл в BytesIO, поэтому не требует ручной подготовки на диске. Вход содержит три заказа: корректный, с невозможной датой и лишним знаком в сумме, а также с отрицательной суммой. После чтения проверяем каждый признак отдельно и сохраняем строку в карантине, если нарушен хотя бы один.

from io import BytesIO
from decimal import Decimal
from openpyxl import Workbook
import pandas as pd
wb = Workbook()
ws = wb.active
ws.append(["code","date","amount"])
ws.append(["00123","03.04.2026","1 234,50"])
ws.append(["00456","31.02.2026","20,005"])
ws.append(["00789","04.04.2026","-5,00"])
buf = BytesIO()
wb.save(buf)
buf.seek(0)
d = pd.read_excel(buf,dtype="string",engine="openpyxl",keep_default_na=False)
d["parsed_date"] = pd.to_datetime(d.date,format="%d.%m.%Y",errors="coerce")
normalized = d.amount.str.replace(" ","",regex=False).str.replace("\u00a0","",regex=False)
amount_ok = normalized.str.fullmatch(r"\d+(?:,\d{1,2})?")
good = amount_ok & d.parsed_date.notna() & d.code.str.fullmatch(r"\d{5}")
accepted = d[good].copy()
accepted["amount_kopecks"] = normalized[good].map(lambda x:int(Decimal(x.replace(",","."))*100))
quarantine = d[~good]
print(accepted[["code","parsed_date","amount_kopecks"]].to_string(index=False))
print("quarantine",quarantine.code.tolist())
assert accepted.code.tolist() == ["00123"]
assert accepted.amount_kopecks.tolist() == [123450]
assert len(quarantine) == 2

Как использовать результат импорта

В принятой таблице остаётся код 00123, дата 3 апреля и 123450 копеек. Две другие строки сохраняются в карантине с исходными значениями. Для рабочего файла к ним стоит добавить отдельные причины: неверная дата, неподдерживаемая денежная запись, отсутствующий код. Тогда владелец экспорта сможет исправить конкретное поле.

Не исправляйте 20,005 до 20,01 автоматически, пока не выяснено происхождение третьего знака. Это может быть цена единицы с повышенной точностью, итог документа или ошибка локализации. Разные поля требуют разных правил округления, а потерянная половина копейки позже проявится в сверке итогов.

Что проверить на настоящей выгрузке

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

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

После нормализации полезно проверить совпадение итогов и ключей: Как сверить два SQL-отчёта: одинаковые суммы могут скрывать ошибки.

Когда автоматическое преобразование нужно остановить

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

Аналогично строка 1,234 может означать три десятичных знака или разделитель тысяч в другой локали. Наш договор отвергнет её, что полезнее случайной интерпретации. Для международных выгрузок храните локаль и валюту отдельными полями либо приводите формат на стороне источника. Сумму разных валют нельзя складывать только потому, что обе успешно преобразовались в числа. Проверка формы — первый слой подготовки, а смысл единицы измерения задаёт следующий.

Продолжить практику

В «Практической аналитике данных» подготовка таблиц связана с последующими выводами: вы проверяете пропуски, дубли и последствия объединений, затем считаете бизнес-метрики. Можно выбрать маршрут pandas или SQL. На учебном магазине вы проходите кейсы продаж, клиентов и рекламы и готовите аналитическую записку. Откройте программу курса.

Продолжить на практике

  • Практическая аналитика данных ↗

    Превратите знания SQL или Python в аналитическую работу: проверяйте данные, считайте бизнес-метрики, стройте дашборды и объясняйте выводы на трёх прикладных кейсах.