Почему в печатной форме 1С внезапно изменился порядок строк и как это исправить

Программист 1С v8.3 (Обычные формы) 1C:Бухгалтерия Бухгалтерский учет Промышленность, строительство и АПК
← На главную

Многие разработчики и администраторы 1С сталкиваются с загадочной ситуацией: печатная форма документа, которая годами выводила данные «строка в строку» в соответствии с экранной формой, вдруг начинает перемешивать позиции. При этом в конфигурацию никто не вносил изменений, а пользователи клянутся, что ничего не нажимали. Рассмотрим подробно, почему это происходит и как раз и навсегда решить проблему с сортировкой в печатных формах.

Анализ ситуации: вчера работало, сегодня — нет

Типичный сценарий: в документе Отчет производства за смену на закладке Материалы данные введены в одном порядке, а при печати формы Требование-накладная (М-11) они выходят вразнобой. Проанализируем причину этого поведения. Проблема кроется в архитектуре взаимодействия платформы 1С с системами управления базами данных (СУБД), такими как Microsoft SQL Server или PostgreSQL.

Разберем по шагам, что происходит «под капотом» программы. Когда мы нажимаем кнопку Печать, код 1С выполняет запрос к табличной части документа. Если в этом запросе программист явно не указал конструкцию УПОРЯДОЧИТЬ ПО, СУБД возвращает данные в наиболее «удобном» для неё порядке. До определенного момента этот «удобный» порядок совпадает с физическим порядком записи строк, но это не гарантированное поведение, а лишь стечение обстоятельств.

Причина №1: Отсутствие явной сортировки в запросе

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

  1. Обновление статистики: СУБД пересчитала распределение данных и решила, что теперь выгоднее использовать другой индекс или другой план выполнения запроса.
  2. Реиндексация или дефрагментация: Физическое расположение строк в таблицах на диске изменилось. Теперь при «последовательном» чтении СУБД считывает строки в ином порядке.
  3. Параллелизм (MAXDOP): SQL Server мог решить выполнить запрос в несколько потоков. Результаты из разных потоков склеиваются в произвольном порядке, что приводит к хаосу в итоговой таблице.

Важный вывод: надеяться на то, что СУБД всегда будет отдавать строки по порядку их ввода без команды УПОРЯДОЧИТЬ ПО, — это «технический долг», который рано или поздно приведет к ошибке.

Причина №2: Влияние метода Свернуть()

Посмотрим на пример кода, который часто используется в типовых и самописных печатных формах:


ТаблицаМатериалов = УчетОС.СформироватьЗапросПоТабличнойЧасти(Объект, "Материалы", СтруктураПолей).Выгрузить();
ТаблицаМатериалов.Свернуть("Материал, МатериалНаименование, Счет, НоменклатурныйНомер", "Количество");

Проанализируем этот фрагмент. Здесь данные сначала получаются запросом, выгружаются в объект ТаблицаЗначений, а затем к ним применяется метод Свернуть(). Важно понимать, что метод Свернуть() в 1С не сохраняет исходный порядок строк. В процессе группировки платформа перестраивает таблицу во внутренней памяти для оптимизации скорости, итоговый порядок строк после сворачивания может быть абсолютно любым.

Решение проблемы через модификацию кода

Чтобы гарантировать стабильный результат, нам необходимо добавить явную сортировку. Рассмотрим два основных способа решения задачи.

Способ 1: Сортировка в запросе по Номеру строки

Это самый правильный метод с точки зрения производительности. Если нам нужно, чтобы печатная форма полностью повторяла порядок строк в документе, мы должны использовать поле НомерСтроки. Рассмотрим, как должен выглядеть запрос:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   ТЧ.Номенклатура КАК Материал,
    |   ТЧ.Количество КАК Количество,
    |   ТЧ.НомерСтроки КАК НомерСтроки
    |ИЗ
    |   Документ.ОтчетПроизводстваЗаСмену.Материалы КАК ТЧ
    |ГДЕ
    |   ТЧ.Ссылка = &Ссылка
    |УПОРЯДОЧИТЬ ПО
    |   НомерСтроки"; // Явное указание порядка

Использование УПОРЯДОЧИТЬ ПО НомерСтроки гарантирует, что данные придут в 1С именно в той последовательности, в которой их видит пользователь на экране.

Способ 2: Сортировка объекта ТаблицаЗначений

Если данные уже получены и, возможно, обработаны методом Свернуть(), нам необходимо принудительно отсортировать итоговую таблицу перед выводом на печать. Рассмотрим пример, расширяющий код из сообщения №3:


// Получаем данные
ТаблицаМатериалов = УчетОС.СформироватьЗапросПоТабличнойЧасти(Объект, "Материалы", СтруктураПолей).Выгрузить();

// Если нам важен порядок как в документе, в запросе должно быть поле НомерСтроки
// Сворачиваем данные (при этом порядок теряется)
ТаблицаМатериалов.Свернуть("Материал, МатериалНаименование, НомерСтроки", "Количество");

// Принудительно возвращаем порядок
ТаблицаМатериалов.Сортировать("НомерСтроки Возр");

// Теперь можно выводить в область печати
Для Каждого СтрокаТЧ Из ТаблицаМатериалов Цикл
    Область.Параметры.Заполнить(СтрокаТЧ);
    // ... вывод области
КонецЦикла;

Если поле НомерСтроки по каким-то причинам недоступно или не подходит (например, при группировке одинаковых материалов в одну строку), рекомендуется сортировать по алфавиту (по наименованию). Это хотя бы обеспечит предсказуемость: пользователь будет знать, что товары всегда идут по алфавиту, а не в случайном порядке.

ТаблицаМатериалов.Сортировать("МатериалНаименование Возр");

Почему это критично для учета?

Разберем ситуацию с точки зрения бухгалтера. В документе Отчет производства за смену порядок материалов может быть важен для визуального сопоставления с технологической картой. Когда печатная форма М-11 выдает список в другом порядке, поиск расхождений становится мучительным процессом. Кроме того, в некоторых конфигурациях (например, старых редакциях БГУ) отсутствие сортировки в запросах приводило к некорректному заполнению аналитики (субконто) в проводках, если платформа выбирала «не ту» строку первой.

Резюме для разработчика

Выясним главные правила, которые помогут избежать подобных проблем в будущем:

  1. Никогда не доверяйте СУБД порядок строк, если он не указан в УПОРЯДОЧИТЬ ПО. Даже если сегодня всё работает правильно, завтра после регламентного обслуживания SQL-сервера порядок изменится.
  2. Помните про Свернуть(). Этот метод — враг последовательности. После любого сворачивания таблицы значений всегда вызывайте метод Сортировать().
  3. Используйте НомерСтроки. Это служебное поле табличных частей специально создано для того, чтобы сохранять пользовательский порядок ввода.
  4. Проверяйте типовые механизмы. Если вы используете функции типа СформироватьЗапросПоТабличнойЧасти, убедитесь, что в структуру полей включен НомерСтроки, и итоговая таблица сортируется по нему.

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

← На главную