новое событие
Информационный поток
Задания вакансии материалы разработки сообщения форума

Пример перевода конфигурации на управляемый интерфейс

  • Добавить свою публикацию
  • для этого требуется регистрация

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

Данными примерами я хочу показать как можно с наименьшим количеством трудозатрат и изменений кода реализовать управляемый интерфейс, для уже написаной конфигурации. Конечно эта технология не будет оптимальной, и в дальнейшем ее нужно переписать. Однако это позволит в короткие сроки создать управляемый интерфейс для уже существующих документовb справочников.


Я не буду писать о том как создавать сам интерфейс управляемой формы, единственное, для упрощения переноса функционала интерфейса я стараюсь расположить элементы формы так-же как и в обычном приложении, реквизиты формы назваю один в один. Это позволяет копировать уже имеющие процедуры и функции изменив только необходимые отличия обращений к объектам формы.
Например в толстом клиенте все элементы формы находяться в объекте  с названием ЭлементыФормы, а в управляемом интерфейсе это будет Элементы.

 


Приведу пример процедуры из конфигурации УТ 10.3:

Процедура ПриИзмененииКонтрагента() Экспорт

	// Выполняем общие действия для всех документов при изменении Контрагент.
	ЗаполнениеДокументов.ПриИзмененииЗначенияКонтрагента(ЭтотОбъект, мСтруктураПараметровДляПолученияДоговора);

	Если НЕ ЗначениеЗаполнено(КонтактноеЛицоКонтрагента) Тогда
		КонтактноеЛицоКонтрагента = Контрагент.ОсновноеКонтактноеЛицо;
	Иначе
		Если КонтактноеЛицоКонтрагента.Владелец  Контрагент Тогда
			КонтактноеЛицоКонтрагента = Контрагент.ОсновноеКонтактноеЛицо;
		КонецЕсли;
	КонецЕсли;

КонецПроцедуры // ПриИзмененииКонтрагента()

 

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

 

 ЭтотОбъект = РеквизитФормыВЗначение("Объект");

 

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

 

ЭтотОбъект = РеквизитФормыВЗначение("Объект");

мСуммаВсего    = ЭтотОбъект.ПолучитьСуммуСНДС();

 

В конце выше приведенной процедуры, нужно будет вернуть данный объект на форму сделать это можно процедурой ЗначениеВРеквизитФормы:

 

ЗначениеВРеквизитФормы(ЭтотОбъект, "Объект") 

 

И еще поскольку теперь нельзя обращаться на прямую к реквизитам формы или объекта, Нам перед каждым реквизитом нужно вставить слово ЭтотОбъект, в результате мы получили такую процедуру:

 

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

	Если НЕ ЗначениеЗаполнено(ЭтотОбъект.КонтактноеЛицоКонтрагента) Тогда
		ЭтотОбъект.КонтактноеЛицоКонтрагента = ЭтотОбъект.Контрагент.ОсновноеКонтактноеЛицо;
	Иначе
		Если ЭтотОбъект.КонтактноеЛицоКонтрагента.Владелец  ЭтотОбъект.Контрагент Тогда
			ЭтотОбъект.КонтактноеЛицоКонтрагента = ЭтотОбъект.Контрагент.ОсновноеКонтактноеЛицо;
		КонецЕсли;
	КонецЕсли;

КонецПроцедуры // ПриИзмененииКонтрагента()

 

Согласитесь, что данная методика чем-то напоминает создание аналогичной внешней печатной формы, когда перед всеми рекизитами документа добавляется  ДокументСсылка.

К сожалению данный метод не панацея т.к. работать во всех случаях не будет, например если вызываемый модуль содержит директивы компиляции #Если Клиент Тогда, то они ни когда не будут отработаны, т.к. в данном случае эта процедура будет всегда выполняться на сервере. И как правило в таких местах располагаются интерактивное взаимодействие с клиентом, т.е вывод сообщений или задаются уточняющие  вопросы.
В таких случаях можно создать аналогичный модуль добавив в конце наименование слово “Клиент”, выполняемый только на клиенте и скопировав туда данную функцию,  необходимо внести соответвующие изменения.
Например поскольку данная процедура или функция будет вызываться на клиенте то работать с объектом  ДокументОбъект у нас нет возможности, у нас есть только объект типа ДанныеФормыСтруктура, а у данного объекта мы можем обращаться только  к реквизитам “первого уровня”.
поэтому если в процедуре или функции встречается такой код:

 

 

Документ.ДоговорКонтрагента.ВидВзаиморасчетов, 

 

 его следует переписать на:

 

ОбщегоНазначения.ПолучитьРеквизитЭлемента(Документ.ДоговорКонтрагента,”ВидВзаиморасчетов”) 

 

Предварительно добавив данную функция в общий модуль(пример кода этой функции приводить не буду т.к. ее можно найти в БСП) Так же в процедурах попадается сравнение с типом, это конструкции вида

 

ТипЗнч(ДокументОбъект) = Тип("ДокументОбъект.ОтчетОРозничныхПродажах") 

 

данный код можно переписать на:

 

ТипЗнч(ДокументОбъект.Ссылка) = Тип("ДокументСсылка.ОтчетОРозничныхПродажах") И ТипЗнч(ДокументОбъект) = Тип("ДанныеФормыСтруктура") 

 

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

конструкцию:

 

Если ВидСклада = Перечисления.ВидыСкладов.Оптовый Тогда 

 

 можно переписать так

 

ВидыСкладов = ОбщегоНазначения.ПолучитьСтруктуруПеречислений("ВидыСкладов")....
Если ВидСклада = ВидыСкладов.Оптовый Тогда
 

 

А в общий модуль вставим процедуру:

 

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

 

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

Если в коде процедуры или функции происходит обращение к пустой ссылке или к предопределенному значению, а так-же к значениям перечислений, например

 

Если Номенклатура = Справочники.Номенклатура.ПустаяСсылка Тогда 

 

то можно переписать код на

 

Если Номенклатура =  ПредопределенноеЗначение("Справочник.Номенклатура.ПустаяСсылка") Тогда 

 

подробнее об этой Функции можно почитать в описании синтакс-помошника.

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

 

МетаданныеДокумента = ДокументОбъект.Метаданные();.
Если ОбщегоНазначения.ЕстьРеквизитДокумента("СкладОрдер", МетаданныеДокумента) Тогда
 

 

одним из решений будет получить структуру реквитов объекта. Для этого например в общем модуле вставляем функцию:

 

 //Возвращает структуру переданного объекта
//
Функция ПолучитьРеквизитыДокумента(Объект) Экспорт

	МетаданныеОбъекта = Новый Структура;

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

		МетаданныеОбъекта.Вставить(РеквизитОбъекта.Имя,РеквизитОбъекта.Имя);

	КонецЦикла;

	ТабличныеЧасти = Новый Структура;

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

		МетаданныеТЧ = Новый Структура;

		Для Каждого РеквизитОбъектаТЧ Из Объект.Метаданные().ТабличныеЧасти[РеквизитОбъекта.Имя].Реквизиты Цикл
			МетаданныеТЧ.Вставить(РеквизитОбъектаТЧ.Имя,РеквизитОбъектаТЧ.Имя);
		КонецЦикла;

		ТабличныеЧасти.Вставить(РеквизитОбъекта.Имя,МетаданныеТЧ);

	КонецЦикла;

	МетаданныеОбъекта.Вставить("ТабличныеЧасти",ТабличныеЧасти);

	Возврат МетаданныеОбъекта;

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

 

В результате нам необходимо предварительно получить структуру данного объекта и переписать код на:

 

МетаданныеДокумента = ОбщегоНащначения.ПолучитьРеквизитыДокумента(Объект)
...
Если МетаданныеДокумента.Свойство("СкладОрдер") Тогда
 

 

для конструкций вида:

 

Метаданные.НайтиПоТипу(ТипЗнч(СсылкаНаОбъект)).Имя 

 

можно опять написать функцию в общем модуле:

 

Функция НайтиПоТипу(Значение) Экспорт
	Возврат Метаданные.НайтиПоТипу(ТипЗнч(Значение)).Имя;
КонецФункции
 

 

и изменить код на

 

ОбщегоНазначения.НайтиПоТипу(СсылкаНаОбъект) 

 

Так же очень часто в коде выполняются запросы, поскольку выполнение запросов возможно только на сервере, то данный кусок кода необходимо вынести например в новый  модуль выполняемый на сервере а для простоты запоминания можно назвать его аналогично поставив в конце наименования слово “Сервер”


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

 

&НаСервере
Функция ПолучитьСтруктуруРеквизитовДокумента();

	СтруктураПараметров = новый Структура();
	СтруктураПараметров.Вставить("СпособЗаполненияЦен",Перечисления.СпособыЗаполненияЦен.ПоЦенамНоменклатуры);
	СтруктураПараметров.Вставить("МетаданныеДокумента",ОбщегоНазначения.ПолучитьРеквизитыДокумента(ЭтотОбъект));..
	Возврат СтруктураПараметров;

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

 

 
0
Читайте также
Будущее программ экономического учета.
Какими будут в будущем программы экономического учета программы?
Принимаем на работу программиста.
Ответственно отнеситест к выбору 1С программиста, т.к. последствия приема специалиста, уровень знаний которого недостаточен могут быть печальными
Разработки
Удаленное управление с помощью нашего сервиса
Возможность удаленного управления
Специализированная конфигурация Autoupdater
Автоматическое внесение изменений в другие конфигурации 1С8
[1С 8] SubSys: Рабочий стол руководителя - центр управления отчетами
Набор готовых отчетов для руководителя 1С8
≡ к списку статей