При переходе с обычных форм на управляемые многие разработчики сталкиваются с концептуальной трудностью. Пытаясь автоматизировать рутинные действия, они часто пытаются повторить интерактивный сценарий работы пользователя: программно открыть форму элемента, найти на ней нужную кнопку, сымитировать её нажатие и затем закрыть форму. Такой подход в корне неверен для платформы 1С:Предприятие 8.3.
В этой статье мы подробно разберем, почему попытка программного нажатия кнопок на форме является критической ошибкой, как устроен механизм заполнения реквизитов по ИНН в типовых конфигурациях и как правильно написать процедуру массового заполнения контрагентов без использования интерфейсных объектов.
Рассмотрим код, который часто пытаются использовать начинающие разработчики:
&НаКлиенте
Процедура ЗаполнитьПоИНН(Команда)
Для Каждого стр Из СП_Контрагенты Цикл
ПараметрыФормы = Новый Структура("Ключ", стр.Значение);
СпрФорма = ПолучитьФорму("Справочник.Контрагенты.Форма.ФормаЭлемента", ПараметрыФормы);
Кнопка = СпрФорма.Элементы.КнопкаЗаполнитьРеквизитыПоИНН;
СпрФорма.Открыть();
СпрФорма.ЗаполнитьРеквизитыПоИНН(Неопределено); // Попытка вызова процедуры кнопки
СпрФорма.Закрыть();
КонецЦикла;
КонецПроцедуры
Данный код неизбежно завершится ошибкой. Проанализируем ключевые причины, почему этот метод считается антипаттерном:
Открыть() управляемой формы выполняется асинхронно. Форма не инициализируется мгновенно в той же строке кода. Платформа отправляет команду клиенту на отрисовку интерфейса, но выполнение кода продолжается. Следующие строки (вызов процедуры заполнения и закрытие формы) выполняются до того, как форма реально будет создана и подготовлена к работе на клиенте.ЗаполнитьРеквизитыПоИНН) обычно компилируется без ключевого слова Экспорт. Она инкапсулирована внутри модуля конкретной формы и недоступна для вызова из внешних обработок или других форм.Важное правило разработки в 1С: Бизнес-логика (получение данных из внешних источников, заполнение реквизитов, запись объектов в базу данных) должна быть полностью отделена от интерфейса. Форма — это лишь средство визуализации данных для пользователя.
Разработчики Библиотеки стандартных подсистем (БСП) давно вынесли логику отправки запросов к веб-сервисам ФНС и разбора ответов в специализированные общие модули. Форма элемента справочника Контрагенты лишь обращается к этим модулям. Нам не нужно дублировать сложный код разбора XML или JSON.
В зависимости от версии БСП и возраста вашей конфигурации, функции получения данных по ИНН могут располагаться в разных общих модулях:
РаботаСКонтрагентами. Основные методы: РаботаСКонтрагентами.РеквизитыЮридическогоЛицаПоИНН() и РаботаСКонтрагентами.РеквизитыПредпринимателяПоИНН().ДанныеЕдиныхГосРеестров с аналогичными методами.СервисДанныхЕдиныхГосРеестров.Все эти методы принимают на вход строку с ИНН, отправляют запрос к серверам «1С:Контрагент» и возвращают готовую структуру со всеми заполненными реквизитами (краткое и полное наименование, КПП, ОГРН, юридический адрес, телефон, ФИО руководителя и т.д.). Наша задача — просто перенести эти значения в объект контрагента на сервере.
Для реализации задачи массового заполнения реквизитов по списку ИНН мы должны перенести всю обработку на сервер. Никакие формы открывать не нужно. Мы будем получать объекты контрагентов, вызывать методы БСП и записывать изменения напрямую в базу данных.
Рассмотрим подробный программный код серверной процедуры:
&НаСервере
Процедура ЗаполнитьКонтрагентовПоИНННаСервере()
Для Каждого СтрокаСписка Из СП_Контрагенты Цикл
СсылкаКонтрагента = СтрокаСписка.Значение;
// Получаем ИНН и очищаем его от случайных пробелов
ИНН = СокрЛП(СсылкаКонтрагента.ИНН);
Если ПустаяСтрока(ИНН) Тогда
Продолжить;
КонецЕсли;
// Получаем объект для редактирования реквизитов
КонтрагентОбъект = СсылкаКонтрагента.ПолучитьОбъект();
// Определяем юридический статус (Юр.лицо или ИП/Физ.лицо)
ЭтоЮридическоеЛицо = (КонтрагентОбъект.ЮрФизЛицо = Перечисления.ЮрФизЛицо.ЮрЛицо);
Данные = Неопределено;
Попытка
// Используем актуальные методы БСП для получения структуры данных
Если ЭтоЮридическоеЛицо Тогда
Данные = РаботаСКонтрагентами.РеквизитыЮридическогоЛицаПоИНН(ИНН);
Иначе
Данные = РаботаСКонтрагентами.РеквизитыПредпринимателяПоИНН(ИНН);
КонецЕсли;
Исключение
// Обрабатываем возможные сетевые сбои или отсутствие лицензии
ЗаписьЖурналаРегистрации(
"ЗаполнениеПоИНН",
УровеньЖурналаРегистрации.Ошибка,
,,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())
);
Продолжить;
КонецПопытки;
// Если сервис успешно вернул структуру с данными, переносим их в объект
Если Данные <> Неопределено Тогда
// Заполняем наименования
КонтрагентОбъект.Наименование = Данные.НаименованиеСокращенное;
КонтрагентОбъект.НаименованиеПолное = Данные.НаименованиеПолное;
// Заполняем специфические реквизиты в зависимости от типа лица
Если ЭтоЮридическоеЛицо Тогда
КонтрагентОбъект.КПП = Данные.КПП;
КонтрагентОбъект.ОГРН = Данные.ОГРН;
Иначе
КонтрагентОбъект.ОГРНИП = Данные.ОГРН;
КонецЕсли;
// Записываем измененный объект контрагента в базу данных
Попытка
КонтрагентОбъект.Записать();
Исключение
ВызватьИсключение "Не удалось записать контрагента с ИНН " + ИНН;
КонецПопытки;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
При использовании программного серверного заполнения существует несколько важных технологических аспектов, которые необходимо учесть заранее:
usr1cv8) имеет доступ к интернету и не блокируется брандмауэром или прокси-сервером организации.HTTPСоединение с последующим разбором JSON/XML ответа.КонтактнаяИнформация (или в одноименном регистре сведений). Чтобы корректно записать адрес в формате ФИАС/КЛАДР, используйте стандартные программные интерфейсы БСП. Например, методы общего модуля УправлениеКонтактнойИнформацией, которые преобразуют текстовый адрес в структурированный вид.Для расширения кругозора разберем вопрос автора темы: «Как на будущее программно обработать кнопку с формы?». Если перед вами действительно стоит задача, требующая обращения к логике открытой формы, это можно сделать двумя корректными способами:
Способ 1: Использование экспортного метода формы.
В модуле формы, логику которой вы хотите вызвать, процедура должна быть объявлена как клиентская и иметь ключевое слово Экспорт:
// В модуле управляемой формы элемента справочника Контрагенты
&НаКлиенте
Процедура ЗаполнитьРеквизитыПоИННЭкспорт() Экспорт
// Здесь размещается логика заполнения
КонецПроцедуры
В таком случае из внешней обработки вы сможете обратиться к форме следующим образом:
ПараметрыФормы = Новый Структура("Ключ", СсылкаНаКонтрагента);
СпрФорма = ПолучитьФорму("Справочник.Контрагенты.Форма.ФормаЭлемента", ПараметрыФормы);
СпрФорма.Открыть();
// Теперь метод доступен, так как он объявлен как Экспорт
СпрФорма.ЗаполнитьРеквизитыПоИННЭкспорт();
СпрФорма.Закрыть();
Способ 2: Передача параметров при открытии формы.
Самым изящным способом управления поведением формы при открытии является передача специальных параметров. Вместо того чтобы вызывать методы формы снаружи, мы передаем в форму флаг, сигнализирующий о необходимости выполнить заполнение:
// В коде внешней обработки
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("Ключ", СсылкаНаКонтрагента);
ПараметрыФормы.Вставить("АвтозаполнениеПоИННПриОткрытии", Истина;
ОткрытьФорму("Справочник.Контрагенты.Форма.ФормаЭлемента", ПараметрыФормы);
В самой форме контрагента в обработчике ПриОткрытии (или ПриСозданииНаСервере) мы анализируем переданные параметры:
// В модуле управляемой формы Контрагента
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Если Параметры.Свойство("АвтозаполнениеПоИННПриОткрытии") И Параметры.АвтозаполнениеПоИННПриОткрытии Тогда
ВыполнитьЗаполнениеПоИНН(); // Внутренняя процедура заполнения
КонецЕсли;
КонецПроцедуры
Подводя итог, помните: программная эмуляция интерактивных действий пользователя на клиенте — это крайняя мера, применимая лишь при тестировании интерфейса. Любые учетные и расчетные операции, включая автозаполнение реквизитов, должны производиться непосредственно на сервере через объектную модель 1С и механизмы общих модулей конфигурации.