Как правильно обращаться к данным и элементам в формах списка и объекта 1С?

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

При начале разработки в среде «1С:Предприятие» многие сталкиваются с путаницей в доступе к данным. Почему в форме документа можно написать Объект.Наименование, и это работает, а в форме списка аналогичная конструкция Список.Наименование вызывает ошибку? В чем разница между Элементы, ЭтаФорма и ТекущаяСтрока? Разберем эти вопросы подробно, разложим по полочкам теорию и рассмотрим практические примеры кода для решения этих задач.

Фундаментальное отличие: Форма Объекта vs Форма Списка

Чтобы понять, как обратиться к данным, нужно сначала осознать, где мы находимся. В 1С существует две основные парадигмы работы с данными на клиенте:

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

Рассмотрим ситуацию, описанную в вопросе: почему нельзя обратиться через точку к списку?

Когда вы пишете Объект.Наименование в модуле формы документа, платформа обращается к реквизиту формы с именем "Объект", у которого есть свойство "Наименование". Это конкретная запись в памяти.

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

Как получить данные текущей строки в форме списка

В форме списка мы не можем просто обратиться к переменной. Нам нужно узнать, на какой строке стоит курсор пользователя. Для этого мы должны использовать коллекцию Элементы.

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

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


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

Важно понимать: через ТекущиеДанные мы получаем структуру, содержащую значения колонок, отображаемых в списке. Это данные только для чтения (в контексте списка). Если вы напишете ТекДанные.Наименование = "Новое имя", это визуально может сработать до обновления списка, но в базе данных ничего не изменится, так как Динамический Список не предназначен для прямой записи.

Как изменить данные из формы списка

Так как список только "отображает" данные, чтобы внести изменения в конкретную строку (в объект базы данных), нам нужно выполнить следующую последовательность действий:

  1. Получить Ссылку на объект из текущей строки списка.
  2. Передать эту Ссылку на сервер (так как менять данные можно только на сервере).
  3. Получить из Ссылки программируемый Объект (ПолучитьОбъект()).
  4. Внести изменения и записать Объект.

Рассмотрим пример реализации команды, которая меняет наименование у выделенного в списке элемента:


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

&НаСервере
Процедура ИзменитьНаименованиеНаСервере(СсылкаНаОбъект, НовоеИмя)
    
    // Получаем объект для записи
    ОбъектБД = СсылкаНаОбъект.ПолучитьОбъект();
    
    // Блокируем объект от изменений другими пользователями
    ОбъектБД.Заблокировать();
    
    // Меняем данные
    ОбъектБД.Наименование = НовоеИмя;
    
    // Записываем в базу
    ОбъектБД.Записать();
    
КонецПроцедуры

Разбор терминов: ЭтаФорма, Элементы, ТекущаяСтрока

Автор вопроса также интересовался разницей между ключевыми понятиями. Давайте систематизируем их.

1. ЭтаФорма (ThisForm)

Это контекст текущего программного модуля формы. Через ЭтаФорма мы имеем доступ ко всем свойствам, методам, реквизитам и элементам данной формы. В управляемых формах (8.3) писать ЭтаФорма. часто избыточно. Например, вместо ЭтаФорма.Элементы можно писать просто Элементы. Однако использование ЭтаФорма полезно, когда нужно передать саму форму как параметр в другую процедуру.

2. Элементы (Items)

Это коллекция всех "визуальных кирпичиков" на экране. Кнопки, поля ввода, декорации, таблицы. Мы обращаемся к ним, когда хотим изменить внешний вид или поведение интерфейса. Например:

Важно не путать Элементы (интерфейс) и Реквизиты (данные). У Элемента нет значения данных, у него есть "ПутьКДанным".

3. ТекущаяСтрока (CurrentRow) vs ТекущиеДанные (CurrentData)

Здесь часто возникает путаница.

Резюме по решению проблемы

Проанализируем итоговый алгоритм действий для разработчика, который хочет работать с данными в форме:

  1. Определите тип формы. Если это Форма объекта, смело используйте реквизит Объект (Объект.Клиент, Объект.Сумма) для чтения и записи.
  2. Если это Форма списка, помните: список только для отображения.
  3. Чтобы прочитать значение из выделенной строки списка: используйте Элементы.ИмяВашегоСписка.ТекущиеДанные.ИмяКолонки.
  4. Чтобы записать значение в объект из формы списка: получите ссылку через ТекущиеДанные.Ссылка, перейдите на сервер, получите объект методом ПолучитьОбъект() и запишите его.

Понимание этой "таблично-объектной" модели, о которой упоминалось в обсуждении, является ключом к успешной разработке на платформе 1С.

← На главную