Разработка и Конфигурация · 12 мин
Как получить данные из формы 1С 8
Как получить данные из формы 1С 8: ЭтаФорма, реквизиты формы, ДанныеФормыВЗначение, работа с табличными частями и передача данных между формами.
Получение данных из формы — одна из базовых задач при доработке конфигураций 1С:Предприятие 8.3. В управляемых формах данные отделены от интерфейса: пользователь видит элементы формы, а значения хранятся в реквизитах формы, которые нужно читать программно. Попытка обратиться к полю ввода напрямую, как к источнику данных, — самая частая ошибка начинающих разработчиков.
Способ получения данных зависит от контекста: код выполняется на клиенте или на сервере, форма относится к объекту (документу, справочнику) или является произвольной, данные нужны внутри самой формы или из другой формы. Для каждого случая платформа предлагает свой механизм: обращение через ЭтаФорма, чтение реквизитов, преобразование ДанныеФормыВЗначение, параметры формы и оповещения.
Ниже разобраны рабочие приёмы с примерами кода на встроенном языке 1С, ограничения тонкого клиента и типичные ошибки, которые приводят к падению кода или получению устаревших значений.
Где хранятся данные формы и почему нельзя читать элементы напрямую
В управляемой форме есть три разных сущности, которые часто путают. Реквизиты формы — это сами данные (объект документа, строки, таблицы значений). Элементы формы — визуальные контролы: поля ввода, таблицы, кнопки. У элемента есть свойство ПутьКДанным, которое связывает его с реквизитом. Читать значение нужно именно из реквизита, а не из элемента.
Обращение к данным внутри модуля формы выполняется через свойство ЭтаФорма. Если реквизит называется «Комментарий», значение получают так: Текст = ЭтаФорма.Комментарий;. Для форм объектов (документов, справочников) основной реквизит обычно называется «Объект», и его поля доступны как Объект.Номер, Объект.Контрагент и так далее.
Важно понимать, что на клиенте данные формы существуют в виде специальных объектов (ДанныеФормыСтруктура, ДанныеФормыКоллекция), а не как прикладные объекты. Поэтому методы вроде Объект.ПолучитьОбъект() на клиенте недоступны — для полноценной работы с объектом нужен серверный вызов.
Как получить значения реквизитов и полей объекта
Простейший сценарий — прочитать значение, которое пользователь ввёл в поле формы. Если поле связано с реквизитом объекта, код выглядит так:
&НаКлиенте
Процедура ПоказатьДанные(Команда)
Контрагент = Объект.Контрагент;
Комментарий = ЭтаФорма.Комментарий;
Сообщить("Контрагент: " + Контрагент + ", комментарий: " + Комментарий);
КонецПроцедуры
Если нужно проверить, заполнено ли значение, используйте функцию ЗначениеЗаполнено() — она корректно обрабатывает пустые ссылки, пустые строки, нулевые даты и неопределено. Прямое сравнение с пустой строкой для ссылочных полей не сработает: пустая ссылка — это не пустая строка.
&НаКлиенте
Процедура ПроверитьЗаполнение(Команда)
Если НЕ ЗначениеЗаполнено(Объект.Контрагент) Тогда
Сообщить("Поле Контрагент не заполнено");
Возврат;
КонецЕсли;
Сообщить("Выбран: " + Объект.Контрагент);
КонецПроцедурыДля чтения нескольких полей объекта удобнее перенести логику на сервер, чтобы не гонять данные между клиентом и сервером по одному реквизиту. Особенно это критично, когда по ссылке нужно получить реквизиты связанного объекта, например ИНН контрагента.
Как получить данные табличной части формы
Табличная часть объекта на клиенте представлена коллекцией ДанныеФормыКоллекция. Обойти её можно циклом, обращаясь к строкам по индексу или через «Для Каждого». Текущую (выделенную) строку таблицы получают через элемент формы: Элементы.Товары.ТекущиеДанные.
&НаКлиенте
Процедура ПосчитатьИтог(Команда)
ИтогоСумма = 0;
Для Каждого Строка Из Объект.Товары Цикл
ИтогоСумма = ИтогоСумма + Строка.Сумма;
КонецЦикла;
Сообщить("Итого по документу: " + ИтогоСумма);
КонецПроцедуры
Обратите внимание на разницу: Элементы.Товары.ТекущаяСтрока возвращает идентификатор строки (число), а не данные. Чтобы получить сами данные по идентификатору, используйте Объект.Товары.НайтиПоИдентификатору(Идентификатор). Путаница между идентификатором строки и её индексом — частый источник ошибок «Значение не является значением объектного типа».
Как преобразовать данные формы в объект на сервере
Когда данных формы недостаточно и нужен полноценный прикладной объект — например, чтобы вызвать его методы, записать или проверить заполнение штатными средствами — используют пару методов РеквизитФормыВЗначение и ЗначениеВРеквизитФормы. Оба доступны только в серверном контексте.
&НаСервере
Процедура ЗаписатьСПроверкойНаСервере()
ДокументОбъект = РеквизитФормыВЗначение("Объект");
Если НЕ ДокументОбъект.ПроверитьЗаполнение() Тогда
Возврат;
КонецЕсли;
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
ЗначениеВРеквизитФормы(ДокументОбъект, "Объект");
КонецПроцедуры
После изменения объекта обязательно верните его обратно в форму через ЗначениеВРеквизитФормы, иначе пользователь увидит старые данные, а при следующем сохранении ваши изменения будут затёрты. Это несоответствие — частая причина жалоб «код отработал, но в базе ничего не изменилось».
Если нужны только реквизиты ссылки (например, наименование и ИНН контрагента), не обязательно преобразовывать всю форму. Дешевле выполнить запрос или обратиться к реквизитам через точку в серверной процедуре: ИНН = Объект.Контрагент.ИНН; — на сервере это работает, хотя и порождает неявный запрос к базе.
Как получить данные из другой формы
Чтение данных из чужой открытой формы напрямую считается плохой практикой: формы не обязаны знать устройство друг друга. Платформа предлагает три штатных механизма обмена: параметры открытия, оповещения о выборе и обработка оповещений.
Передача данных при открытии формы
При открытии формы передайте структуру параметров. В открываемой форме они доступны в обработчике ПриСозданииНаСервере через Параметры.ИмяПараметра:
&НаКлиенте
Процедура ОткрытьПодбор(Команда)
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("Контрагент", Объект.Контрагент);
ОткрытьФорму("Справочник.Номенклатура.Форма.ФормаПодбора",
ПараметрыФормы, ЭтаФорма);
КонецПроцедуры
Получение результата выбора обратно
Форма подбора возвращает результат через ОповеститьОВыборе(Результат) или Закрыть(Результат). В вызывающей форме результат приходит в обработчик ОбработкаВыбора либо в описание оповещения, переданное в ОткрытьФорму:
&НаКлиенте
Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора)
Если ТипЗнч(ВыбранноеЗначение) = Тип("Структура")
И ВыбранноеЗначение.Свойство("Номенклатура") Тогда
НоваяСтрока = Объект.Товары.Добавить();
НоваяСтрока.Номенклатура = ВыбранноеЗначение.Номенклатура;
КонецЕсли;
КонецПроцедуры
- 1В вызывающей форме сформируйте структуру параметров и передайте её в ОткрытьФорму
- 2В открываемой форме прочитайте параметры в ПриСозданииНаСервере через Параметры.ИмяПараметра
- 3По завершении работы вызовите ОповеститьОВыборе или Закрыть с результатом
- 4В вызывающей форме обработайте результат в ОбработкаВыбора или через ОписаниеОповещения
- 5Проверьте тип и наличие ключей в полученном значении перед использованием
Получение данных в обычных формах и внешних обработках
В обычных формах (режим совместимости, старые конфигурации) механика проще: элементы формы имеют свойство Значение, и читать данные можно прямо из поля ввода. Однако основной способ — тот же: реквизиты объекта доступны напрямую, без ЭтаФорма, например Контрагент в модуле формы документа.
Во внешних обработках с управляемой формой действуют те же правила, что и в формах конфигурации: данные — в реквизитах формы, объект обработки на сервере получают через РеквизитФормыВЗначение("Объект"). Если обработка открывается в тонком клиенте, вся работа с запросами и объектами должна выполняться в серверных процедурах.
Способы получения данных из формы
Основной способ на клиенте. Подходит для чтения введённых значений, не требует серверного вызова
Серверный метод для получения полноценного объекта. Нужен для вызова методов объекта и записи, но создаёт копию данных
Штатный обмен между формами. Единственный безопасный способ получить данные из другой формы
Получение выделенной строки табличной части. Работает только для таблиц, у которых есть текущая строка
Как проверить результат и избежать типовых сбоев
После получения данных проверяйте три вещи: тип значения, заполненность и актуальность. Тип проверяют через ТипЗнч(), заполненность — через ЗначениеЗаполнено(), актуальность — сравнением с тем, что видит пользователь: если объект был изменён на сервере, форму нужно перечитать методом Прочитать() или обновить данные вручную.
При отладке используйте Сообщить() или точку останова в конфигураторе, чтобы увидеть реальное содержимое реквизитов. Если код падает с ошибкой «Поле объекта не обнаружено», почти всегда причина в опечатке в имени реквизита или в обращении к реквизиту, которого нет у данного типа формы.
Как проверить результат
Тип и содержимое соответствуют ожиданиям, ссылка заполнена
Неопределено или значение другого типа — проверьте имя реквизита и ПутьКДанным элемента
Форма отображает обновлённые значения после ЗначениеВРеквизитФормы или Прочитать
В форме старые данные — забыто обратное преобразование
ОбработкаВыбора срабатывает, структура содержит нужные ключи
Обработчик не вызывается — проверьте владельца формы и вызов ОповеститьОВыборе
Часто задаваемые вопросы
Как получить значение поля ввода, если у него нет связанного реквизита?
В управляемой форме поле ввода без пути к данным невозможно — элемент всегда связан с реквизитом формы. Если реквизита нет, добавьте его через палитру реквизитов формы в конфигураторе и укажите его в свойстве ПутьКДанным элемента. После этого читайте значение через ЭтаФорма.ИмяРеквизита.
Почему на клиенте недоступен метод ДанныеФормыВЗначение?
Преобразование данных формы в прикладной объект требует серверного контекста, где доступна объектная модель. На клиенте существуют только облегчённые представления данных. Вынесите код в процедуру с директивой &НаСервере и вызывайте её из клиентской.
Как получить данные строки табличной части по двойному щелчку?
В обработчике события таблицы Выбор или Нажатие используйте Элементы.ИмяТаблицы.ТекущиеДанные — это объект ДанныеФормыЭлементКоллекции со всеми полями строки. Свойство ТекущаяСтрока вернёт только идентификатор, а не данные.
Можно ли прочитать данные формы, не открывая её?
Нет, и это не нужно: данные хранятся в базе, а форма лишь отображает их. Чтобы получить данные документа или справочника без формы, используйте запрос или объектную модель: Справочники.Номенклатура.НайтиПоКоду(), Документы.Реализация.ПолучитьСсылку() и чтение реквизитов через точку на сервере.
Чем отличается ЭтаФорма.Объект от РеквизитФормыВЗначение("Объект")?
ЭтаФорма.Объект — это данные формы (ДанныеФормыСтруктура), доступные и на клиенте, но без методов прикладного объекта. РеквизитФормыВЗначение возвращает настоящий объект (ДокументОбъект и т.п.) только на сервере, с которым можно работать полноценно: вызывать Записать, ПроверитьЗаполнение, обработчики событий.
Как передать таблицу значений из одной формы в другую?
Напрямую таблицу значений через параметры формы передать нельзя — параметры сериализуются. Поместите таблицу во временное хранилище на сервере (ПоместитьВоВременноеХранилище), передайте адрес хранилища параметром, а в открываемой форме извлеките данные через ПолучитьИзВременногоХранилища в ПриСозданииНаСервере.
Что важно запомнить
Данные формы 1С 8 живут в реквизитах, а не в элементах: читайте их через ЭтаФорма и Объект. Для серверной обработки используйте РеквизитФормыВЗначение с обязательным возвратом через ЗначениеВРеквизитФормы. Между формами данные передавайте параметрами и оповещениями, а результат всегда проверяйте на тип и заполненность.