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