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