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 )); КонецЦикла;
Возврат МассивСтрок ;
КонецФункции
На данном этапе, все уже готово для использования. Вот видео-пример использования механизма.
Только для существующего объекта. Подготовка доп.данных, зависящих от данных объекта. Объект - основной элемент открываемой формы; ТекущийОбъект - объект, прочитанный из БД (доступны экспортные методы объекта)
ОбработкаЗаполнения()(1)
Только для нового объекта. Начальное заполнение объекта данными. Доступны ДанныеЗаполнения (ссылка на объект-основание либо структура отбора). В случае "СтандартнаяОбработка = Истина", после обработки заполнения, обрабатываются сначала ДанныеЗаполнения, затем ЗначенияЗаполнения
ПриСозданииНаСервере()
Окончательная подготовка формы (ее представления) к открытию
ПриОткрытии()
Действия, связанные с открытием, которые на сервере выполнить невозможно; выполняемые тогда, когда форма наверняка открывается. Последний обработчик перед открытием, в котором можно отказаться от открытия
2. Запись объекта из формы
ПередЗаписью()
Анализ готовности вспомогательных данных для записи объекта
1. ОбработкаПроверкиЗаполненияНаСервере()
Проверка данных, не относящихся к объекту. Параметр ПроверяемыеРеквизиты содержит массив имен реквизитов формы
2. ОбработкаПроверкиЗаполнения()
Всё, что относится к проверкам реквизитов основного объекта БД. Параметр ПроверяемыеРеквизиты содержит массив имен реквизитов объекта
ПередЗаписьюНаСервере()
Объект - основной реквизит формы объекта; ТекущийОбъект - объект, который реально будет записан в БД. Анализировать данные и дозаполнять реквизиты нужно через ТекущийОбъект, модификация Объекта ни к чему не приведет. Обработчик вызывается только при записи из формы
ПередЗаписью()
Вызывается при любом способе записи. Данные объекта записываются в БД, но транзакция не закрывается
ПриЗаписи()
Выполняются действия над доп.данными, которые неразрывно связаны с основными данными объекта
ПриЗаписиНаСервере()
Предназначение аналогично ПриЗаписи(), но при обработке доп.данных можно использовать данные формы. ТекущийОбъект - данные, которые были записаны в БД, работать следует именно с ним; Объект - данные основного реквизита формы, которые были до записи, его модификация бесполезна. Если это запись нового объекта, то у Объект свойство Ссылка пустое, а у ТекущийОбъект уже заполнено
ПослеЗаписиНаСервере()
Действия над формой, которые выполняются только в том случае, когда объект гарантированно записан. ТекущийОбъект загружен в Объект, и теперь следует работать с Объектом, т.к. ТекущийОбъект будет уничтожен после обработчика. Но его можно использовать для вызова экспортных методов объекта
ПослеЗаписи()
Действия, которые невозможно выполнить на сервере, или требующие интерактивного взаимодействия с пользователем. Объект гарантированно записан
3. Закрытие формы
ПередЗакрытием()
Проверка, можно закрыть форму или нельзя. Если отключить стандартную обработку, то форма будет закрыта, независимо от модифицированности
ПриЗакрытии()
Выполняется, если форма 100% закрывается. На момент вызова пользователь форму уже не видит
1) Вызывается только один из двух обработчиков, в зависимости от того, записан объект в БД или создаётся новый;
2) Параметр Отказ нужен для отказа от записи объекта (не будет вызываться обработчик ПередЗаписьюНаСервере()). Чтобы отказаться от проверки заполнения, нужно очистить массив ПроверяемыеРеквизиты. При этом, если в обработчике [1] удалить из массива значение Объект, то обработчик [2] вызываться не будет. Если проверяемый реквизит привязан к функциональной опции, то при ее отключении заполнение реквизита проверяться не будет (имя отсутствует в массиве ПроверяемыеРеквизиты);
При совершении любых действий пользователем платформа 1С генерирует программные события. Как правило генерируется не одно событие, а целая цепочка событий. Задача программиста правильно разместить программный код в событиях, чтобы добиться ожидаемого поведения от программы. Однако начинающему программисту по 1С это не просто будет сделать, по причинам перечисленным ниже.
В управляемой форме могут быть сгенерированы события: ПриЧтенииНаСервере, ПриСозданииНаСервере, ПриОткрытии и т.д.
События в управляемой форме генерируются на клиенте и на сервере: ПередЗаписью, ПередЗаписьюНаСервере.
События вызываются в разных модулях: ФормаЭлемента, МодульОбъекта, МодульМенеджера.
Некоторые события могут вызываться несколько раз, если в списке несколько элементов справочника, например: ОбработкаПолученияПредставления.
Управляемая форма может быть открыта в результате выполнения разных действий пользователя при этом цепочки вызова событий будут различаться. При любых следующих действиях пользователя со справочником будет открыта управляемая форма: создание нового элемента, копирование элемента, изменение существующего элемента справочника.
События также генерируются элементами формы: при добавлении строки в табличную часть, при редактировании строки табличной части, при активизации строки или поля, при выборе элемента справочника в поле ввода и т.д.
Чтобы лучше понять логику и последовательность вызываемых событий, можно воспользоваться разработкой «Изучение событий» прикрепленной к данной статье. Зная контекст вызова события, последовательность событий и действия которые будет выполнять пользователь будет легче понять в какой обработчик событий лучше всего поместить свой программный код.
Инструкция к применению программы «Изучение событий»
Программа «Изучение событий» показывает события, которые генерирует платформа 1С при интерактивных действиях пользователя. Принцип работы следующий, пользователь открывает справочник, программа показывает цепочку событий. Пользователь помечает на удаление элемент справочника, программа выводит последовательность возникающих событий. События отображаются с небольшой задержкой по умолчанию 3 секунды, это необходимо чтобы отделить одну цепочку событий от другой цепочки событий. Поэтому выполнять интерактивные действия нужно «неторопливо».
Все события отображаются в специальном окне «Последние события». В нем можно включить или выключить запись событий. По умолчанию при первом открытии запись событий включена. Окно «Последние события» советую закрепить снизу экрана сразу при запуске программы, для удобного просмотра событий.
Программа не может сама определить каким действием вызвана цепочка событий, советую в поле «Действие причина» набирать с клавиатуры названия ваших последних действий, например «Открыта форма списка справочника», «Помечен на удаление элемент в списке справочника» и т.д. Это облегчит затем анализ действий и событий.
События записываются и отображаются для объектов, размещенных в разделе «Трассировка событий» при условии включенной записи событий в форме «Последние события».
Все записанные события можно посмотреть через «Отчет по событиям», который находится в разделе «Сервис».
Чтобы быстро очистить все записанные действия и события в разделе «Сервис» выбираем «Очистить события и действия».
Работа программы тестировалась на 1С платформе версии «8.3.9».
Программа «Изучение событий» может полезна как новичкам, так и программистам с опытом.
Читайте также: