Импорт папки: один новый файл вместо нового листа

В общей папке лежат продажи за январь–август. Рядом — временный файл ~$Август.xlsx, черновик менеджера и сентябрьская выгрузка с переименованным листом.

Кнопка «Из папки» прочитает всё, что увидит. Поэтому надёжное объединение начинается не с раскрытия бинарного столбца, а с договора о папке: какие расширения допустимы, как называются рабочие файлы, есть ли подпапки и что считать датой отчёта.

Фильтр до чтения содержимого

Таблица Folder.Files содержит метаданные и бинарный столбец Content. Сначала отбрасываем скрытые, временные и неверно названные файлы — это дешевле, чем открывать каждую книгу.

let
    Files = Folder.Files(SalesFolder),
    XlsxOnly = Table.SelectRows(
        Files,
        each [Extension] = ".xlsx"
            and not Text.StartsWith([Name], "~$")
            and Text.StartsWith([Name], "sales_")
    ),
    AddPeriod = Table.AddColumn(
        XlsxOnly,
        "PeriodFromName",
        each Date.FromText(
            Text.BetweenDelimiters([Name], "sales_", ".xlsx") & "-01"
        ),
        type date
    ),
    Transform = Table.AddColumn(
        AddPeriod,
        "Rows",
        each fxReadSales([Content], [Name])
    ),
    Expanded = Table.ExpandTableColumn(
        Transform,
        "Rows",
        {"OrderID", "OrderDate", "SKU", "Amount"}
    )
in
    Expanded

Период извлекается из имени, а не из Date modified: дата изменения меняется при копировании и не описывает бизнес-период. Если имя не соответствует маске, преобразование должно дать диагностическую ошибку, а не случайную дату.

Образец — не особенный файл

Автоматический интерфейс создаёт запрос-образец и функцию преобразования. Частая ловушка — вручную исправить запрос конкретного файла, но не функцию. На экране всё выглядит верно для образца, а остальные книги обрабатываются по старым правилам. В рабочем решении функция принимает бинарное содержимое и имя файла; вся очистка живёт внутри неё.

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

Один плохой файл не должен исчезнуть

Можно обернуть вызов функции в try и получить запись с полями HasError, Value и Error. Но затем ошибочные файлы нужно вывести отдельной таблицей контроля. Если просто заменить ошибку пустой таблицей, месячный отчёт недосчитается без единого предупреждения.

ФайлСтрокСостояние
sales_2026-07.xlsx18 204OK
sales_2026-08.xlsx19 031OK
sales_2026-09.xlsx0нет листа Data

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

Защита от двойной загрузки

Один файл могут скопировать под другим именем. После объединения проверяем бизнес-ключ заказа и добавляем имя источника. Дубликаты не удаляем автоматически, пока не определено правило: одинаковый OrderID может быть ошибкой копирования, а может повторяться между филиалами и требовать составного ключа.

Краш-тест папки: добавьте временный файл Excel, книгу без листа Data и копию июля под другим именем. Корректный запрос пропустит временный файл, покажет сентябрь в контроле ошибок и обнаружит дубли июля.

Проверьте себя
1. Почему бизнес-период лучше извлекать из согласованного имени файла, а не Date modified?
AДата изменения может поменяться при копировании
BPower Query не видит даты файлов
CИмя всегда короче
DExcel запрещает сортировку по дате
2. Где должны находиться общие шаги очистки всех файлов?
AВручную в каждом месячном листе
BВ функции преобразования бинарного файла
CТолько в запросе выбранного образца
DВ названии папки
3. Почему опасно заменять любую ошибку файла пустой таблицей?
AОтчёт может молча потерять целый период
BФайл станет слишком большим
CИсчезнут имена запросов
DExcel отключит формулы