Как правильно обратиться к строке таблицы и почему НомерСтроки — не лучший выбор

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

В процессе разработки на платформе 1С:Предприятие часто возникает задача программного обращения к конкретной строке табличной части документа или таблицы значений. На первый взгляд, использование стандартного реквизита НомерСтроки кажется самым простым и очевидным решением. Однако на практике разработчики сталкиваются с рядом ошибок, таких как «Метод объекта не обнаружен (Количество)» или «Недопустимое значение параметра» при вызове ЗаполнитьЗначенияСвойств. В этой статье мы подробно разберем, как правильно работать с индексами, почему методы поиска ведут себя по-разному и как организовать надежную связь между основной таблицей и вспомогательными данными.

Разбор первой проблемы: НайтиСтроки против обращения по индексу

Рассмотрим типичную ситуацию, с которой столкнулся автор темы. При попытке найти строку по номеру используется метод НайтиСтроки(). Этот метод всегда возвращает объект типа Массив, даже если найдена всего одна строка или не найдено ничего. Если же мы прислушаемся к совету использовать прямое обращение через индекс Товары[НомерСтроки - 1], мы получим не массив, а конкретный объект типа СтрокаТабличнойЧасти (или СтрокаТаблицыЗначений).

Проанализируем ошибку из сообщения №4: Метод объекта не обнаружен (Количество). Она возникает именно из-за подмены типов. Посмотрим на фрагмент кода:


// Ошибочный подход при замене НайтиСтроки на обращение по индексу
МассивСтрок = Товары[ВыбранноеЗначение.НомерСтроки - 1]; 

// Ошибка возникнет здесь, так как МассивСтрок теперь — это одна строка, а не массив
Если МассивСтрок.Количество() > 0 Тогда 
    // ... логика
КонецЕсли;

Выясним причину: у объекта «Строка» нет метода Количество(). Если мы обращаемся к таблице напрямую по индексу, нам больше не нужно проверять количество элементов в массиве. Мы сразу получаем доступ к полям этой строки.

Проблема использования НомерСтроки как идентификатора

Важно понимать критическую особенность платформы 1С: НомерСтроки является динамическим реквизитом. Рассмотрим ситуацию: у нас есть три строки с номерами 1, 2 и 3. Если пользователь удалит вторую строку, бывшая третья строка автоматически получит номер 2. Если же мы отсортируем таблицу, номера строк также будут пересчитаны в соответствии с новым визуальным порядком.

Именно поэтому попытка связать данные основной таблицы (например, «Товары») с вспомогательной таблицей значений («ИзмененияКоличества») через НомерСтроки — это архитектурная ошибка. Как только состав или порядок строк в основной таблице изменится, связь со вспомогательной таблицей «развалится» или, что еще хуже, данные привяжутся к чужим строкам.

Правильное решение: Использование Уникального Идентификатора

Проанализируем более надежный способ, предложенный в сообщении №10. Чтобы однозначно идентифицировать строку на протяжении всего сеанса работы с формой, необходимо добавить в табличную часть реквизит (например, с именем ИдентификаторСтроки) с типом УникальныйИдентификатор или Число.

Разберем по шагам, как реализовать генерацию идентификатора при добавлении новой строки:


Процедура ТоварыПриНачалеРедактирования(Элемент, НоваяСтрока, Копирование)
    Если НоваяСтрока Тогда
        // Генерируем уникальный ключ для новой строки
        Элемент.ТекущиеДанные.ИдентификаторСтроки = Новый УникальныйИдентификатор;
    КонецЕсли;
КонецПроцедуры

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


Процедура ТоварыОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)
    Если ТипЗнч(ВыбранноеЗначение) = Тип("Структура") Тогда
        // Используем надежный идентификатор вместо номера строки
        Отбор = Новый Структура("ИдентификаторСтроки", ВыбранноеЗначение.ИдентификаторСтроки);
        
        // Вспомогательная таблица, где мы храним детали изменений
        СтрокиИзменений = ИзмененияКоличества.НайтиСтроки(Отбор);
        
        Если СтрокиИзменений.Количество() = 1 Тогда
            СтрокаИзменения = СтрокиИзменений[0];
        Иначе
            // Если раньше записей не было, создаем новую
            СтрокаИзменения = ИзмененияКоличества.Добавить();
        КонецЕсли;
        
        // Переносим данные из структуры в найденную/созданную строку
        ЗаполнитьЗначенияСвойств(СтрокаИзменения, ВыбранноеЗначение);
        СтандартнаяОбработка = Ложь;
    КонецЕсли;
КонецПроцедуры

Почему возникает ошибка в ЗаполнитьЗначенияСвойств?

В тексте темы упоминается ошибка: Ошибка при вызове метода контекста (ЗаполнитьЗначенияСвойств) по причине: Недопустимое значение параметра (параметр номер '1'). Рассмотрим подробнее ситуацию, когда это происходит. Метод ЗаполнитьЗначенияСвойств(Приемник, Источник) ожидает, что в первом параметре будет передан объект (строка таблицы, структура и т.д.).

Если логика поиска в коде нарушена и переменная СтрокаИзменения осталась со значением Неопределено (например, из-за того, что условие создания новой строки было пропущено), система выдаст ошибку. Проанализируем типичный сценарий: если ИзмененияКоличества.НайтиСтроки(Отбор) вернул пустой массив и при этом блок Иначе СтрокаИзменения = ИзмененияКоличества.Добавить() не отработал корректно, метод заполнения свойств не сможет работать с «пустотой».

Работа с индексами в Таблице Значений

Если вы все же уверены, что коллекция не меняется, и хотите использовать индекс (номер строки минус один), важно помнить о различиях между объектами. В 1С ТабличнаяЧасть документа и объект ТаблицаЗначений в памяти — это разные сущности.

  1. Обращение по индексу: Всегда используйте квадратные скобки Таблица[Индекс]. Помните, что индекс начинается с 0, а НомерСтроки в интерфейсе — с 1.
  2. Метод НайтиСтроки(): Требует структуру отбора. Всегда возвращает массив. Удобен, когда нужно найти несколько строк по одному критерию.
  3. Метод Найти(): Возвращает первую найденную строку или Неопределено. Удобен для поиска по уникальному значению в одной колонке.

Рекомендации для надежного кода

Чтобы избежать ошибок, которые мы разобрали выше, придерживайтесь следующих правил при работе с таблицами:

Во-первых, никогда не завязывайте бизнес-логику на НомерСтроки, если предполагается сохранение связи между объектами после закрытия формы или при наличии возможности сортировки таблицы.

Во-вторых, всегда проверяйте результат поиска перед тем, как использовать его в методах типа ЗаполнитьЗначенияСвойств. Простая проверка Если СтрокаИзменения <> Неопределено Тогда убережет вашу программу от аварийного завершения.

В-третьих, учитывайте контекст выполнения. Если вы работаете на управляемых формах (версия 8.3), платформа предоставляет встроенные механизмы идентификации строк через Элементы.ИмяТаблицы.ТекущаяСтрока, что избавляет от необходимости вручную создавать GUID для каждой строки в рамках работы текущей формы.

Проанализировав все ошибки автора темы, мы видим, что переход к использованию ИдентификаторСтроки (Message 15) полностью решил проблему нестабильного поиска и ошибок типов данных. Это подтверждает, что правильное проектирование структуры данных первичнее, чем попытки «обмануть» стандартное поведение индексов и номеров строк.

← На главную