Программное управление обычными формами документов и справочников в УПП/КА

Если с программным изменением управляемых форм 1С все более или менее понятно, то с программированием обычных форм примеров не так уж много в сети. А уж примеров готовых решений совсем не видно.
В данной статье я покажу, как можно реализовать аналог «управляемых» форм в своих конфигурациях с обычными формами и забыть о сложностях обновлений форм.

Часть 1

Чтобы не снимать с поддержки все формы конфигурации и не вставлять свои обработчики в процедуры «ПриОткрытии», будем искать такую процедуру, которая вызывается во всех формах документах и справочников.

Для форм документов — это функция общего модуля «РаботаСДиалогами.АктивизироватьРеквизитВФорме». Она как раз вызывается из процедуры форм документов «При открытии» и двойное бинго — в конце процедуры, после стандартных процедур по изменению формы.

И так, снимаем с поддержки общий модуль «РаботаСДиалогами».
Находим функцию «АктивизироватьРеквизитВФорме» и сразу после объявления функции добавляем строку вызова нашей процедуры:

Функция АктивизироватьРеквизитВФорме(Объект, ФормаОбъекта, СтруктураРеквизитов = Неопределено, ТабличнаяЧасть = неопределено, СтраницыСТабЧастями = неопределено) Экспорт
ИТ_РаботаСДиалогами.ДополнитьФормуДокумента(Объект, ФормаОбъекта);//Вызов нашей будущей процедуры
//...
КонецФункции// АктивизироватьРеквизитВФорме()

Для форм справочников — это процедура общего модуля  «МеханизмНумерацииОбъектов.УстановитьДоступностьПоляВводаНомера».
Находим модуль  
 «МеханизмНумерацииОбъектов", в процедуре «УстановитьДоступностьПоляВводаНомера», сразу после ее объявления, добавляем строку вызова нашей процедуры:

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

Все. Отделались снятием с поддержки двух модуле с добавлением в них двух строк. Обновлять будет легко.

Часть 2

Теперь самое главное.

Добавляем в конфигурацию общий модуль «ИТ_РаботаСДиалогами». В свойствах ставим галочки на использование в клиенте.

Свойства нового модуля

В модуль помещаем вызываемые функции.

//*******************************************************************************************
//*В ЭТОМ МОДУЛЕ ПРОЦЕДУРЫ И ФУНКЦИИ, СВЯЗАННЫЕ С ДИНАМИЧЕСКИМ ФОРМИРОВАНИЕМ ФОРМ ДОКУМЕНТОВ*
//*******************************************************************************************

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


//******************* ЗАПОЛНЕНИЕ ФОРМ СПРАВОЧНИКОВ ****************************
//Вызывается из процедуры МеханизмНумерацииОбъектов.УстановитьДоступностьПоляВводаНомера
//В свою очередь процедура "УстановитьДоступностьПоляВводаНомера" вызывается почти в каждой форме справочника при открытии.

Процедура ДополнитьФормуСправочника(ОбъектМетоданных, ФормаСправочника) Экспорт
//!ВНИМАНИЕ! Процедура вызывается и при открытии формы элемента справочника, и при открытии формы списка справочника. Отличить место вызова процедуры можно по имени формы, но имя формы у них приходится получать по разному.
Попытка
ИмяФормы = ФормаСправочника.Имя;
Исключение
ИмяФормы = ФормаСправочника.Заголовок;
КонецПопытки;
//Примеры вызова процедур для изменения формы элемента справочника.
Если  ОбъектМетоданных.ПолноеИмя()="Справочник.Склады"
И ИмяФормы="Склады (места хранения)" Тогда
ПриОткрытии_Склады(ОбъектМетоданных, ФормаСправочника);
ИначеЕсли ОбъектМетоданных.ПолноеИмя()="Справочник.СтатьиДвиженияДенежныхСредств"
И ИмяФормы="Статьи движения денежных средств" Тогда
ПриОткрытии_СтатьиДвиженияДенежныхСредств(ОбъектМетоданных, ФормаСправочника);
КонецЕсли;

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

Обратите внимание, что работа с формами справочника имеет особенности. Поскольку процедура "МеханизмНумерацииОбъектов.УстановитьДоступностьПоляВводаНомера" вызывается как из формы списка справочника, так и из формы самого элемента справочника. Различить можно только по составу передаваемых метаданных или просто по имени формы.

 

Часть 3

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

 — Функция добавления поля ввода на форму (одна из ранних наших функций).

Эта функция позволяет разместить на форму реквизит данный как поле ввода и его заголовок как надпись.
Есть некоторые особенности использования этой функции:
— При наличии заголовка в параметрах, он отображается как надпись на форме слева от поля ввода, если поле ввода имеет флаг РастягиватьПоВысоте=Истина, то заголовок выводится слева-сверху от поля ввода.
— В параметр "ДействиеПриИзменении" можно указать название процедуры, вызываемый при изменении реквизита, добавленного на форму. !ВАЖНО! указываемая процедура должна быть размещена в модуле формы, где добавляется реквизит.

//****************** ФУНКЦИИ РИСОВАНИЯ ОБЪЕКТОВ НА ФОРМЕ *******************
Функция ДобавитьПолеВводаНаФорму(ФормаОбъекта,Заголовок="",ИмяДанных,ИмяЭлементаПривязки="",ИндексЭлемента=0,РастягиватьПоШирине=Ложь,РастягиватьПоВысоте=Ложь,ШиринаЗаголовка = 88, ДействиеПриИзменении="")
СдвигВПраво = 0;
ЭлементыФормы = ФормаОбъекта.ЭлементыФормы;
МинимальнаяВысотаФормы = 5 + (ИндексЭлемента * 20)+ 19+5+ЭлементыФормы.ОсновныеДействияФормы.Высота;
//Увеличение высоты формы и смещение нижних кнопок при недостаточности высоты формы.
Если ФормаОбъекта.Высота < МинимальнаяВысотаФормы Тогда
РазницаВВысоте = МинимальнаяВысотаФормы - ФормаОбъекта.Высота;
ФормаОбъекта.Высота = ФормаОбъекта.Высота + РазницаВВысоте+2;
ШиринаВерхКнопок =  ЭлементыФормы.ОсновныеДействияФормы.ширина;
НовыйВерхКнопок =  ЭлементыФормы.ОсновныеДействияФормы.Верх + РазницаВВысоте;
ЭлементыФормы.ОсновныеДействияФормы.Верх=НовыйВерхКнопок;
Shell = Новый COMОбъект("WScript.Shell");
Shell.SendKeys("%+R"); // вызов Alt+Shift+R
КонецЕсли;

//Имя панели, на которую выводится новое поле ввода.
Если ПустаяСтрока(ИмяЭлементаПривязки) Тогда
ЭлементПривязки=ФормаОбъекта.ТекущийЭлемент;
Ширина = ФормаОбъекта.Ширина;
Высота = ФормаОбъекта.Высота;
Иначе
ЭлементПривязки = ЭлементыФормы[ИмяЭлементаПривязки];
Ширина = ЭлементПривязки.Ширина;
Высота = ЭлементПривязки.Высота;
КонецЕсли;

//Выводим заголовок поля на форме как надпись.
Если Не ПустаяСтрока(Заголовок) Тогда
НоваяНадпись = ЭлементыФормы.Добавить(Тип("Надпись"),"Надпись"+ИмяДанных,,ЭлементПривязки);
НоваяНадпись.Заголовок = Заголовок;
НоваяНадпись.Верх = 5 + (ИндексЭлемента * 20);
НоваяНадпись.Лево = 5;
НоваяНадпись.Ширина = ШиринаЗаголовка;
НоваяНадпись.Высота = 19;
НоваяНадпись.УстановитьПривязку(ГраницаЭлементаУправления.Верх,ЭлементПривязки,ГраницаЭлементаУправления.Верх);
НоваяНадпись.УстановитьПривязку(ГраницаЭлементаУправления.Лево,ЭлементПривязки,ГраницаЭлементаУправления.Лево);
ЗаголовокСверху = (РастягиватьПоВысоте И РастягиватьПоШирине);
Если ЗаголовокСверху Тогда
НоваяНадпись.Ширина = Ширина-10;
НоваяНадпись.УстановитьПривязку(ГраницаЭлементаУправления.Право,ЭлементПривязки,ГраницаЭлементаУправления.Право);
ИндексЭлемента = ИндексЭлемента + 1;
Иначе
СдвигВПраво = ШиринаЗаголовка;
КонецЕсли;
КонецЕсли;

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

НовоеПолеВвода.Верх = 5+(ИндексЭлемента*20);
НовоеПолеВвода.Лево = 5+СдвигВПраво;
НовоеПолеВвода.Ширина = ?(РастягиватьПоШирине,Ширина-15-СдвигВПраво,220);
НовоеПолеВвода.Высота = ?(РастягиватьПоВысоте,Высота-15-(ИндексЭлемента*20),19);
;
НовоеПолеВвода.Подсказка = Заголовок;
//НовоеПолеВвода.МногострочныйРежим  = Истина;
НовоеПолеВвода.УстановитьПривязку(ГраницаЭлементаУправления.Верх,ЭлементПривязки,ГраницаЭлементаУправления.Верх);
НовоеПолеВвода.УстановитьПривязку(ГраницаЭлементаУправления.Лево,ЭлементПривязки,ГраницаЭлементаУправления.Лево);
Если РастягиватьПоВысоте Тогда
НовоеПолеВвода.УстановитьПривязку(ГраницаЭлементаУправления.Низ,ЭлементПривязки,ГраницаЭлементаУправления.Низ);
Иначе
НовоеПолеВвода.УстановитьПривязку(ГраницаЭлементаУправления.Низ,ЭлементПривязки,ГраницаЭлементаУправления.Верх);
КонецЕсли;
Если РастягиватьПоШирине Тогда
НовоеПолеВвода.УстановитьПривязку(ГраницаЭлементаУправления.Право,ЭлементПривязки,ГраницаЭлементаУправления.Право);
Иначе
НовоеПолеВвода.УстановитьПривязку(ГраницаЭлементаУправления.Право,ЭлементПривязки,ГраницаЭлементаУправления.Лево);
КонецЕсли;

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

 — Функция добавления флажка на форму.

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

Код этой функции почти идентичны предыдущим, по этому убран под спойлер.

 
Функция ДобавитьФлажокНаФорму(ФормаОбъекта,Заголовок,ИмяДанных,ИмяЭлементаПривязки="",ИндексЭлемента=0,РастягиватьПоШирине=Ложь,РастягиватьПоВысоте=Ложь, ДействиеПриИзменении="", НадписьСправа=Истина)
СдвигВПраво = 0;
ЭлементыФормы = ФормаОбъекта.ЭлементыФормы;
МинимальнаяВысотаФормы = 5 + (ИндексЭлемента * 20)+ 19+5+ЭлементыФормы.ОсновныеДействияФормы.Высота;
//Увеличение высоты формы и смещение нижних кнопок при недостаточности высоты формы.
Если ФормаОбъекта.Высота < МинимальнаяВысотаФормы Тогда
РазницаВВысоте = МинимальнаяВысотаФормы - ФормаОбъекта.Высота;
ФормаОбъекта.Высота = ФормаОбъекта.Высота + РазницаВВысоте+2;
ШиринаВерхКнопок =  ЭлементыФормы.ОсновныеДействияФормы.ширина;
НовыйВерхКнопок =  ЭлементыФормы.ОсновныеДействияФормы.Верх + РазницаВВысоте;
ЭлементыФормы.ОсновныеДействияФормы.Верх=НовыйВерхКнопок;
Shell = Новый COMОбъект("WScript.Shell");
Shell.SendKeys("%+R"); // вызов Alt+Shift+R
КонецЕсли;

//Имя панели, на которую выводится новый флажок.
Если ПустаяСтрока(ИмяЭлементаПривязки) Тогда
ЭлементПривязки=ФормаОбъекта.ТекущийЭлемент;
Ширина = ФормаОбъекта.Ширина;
Высота = ФормаОбъекта.Высота;
Иначе
ЭлементПривязки = ЭлементыФормы[ИмяЭлементаПривязки];
Ширина = ЭлементПривязки.Ширина;
Высота = ЭлементПривязки.Высота;
КонецЕсли;

//Добавление самого флажка (вашего реквизита) на форму
НовоеПолеВвода = ЭлементыФормы.Добавить(Тип("Флажок"),ИмяДанных,,ЭлементПривязки);
НовоеПолеВвода.Данные = ИмяДанных;

НовоеПолеВвода.Верх = 5+(ИндексЭлемента*20);
НовоеПолеВвода.Лево = 5+СдвигВПраво;
НовоеПолеВвода.Ширина = ?(РастягиватьПоШирине,Ширина-15-СдвигВПраво,220);
НовоеПолеВвода.Высота = ?(РастягиватьПоВысоте,Высота-15-(ИндексЭлемента*20),19);
НовоеПолеВвода.Заголовок = Заголовок;
НовоеПолеВвода.Подсказка = Заголовок;
НовоеПолеВвода.ПоложениеЗаголовка = ?(НадписьСправа,ПоложениеЗаголовка.ЗаголовокСправа,ПоложениеЗаголовка.ЗаголовокСлева);
НовоеПолеВвода.ПрозрачныйФон = Истина;
НовоеПолеВвода.УстановитьПривязку(ГраницаЭлементаУправления.Верх,ЭлементПривязки,ГраницаЭлементаУправления.Верх);
НовоеПолеВвода.УстановитьПривязку(ГраницаЭлементаУправления.Лево,ЭлементПривязки,ГраницаЭлементаУправления.Лево);
Если РастягиватьПоВысоте Тогда
НовоеПолеВвода.УстановитьПривязку(ГраницаЭлементаУправления.Низ,ЭлементПривязки,ГраницаЭлементаУправления.Низ);
Иначе
НовоеПолеВвода.УстановитьПривязку(ГраницаЭлементаУправления.Низ,ЭлементПривязки,ГраницаЭлементаУправления.Верх);
КонецЕсли;
Если РастягиватьПоШирине Тогда
НовоеПолеВвода.УстановитьПривязку(ГраницаЭлементаУправления.Право,ЭлементПривязки,ГраницаЭлементаУправления.Право);
Иначе
НовоеПолеВвода.УстановитьПривязку(ГраницаЭлементаУправления.Право,ЭлементПривязки,ГраницаЭлементаУправления.Лево);
КонецЕсли;

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

 

 

— Функция добавления надписи на форму.

Эта функция позволяет разместить на форму надпись.
Правила использования такие же как у предыдущей функции. Фактически это вырезка вывода надписи из первой функции..

Код убран под спойлер

 

Функция ДобавитьНадписьНаФорму(ФормаОбъекта,Надпись,ИмяЭлементаПривязки="",ИндексЭлемента=0,РастягиватьПоШирине=Ложь,РастягиватьПоВысоте=Ложь)
СдвигВПраво = 0;
ЭлементыФормы = ФормаОбъекта.ЭлементыФормы;
МинимальнаяВысотаФормы = 5 + (ИндексЭлемента * 20)+ 19+5+ЭлементыФормы.ОсновныеДействияФормы.Высота;
Если ФормаОбъекта.Высота < МинимальнаяВысотаФормы Тогда
РазницаВВысоте = МинимальнаяВысотаФормы - ФормаОбъекта.Высота;
ФормаОбъекта.Высота = ФормаОбъекта.Высота + РазницаВВысоте+2;
ШиринаВерхКнопок =  ЭлементыФормы.ОсновныеДействияФормы.ширина;
НовыйВерхКнопок =  ЭлементыФормы.ОсновныеДействияФормы.Верх + РазницаВВысоте;
ЭлементыФормы.ОсновныеДействияФормы.Верх=НовыйВерхКнопок;
Shell = Новый COMОбъект("WScript.Shell");
Shell.SendKeys("%+R"); // вызов Alt+Shift+R
КонецЕсли;
Если ПустаяСтрока(ИмяЭлементаПривязки) Тогда
ЭлементПривязки=ФормаОбъекта.ТекущийЭлемент;
Ширина = ФормаОбъекта.Ширина;
Высота = ФормаОбъекта.Высота;
Иначе
ЭлементПривязки = ЭлементыФормы[ИмяЭлементаПривязки];
Ширина = ЭлементПривязки.Ширина;
Высота = ЭлементПривязки.Высота;
КонецЕсли;
Если Не ПустаяСтрока(Надпись) Тогда
НоваяНадпись = ЭлементыФормы.Добавить(Тип("Надпись"),"Надпись"+ФОРМАТ(ИндексЭлемента,"ЧЦ=2; ЧН=00; ЧВН=; ЧГ="),,ЭлементПривязки);
НоваяНадпись.Заголовок = Надпись;
НоваяНадпись.Верх = 5+(ИндексЭлемента*20);
НоваяНадпись.Лево = 5+СдвигВПраво;
НоваяНадпись.Ширина = ?(РастягиватьПоШирине,Ширина-15-СдвигВПраво,220);
НоваяНадпись.Высота = ?(РастягиватьПоВысоте,Высота-15-(ИндексЭлемента*20),19);
НоваяНадпись.УстановитьПривязку(ГраницаЭлементаУправления.Верх,ЭлементПривязки,ГраницаЭлементаУправления.Верх);
НоваяНадпись.УстановитьПривязку(ГраницаЭлементаУправления.Лево,ЭлементПривязки,ГраницаЭлементаУправления.Лево);
Если РастягиватьПоВысоте Тогда
НоваяНадпись.УстановитьПривязку(ГраницаЭлементаУправления.Низ,ЭлементПривязки,ГраницаЭлементаУправления.Низ);
Иначе
НоваяНадпись.УстановитьПривязку(ГраницаЭлементаУправления.Низ,ЭлементПривязки,ГраницаЭлементаУправления.Верх);
КонецЕсли;
Если РастягиватьПоШирине Тогда
НоваяНадпись.УстановитьПривязку(ГраницаЭлементаУправления.Право,ЭлементПривязки,ГраницаЭлементаУправления.Право);
Иначе
НоваяНадпись.УстановитьПривязку(ГраницаЭлементаУправления.Право,ЭлементПривязки,ГраницаЭлементаУправления.Лево);
КонецЕсли;
КонецЕсли;
КонецФункции

 

 

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

Эта более универсальная процедура. Появилась в нашем арсенале гораздо позже. Основное ее преимущество в том, что она может автоматически копировать оформление и привязку с других элементов на форме.
Так же можно назначить выполнение любого события, а не только "При изменении". Работает через структуру в параметрах.
Обязательные поля структуре  — "ТипПоля,ИмяПоля,Данные,ЭлементЭталон,Подсказка,ПолеСдвига". Не забывайте их заполнять при вызове этой процедуры.

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

Процедура ДобавитьЭлементНаФорму(ДокументОбъект, ФормаДокумента, СтруктураЗаполнения, ИмяСобытия="", ИмяДействия="", ИмяЭлементаПривязки="", РазмерОтступа=5, ИмяПоляВладельца = "")

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

НовоеПоле.Верх  = ВерхПервого+РазмерОтступа+ЭлементЭталон.Высота;
Если Врег(СтруктураЗаполнения.ТипПоля) = ВРег("ПолеВвода") тогда
НовоеПоле.Значение  = "";
НовоеПоле.Данные  = СтруктураЗаполнения.Данные;

Если ЗначениеЗаполнено(ИмяПоляВладельца) Тогда
НовоеПоле.ВыборПоВладельцу = ФормаДокумента.ЭлементыФормы[ИмяПоляВладельца].Значение;
КонецЕсли;
НовоеПоле.Подсказка  = СтруктураЗаполнения.Подсказка;
ЗаполнитьЗначенияСвойств(НовоеПоле, ЭлементЭталон,"Ширина, Высота, Лево",);
ИначеЕсли Врег(СтруктураЗаполнения.ТипПоля) = ВРег("Надпись") тогда
НовоеПоле.Заголовок  = СтруктураЗаполнения.Подсказка;
ЗаполнитьЗначенияСвойств(НовоеПоле, ЭлементЭталон,,"Имя, Верх,Значение, Заголовок");
ИначеЕсли Врег(СтруктураЗаполнения.ТипПоля) = ВРег("Флажок") тогда
НовоеПоле.Заголовок  = СтруктураЗаполнения.Подсказка;
НовоеПоле.Данные      = СтруктураЗаполнения.Данные;
НовоеПоле.Подсказка  = СтруктураЗаполнения.Подсказка;
НовоеПоле.ПоложениеЗаголовка = ПоложениеЗаголовка.ЗаголовокСправа;
НовоеПоле.ПрозрачныйФон = Истина;
ЗаполнитьЗначенияСвойств(НовоеПоле, ЭлементЭталон,"Ширина, Высота, Лево",);
КонецЕсли;
Если СтруктураЗаполнения.Свойство("Доступность") Тогда
НовоеПоле.Доступность = СтруктураЗаполнения.Доступность;
Конецесли;
Если СтруктураЗаполнения.Свойство("Видимость") Тогда
НовоеПоле.Видимость = СтруктураЗаполнения.Видимость;
Конецесли;
НовоеПоле.УстановитьПривязку(ГраницаЭлементаУправления.Верх,ЭлементЭталон,ГраницаЭлементаУправления.Верх);
НовоеПоле.УстановитьПривязку(ГраницаЭлементаУправления.Лево,ЭлементЭталон,ГраницаЭлементаУправления.Лево);
НовоеПоле.УстановитьПривязку(ГраницаЭлементаУправления.Право,ЭлементЭталон,ГраницаЭлементаУправления.Право);
ВысотаСдвига = РазмерОтступа + ЭлементЭталон.Высота;

Если не ПустаяСтрока(СтруктураЗаполнения.ПолеСдвига) тогда
ФормаДокумента.ЭлементыФормы[СтруктураЗаполнения.ПолеСдвига].Верх =ФормаДокумента.ЭлементыФормы[СтруктураЗаполнения.ПолеСдвига].Верх + ВысотаСдвига;
ФормаДокумента.Высота = ФормаДокумента.Высота + ВысотаСдвига;
КонецЕсли;

Если Не ПустаяСтрока(ИмяСобытия) и не ПустаяСтрока(ИмяДействия) тогда
НовоеПоле.УстановитьДействие(ИмяСобытия, Новый Действие(ИмяДействия));
КонецЕсли;

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

 

— Процедура добавления колонки в табличную часть формы.
Это универсальная процедура добавления колонки на форму.
Обязательные поля структуреколонки  — "Имя,Данные,КолонкаЭталон,Подсказка". Не забывайте их заполнять при вызове этой процедуры. Остальные свойства для новой колонки будут скопированы с колонки эталон, указанной в структуре.

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

 

— Процедура удаления колонки в табличной части формы.
Иногда возникает необходимость удалять колонки с формы документа. Тут все просто.

Процедура УдалитьКолонкуТабличнойЧасти(ФормаДокумента, ИмяТабЧасти, ПризнакКолонки)
Для каждого Элемент из ФормаДокумента.ЭлементыФормы[ИмяТабЧасти].Колонки Цикл
Если Найти(Элемент.Имя,ПризнакКолонки ) > 0 тогда
ФормаДокумента.ЭлементыФормы[ИмяТабЧасти].Колонки.Удалить(Элемент);
УдалитьКолонкуТабличнойЧасти(ФормаДокумента,"Товары", ПризнакКолонки);
КонецЕсли;
КонецЦикла;

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

— Процедура удаления элемента формы.
 

Процедура УдалитьЭлемент(ФормаДокумента, ПризнакЭлемента)

Для каждого Элемент из ФормаДокумента.ЭлементыФормы Цикл
Если Найти(Элемент.Имя,ПризнакЭлемента ) > 0 тогда
ФормаДокумента.ЭлементыФормы.Удалить(Элемент);
УдалитьЭлемент(ФормаДокумента,ПризнакЭлемента);
КонецЕсли;
КонецЦикла;

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

 

Часть 4

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

Процедура ПриОткрытии_УвольнениеИзОрганизаций(ДокументОбъект, ФормаДокумента)

Если ДокументОбъект.Метаданные().ТабличныеЧасти.РаботникиОрганизации.Реквизиты.Найти("ИТ_ПричиныУвольнения") = Неопределено тогда
Возврат;
КонецЕсли;

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

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

Пример добавления колонки на форму

Еще пример с добавлением полей в отдельной закладке:


Процедура ПриОтккрытии_РеализацияТоваровУслуг(ДокументОбъект, ФормаДокумента)
Если ДокументОбъект.Метаданные().Реквизиты.Найти("Автомобиль") = Неопределено Тогда
Возврат;
КонецЕсли;
ЭлементыФормы=ФормаДокумента.ЭлементыФормы;
СтараяСтраница = ЭлементыФормы.ОсновнаяПанель.ТекущаяСтраница;
СтраницаТТН = ЭлементыФормы.ОсновнаяПанель.Страницы.Найти("ТТН");
Если СтраницаТТН=Неопределено Тогда
СтраницаТТН = ЭлементыФормы.ОсновнаяПанель.Страницы.Добавить("ТТН","ТТН",,);
ЭлементыФормы.ОсновнаяПанель.ТекущаяСтраница=СтраницаТТН;
НовоеПолеВвода = ДобавитьПолеВводаНаФорму(ФормаДокумента,"Автомобиль:","Автомобиль","ОсновнаяПанель",0,Истина,Ложь,120,"АвтомобильПриИзменении");
НовоеПолеВвода = ДобавитьПолеВводаНаФорму(ФормаДокумента,"Водитель:","Водитель","ОсновнаяПанель",1,Истина,Ложь,120);
НовоеПолеВвода = ДобавитьПолеВводаНаФорму(ФормаДокумента,"Транспортная компания:","ТрансКомпания","ОсновнаяПанель",2,Истина,Ложь,120);

НовоеПолеВвода = ДобавитьПолеВводаНаФорму(ФормаДокумента,"Менеджер:","Менеджер","ОсновнаяПанель",4,Истина,Ложь,120);

КонецЕсли;
ЭлементыФормы.ОсновнаяПанель.ТекущаяСтраница=СтараяСтраница;

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

Пример добавления реквизитов на отдельную закладку

Еще пример работы с формой справочника.


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

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

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

Пример работы с формой справочника

Часть 5

Доработки по совместимости и универсальности.

Желательно весь код модуля "ИТ_РаботаСДиалогами" обрамить в клиента
 

#Если Клиент Тогда
//…..
#КонецЕсли

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

Если ДокументОбъект.Метаданные().Реквизиты.Найти("ВидОперации") = Неопределено Тогда
Возврат;
КонецЕсли;

Поскольку вызов функции может происходить многократно в одной форме, всегда проверяйте, выведен ли уже реквизит на форму.
Например так:

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

Такие проверки позволят вам копировать общий модуль «ИТ_РаботаСДиалогами» во все ваши конфигурации УПП/КА и не бояться вызова исключений.

9 Comments

  1. Batman

    Доброго времени суток

    Дополню своими наблюдениями

    Пошел аналогичным путем, через «точку входа» — МеханизмНумерацииОбъектов.УстановитьДоступностьПоляВводаНомера

    1а. Для формы списка вызываю другую процедуру, в таком виде

    Процедура ФормаСпискаПриОткрытии(ЭтаФорма) Экспорт
    
    ЭлементыФормы = ЭтаФорма.ЭлементыФормы;
    
    ИмяРеквизитаСписка = «Список»;
    Если НЕ ЭлементыФормы.Найти(ИмяРеквизитаСписка) = Неопределено Тогда
    мТип = ТипЗнч(ЭтаФорма.ЭлементыФормы[ИмяРеквизитаСписка].Значение);
    ТабличноеПолеПриОткрытии(ЭлементыФормы[ИмяРеквизитаСписка], мТип, ЭлементыФормы);
    КонецЕсли;
    

    Показать

    1б. и процедурой обрабатываю каждый тип

    Процедура ТабличноеПолеПриОткрытии(мТабличноеПоле, мТип, ЭлементыФормы)
    
    Если мТип = Тип(«ДокументСписок.РеализацияТоваровУслуг») Тогда
    ДокументСписок_РеализацияТоваровУслуг(мТабличноеПоле, ЭлементыФормы);

    1в. Если по колонке, добавленно программным способом. требуется будет устанавливать отбор — предусматриваем такую возможность

    мОтбор = мТабличноеПоле.НастройкаОтбора.Найти(«ЕстьОригиналДокумента»);
    Если мОтбор = Неопределено тогда
    мОтбор = мТабличноеПоле.НастройкаОтбора.Добавить(«ЕстьОригиналДокумента», Истина);
    КонецЕсли;
    мОтбор.Доступность = Истина;
    

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

    мОбъект = ЭтаФорма.ЭтотОбъект;
    
    ЭтоСправочник = Метаданные.Справочники.Содержит(мОбъект.Метаданные());
    
    Если ЭтоСправочник И мОбъект.ЭтоГруппа Тогда
    Возврат;
    КонецЕсли;

    2в. После обработки формы возвращаемся (активизируем) текущую страницу панели формы

    ЭлементыФормы = ЭтаФорма.ЭлементыФормы;
    
    Если ТипЗнч(мОбъект) = Тип(«ДокументОбъект.ПоступлениеТоваровУслуг») Тогда
    мТекущаяСтраница = ЭлементыФормы.ОсновнаяПанель.ТекущаяСтраница;
    ПоступлениеТоваровУслуг(ЭлементыФормы, ЭтаФорма, мОбъект);
    ЭлементыФормы.ОсновнаяПанель.ТекущаяСтраница = мТекущаяСтраница;

    P.S. Кстати, некоторое время назад от уважаемой Евгения Карук (ekaruk) была интересная статья о программном восстановлении расположения колонок в табличных частях управляемых форм, в случае, если пользователь скрыл колонки путем настройки списка

    https://infostart.ru/public/259747/

    Reply
  2. dima_home

    Спасибо за дополнение. Хорошо, когда можно собрать все сведения о программировании форм в одном месте.

    Reply
  3. script

    Все это интересно до того момента когда новому элементу, размещенному на форме программно, нужно назначить обработчик одного из событий. Вот тут все и заканчивается, потому что процедуру-обработчик нужно полюбому разместить в модуле формы. И тогда становится понятным, что самым удобным способом является подмена стандартных обработчиков событий формы на свои. Эта методика подробно описана в статье: Методика переопределения и вызова обработчиков событий формы в 1С 8 и показала свою незаменимость

    Reply
  4. dima_home

    (3)

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

    Ну я тут с вами не могу согласиться.

    Исходя из личной практики:

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

    Более того, незначительная часть событий «ПриИзменении» можно привязать к стандартным процедурам, вызываемым из других стандартных реквизитов на форме, когда там и так выполняются те действия, которые вам надо проделать ( например «ПриИзмененииТабличнойЧасти»)

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

    Процедура ПриИзмененииНовогоРеквизита(Элемент)
    ИТ_РаботаСФормой.ПриИзмененииНовогоРеквизита(Элемент, ЭлементыФормы);
    КонецПроцедуры
    

    чем городить предложенную методологию.

    Хотя, как говориться, на вкус и цвет…

    Тоже касается, когда приходится добавлять на форму новые кнопки.

    Reply
  5. pm74

    (3) можно по принципу «чтобы купить что-то полезное нужно продать нужно продать что-то бесполезное » , другими словами в типовых любят делать вызовы общих модулей на команды формы , которые можно слегка подправить

    Reply
  6. dima_home

    (5)

    которые можно слегка подправить

    В каждом случае решение индивидуально — что выгоднее, то и надо делать. Только рассматривая выгоду, всегда нужно учитывать удобство дальнейшего обновления.

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

    Reply
  7. ILM

    Так и хочется написать: — Господя, а ЭТО то тут зачем?

    В УПП и КА 5 лет уже ничего не меняется. Куча форм переделаны на сто рядов и проблем с обновлением нет совсем никаких. А тут на тебе откровение свыше. Программное добавление элементов на форму. Я бы умер поддерживать такими «программными средствами» нашу УПП с доработками по ТОС, планированию спроса, управлению качеством, раздельным учетом, требованиями ГОЗ и т.д. в одно лицо

    Reply
  8. dima_home

    (7)

    В УПП и КА 5 лет уже ничего не меняется.

    -Мм, да вы батенька либо в упр. учете застряли или на производстве только табуретки из демо-версии собираете.

    Не обижайтесь… но серьезно…

    1. Посту уже больше года.

    2. УПП будет поддерживаться еще до 2022 года, как и мы, многие производители до последнего будут отодвигать переход на ЕРП2, хоть его и приобрели.

    3. А по поводу не меняется: наберите в гугле изменения налогового/трудового законодательства, акцизы табака (у нас), алкоголь, онлайн кассы, маркировка (будут изменения к декабрю).

    А вообще каждый сам для себя решает, как вести изменения в 1С.

    Я лишь делился опытом, который использовал ранее и использую сейчас.

    Reply
  9. ILM

    (8) У нас уникальное научно-техническое производство не имеющее аналогов в России. Таких заводов всего три в мире, а технологий всего две в Америке и в России — это к «табуреткам» если что. В УПП у нас считается налог на прибыль, и зачем нам эта ЕРП? Её дорабатывать придётся пару лет просто до уровня нашей УПП пятилетней давности.

    Онлайн-кассы у нас две штуки в столовой стоит, а табак, алкоголь и т.д. это точно не к нам.

    (7) Поддержка программных изменений форм и их доработка занимает в разы больше времени.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *