Работа с формами в 1С:Предприятие 8.3 — одна из самых частых задач для разработчиков и администраторов системы. Некорректное обращение к полям может привести к ошибкам выполнения, потере данных или неожиданному поведению интерфейса. Эта статья поможет разобраться, как правильно получать и изменять значения полей на управляемых и обычных формах, используя встроенный язык .

Мы рассмотрим пять основных способов доступа к элементам формы: через ЭлементыФормы, метод ПолучитьФорму(), работу с реквизитами формы, динамическое обращение по имени и использование конструктора запросов. Особое внимание уделим типичным ошибкам, которые допускают начинающие программисты, и покажем, как их избежать.

Все примеры кода в статье актуальны для последних версий платформы 1С:Предприятие 8.3 (включая 8.3.23). Если вы работаете со старыми релизами (ниже 8.3.10), некоторые методы могут требовать адаптации — это отмечено в соответствующих разделах.

📊 Какой тип форм вы чаще используете в 1С?
Управляемые формы
Обычные формы
Оба типа примерно одинаково
Не работаю с формами

1. Базовые понятия: реквизиты vs элементы формы

Прежде чем переходить к практике, важно понять разницу между двумя ключевыми сущностями:

  • 📌 Реквизиты формы — это данные, которые хранятся в памяти формы. Они могут быть привязаны к полям ввода, но не обязательно. Например, реквизит ДатаДокумента может существовать независимо от того, отображается ли он на экране.
  • 🖥️ Элементы формы — визуальные компоненты интерфейса (поля ввода, кнопки, таблицы). Они могут быть привязаны к реквизитам или работать автономно.

В управляемых формах (начиная с версии 8.2) элементы автоматически привязываются к реквизитам через свойство ПутьКДанным. В обычных формах (устаревший формат) связь настраивается вручную через свойство Данные.

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

  • Реквизит формы — это переменная ДатаДокумента (тип Дата), которая хранит значение.
  • Элемент формы — это объект ПолеВводаДатаДокумента (тип ПолеВвода), который отображает и позволяет редактировать это значение.
⚠️ Внимание: В управляемых формах нельзя напрямую изменять значение реквизита через элемент формы, если он не привязан к данным. Например, код ЭлементыФормы.ПолеВвода1.Значение = 100 не изменит значение реквизита, если у поля не настроен ПутьКДанным.

2. Способ 1: Обращение через коллекцию ЭлементыФормы

Самый распространённый способ — использование коллекции ЭлементыФормы, которая доступна в контексте любой формы. Этот метод работает и для управляемых, и для обычных форм, но имеет нюансы.

Синтаксис:

ЭлементыФормы.<ИмяЭлемента>.<Свойство>

Примеры:

  • 📝 Получить значение поля ввода:
    ТекущаяДата = ЭлементыФормы.ПолеВводаДата.Значение;
  • 🔄 Изменить текст надписи:
    ЭлементыФормы.НадписьЗаголовок.Заголовок = "Новый текст";
  • 🎨 Изменить цвет фона поля:
    ЭлементыФормы.ПолеВводаСумма.ЦветФона = ВебЦвета.Красный;

Особенности метода:

  • ✅ Работает во всех версиях 1С, включая 8.1.
  • ⚠️ В управляемых формах изменение значения через ЭлементыФормы не всегда синхронизируется с реквизитом (нужно использовать Значение реквизита напрямую).
  • 🚫 Не работает для динамически созданных элементов (нужно использовать ЭлементыФормы.Получить()).

☑️ Проверка перед использованием ЭлементыФормы

Выполнено: 0 / 4

3. Способ 2: Работа с реквизитами формы напрямую

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

Синтаксис:

ЗначениеРеквизита = Объект.<ИмяРеквизита>;

Примеры:

Действие Код для управляемой формы Код для обычной формы
Получить значение ДатаДок = Объект.Дата; ДатаДок = ЭлементыФормы.ПолеВводаДата.Значение;
Изменить значение Объект.Сумма = 1000; ЭлементыФормы.ПолеВводаСумма.Значение = 1000;
Проверить заполненность Если НЕ ЗначениеЗаполнено(Объект.Контрагент) Тогда... Если ЭлементыФормы.ПолеВводаКонтрагент.Значение = "" Тогда...

Критическое отличие: В управляемых формах изменение реквизита автоматически обновляет связанный элемент интерфейса, а в обычных формах нужно вручную синхронизировать данные через метод Обновить().

Пример полного цикла работы с реквизитом:

// 1. Получить значение

ТекущаяСумма = Объект.СуммаДокумента;

// 2. Изменить значение с проверкой

Если ТекущаяСумма < 0 Тогда

Объект.СуммаДокумента = 0;

Сообщить("Сумма не может быть отрицательной!");

КонецЕсли;

// 3. Вызвать обработчик изменения (если нужно)

Объект.ПриИзмененииСуммы();

⚠️ Внимание: При работе с реквизитами-коллекциями (например, табличные части) изменение элементов массива не всегда триггерит событие ПриИзменении. В таких случаях нужно явно вызывать Объект.УстановитьИзменение().

4. Способ 3: Динамическое обращение по имени элемента

Если имя элемента формы формируется динамически (например, в циклах или при работе с шаблонами), можно использовать метод Получить() коллекции ЭлементыФормы.

Синтаксис:

Элемент = ЭлементыФормы.Получить(<ИмяЭлемента>);

Примеры:

  • 🔍 Поиск элемента по шаблону:
    Для Сч = 1 По 10 Цикл
    

    ИмяЭлемента = "ПолеВводаСтрока" + Формат(Сч, "ЧГ=0");

    Поле = ЭлементыФормы.Получить(ИмяЭлемента);

    Если Поле <> Неопределено Тогда

    Поле.ЦветФона = ВебЦвета.Желтый;

    КонецЕсли;

    КонецЦикла;

  • 🛠️ Проверка существования элемента перед обращением:
    Если ЭлементыФормы.Получить("КнопкаСохранить") <> Неопределено Тогда
    

    ЭлементыФормы.КнопкаСохранить.Доступность = Ложь;

    КонецЕсли;

Преимущества метода:

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

Возврат ЭлементыФормы.Получить(ИмяЭлемента);

КонецФункции

Это упростит код и уменьшит риск ошибок.-->

5. Способ 4: Использование метода ПолучитьФорму()

Для доступа к форме из внешнего кода (например, из модуля объекта или глобального модуля) используется метод ПолучитьФорму(). Он возвращает объект формы, через который можно работать с элементами и реквизитами.

Синтаксис:

ФормаОбъекта = Объект.ПолучитьФорму();

Элемент = ФормаОбъекта.ЭлементыФормы.<ИмяЭлемента>;

Пример полного сценария:

// 1. Получить форму документа

ФормаДокумента = Документы.ЗаказПокупателя.НайтиПоНомеру("000000001").ПолучитьФорму();

// 2. Изменить значение поля

ФормаДокумента.Объект.Дата = ТекущаяДата();

// 3. Обновить элемент интерфейса (если нужно)

ФормаДокумента.ЭлементыФормы.ПолеВводаДата.Обновить();

// 4. Закрыть форму с сохранением

ФормаДокумента.Закрыть(Истина);

Важные нюансы:

  • 🔧 Метод работает только для открытых форм. Если форма не открыта, вернёт Неопределено.
  • 🔄 Для управляемых форм после изменения реквизитов нужно явно вызывать Обновить() у элементов, чтобы интерфейс отреагировал на изменения.
  • 🚫 Нельзя использовать этот метод в тонком клиенте для форм, открытых на сервере.
⚠️ Внимание: При работе с формами в веб-клиенте метод ПолучитьФорму() может возвращать неполный объект из-за ограничений безопасности. В таких случаях используйте серверные вызовы через НаСервере.
💡

Метод ПолучитьФорму() — единственный официальный способ доступа к форме из внешнего кода. Альтернативы вроде глобального поиска по идентификатору (НайтиФормуПоИдентификатору()) не dokumentированы и могут перестать работать в новых версиях платформы.

6. Способ 5: Обращение через конструктор запросов

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

Пример: получение данных из формы документа в запросе:

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| ЗаказПокупателя.Ссылка КАК Ссылка,

| ЗаказПокупателя.Дата КАК Дата,

| ЗаказПокупателя.СуммаДокумента КАК Сумма

|ИЗ

| Документ.ЗаказПокупателя КАК ЗаказПокупателя

|ГДЕ

| ЗаказПокупателя.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", Объект.Ссылка);

Результат = Запрос.Выполнить();

Ограничения метода:

  • 📊 Подходит только для чтения данных, но не для их изменения.
  • 🔗 Требует явной привязки к объекту базы данных (не работает с временными данными формы).
  • ⚠️ Может возвращать устаревшие данные, если форма не сохранена.

Альтернатива для управляемых форм — использование временных таблиц:

// 1. Создать временную таблицу

ТаблицаДанных = Новый ТаблицаЗначений;

ТаблицаДанных.Колонки.Добавить("Поле");

ТаблицаДанных.Колонки.Добавить("Значение");

// 2. Заполнить данными из формы

Для Каждого Реквизит Из Объект.Метаданные().Реквизиты Цикл

НоваяСтрока = ТаблицаДанных.Добавить();

НоваяСтрока.Поле = Реквизит.Имя;

НоваяСтрока.Значение = Объект[Реквизит.Имя];

КонецЦикла;

7. Типичные ошибки и как их избежать

Даже опытные разработчики иногда допускают ошибки при работе с полями формы. Вот самые распространённые из них:

Ошибка Причина Как исправить
Ошибка при получении свойства: Значение Попытка получить значение у элемента, который не привязан к данным (например, Надпись или Кнопка). Проверять тип элемента через ТипЗнч() или использовать только поля ввода.
Изменение значения не отображается на форме В управляемых формах изменён реквизит, но не вызван метод Обновить() для элемента. Явно обновлять элемент: ЭлементыФормы.ПолеВвода.Обновить().
Поле не найдено: ИмяЭлемента Опечатка в имени элемента или обращение к динамически созданному элементу без проверки. Использовать ЭлементыФормы.Получить() с проверкой на Неопределено.
Циклическая зависимость при изменении значений В обработчике ПриИзменении меняется тот же реквизит, что вызвал событие. Использовать флаг блокировки или переносить логику в ПередЗаписью.

Советы для отладки:

  • 🐞 Используйте Сообщить(ТипЗнч(ЭлементыФормы.ПолеВвода)), чтобы убедиться, что работаете с правильным типом элемента.
  • 🔍 Для анализа структуры формы выведите все элементы в отладочное сообщение:
    Для Каждого Элемент Из ЭлементыФормы Цикл
    

    Сообщить(Элемент.Имя + " | " + ТипЗнч(Элемент));

    КонецЦикла;

  • 📋 В управляемых формах проверяйте привязку элементов через ПутьКДанным:
    Сообщить(ЭлементыФормы.ПолеВвода.ПутьКДанным); // Должен вернуть путь к реквизиту
Что делать, если поле не обновляется?

Если после изменения реквизита поле на форме не обновляется, проверьте:

1. Привязку элемента к данным (свойство ПутьКДанным).

2. Наличие обработчика ПриИзменении, который может блокировать обновление.

3. Вызов метода Обновить() для элемента.

4. Режим отображения формы (в модальном окне обновление может работать иначе).

8. Практические примеры для разных сценариев

Разберём несколько реальных задач, с которыми сталкиваются разработчики.

Задача 1: Изменить цвет фона поля ввода, если сумма документа превышает 100 000.

Процедура ПриИзмененииСуммы(Элемент)

Если Объект.СуммаДокумента > 100000 Тогда

ЭлементыФормы.ПолеВводаСумма.ЦветФона = ВебЦвета.Красный;

Иначе

ЭлементыФормы.ПолеВводаСумма.ЦветФона = ВебЦвета.Белый;

КонецЕсли;

КонецПроцедуры

Задача 2: Динамически скрыть поля в зависимости от типа документа.

Процедура ПриОткрытии()

Если Объект.ВидДокумента = ВидДокумента.Возврат Тогда

ЭлементыФормы.ПолеВводаКонтрагент.Видимость = Ложь;

ЭлементыФормы.ПолеВводаДоговор.Видимость = Ложь;

КонецЕсли;

КонецПроцедуры

Задача 3: Массовое заполнение полей из справочника.

Процедура ЗаполнитьДанныеКонтрагента(Контрагент)

Объект.Контрагент = Контрагент;

Объект.ИНН = Контрагент.ИНН;

Объект.Адрес = Контрагент.Адрес;

Объект.Телефон = Контрагент.Телефон;

// Обновить элементы формы

ЭлементыФормы.ПолеВводаИНН.Обновить();

ЭлементыФормы.ПолеВводаАдрес.Обновить();

КонецПроцедуры

Задача 4: Проверка заполненности обязательных полей перед сохранением.

Функция ПроверитьЗаполненность()

Если НЕ ЗначениеЗаполнено(Объект.Контрагент) Тогда

Сообщить("Не заполнен контрагент!", СтатусСообщения.Важное);

Возврат Ложь;

КонецЕсли;

Если Объект.СуммаДокумента <= 0 Тогда

Сообщить("Сумма должна быть больше 0!", СтатусСообщения.Важное);

Возврат Ложь;

КонецЕсли;

Возврат Истина;

КонецФункции

💡

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

❓ Как обратиться к полю табличной части на форме?

Для работы с полями табличной части используйте путь к данным через точку. Например, чтобы получить значение ячейки в строке таблицы:

// Получить значение поля "Количество" в текущей строке табличной части "Товары"

ТекущееКоличество = Объект.Товары[ИндексСтроки].Количество;

// Изменить значение

Объект.Товары[ИндексСтроки].Цена = НоваяЦена;

Для доступа к элементу интерфейса (например, чтобы изменить цвет ячейки) используйте:

ЭлементТаблицы = ЭлементыФормы.ТаблицаТовары.ПолучитьЭлемент(ИндексСтроки, "Количество");

ЭлементТаблицы.ЦветФона = ВебЦвета.Желтый;

❓ Можно ли обратиться к полю формы из другого клиента (например, из тонкого клиента к толстому)?

Нет, напрямую это невозможно из-за архитектуры 1С:Предприятие. Формы существуют в контексте сеанса пользователя. Для обмена данными между клиентами используйте:

  • 📤 Серверные функции с параметрами (через НаСервере или НаКлиентеНаСервереБезКонтекста).
  • 🗃️ Общие реквизиты (например, в справочниках или регистрах).
  • 📡 Механизм обмена данными (для распределённых баз).

Пример серверной функции:

// На сервере

Процедура ПолучитьДанныеФормы(Знач Параметр) Экспорт

Возврат Объект.НайтиПоПараметру(Параметр).ПолучитьДанные();

КонецПроцедуры

// На клиенте

Данные = Сервер.ПолучитьДанныеФормы("123");

❓ Как узнать, какое поле формы сейчас в фокусе?

В управляемых формах для этого используется свойство ТекущийЭлемент:

ТекущийЭлемент = ЭлементыФормы.ТекущийЭлемент;

Если ТекущийЭлемент <> Неопределено Тогда

Сообщить("В фокусе: " + ТекущийЭлемент.Имя);

КонецЕсли;

Для отслеживания изменений фокуса используйте событие ПриАктивизацииЭлемента:

Процедура ПриАктивизацииЭлемента(Элемент)

Если Элемент.Имя = "ПолеВводаСумма" Тогда

Сообщить("Активировано поле суммы!");

КонецЕсли;

КонецПроцедуры

❓ Почему при изменении реквизита не срабатывает событие ПриИзменении?

Это типичная проблема управляемых форм. Событие ПриИзменении срабатывает только при:

  • 🖱️ Изменении значения пользователем через интерфейс.
  • 📝 Программном изменении реквизита с вызовом метода УстановитьИзменение().

Решение:

Объект.Сумма = 1000;

Объект.УстановитьИзменение("Сумма"); // Явно уведомить форму об изменении

Или вызов обработчика вручную:

Объект.Сумма = 1000;

ПриИзмененииСуммы(ЭлементыФормы.ПолеВводаСумма);

❓ Как обратиться к полю формы из внешней обработки?

Из внешней обработки можно получить доступ к форме текущего документа через:

  1. 🔗 Параметры формы: передать форму как параметр при открытии обработки.
  2. 🔍 Глобальный поиск: использовать недокументированный метод НайтиФормуПоИдентификатору() (не рекомендуется для продуктивных систем).
  3. 📋 Работа с данными: изменять реквизиты объекта, а не элементы формы.

Пример передачи формы как параметра:

// В модуле формы документа

Процедура ОткрытьОбработку(Команда)

Обработка = ОткрытьФорму("Обработка.МояОбработка");

Обработка.УстановитьПараметр("ФормаДокумента", ЭтаФорма);

КонецПроцедуры

// В модуле обработки

ФормаДокумента = Параметры.ФормаДокумента;

ФормаДокумента.Объект.Комментарий = "Изменено из обработки";