Как правильно получить данные строки в событии "Выбор" в управляемой форме 1С и избежать ошибки "Индекс находится за границами массива"?

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

При разработке на платформе 1С в режиме управляемых форм многие сталкиваются с ситуацией, когда код для работы с табличной частью на форме внезапно перестает работать после удаления или добавления строк. Чаще всего это сопровождается ошибкой "Индекс находится за границами массива". Давайте подробно разберем, почему это происходит и как правильно обрабатывать события таблиц, чтобы код был надежным и предсказуемым.

В чем заключается проблема? Анализируем типичный сценарий

Рассмотрим ситуацию, описанную в теме на форуме. У разработчика есть табличная часть на форме и обработчик события Выбор, который должен изменять данные в выбранной двойным кликом строке. Изначальный код выглядит примерно так:


&НаКлиенте
Процедура МояТаблицаВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка) 
    // Получаем данные строки по параметру "ВыбраннаяСтрока"
    // Предполагаем, что это индекс
    ДанныеСтроки = Объект.МояТаблица.Получить(ВыбраннаяСтрока);

    // Выполняем какие-то действия с данными строки
    ДанныеСтроки.ИмяКолонки = "Новое значение";
КонецПроцедуры

Сначала этот код работает безупречно. Пользователь открывает форму, добавляет несколько строк, кликает на них, и данные меняются. Но затем пользователь очищает таблицу с помощью метода Очистить(), добавляет новые строки и снова пытается выполнить двойной клик. В этот момент система выдает ошибку "Индекс находится за границами массива". Давайте выясним причину.

Ключевое различие: Индекс и Идентификатор

Корень проблемы кроется в фундаментальном непонимании разницы между двумя характеристиками строки в таблице на управляемой форме: ее индексом и ее идентификатором.

Индекс — это порядковый номер строки в коллекции. Нумерация всегда начинается с 0. Это динамическая характеристика. Если вы добавите строку, у нее будет последний индекс. Если вы удалите строку из середины таблицы, индексы всех последующих строк уменьшатся на единицу. Для доступа к строке по ее текущему положению (индексу) используется метод Получить(Индекс).

Идентификатор — это уникальный внутренний номер, который платформа присваивает строке в момент ее создания на форме. Это статическая характеристика. Идентификатор строки не меняется на протяжении всего ее "жизненного цикла" в рамках открытой формы, независимо от того, сколько строк было добавлено или удалено вокруг нее. Счетчик идентификаторов сбрасывается только при полном пересоздании формы (например, при ее закрытии и повторном открытии).

Самое главное: в обработчики событий таблиц, такие как Выбор или ПриАктивизацииСтроки, в параметр ВыбраннаяСтрока платформа передает именно ИДЕНТИФИКАТОР, а не текущий индекс строки.

Теперь проанализируем ситуацию, приводящую к ошибке, по шагам:

  1. Пользователь открывает форму и добавляет в таблицу 3 строки.
    • Строка 1: Индекс = 0, Идентификатор = 0
    • Строка 2: Индекс = 1, Идентификатор = 1
    • Строка 3: Индекс = 2, Идентификатор = 2
  2. Пользователь очищает таблицу. Все строки удалены.
  3. Далее пользователь добавляет 2 новые строки. Счетчик идентификаторов не сбросился и продолжает свою работу.
    • Новая Строка 1: Индекс = 0, Идентификатор = 3
    • Новая Строка 2: Индекс = 1, Идентификатор = 4
  4. Пользователь делает двойной клик на первой (визуально) строке. Ее индекс равен 0, но идентификатор — 3.
  5. В обработчик события МояТаблицаВыбор передается параметр ВыбраннаяСтрока со значением 3.
  6. Код пытается выполнить операцию Объект.МояТаблица.Получить(3). Он пытается получить строку с индексом 3, но в таблице всего 2 строки (с индексами 0 и 1).
  7. Результат — ошибка "Индекс находится за границами массива".

Решение 1: Используем правильный метод НайтиПоИдентификатору()

Платформа 1С предоставляет специальный метод, который предназначен именно для поиска строки по ее уникальному неизменяемому идентификатору. Это метод НайтиПоИдентификатору().

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

Правильный код:


&НаКлиенте
Процедура МояТаблицаВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
    // ВыбраннаяСтрока здесь - это Идентификатор, а не Индекс.
    // Ищем данные строки в коллекции по ее идентификатору.
    ДанныеСтроки = Объект.МояТаблица.НайтиПоИдентификатору(ВыбраннаяСтрока);

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

Этот код будет работать стабильно и надежно, независимо от того, сколько раз таблица очищалась или как менялся порядок строк. Он всегда будет находить именно ту строку, на которой пользователь совершил действие, потому что опирается на ее постоянный идентификатор.

Решение 2: Альтернативный способ через свойство ТекущиеДанные

Есть еще один, зачастую более простой и элегантный способ получить доступ к данным активной строки. У элемента формы типа "Таблица" есть свойство ТекущиеДанные. Оно напрямую возвращает объект с данными строки, на которой в данный момент стоит курсор. Этот способ избавляет от необходимости что-либо искать.

Пример использования:


&НаКлиенте
Процедура МояТаблицаВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
    // Получаем данные текущей (активной) строки напрямую из элемента формы.
    ТекущиеДанныеСтроки = Элементы.МояТаблица.ТекущиеДанные;

    // Также рекомендуется проверять, что текущая строка определена.
    Если ТекущиеДанныеСтроки <> Неопределено Тогда
        // Выполняем действия с данными
        ТекущиеДанныеСтроки.ИмяКолонки = "Новое значение";
    КонецЕсли;
КонецПроцедуры

Этот подход особенно удобен в событиях, которые непосредственно связаны с текущей активностью пользователя в таблице, таких как Выбор или ПриАктивизацииСтроки. В этом случае вам даже не нужно использовать параметр ВыбраннаяСтрока.

Когда какой способ выбрать?

Итоги

Чтобы избежать ошибок при работе с таблицами на управляемых формах, запомните простое правило: параметр ВыбраннаяСтрока в событиях — это идентификатор, а не индекс.

Для получения данных строки на основе этого параметра всегда используйте метод Объект.<ИмяТаблицы>.НайтиПоИдентификатору(ВыбраннаяСтрока). В качестве более простой альтернативы для обработки текущей активной строки используйте свойство Элементы.<ИмяТаблицы>.ТекущиеДанные. Такой подход сделает ваш код устойчивым к любым манипуляциям с данными в таблице и избавит от трудноуловимых ошибок.

← На главную