1с переопределить стандартную команду

Обновлено: 07.07.2024

Введение в управляемая форма 1С реквизиты элементы команды

Рекомендуется модифицировать управляемые формы типового решения 1С программно для удобного будущего обновления и исключения конфликтов, а также для удобной работы с изменениями и надежности при использовании механизма расширений.
В некоторых типовых конфигурациях 1С (ЕРП 2, УТ 11) используется механизм упрощенного изменения конфигурации. Статьи о типовом механизме можно найти в разделе полезных ссылок. Данный механизм используется в БСП, и его необходимо знать при модификации типовых конфигураций.
При добавлении элементов на форму программно можно отредактировать практически любое свойство из панель свойств, которое можно установить вручную в конфигураторе.
Также все описанные в текущем разделе процедуры и функции находятся во внешней обработке УпрФормы.

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

В теле модуля формы:

А в новой процедуре нужно добавить вызов основной, если такая процедура есть.

Аналогично можно поступить и с обработчиками элементов формы:

Программное создание групп формы.

Доступные виды групп формы:


Программное добавление команды на форму.

Удалить команду можно при помощи метода коллекции формы команд: Команды.Удалить(<Команда>). Удалять можно только те команды, которые были созданы программно.

Программное создание декораций форм.

Программное добавление реквизита на форму.

Добавлять новые реквизиты в управляемую форму и удалять необходимо с помощью метода ИзменитьРеквизиты(), куда в параметры передается массив добавляемых реквизитов и массив удаляемых. Удалять при этом можно только те реквизиты, которые были созданы программно.

Вывод реквизитов на форму.

Вызов процедур при создании на сервере 1С

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

Некоторые советы при программном редактировании формы


Итак, взглянем на получившийся результат. Все элементы на форме созданы программно:

Предлагаемый метод состоит в том, чтобы в модуле формы в процедуре «ПриСозданииНаСервере» переопределить обработчики событий для этой формы, которые будут вызывать старые обработчики (если это нужно) и выполнить нужный код до и после этого вызова. Так же обеспечить возможность вносить изменения в поведения программы на лету – без отключения от базы пользователей и без использования динамического обновления конфигурации, то есть изменения уже будут готовы к использованию. Что же для этого нужно? Рассматриваемый пример работает на конфигурации «Управление торговлей, редакция 11», для любой другой конфигурации адаптировать его не составит большого труда.

1. Нужно создать общий модуль МодульПереназначенияОбра ботчиков, вот такой он у меня:

// Общая процедура перед переназначения обработчиков
//
// Параметры:
// УправляемаяФорма – УправляемаяФорма – Управляемая форма.
//
Процедура ПереназначитьОбработчики ( УправляемаяФорма ) Экспорт
Если ТипЗнч ( УправляемаяФорма ) = Тип ( "УправляемаяФорма" ) Тогда
ОбщаяВнешняяОбработка = ПолучитьВнешнийОбъект ( "Библиотека внешних обработок" );

ВнешняяОбработкаСерийныеНомера = ПолучитьВнешнийОбъект ( "Серийные номера" );
ИмяВнешнейОбработкиСерийныеНомера = ПолучитьИмяВнешнегоОбъекта ( "Серийные номера" );
ВнешняяОбработкаСерийныеНомера . ПодготовитьСерийныеНомераКРаботе ( УправляемаяФорма , ОбщаяВнешняяОбработка , ИмяВнешнейОбработкиСерийныеНомера );

ОбщаяВнешняяОбработка . ПодменитьДействиеУправляемоеПриложение ( УправляемаяФорма , "ПриЗакрытии" , , "ВыполнитьОткатОбработчиков" );

//Пример как можно изменить свойства управляемой формы
УправляемаяФорма . ПоведениеКлавишиEnter = ТипПоведенияКлавишиEnter . ПереходПоЭлементамФормы ;
КонецЕсли;
КонецПроцедуры

// Получаем внешнюю обработку или внешний отчет.
//
// Параметры:
// ИмяВнешнегоОбъекта – Строка - имя внешнего объекта;
// ЭтоОтчет – Булево – Ложь (Внешняя обработка), Истина (Внешний отчет).
//
// Возвращаемое значение:
// – ВнешняяОбработка или ВнешнийОтчет
//
Функция ПолучитьВнешнийОбъект ( ИмяВнешнегоОбъекта , ЭтоОтчет = Ложь) Экспорт
Ссылка = Справочники . ДополнительныеОтчетыИОбработки . НайтиПоНаименованию ( ИмяВнешнегоОбъекта );
Если Ссылка = Неопределено Тогда
ВызватьИсключение "Внешний объект с именем не найден: " + ИмяВнешнегоОбъекта ;
КонецЕсли;
ДвоичныеДанные = Ссылка . ХранилищеОбработки . Получить ();
АдресХранилища = ПоместитьВоВременноеХранилище ( ДвоичныеДанные );
ИмяВнОбработки = ?( ЭтоОтчет , ВнешниеОтчеты , ВнешниеОбработки ). Подключить ( АдресХранилища , , Ложь);
ОбработкаОбъект = ?( ЭтоОтчет , ВнешниеОтчеты , ВнешниеОбработки ). Создать ( ИмяВнОбработки );
Возврат ОбработкаОбъект ;
КонецФункции

// Получаем имя внешней обработки или внешнего отчета.
//
// Параметры:
// ИмяВнешнегоОбъекта – Строка - имя внешнего объекта;
// ЭтоОтчет – Булево – Ложь (Внешняя обработка), Истина (Внешний отчет).
//
// Возвращаемое значение:
// – Строка - Имя внешней обработки или отчета.
//
Функция ПолучитьИмяВнешнегоОбъекта ( ИмяВнешнегоОбъекта , ЭтоОтчет = Ложь) Экспорт
Ссылка = Справочники . ДополнительныеОтчетыИОбработки . НайтиПоНаименованию ( ИмяВнешнегоОбъекта );
Если Ссылка = Неопределено Тогда
ВызватьИсключение "Внешний объект с именем не найден: " + ИмяВнешнегоОбъекта ;
КонецЕсли;
ДвоичныеДанные = Ссылка . ХранилищеОбработки . Получить ();
АдресХранилища = ПоместитьВоВременноеХранилище ( ДвоичныеДанные );
Возврат ?( ЭтоОтчет , ВнешниеОтчеты , ВнешниеОбработки ). Подключить ( АдресХранилища , , Ложь);
КонецФункции

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

2. Далее, нужно загрузить общую внешнюю обработку в режиме предприятия. Код обработки:

// Функция добавляет элемент в коллекцию элементов формы и возращает его.
//
// Параметры:
// ЭлементыФормы – ВсеЭлементыФормы – Содержит коллекцию всех элементов управляемой формы;
// Параметры – Структура – параметры добавляемого элемента;
// Родитель – ГруппаФормы, ТаблицаФормы, УправляемаяФорма – родитель добавляемого элемента.
//
// Возвращаемое значение:
// – ДекорацияФормы, ГруппаФормы, КнопкаФормы, ТаблицаФормы, ПолеФормы – элемент управляемой формы.
//
Функция ДобавитьЭлементВКоллекциюЭлементовФормы ( ЭлементыФормы , Параметры , Родитель = Неопределено) Экспорт

Перем ИмяЭлемента , ТипЭлемента ;

Если НЕ ТипЗнч ( Параметры ) = Тип ( "Структура" ) Тогда
ВызватьИсключение "Параметры элемента формы не заданы!" ;
КонецЕсли;

Если НЕ Параметры . Свойство ( "Имя" , ИмяЭлемента ) Тогда
ВызватьИсключение "Имя элемента формы не задано!" ;
КонецЕсли;

Если НЕ Параметры . Свойство ( "ТипЭлемента" , ТипЭлемента ) Тогда
ВызватьИсключение "Тип элемента формы не задан!" ;
КонецЕсли;

Если НЕ Родитель = Неопределено Тогда
Если ТипЗнч ( Родитель ) <> Тип ( "ГруппаФормы" )
И ТипЗнч ( Родитель ) <> Тип ( "ТаблицаФормы" )
И ТипЗнч ( Родитель ) <> Тип ( "УправляемаяФорма" ) Тогда
ВызватьИсключение "Родитель должен иметь один из перечисленных типов: ГруппаФормы; ТаблицаФормы; УправляемаяФорма." ;
КонецЕсли;
КонецЕсли;

ЭлементФормы = ЭлементыФормы . Добавить ( ИмяЭлемента , ТипЭлемента , Родитель );
ЗаполнитьЗначенияСвойств ( ЭлементФормы , Параметры );
Возврат ЭлементФормы ;

// Функция добавляет команду в коллекцию команд формы и возращает его.
//
// Параметры:
// Команды – КомандыФормы – Содержит коллекцию всех элементов управляемой формы;
// Параметры – Структура – параметры добавляемой команды.
//
// Возвращаемое значение:
// – КомандаФормы – команда управляемой формы.
//
Функция ДобавитьКомандуВКоллекциюКомандФормы ( Команды , Параметры ) Экспорт

Если НЕ ТипЗнч ( Параметры ) = Тип ( "Структура" ) Тогда
ВызватьИсключение "Параметры команды не заданы!" ;
КонецЕсли;

Если НЕ Параметры . Свойство ( "Имя" , ИмяЭлемента ) Тогда
ВызватьИсключение "Имя команды не задано!" ;
КонецЕсли;

Команда = Команды . Добавить ( ИмяЭлемента );
ЗаполнитьЗначенияСвойств ( Команда , Параметры );
Возврат Команда ;

Процедура ПереместитьЭлементВКоллекциюЭлементовФормы ( ЭлементыФормы , ИмяЭлемента , ИмяРодителя , МестоРасположения ) Экспорт
ЭлементыФормы . Переместить ( ЭлементыФормы . Найти ( ИмяЭлемента ), ЭлементыФормы . Найти ( ИмяРодителя ), ЭлементыФормы . Найти ( МестоРасположения ));
КонецПроцедуры

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

Объект = Форма ;
ИмяЭлементаФормы = "" ;
Если НЕ ПустаяСтрока ( ПолноеИмяЭлементаФормы ) Тогда

МассивФрагментов = РазобратьСтрокуВМассивПоРазделителю ( ПолноеИмяЭлементаФормы );
ИмяЭлементаФормы = МассивФрагментов [ 0 ];
Объект = Форма . Элементы . Найти ( ИмяЭлементаФормы );
Если Объект = Неопределено Тогда
ВызватьИсключение "Элемент формы: " + ИмяЭлементаФормы + " не найден!" ;
КонецЕсли;

Если МассивФрагментов . Количество () > 1 Тогда
ИмяЭлементаФормы = ИмяЭлементаФормы + МассивФрагментов [ 1 ];
Если ТипЗнч ( Объект ) = Тип ( "ТаблицаФормы" ) Тогда
Объект = Объект . Колонки [ МассивФрагментов [ 1 ]]. ЭлементУправления ;
ИначеЕсли ТипЗнч ( Объект ) = Тип ( "КоманднаяПанель" ) Тогда
Объект = Объект . Кнопки [ МассивФрагментов [ 1 ]];
Иначе
ВызватьИсключение "Ошибка на этапе получения элемента формы. Тип значения(" + ТипЗнч ( Объект ) + ")" ;
КонецЕсли;
КонецЕсли;
КонецЕсли;

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

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

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

Если ОбработкаИсключений И НЕ СтароеДействие = Неопределено Тогда
ВызватьИсключение "Конфликт обработчиков события """ + ИмяСобытияФормы + """ объекта """ + Строка ( Объект ) + """" ;
КонецЕсли;

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

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

// Возвращает старый обработчик события формы.
//
// Параметры:
// Форма – УправляемаяФорма – Управляемая форма;
// ИмяСобытияФормы – Строка – имя события;
// ПолноеИмяЭлементаФормы – Строка – полное имя элемента формы;
// СтароеДействие - Строка - имя процедуры обработчика.
//
Процедура ОткатитьДействиеУправляемоеПриложение ( Форма , ИмяСобытияФормы = "" , ПолноеИмяЭлементаФормы = "" , СтароеДействие ) Экспорт

Объект = Форма ;
ИмяЭлементаФормы = "" ;
Если НЕ ПустаяСтрока ( ПолноеИмяЭлементаФормы ) Тогда

МассивФрагментов = РазобратьСтрокуВМассивПоРазделителю ( ПолноеИмяЭлементаФормы );
ИмяЭлементаФормы = МассивФрагментов [ 0 ];
Объект = Форма . Элементы . Найти ( ИмяЭлементаФормы );
Если Объект = Неопределено Тогда
ВызватьИсключение "Элемент формы: " + ИмяЭлементаФормы + " не найден!" ;
КонецЕсли;

Если МассивФрагментов . Количество () > 1 Тогда
ИмяЭлементаФормы = ИмяЭлементаФормы + МассивФрагментов [ 1 ];
Если ТипЗнч ( Объект ) = Тип ( "ТаблицаФормы" ) Тогда
Объект = Объект . Колонки [ МассивФрагментов [ 1 ]]. ЭлементУправления ;
ИначеЕсли ТипЗнч ( Объект ) = Тип ( "КоманднаяПанель" ) Тогда
Объект = Объект . Кнопки [ МассивФрагментов [ 1 ]];
Иначе
ВызватьИсключение "Ошибка на этапе получения элемента формы. Тип значения(" + ТипЗнч ( Объект ) + ")" ;
КонецЕсли;
КонецЕсли;

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

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

// Функция разбивает строку разделителем.
//
// Параметры:
// Строка - Строка - которую разбиваем;
// Разделитель - Строка - символ-разделитель.
//
// Возвращаемое значение:
// - Массив - содержащий фрагменты, на которые разбивает строку разделитель.
//
Функция РазобратьСтрокуВМассивПоРазделителю ( Строка , Разделитель = "." ) Экспорт
МассивСтрок = Новый Массив ;
СтрокаЗамены = СтрЗаменить ( Строка , Разделитель , Символы . ПС );
Для i = 1 По СтрЧислоСтрок ( СтрокаЗамены ) Цикл МассивСтрок . Добавить ( СтрПолучитьСтроку ( СтрокаЗамены , i )); КонецЦикла;
Возврат МассивСтрок ;
КонецФункции

На данном этапе, все уже готово для использования. Вот видео-пример использования механизма.

Одним из требований для прохождения аудита расширения в модели сервиса является программная модификация управляемых форм без заимствования самой формы в расширение.

Мы рассмотрим основные составляющие этой задачи: добавление реквизитов, добавление элементов формы и назначение обработчиков событий элементов формы.

Добавление реквизитов

Для добавления реквизитов используется метод объекта ФормаКлиентскогоПриложения

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

Переменная ДобавляемыеРеквизиты является массивом объектов типа РеквизитФормы .

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

Процедуру ИзменитьРеквизиты логично вызывать из обработчика ПриСозданииНаСервере , но т.к. мы не заимствуем форму в расширение, то следует найти другую точку входа. Для конфигураций УТ 11, КА 2 и ERP 2 существует типовой механизм упрощенного изменения конфигураций. Нас интересует модуль МодификацияКонфигурацииПереопределяемый , в состав которого входит процедура

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

Для остальных конфигураций придется переопределять другие процедуры. Например

Использование той или иной процедуры следует проверить в модуле редактируемой формы.

Изменение элементов формы

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

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

По аналогии с добавлением реквизитов, данный код можно выполнять в функциях МодификацияКонфигурацииПереопределяемый.ПриСозданииНаСервере (УТ, КА, ERP) , ПодключаемыеКоманды.ПриСозданииНаСервере или ВерсионированиеОбъектов.ПриСозданииНаСервере .

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

Обработка событий формы

Выполнить код по событию элемента формы можно двумя способами:

  • Создать команду, указать для этой команды имя обработчика события и назначить эту команду элементу формы
  • Выполнить метод УстановитьДействие элемента формы, чтобы указать имя обработчика события в модуле формы

Оба метода предполагают наличие в модуле формы процедуры с сигнатурой, соответствующей обработчику события. Для первого способа в модуле формы должна быть клиентская процедура, принимающая единственный аргумент - Команда. Для второго - всё зависит от события, для которого выполняется обработчик. Так, например, для события ПриИзменении элемента формы с типом ПолеВвода будет требоваться процедура, принимающая единственный аргумент - ЭлементФормы . А для события ПередНачаломДобавления таблицы формы - целых 6 аргументов ( ЭлементФормы , Отказ , Копирование , Родитель , ЭтоГруппа , Параметр ). Поэтому для некоторых событий попросту невозможно подобрать соответствующие клиентские методы в модуле формы и заимствования формы в расширение не избежать.

Для самых простых случаев (команда или событие без параметров) можно использовать следующие комбинации обработчиков и переопределяемых процедур:

  • обработчик Подключаемый_ВыполнитьПереопределяемуюКоманду с переопределением процедуры МодификацияКонфигурацииКлиентПереопределяемый.ВыполнитьПереопределяемуюКоманду для УТ, КА и ERP;
  • обработчик Подключаемый_ВыполнитьКоманду с переопределением процедуры ПодключаемыеКомандыКлиент.ВыполнитьКоманду

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

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

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

Полезные советы

Работа с динамическими списками

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

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

Переопределение открываемой формы

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

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

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

Переопределяемые и поставляемые объекты библиотеки

Область применения: управляемое приложение, мобильное приложение, обычное приложение.

1. С точки зрения возможностей по настройке функциональности библиотеки для работы в конкретной конфигурации-потребителе все объекты библиотеки условно делятся на три категории:

  • Непереопределяемые объекты – «готовые» объекты, которые можно брать и использовать в конфигурации-потребителе «как есть». Их не следует изменять в конфигурации-потребителе, чтобы они были гарантированно одинаковы во всех конфигурациях, основывающихся на данной библиотеке. Более того, такие объекты обязательно должны присутствовать в конфигурациях, использующих библиотеку. Примеры: справочник Пользователи .
  • Переопределяемые объекты – «изменяемые» объекты для настройки библиотеки под конкретную конфигурацию. Они могут или должны быть изменены в конфигурации-потребителе. С помощью таких объектов решаются задачи изменения поведения библиотечной функциональности, ее параметризации спецификой конфигурации-потребителя, а также для подключения библиотечной функциональности к объектам конфигурации-потребителя.
  • Определители типов – объекты-«классификаторы», которые не имеют базовой реализации. Предназначены для формирования единого пространства имен в конфигурациях, а реализация при этом может как угодно сильно различаться в конфигурациях-потребителях. Например: справочники-классификаторы, в которых определено только «название»; сущность «организация» должна быть везде представлена справочником с именем Организации и т.п.

2. Рекомендуется устанавливать для объектов этих категорий следующие правила поставки :

  • Непереопределяемые объекты – «изменения не рекомендуются»;
  • Переопределяемые объекты и определители типов – «изменения разрешены».

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

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

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

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

    3.1. Переопределяемые общие модули следует называть с постфиксом Переопределяемый .

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

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

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

    Функция ПапкаФайлов(ВладелецФайловСсылка) Экспорт

    СтандартнаяОбработка = Истина;
    Результат = Неопределено;
    ПапкиФайловПереопределяемый.ПриПолученииПапкиФайлов(ВладелецФайловСсылка, Результат, СтандартнаяОбработка);

    Если СтандартнаяОбработка Тогда
    // реализация по умолчанию
    Результат = .
    КонецЕсли;
    Возврат Результат;

    а в модуле ПапкиФайловПереопределяемый - процедура-обработчик ПриПолученииПапкиФайлов :

    // Вызывается из библиотеки при необходимости получить папку файлов для указанного владельца.
    //
    // Параметры:
    // ВладелецФайловСсылка – ЛюбаяСсылка - владелец файлов, для которого нужно вернуть папку.
    // ПапкаФайлов – СправочникСсылка.ПапкиФайлов - в этот параметр нужно записать результат.
    // СтандартнаяОбработка – Булево - по умолчанию, Истина. В этом случае папка будет получена способом по умолчанию.
    // Если значение параметра установить в Ложь, то в этой процедуре можно реализовать свой способ,
    // которым в конфигурации получают папки файлов.
    //
    Процедура ПриПолученииПапкиФайлов(ВладелецФайловСсылка, ПапкаФайлов, СтандартнаяОбработка) Экспорт

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

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

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

    Функция НастройкаПараметровРаботы() Экспорт

    ПараметрыРаботы = Новый Структура;
    // если настройки по умолчанию не подходят, то измените их.
    ПараметрыРаботы.Вставить("ПоказыватьЕдинственныйРаздел", Ложь);
    ПараметрыРаботы.Вставить("ЗадаватьДатуДляПрочихРазделов", Ложь);
    ПараметрыРаботы.Вставить("ИспользоватьВнешнихПользователей", Ложь);
    Возврат ПараметрыРаботы;

    // Позволяет настроить работу подсистемы.
    //
    // Параметры:
    // ПараметрыРаботы - Структура - содержит свойства:
    // * ПоказыватьЕдинственныйРаздел - Булево - по умолчанию Ложь.
    // * ЗадаватьДатуДляПрочихРазделов - Булево - по умолчанию Ложь.
    // * ИспользоватьВнешнихПользователей - Булево - по умолчанию Ложь.
    //
    Процедура ПриПолученииНастроекПараметровРаботы(ПараметрыРаботы) Экспорт

    а установку значений по умолчанию перенести в непереопределяемый общий модуль библиотеки:

    ПараметрыРаботы = Новый Структура;
    // настройки по умолчанию
    ПараметрыРаботы.Вставить("ПоказыватьЕдинственныйРаздел", Ложь);
    ПараметрыРаботы.Вставить("ЗадаватьДатуДляПрочихРазделов", Ложь);
    ПараметрыРаботы.Вставить("ИспользоватьВнешнихПользователей", Ложь);

    // а теперь запросим конфигурацию-потребитель на случай,
    // если эти умолчания не устраивают
    МояБиблиотекаПереопределяемый.ПриПолученииНастроекПараметровРаботы(ПараметрыРаботы);
    Возврат ПараметрыРаботы;

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

    Читайте также: