В этом материале разберем основы доработок кода в расширении.
Мы рассмотрим практическое применение расширений на примере обработки для загрузки курсов валют с сайта Центрального Банка. В основной конфигурации у нас есть готовая форма, которая умеет инициализировать список валют, отправлять HTTP-запрос, фильтровать результат и выводить данные на экран. С помощью расширения мы добавим новые возможности, используя встроенные инструменты платформы. Скачать базу с примером расширения можно по ссылке.
Типы вызова
Всего существует четыре типа вызова, и когда мы добавляем метод в расширение, платформа показывает нам диалог, где мы должны выбрать, какой тип вызова у нас будет.
Подготовка данных перед началом работы: аннотация Перед
Иногда нам требуется выполнить предварительные действия перед тем, как сработает стандартный метод. Для этого применяется аннотация &Перед. Наш код выполнится первым, а сразу после него платформа автоматически запустит оригинальный метод.
В нашей обработке есть процедура ЗаполнитьНачальныеЗначения, которая заполняет список валют при создании формы. Если эта процедура будет вызвана повторно во время работы формы, новые строки просто допишутся в конец, из-за чего список валют продублируется. Мы решим эту проблему, очистив коллекцию перед запуском основного алгоритма.
Для этого находим нужный метод в основной конфигурации, жмем по его названию правой кнопкой, и в контекстном меню выбираем "Добавить в расширение". Тип вызова выбираем "Вызывать перед":
&НаСервере &Перед("ЗаполнитьНачальныеЗначения") Процедура Д_ЗаполнитьНачальныеЗначения() ВыбранныеВалюты.Очистить(); КонецПроцедуры
Дополнение стандартных алгоритмов: аннотация После
Прямой противоположностью предыдущему механизму является аннотация &После. Написанный под ней код сработает сразу после того, как оригинальная процедура полностью завершит свое выполнение. Это очень удобно, когда базовую логику нужно дополнить новыми данными.
Вернемся к той же процедуре инициализации списка валют. Основная конфигурация добавляет в список доллар, евро, юань, белорусский рубль и тенге. Мы хотим расширить этот список и предложить пользователю дополнительные валюты — турецкую лиру и армянский драм.
&НаСервере &После("ЗаполнитьНачальныеЗначения") Процедура Д_ЗаполнитьНачальныеЗначения1() ВыбранныеВалюты.Добавить("TRY", "Турецкая лира", Истина); ВыбранныеВалюты.Добавить("AMD", "Армянский драм", Ложь); КонецПроцедуры
Сначала отработает оригинальный код, создав базовый набор строк, а затем наш обработчик допишет в конец таблицы еще две валюты.
Обратите внимание, что аннотациями Перед и После мы можем расширять одну и ту же процедуру одновременно.
Полное управление логикой и подмена результатов: аннотация Вместо
Бывают ситуации, когда логику стандартного метода нужно изменить кардинально. Для этого существует аннотация &Вместо. Она полностью заменяет оригинальную функцию или процедуру нашей собственной.
При этом внутри нашего метода мы можем использовать функцию ПродолжитьВызов(). Она запускает оригинальный алгоритм, возвращая его результат. Это позволяет нам не переписывать код заново, а лишь «обернуть» его в свою логику.
Давайте доработаем функцию ОтфильтроватьВалюты. По умолчанию, если пользователь не отметил галочкой ни одну валюту, оригинальная функция выводит предупреждение и возвращает значение Неопределено, из-за чего загрузка прекращается. Мы перепишем это поведение: если пользователь забыл выбрать валюты, мы перехватим предупреждение и загрузим курсы доллара и евро в качестве страховки.
&НаСервере &Вместо("ОтфильтроватьВалюты") Функция Д_ОтфильтроватьВалюты() Результат = ПродолжитьВызов(); Если Результат = Неопределено Тогда ПолучитьСообщенияПользователю(Истина); РезервныйСписок = Новый Массив; РезервныйСписок.Добавить("USD"); РезервныйСписок.Добавить("EUR"); Возврат РезервныйСписок; КонецЕсли; Возврат Результат; КонецФункции
Точечные правки в сложном коде: аннотация ИзменениеИКонтроль
Если метод очень большой и сложный, использовать аннотацию &Вместо становится небезопасно. Если при обновлении поставщик конфигурации изменит логику этого метода, наша заменяющая функция в расширении продолжит работать по-старому, что может привести к скрытым ошибкам.
Для таких случаев создана аннотация &ИзменениеИКонтроль. Мы копируем оригинальный метод целиком, а нужные строки выделяем специальными операторами. Платформа будет контролировать, чтобы остальной код метода совпадал с основной конфигурацией, и предупредит нас, если там что-то изменится.
Давайте внесем изменения в функцию ПолучитьXMLОтвет. Мы заменим адрес сервера Центрального Банка, убрав поддомен «www», и ограничим время ожидания ответа сервера десятью секундами, чтобы сеанс пользователя не зависал при сетевых сбоях.
&НаСервере &ИзменениеИКонтроль("ПолучитьXMLОтвет") Функция Д_ПолучитьXMLОтвет() СтрокаДата = Формат(ДатаКурса, "ДФ=dd/MM/yyyy"); #Удаление Сервер = "www.cbr.ru"; #КонецУдаления #Вставка Сервер = "cbr.ru"; #КонецВставки Ресурс = "/scripts/XML_daily.asp?date_req=" + СтрокаДата; Попытка #Удаление Соединение = Новый HTTPСоединение(Сервер,,,,,, Новый ЗащищенноеСоединениеOpenSSL()); #КонецУдаления #Вставка // Указываем таймаут в 10 секунд шестым параметром конструктора Соединение = Новый HTTPСоединение(Сервер,,,,, 10, Новый ЗащищенноеСоединениеOpenSSL()); #КонецВставки Запрос = Новый HTTPЗапрос(Ресурс); Ответ = Соединение.Получить(Запрос); Исключение ВызватьИсключение "Не удалось подключиться к сайту ЦБ РФ: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке()); КонецПопытки; Если Ответ.КодСостояния <> 200 Тогда ВызватьИсключение "Ошибка сервера ЦБ РФ. Код состояния: " + Ответ.КодСостояния; КонецЕсли; // 3. Чтение XML с фильтрацией ЧтениеXML = Новый ЧтениеXML; ЧтениеXML.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку()); Возврат ЧтениеXML; КонецФункции
Директивы вставки и удаления четко показывают платформе и другим разработчикам, какие именно строки были скорректированы.
Работа с клиентскими командами через свойства формы
В коде нашего расширения есть еще одна важная процедура: Д_ЗагрузитьКурсыПеред. Она проверяет, не выбрал ли пользователь будущую дату, и выводит предупреждение.
&НаКлиенте Процедура Д_ЗагрузитьКурсыПеред(Команда) Если ДатаКурса > ТекущаяДата() Тогда ПоказатьПредупреждение(, "Вы выбрали будущую дату. Данные за этот день могут быть еще не опубликованы."); КонецЕсли; КонецПроцедуры
Обратите внимание, что над этой процедурой нет текстовых аннотаций программного перехвата. Это связано с тем, что она является обработчиком события формы. Для таких процедур связь настраивается визуально через палитру свойств.
Когда мы заимствуем форму в расширение и переопределяем событие кнопки, конфигуратор предлагает связать его программно или через свойства формы. Мы выбираем связь через свойства с типом вызова «Вызывать перед». Платформа сама прописывает эту зависимость в метаданных формы расширения. Программа понимает, что сначала нужно запустить наш клиентский метод, а затем перейти к оригинальной команде ЗагрузитьКурсы.
Заключение
Понимание логики того, как работают аннотации - Перед, После, Вместо и ИзменениеИКонтроль - позволит вам грамотно проектировать доработки в расширениях, не опасаясь сломать типовой код основной конфигурации, и получать предсказуемые результаты.
Чувствуете, что застряли в основах 1С?
Информация в интернете кажется обрывочной, а на решение простых задач уходят часы? Вы не одиноки. Я запустил Клуб для 1С разработчиков Alexcode.PRO. Внутри - продвинутые статьи, видео, материалы для скачивания, закрытый чат для резидентов и возможность влиять на контент.
