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