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