Разработка и Конфигурация · 10 мин
Как пронумеровать строки в запросе 1С
Способы нумерации строк в запросе 1С: функция АВТОНОМЕРЗАПИСИ, нумерация в СКД, программный счётчик при обходе выборки. Примеры кода, ограничения и типичные ошибки.
Нумерация строк результата запроса — частая задача при построении отчётов, выгрузках данных и подготовке таблиц для печатных форм. В языке запросов 1С есть встроенный механизм — функция АВТОНОМЕРЗАПИСИ(), но она имеет особенности, о которых нужно знать, чтобы не получить «дырявую» или нестабильную нумерацию.
Помимо встроенной функции существуют альтернативные подходы: нумерация средствами СКД, программный счётчик при обходе выборки и нумерация в таблице значений после выполнения запроса. Выбор зависит от того, где используется результат — в отчёте, в обработке или в печатной форме.
В материале разобраны все рабочие способы с примерами кода, ограничения каждого подхода и типичные ошибки, из-за которых нумерация «ломается».
Функция АВТОНОМЕРЗАПИСИ: базовый синтаксис
Функция АВТОНОМЕРЗАПИСИ() вставляется в список полей выборки и автоматически присваивает каждой строке результата порядковый номер, начиная с единицы. Функция не принимает параметров.
ВЫБРАТЬ
АВТОНОМЕРЗАПИСИ() КАК НомерСтроки,
Номенклатура.Ссылка КАК Товар,
Номенклатура.Код КАК Код
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
НЕ Номенклатура.ПометкаУдаления
Результат: первая колонка содержит последовательные номера 1, 2, 3 и так далее. Поле можно назвать любым именем через ключевое слово КАК — стандартное соглашение: НомерСтроки или НПП.
Важно понимать: функция нумерует строки в том порядке, в котором их вернул запрос. Если упорядочивание не задано явно через УПОРЯДОЧИТЬ ПО, порядок строк (и, соответственно, номера) может меняться от выполнения к выполнению.
Нумерация с упорядочиванием и группировкой
Чтобы номера строк соответствовали осмысленному порядку, всегда добавляйте секцию УПОРЯДОЧИТЬ ПО. Нумерация применяется к уже отсортированному результату:
ВЫБРАТЬ
АВТОНОМЕРЗАПИСИ() КАК НомерСтроки,
Продажи.Номенклатура КАК Товар,
СУММА(Продажи.Количество) КАК Количество
ИЗ
РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , ) КАК Продажи
СГРУППИРОВАТЬ ПО
Продажи.Номенклатура
УПОРЯДОЧИТЬ ПО
Количество УБЫВ
Такой запрос вернёт товары, отсортированные по убыванию продаж, и пронумерует их — фактически это готовый рейтинг с позициями.
Нумерация внутри групп
Функция АВТОНОМЕРЗАПИСИ не умеет нумеровать строки «заново» внутри каждой группы (например, нумеровать товары отдельно по каждому складу). Если нужна сквозная нумерация внутри групп, варианты такие:
- выполнить запрос с группировкой и присваивать номера программно при обходе выборки, сбрасывая счётчик при смене группы;
- в СКД использовать поле «Номер по порядку в группировке»;
- разбить задачу на несколько запросов по одному на группу — приемлемо только при малом числе групп.
Ограничения и особенности АВТОНОМЕРЗАПИСИ
У встроенной функции есть несколько ограничений, которые важно учитывать до выбора решения:
- нумерация всегда начинается с 1 и идёт с шагом 1 — задать начальное значение или шаг нельзя;
- функция несовместима с ключевым словом
РАЗЛИЧНЫЕ— запрос с такой комбинацией вернёт ошибку; - нельзя использовать в итоговых и временных таблицах пакета избирательно: функция применяется к каждому запросу пакета отдельно, нумерация не «переходит» между таблицами;
- порядок номеров определяется порядком вывода строк, а не значениями данных — при изменении сортировки номера перераспределяются.
Ещё одна тонкость: при использовании ОБЪЕДИНИТЬ ВСЕ функцию нужно размещать в каждой части объединения, иначе нумерация будет неполной. При этом номера в разных частях объединения начинаются независимо, что может дать дубликаты номеров — проверяйте результат.
Нумерация программным счётчиком при обходе выборки
Если возможностей АВТОНОМЕРЗАПИСИ не хватает — нужна нумерация внутри групп, произвольный шаг или пропуск строк по условию — номера присваивают программно при обходе результата:
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| Продажи.Номенклатура КАК Товар,
| СУММА(Продажи.Количество) КАК Количество
|ИЗ
| РегистрНакопления.Продажи.Обороты(&Начало, &Конец, , ) КАК Продажи
|СГРУППИРОВАТЬ ПО
| Продажи.Номенклатура
|УПОРЯДОЧИТЬ ПО
| Количество УБЫВ";
Запрос.УстановитьПараметр("Начало", НачалоПериода);
Запрос.УстановитьПараметр("Конец", КонецПериода);
Выборка = Запрос.Выполнить().Выбрать();
НомерСтроки = 0;
Пока Выборка.Следующий() Цикл
НомерСтроки = НомерСтроки + 1;
// НомерСтроки — текущий порядковый номер
КонецЦикла;
Программный подход даёт полный контроль: можно пропускать строки по условию, нумеровать с любого числа, сбрасывать счётчик при смене группы. Минус — нумерация существует только в момент обхода, её нельзя вывести в консоли запросов или передать дальше как поле запроса.
Нумерация в таблице значений
Если результат запроса выгружается в таблицу значений, номер удобно добавить колонкой:
ТаблицаРезультат = Запрос.Выполнить().Выгрузить();
ТаблицаРезультат.Колонки.Добавить("НомерСтроки", Новый ОписаниеТипов("Число"));
Для Номер = 0 По ТаблицаРезультат.Количество() - 1 Цикл
ТаблицаРезультат[Номер].НомерСтроки = Номер + 1;
КонецЦикла;
Этот способ удобен, когда таблица дальше передаётся в печатную форму, обмен или на форму обработки.
- 1Определите, где используется нумерация: отчёт СКД, программная обработка, печатная форма
- 2Если нужен простой номер в запросе — добавьте АВТОНОМЕРЗАПИСИ() и обязательно УПОРЯДОЧИТЬ ПО
- 3Если нужна нумерация внутри групп или по условию — реализуйте счётчик при обходе выборки
- 4Если нумерация нужна в отчёте на СКД — используйте поле НомерПоПорядку из системных полей
- 5Проверьте результат на тестовых данных: номера идут подряд, без пропусков и дублей
Нумерация строк в СКД
В системе компоновки данных нумеровать строки в запросе часто вообще не нужно — есть встроенные системные поля. При построении схемы компоновки доступны поля:
НомерПоПорядку— сквозная нумерация строк всего отчёта;НомерПоПорядкуВГруппировке— нумерация внутри текущей группировки, сбрасывается при переходе к следующей группе;УровеньиУровеньВГруппировке— для работы с иерархией.
Чтобы вывести номер в отчёте, перетащите системное поле в список выбранных полей на закладке «Настройки» или добавьте его в ресурсы/поля набора данных. Дополнительного кода не требуется — СКД посчитает номера автоматически при формировании отчёта.
Это предпочтительный способ для отчётов: нумерация корректно работает с группировками, отборами и динамической сортировкой, которую пользователь меняет в настройках отчёта. АВТОНОМЕРЗАПИСИ в запросе набора данных СКД, напротив, пронумерует строки до применения пользовательской сортировки, и номера могут не совпасть с видимым порядком строк.
Сравнение вариантов
Быстро и без кода, но только сквозная нумерация, несовместима с РАЗЛИЧНЫЕ, требует явной сортировки
Полный контроль: группы, условия, произвольный шаг. Номер существует только в коде, не виден в консоли запросов
Удобно для передачи в печатные формы и обмены, но требует дополнительного прохода по таблице
Идеально для отчётов: учитывает группировки и пользовательскую сортировку. Не применимо вне СКД
Проверка результата и отладка
После добавления нумерации проверьте результат на реальных данных. Удобнее всего это делать в консоли запросов (в режиме предприятия) до переноса текста в модуль.
Как проверить результат
Нумерация начинается с 1
Начинается с 0 или другого числа — проверьте, не смешаны ли подходы
Номера идут подряд без пропусков и дублей
Пропуски или дубли — вероятно, ОБЪЕДИНИТЬ с независимой нумерацией частей
Номера одинаковые при каждом запуске
Номера «плавают» — отсутствует УПОРЯДОЧИТЬ ПО
Номер 1 у первой по сортировке строки
Номера не совпадают с видимым порядком — в СКД сортировка применяется после нумерации запроса
Если запрос — часть пакета с временными таблицами, помните: АВТОНОМЕРЗАПИСИ нумерует результат каждого отдельного запроса пакета. Если временная таблица создаётся в одном запросе, а нумеровать нужно итоговый результат — размещайте функцию в финальном запросе пакета.
При отладке больших запросов удобно временно выводить АВТОНОМЕРЗАПИСИ рядом с ключевым полем (например, ссылкой на документ): так проще отследить, в каком порядке запрос реально возвращает строки, и сразу видно, где не хватает упорядочивания.
Частые вопросы
Можно ли начать нумерацию не с единицы?
АВТОНОМЕРЗАПИСИ всегда начинает с 1. Если нужен другой старт, добавьте смещение арифметически: АВТОНОМЕРЗАПИСИ() + 100 КАК НомерСтроки — нумерация начнётся со 101. Либо используйте программный счётчик с нужным начальным значением.
Почему запрос с АВТОНОМЕРЗАПИСИ и РАЗЛИЧНЫЕ выдаёт ошибку?
Это задокументированное ограничение платформы: функция несовместима с ключевым словом РАЗЛИЧНЫЕ в одном запросе. Решение — вынести выборку различных значений во временную таблицу или подзапрос, а нумерацию применить во внешнем запросе.
Как пронумеровать строки табличной части документа при выводе на печать?
Если печатная форма построена на СКД, используйте системное поле НомерПоПорядку. При программном формировании табличного документа заведите переменную-счётчик и увеличивайте её в цикле вывода строк, подставляя в параметр области макета.
Работает ли АВТОНОМЕРЗАПИСИ в динамических списках?
В произвольном запросе динамического списка функцию использовать можно, но с осторожностью: динамический список сам управляет сортировкой и выборкой, поэтому нумерация может не совпадать с отображаемым порядком. Для колонки «№» в списке надёжнее нумеровать при выводе данных, а не в запросе.
Как пронумеровать строки внутри каждой группы отчёта?
В отчёте на СКД выведите системное поле НомерПоПорядкуВГруппировке — оно автоматически сбрасывается в каждой группе. Вне СКД обходите выборку с группировкой (метод ОбходРезультатаЗапроса.ПоГруппировкам) и сбрасывайте счётчик при переходе к следующей группе.
Что важно запомнить
АВТОНОМЕРЗАПИСИ() — самый быстрый способ пронумеровать строки запроса, но всегда добавляйте УПОРЯДОЧИТЬ ПО и помните про несовместимость с РАЗЛИЧНЫЕ. Для отчётов на СКД используйте системные поля нумерации, для сложной логики — программный счётчик при обходе выборки.