Как пронумеровать строки при выгрузке запроса в таблицу значений на форме 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке отчетов и обработок в среде 1С:Предприятие программисты часто сталкиваются с задачей вывода данных во вспомогательные таблицы на форме. Мы пишем запрос, получаем результат, выгружаем его в таблицу значений (ТЗ) одной командой Выгрузить(), но внезапно обнаруживаем, что пользователю не хватает важной детали — сквозной нумерации строк. В стандартном результате запроса поля «Номер строки» нет, а колонка с красивыми порядковыми номерами (1, 2, 3...) крайне важна для удобства восприятия информации.

В этой статье мы подробно разберем все возможные способы решения этой задачи: от простого и надежного программного обхода до современных возможностей платформы 1С v8.3 и использования альтернативных элементов интерфейса.

Способ 1. Программный обход коллекции (Самый надежный и универсальный метод)

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

Рассмотрим по шагам, как выглядит этот процесс в коде:

  1. Выполняем запрос и выгружаем результат во временную ТЗ или напрямую в реквизит формы.
  2. Запускаем цикл по строкам таблицы значений.
  3. В каждой итерации присваиваем колонке номера строки значение счетчика и увеличиваем его на единицу.

Давайте посмотрим на практический пример реализации этого алгоритма:


// 1. Выполняем запрос и загружаем данные в ТЗ на форме
РезультатЗапроса = Запрос.Выполнить();
ТЗДляВыгрузки.Загрузить(РезультатЗапроса.Выгрузить());

// 2. Заполняем номера строк последовательно
НомСтр = 1;
Для Каждого СтрТз Из ТЗДляВыгрузки Цикл
    СтрТз.НомерСтроки = НомСтр;
    НомСтр = НомСтр + 1;
КонецЦикла;

Преимущества метода: работает абсолютно на любой версии платформы (начиная с 7.7 и заканчивая самыми свежими релизами 8.3), корректно обрабатывает любые дублирующиеся строки и не требует сложных манипуляций с языком запросов. Метод гарантирует строго последовательную нумерацию от 1 до N без «дыр» и пропусков.

Способ 2. Использование современной функции запроса АВТОНОМЕРЗАПИСИ()

Начиная с версии платформы 1С 8.3.13, разработчикам стал доступен долгожданный механизм нумерации строк прямо внутри СУБД — функция АВТОНОМЕРЗАПИСИ(). Этот способ позволяет получить готовые номера строк прямо из запроса, не прибегая к последующим циклам в коде 1С.

Однако здесь есть важное технологическое ограничение: функцию АВТОНОМЕРЗАПИСИ() можно использовать только во временных таблицах (при конструкции ПОМЕСТИТЬ).

Разберем пример запроса, переписанного с использованием этого механизма:


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

Запрос.УстановитьПараметр("НачДата", Период.ДатаНачала);
Запрос.УстановитьПараметр("КонДата", Период.ДатаОкончания);

ТЗДляВыгрузки.Загрузить(Запрос.Выполнить().Выгрузить());

Важное предупреждение («Подводные камни»): Функция АВТОНОМЕРЗАПИСИ() гарантирует уникальность номеров и их возрастание по порядку выборки, но платформа 1С не гарантирует, что нумерация всегда будет начинаться именно с единицы. Из-за особенностей внутреннего устройства СУБД и кэширования, при повторных вызовах или в распределенных базах нумерация во временной таблице может начаться, например, со 101 или с любого другого числа. Поэтому для вывода «красивых» и строгих номеров на форму пользователю этот метод следует применять с осторожностью.

Способ 3. Переход от Таблицы значений к Табличной части (ТЧ)

В процессе обсуждения на форумах часто звучит совет: «Используй ТЧ, а не ТЗ». Выясним причину этой рекомендации и что именно она дает начинающему разработчику.

У любого объекта конфигурации (будь то обработка, документ или справочник) можно создать полноценную Табличную часть. Главное ее преимущество перед произвольной Таблицей значений заключается в том, что табличная часть обладает системным предопределенным реквизитом НомерСтроки.

Когда мы выгружаем результат запроса в табличную часть объекта, платформа автоматически генерирует и поддерживает актуальность номеров строк. Нам больше не нужно писать циклы для пересчета номеров при выводе!

Пример заполнения табличной части обработки:


// Загружаем результат запроса напрямую в табличную часть обработки.
// Платформа сама назначит правильные номера строк автоматически!
ТабличнаяЧастьТовары.Загрузить(Запрос.Выполнить().Выгрузить());

Если ваша обработка не требует динамического изменения состава колонок на лету, использование встроенной табличной части вместо программно создаваемой таблицы значений — это наиболее грамотное архитектурное решение в 1С.

Особенности ведения нумерации на Управляемых формах (УФ)

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

Если пользователь в процессе работы с формой имеет право интерактивно добавлять новые строки, удалять их или менять местами (кнопками «Переместить вверх» / «Переместить вниз»), то статическая нумерация, которую мы проставили после запроса, неминуемо собьется.

Чтобы поддерживать нумерацию в актуальном состоянии на клиенте, нам необходимо обновлять номера строк при любом изменении коллекции. Для этого следует привязаться к событиям элемента формы «Таблица» (например, ПриИзменении или ПослеУдаления) и вызывать быструю процедуру пересчета:


&НаКлиенте
Процедура ТЗДляВыгрузкиПриИзменении(Элемент)
    
    // Пересчитываем номера строк по порядку на клиенте без обращений к серверу
    Индекс = 1;
    Для Каждого Стр Из ТЗДляВыгрузки Цикл
        Стр.НомерСтроки = Индекс;
        Индекс = Индекс + 1;
    КонецЦикла;
    
КонецПроцедуры

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

Резюме и рекомендации

Мы рассмотрели различные варианты решения проблемы отсутствия номеров строк. Подведем итоги:

← На главную