При обновлении конфигураций (например, 1С:Управление нашей фирмой) или при печати типовых форм пользователей может встретить неприятная проблема: порядок позиций в печатной форме документа не соответствует порядку строк в его табличной части. Попытки очистить кэш платформы или выполнить тестирование и исправление информационной базы дают лишь временный эффект — для новых документов порядок строк снова сбивается.
Рассмотрим подробно причины такого поведения СУБД и платформы 1С, а также разберем, как правильно скорректировать запрос для получения гарантированной сортировки.
Проанализируем ситуацию с точки зрения работы баз данных. В языке запросов 1С порядок строк без явно заданного условия сортировки считается произвольным. Системы управления базами данных (Microsoft SQL Server, PostgreSQL и др.) возвращают записи так, как им удобнее в конкретный момент — в порядке размещения на диске, по первичному индексу или с учетом текущего плана выполнения запроса.
После проведения процедуры «Тестирование и исправление» индексы таблицы перестраиваются, и СУБД какое-то время может выдавать данные последовательно. Однако по мере добавления новых документов и фрагментации индексов порядок выдачи записей снова начинает меняться.
Особое внимание стоит обратить на конструкцию запросов, выбирающих данные через синтаксис вложенных таблиц, например ЗаказПокупателя.Запасы.(...). Если в секции УПОРЯДОЧИТЬ ПО указать неуточненное имя поля НомерСтроки, транслятор запросов 1С не сможет корректно сопоставить его со строками вложенных таблиц шапки документа.
Посмотрим на пример запроса, в котором сортировка задана некорректно для вложенных табличных частей:
ВЫБРАТЬ
ЗаказПокупателя.Ссылка КАК Ссылка,
ЗаказПокупателя.Номер КАК Номер,
ЗаказПокупателя.Работы.(
НомерСтроки КАК НомерСтроки,
Номенклатура.Наименование КАК Запас
),
ЗаказПокупателя.Запасы.(
НомерСтроки КАК НомерСтроки,
Номенклатура.Наименование КАК Запас
)
ИЗ
Документ.ЗаказПокупателя КАК ЗаказПокупателя
ГДЕ
ЗаказПокупателя.Ссылка В(&МассивОбъектов)
УПОРЯДОЧИТЬ ПО
Ссылка,
НомерСтроки
В этом варианте условие УПОРЯДОЧИТЬ ПО НомерСтроки игнорируется для вложенных выборок Работы и Запасы, так как реквизита НомерСтроки нет у самого документа-родителя. В результате строки внутри выгруженных таблиц выводятся в хаотичном порядке.
Чтобы сортировка сработала для каждой вложенной табличной части, необходимо в секции УПОРЯДОЧИТЬ ПО явно обратиться к реквизитам НомерСтроки соответствующего вложенного поля через точку.
Исправленный вариант запроса выглядит следующим образом:
ВЫБРАТЬ
ЗаказПокупателя.Ссылка КАК Ссылка,
ЗаказПокупателя.Номер КАК Номер,
ЗаказПокупателя.Работы.(
НомерСтроки КАК НомерСтроки,
Номенклатура.Наименование КАК Запас
),
ЗаказПокупателя.Запасы.(
НомерСтроки КАК НомерСтроки,
Номенклатура.Наименование КАК Запас
)
ИЗ
Документ.ЗаказПокупателя КАК ЗаказПокупателя
ГДЕ
ЗаказПокупателя.Ссылка В(&МассивОбъектов)
УПОРЯДОЧИТЬ ПО
Ссылка,
ЗаказПокупателя.Запасы.НомерСтроки,
ЗаказПокупателя.Работы.НомерСтроки
После такого уточнения платформа передает в СУБД корректные инструкции по сортировке внутри каждой вложенной выборки, и порядок строк при печати строго совпадает с табличной частью документа.
Использование синтаксиса вложенных таблиц в секции ВЫБРАТЬ считается устаревшей практикой разработки. Для гарантированного порядка строк и высокой читаемости кода рекомендуется запрашивать данные табличной части напрямую как самостоятельный источник.
Разберем по шагам построение такого запроса:
Документ.ЗаказПокупателя.Запасы.Пример запроса по стандартам разработки 1С:
ВЫБРАТЬ
ЗаказыЗапасы.Ссылка КАК Ссылка,
ЗаказыЗапасы.Ссылка.Номер КАК Номер,
ЗаказыЗапасы.НомерСтроки КАК НомерСтроки,
ЗаказыЗапасы.Номенклатура.Наименование КАК Запас,
ЗаказыЗапасы.Количество КАК Количество
ИЗ
Документ.ЗаказПокупателя.Запасы КАК ЗаказыЗапасы
ГДЕ
ЗаказыЗапасы.Ссылка В(&МассивОбъектов)
УПОРЯДОЧИТЬ ПО
Ссылка,
НомерСтроки ВОЗР
Если текст запроса менять нежелательно или механизм формирования печатной формы закрыт, порядок строк можно восстановить программно во встроенном языке 1С перед выводом в макет.
После выполнения запроса выгрузим вложенную выборку или табличную часть в объект ТаблицаЗначений и вызовем метод Сортировать():
// Выгружаем результат выборки в таблицу значений
ТаблицаЗапасов = ВыборкаСтрок.Запасы.Выгрузить();
// Принудительно сортируем по возрастанию номера строки
ТаблицаЗапасов.Сортировать("НомерСтроки ВОЗР");
// Далее производим обход выгруженной таблицы и вывод в область макета
Для Каждого СтрТаблицы Из ТаблицаЗапасов Цикл
// Заполнение параметров области печатной формы
КонецЦикла;
Любые действия по обслуживанию базы (чистка кэша, переиндексация) не гарантируют постоянного порядка выгрузки данных, если порядок не зафиксирован в самом коде. Чтобы предотвратить сбой порядка строк в печатных формах, всегда задавайте явное упорядочивание по полю НомерСтроки с полным указанием пути к табличной части либо используйте прямой запрос к табличным частям документа.