Почему увеличивается значение ТекущаяСтрока в таблице значений и как правильно получить данные строки

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При работе с управляемыми формами в 1С:Предприятии 8 разработчики часто сталкиваются со странным поведением: после очистки и повторного заполнения таблицы значений идентификатор текущей строки (ТекущаяСтрока) начинает принимать значения, значительно превышающие общее количество строк в таблице. Это приводит к ошибке «Индекс находится за границами диапазона» при попытке получить строку методом Получить(). В этой статье мы подробно разберем, почему это происходит и как правильно работать с данными таблицы в таких ситуациях.

Разбираем причину: Идентификатор против Индекса

Для начала проанализируем ситуацию и выясним причину такого поведения платформы. В управляемом приложении свойство Элементы.ТвояТаблица.ТекущаяСтрока возвращает не индекс строки (0, 1, 2...), а её внутренний идентификатор. Это уникальное числовое значение, которое присваивается строке в рамках текущего сеанса работы формы.

Рассмотрим механизм работы идентификаторов по шагам:

  1. Вы создали таблицу и добавили в нее 10 строк. Платформа присвоила им идентификаторы от 0 до 9.
  2. Вы вызываете метод ТЗ.Очистить(). Данные удалены, но внутренний счетчик идентификаторов для этого элемента формы не сбрасывается.
  3. Вы снова добавляете 10 строк. Теперь их идентификаторы будут начинаться с 10 и закончатся на 19.
  4. Если вы попытаетесь выполнить код ТЗ.Получить(Элементы.ТЗ.ТекущаяСтрока), где ТекущаяСтрока равна 10, система выдаст ошибку, так как в коллекции ТЗ по-прежнему всего 10 строк с индексами от 0 до 9.

Важно понимать, что метод Обновить() лишь перерисовывает графический интерфейс и никак не влияет на логику работы с индексами или идентификаторами в памяти.

Решение 1: Использование свойства ТекущиеДанные на клиенте

Самый простой и безопасный способ получить данные текущей строки на стороне клиента — это обращение к свойству ТекущиеДанные. Многие ошибочно полагают, что если колонка не выведена на форму (не создано соответствующее ПолеФормы), то ее нельзя получить через это свойство. Это не так.

Рассмотрим пример: если в реквизите формы «ТаблицаЗначений» есть колонка «СкрытыйПараметр», но на форме она не отображается, мы все равно можем ее прочитать:


&НаКлиенте
Процедура ОбработкаВыбораСтроки(Команда)
    ТекДанные = Элементы.ТЗ.ТекущиеДанные;
    Если ТекДанные <> Неопределено Тогда
        // Обращаемся к данным напрямую, индекс нам не нужен
        ЗначениеПараметра = ТекДанные.СкрытыйПараметр;
        Сообщить("Выбрана строка с параметром: " + ЗначениеПараметра);
    КонецЕсли;
КонецПроцедуры

Этот способ является предпочтительным, так как он избавляет от необходимости передавать идентификаторы на сервер и выполнять там поиск.

Решение 2: Корректная работа на сервере через НайтиПоИдентификатору

Если же логика приложения требует передачи ссылки на строку на сервер (например, для сложной обработки данных в контексте всей таблицы), необходимо использовать метод НайтиПоИдентификатору(). Этот метод доступен у объекта типа ДанныеФормыКоллекция.

Проанализируем правильный алгоритм взаимодействия клиента и сервера:


&НаКлиенте
Процедура ВыполнитьДействиеНаСервере(Команда)
    ИдентификаторСтроки = Элементы.ТЗ.ТекущаяСтрока;
    Если ИдентификаторСтроки <> Неопределено Тогда
        ОбработатьНаСервере(ИдентификаторСтроки);
    КонецЕсли;
КонецПроцедуры

&НаСервере
Процедура ОбработатьНаСервере(ИдентификаторСтроки)
    // ТЗ здесь - это реквизит формы (ДанныеФормыКоллекция)
    СтрокаДанных = ТЗ.НайтиПоИдентификатору(ИдентификаторСтроки);
    
    Если СтрокаДанных <> Неопределено Тогда
        // Теперь мы получили доступ к строке
        СтрокаДанных.Статус = "Обработано";
    КонецЕсли;
КонецПроцедуры

Обратите внимание: если внутри серверной процедуры вы преобразуете данные формы в обычную таблицу значений с помощью ДанныеФормыВЗначение("ТЗ", Тип("ТаблицаЗначений")), то идентификаторы будут потеряны. В "чистой" ТаблицеЗначений поиск по ID невозможен, там работают только индексы.

Решение 3: Удаление строк по условию

Часто вопрос получения текущей строки возникает при необходимости удаления данных. Посмотрим, как это сделать правильно на клиенте и на сервере, используя примеры из практики.

Пример удаления на клиенте:


&НаКлиенте
Процедура УдалитьТекущуюСтроку(Команда)
    // Передаем идентификатор напрямую в метод Удалить() коллекции данных формы
    ТЗ.Удалить(Элементы.ТЗ.ТекущаяСтрока);
КонецПроцедуры

Если же нужно удалить строки по определенному условию, разберем пример с использованием структуры отбора:


&НаСервере
Процедура УдалитьСтрокиПоУсловиюНаСервере()
    ПараметрыОтбора = Новый Структура("РеквизитБулево", Истина);
    НайденныеСтроки = ТЗ.НайтиСтроки(ПараметрыОтбора);
    
    Для Каждого СтрокаДляУдаления Из НайденныеСтроки Цикл
        ТЗ.Удалить(СтрокаДляУдаления);
    КонецЦикла;
КонецПроцедуры

Рекомендации и важные нюансы

Выяснив основные причины проблем, сформулируем правила "хорошего тона" при работе с таблицами в управляемых формах:

  1. Никогда не используйте индекс для поиска строки, если вы получили его из свойства ТекущаяСтрока. Эти величины не равнозначны.
  2. Используйте уникальные ключи данных. Если таблица полностью перезаполняется из базы данных, идентификаторы строк 100% изменятся. Чтобы "найти" ту же самую строку после обновления, лучше ориентироваться на уникальный реквизит (например, Ссылка, Артикул или НомерСтроки из документа).
  3. Очистка данных. Перед перезаполнением таблицы всегда используйте ТЗ.Очистить(). Хотя это и не сбрасывает счетчик идентификаторов, это гарантирует отсутствие "мусорных" данных в коллекции.
  4. Обновление интерфейса. Если после программного изменения данных формы таблица на экране не обновилась (что редко, но бывает в сложных интерфейсах), используйте Элементы.ТЗ.Обновить() только для визуального обновления.

Таким образом, понимание внутреннего устройства работы 1С с идентификаторами строк позволяет избежать типичных ошибок и писать более стабильный код. Помните: ТекущаяСтрока — это ссылка на ID, а ТекущиеДанные — это самый короткий путь к значениям колонок.

← На главную