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