Обработка расширением на клиенте

31.10.19

Разработка - Универсальные функции

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

Данный прием помогает в таких ситуациях, когда нужные алгоритмы по обработке единичного объекта уже написаны в его форме разработчиком конфигурации (обработка заполнения при изменении реквизита, заполнение по отдельной кнопке на форме и т.д.) и они достаточно сложные, чтобы тратить время на их разработку и тестирование вне контекста формы.
Несмотря на кажущуюся сложность приема, он сильно экономит время в таких ситуациях.
При наработке этого подхода второй и третий раз сложные вещи можно сделать достаточно быстро.
Разумеется, если основной код уже написан, но не доступен иначе как в форме какого-то объекта.

 

Кейсы: 

  1. загрузили через XML из старой системы в ERP контрагентов, хотим массово заполнить по ИНН,
  2. хотим массово по профилям заполнить группы доступа,
  3. загрузили через XML из старой системы в ERP пользователей, хотим массово создать пользователей ИБ, что бы при этом им были предоставлены доступы согласно настройкам профилей и групп доступа
  4. и так далее

Общий принцип работы

Две формы: списка и объекта, из формы списка вызывается форма объекта, по возвращении в форму списка (после закрытия формы объекта) вызывается форма следующего объекта и так далее. Пр этом на форму объекта передается параметр для обработки. На форме объекта этот параметр при создании на сервере передается в реквизит формы, после открытия через обработчик ожидания выполняется собственно необходимая обработка, она же обращается к процедурам и функциям формы, после заполнения она записывается и закрывается.
Пользователь при выполнении видит, как открываются и закрываются формы. 

На примере кейса "ЗаполнениеПоИНН":
методы, без которых ничего не получится, написаны в форме элемента справочника "Контрагенты", писать их отдельно в своей обработке совсем не хочется, но хочется обратиться к ним. Если бы это была экспортная процедура либо функция из общего модуля, модуля менеджера или хотя бы из модуля какого-то объекта, то проблемы нет: взяли и вызвали этот метод в своей групповой обработке. Но если нужный метод написан в форме объекта, то добраться до него без открытия формы не получится.
Надо соответственно открывать каждую форму и там обращаться к этим методам, а потом записывать и закрывать.
Ниже изложено как это можно реализовать своими руками. 

Разработка по шагам 

Шаг 1: Создание расширения

Создадим отдельное расширение, назовем "Временные доработки", префикс "ВД_".
Лучше отдельное, потому что расширения клиента и менеджер данных (если он у Вас есть) не должны содержать в себе этот сугубо одноразовый функционал, при необходимости после обработки данных или после окончания проекта внедрения это можно за собой удалить. Кроме того созданный инструмент может пригодиться потом где-нибудь еще.
Лично я такие временные обработки "коллекционирую" в одном расширении "временные доработки", но не факт, что это правильный подход.

Шаг 2: Заимствование

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

Шаг 3: Доработка формы списка

Добавляем команду "ГрупповоеЗаполнение" (или как нравится из контекста задачи, в моем примере "ЗаполнитьПоИНН_Списком"). Команду выводим на командную панель.

У команды клиентский обработчик после (без вызова сервера)

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

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

Основной рабочий метод в форме списка "ВД_ОткрытьЗаполнить" (или как в этом примере "ВД_ЗаполнитьПоИНН_Открыть") выполняется так же на клиенте, экспортный.

&НаКлиенте
Процедура ВД_ЗаполнитьПоИНН_Открыть(Результат, СтарыйМассивПройти) Экспорт
	Если ТипЗнч(Результат) = Тип("Структура") Тогда
		Сообщение = Новый СообщениеПользователю;
		ЗаполнитьЗначенияСвойств(Сообщение, Результат);
		Сообщение.Сообщить();
	КонецЕсли;
	МассивПройти = Новый Массив;
	ПервыйЕсть = ЛОЖЬ;
	Первый = Неопределено;
	Для Каждого ВыделеннаяСтрока Из СтарыйМассивПройти Цикл
		Если ПервыйЕсть Тогда
			МассивПройти.Добавить(ВыделеннаяСтрока);
		Иначе
			Первый = ВыделеннаяСтрока;
			ПервыйЕсть = Истина;
		КонецЕсли;
	КонецЦикла;
	Если НЕ Первый = Неопределено Тогда
		ПараметрыОткрытия = Новый Структура("Ключ, ВД_ЗаполнитьПоИНН", Первый, Истина);
		ОписаниеОповещения = Новый ОписаниеОповещения(
			"ВД_ЗаполнитьПоИНН_Открыть",
			ЭтотОбъект,
			МассивПройти);
		ОткрытьФорму("Справочник.Контрагенты.ФормаОбъекта",
			ПараметрыОткрытия,
			ЭтотОбъект,
			1,
			,
			,
			ОписаниеОповещения,
			РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
	Иначе
		ПоказатьПредупреждение(,"Заполнение по ИНН завершено" );
	КонецЕсли;
КонецПроцедуры

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

Шаг 4: Доработка формы объекта

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

При создании на сервере передаем параметры в реквизиты.

При открытии если параметр"ВД_ЗаполнитьЗаписатьЗакрыть" (или "ВД_ЗаполнитьПоИНН" как в моем примере), определяющий необходимость обработки = истина, то через обработчик ожидания с задержкой 0.2 секунды вызвать основной метод, который заполнит нужные поля и обратится к нужным методам формы, после чего запишет объект с передачей ссылки и комментария (для вывода в сообщения)

при создании на сервере переносим параметр в реквизит
 

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

при открытии запускаем обработчик ожидания (чтобы наш код выполнился в открытой и полностью инициализированной форме)

&НаКлиенте
Процедура ВД_ПриОткрытииПосле(Отказ)
	Если ВД_ЗаполнитьПоИНН Тогда
		ПодключитьОбработчикОжидания("ВД_ЗаполнитьПоИНН_Сразу", 0.2, Истина);
	КонецЕсли;
КонецПроцедуры

заполнение - основная часть данного расширения, в нем вызываются методы, которые определены только в самой форме (в данном примере нас интересуют методы "ЗаполнениеРеквизитовПоДаннымИННВозможно" и "ЗаполнитьРеквизитыКонтрагентаПоПолученнымДанным", в случае успешного выполнения записываем и закрываем)

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

&НаКлиенте
Процедура ВД_ЗаписатьСКомментариемИЗакрыть(Знач Записывать, Комментарий)
	Если ПустаяСтрока(Объект.ДополнительнаяИнформация) Тогда
		Объект.ДополнительнаяИнформация = Комментарий;
		Записывать = Истина;
	ИначеЕсли СтрНайти(Объект.ДополнительнаяИнформация, Комментарий) = 0 Тогда
		Объект.ДополнительнаяИнформация = Объект.ДополнительнаяИнформация + Символы.ПС + Комментарий;
		Записывать = Истина;
	КонецЕсли;
	Если Записывать Тогда
		Записать();
	КонецЕсли;
	Закрыть(Новый Структура("КлючДанных, Текст", Объект.Ссылка, Строка(Объект.Ссылка) + ": " + Комментарий));
КонецПроцедуры


Результат

открываем список контрагентов, выделяем нужных, запускаем, перед нами постоянно открывается форма контрагента и сразу закрывается, после окончания выводится предупреждение "Заполнение по ИНН завершено", и все объекты с комментариями в форме списка,
после выполнения расширение можно удалить: конфигурация заказчика останется на замке (ну по крайней мере без наших доработок), мы сэкономили время и не разбирались со сложным кодом и при этом получили инструмент, которым можно воспользоваться еще раз.

расширение обработка прием работы

См. также

Печать любых непроведенных документов для УТ, КА, ERP. Настройка печати по пользователям, документам и печатным формам

Пакетная печать Печатные формы Адаптация типовых решений Универсальные функции Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Платные (руб)

Расширение для программ 1С:Управление торговлей, 1С:Комплексная автоматизация, 1С:ERP, которое позволяет распечатывать любые печатные формы для непроведенных документов. Можно настроить, каким пользователям, какие конкретные формы документов разрешено печатать без проведения документа.

3480 руб.

22.08.2023    806    1    0    

1

Валидация JSON через XDTO (включая массивы)

WEB-интеграция Универсальные функции Механизмы платформы 1С Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    3183    YA_418728146    3    

85

Расширение: Быстрые отборы через буфер [Alt+C] Копировать список, [Alt+V] Вставить список, [Ctrl+C] Копировать из файлов

Инструментарий разработчика Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Копирует в буфер значения из списков, из ячеек отчетов, таблиц, настроек списков, других отборов и вставляет в выбранную настройку отбора. Работает с Объект не найден. Работает как в одной так и между разными базами 1С. Использует комбинации [Alt+C] Копировать список, [Alt+V] Вставить список. Также для копирования данных используется стандартная [Ctrl+C] (например из открытого xls, mxl, doc и т.п. файла скопировать список наименований)

1 стартмани

13.10.2022    13233    102    sapervodichka    106    

118

Система контроля ведения учета [БСП]

Универсальные функции Механизмы типовых конфигураций БСП (Библиотека стандартных подсистем) Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

В данном материале рассмотрим типовой алгоритм подсистемы контроля учета БСП в конфигурациях на примерах.

18.07.2022    6341    quazare    8    

103

Хитрости СКД. Часть 3

СКД Универсальные функции Платформа 1С v8.3 Система компоновки данных Конфигурации 1cv8 Бесплатно (free)

Столкнулся с тем, что мне приходится писать гору отчетов. Во многих приходится использовать повторяющиеся приемы. Решил написать шпаргалку, которая, надеюсь пригодится не только мне. В этой статье: Объединение ячеек в отчете только на определенном уровне иерархии, Постобработка итогов в табличном документе, Скрытие колонок в зависимости от количества месяцев в периоде.

28.05.2022    7684    milkers    11    

87

Базовые принципы работы с регламентными заданиями подсистем БСП

Универсальные функции БСП (Библиотека стандартных подсистем) Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

В очередной публикации рассмотрим некоторые базовые приемы работы с регламентными заданиями в рамках библиотеки стандартных подсистем

22.05.2022    12547    quazare    25    

57
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. VmvLer 31.10.19 14:40 Сейчас в теме
осилил.
субъективно: язык изложения очень костный и путанный
Yashazz; EvgenURNN; +2 Ответить
2. EvgenURNN 99 31.10.19 14:59 Сейчас в теме
(1) спасибо за замечание, добавил раздел с описанием принципа действия в целом, сегондя еще пару раз перечитаю, попробую переписать более понятным языком
3. RocKeR_13 1244 31.10.19 16:05 Сейчас в теме
недокументированный прием работы с расширением

Заинтриговали, но дальше оказалось, что интриги-то и нет никакой) Скорей хитрости
4. EvgenURNN 99 31.10.19 17:06 Сейчас в теме
(3) то есть точнее назвать "Хитрый прием работы с расширением"?
5. RocKeR_13 1244 31.10.19 17:11 Сейчас в теме
(4) как вариант) Можно просто опустить слово "недокументированный".
6. mangy 30 02.11.19 10:56 Сейчас в теме
1. Почему просто с помощью расширения не сделать процедуры формы экспортными и с помощью внешней обработки не обратится к ним после метода Открыть форму?
2. Для чего в данном случае используется обработчик ожидания?
EvgenURNN; +1 Ответить
7. EvgenURNN 99 02.11.19 12:44 Сейчас в теме
(6)
мысль интересная,
я так не пробовал,
мне тут подкинули еще идею упростить через "ПолучитьФорму" и в ней просто выполнить точно также экспортный метод через расширение,

Обработчик ожидания чтобы успели отработать все обработчики открытия и чтобы можно было закрыть
8. Yashazz 4554 03.11.19 23:16 Сейчас в теме
Тут уже правильно сказали - можно прямее и проще. А так, имхо, костыль.
9. RustIG 1730 09.11.19 14:58 Сейчас в теме
(0) по идее, у вас групповая обработка объектов - и по идее, групповая обработка не должна зависеть от контекста формы... в принципе....
...ваш хитрый прием придуман, чтобы не особо разбираться в коде модуля формы?
часть процедур можно сделать экспортными, вынести в модуль объекта или во внешнюю обработку - но вы почему-то посчитали, что это будет сложнее...
я не увидел "почему"... можете сложности прояснить?

а так, метод имеет право на существование....другой взгляд на решение проблем задачи...
10. Xershi 1402 18.10.20 15:04 Сейчас в теме
Проще код перенести во внешнюю обработку и такого треша не будет.
Это скорее по не опытности.
Также стоит разработчикам написать, чтобы функционал был продублирован на сервере, тогда тем более это не нужно будет заниматься.
Оставьте свое сообщение