7 февр. 2021 г.

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

 Бывает затруднено динамическое обновление клиентской базы, поэтому часто програмный код, который "не устойчив" пишу на стороне модуля внешней обработки, который потом вызываю в нужном для себе месте. 

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

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

Пример вызова процедуры из параметрами, которая находиться в модуле внешней обработки 

с именем "[ИС] Внешние процедуры и функции".

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

Общий модуль "исОбщегоНазначения" можно посмотреть в этой публикации

Открыть внешнюю обработку из обработки

Нужно, при открытии формы обработки чтобы текущая открытая форма обработки закрывалась и сразу же открывалась внешняя форма обработки.

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

Модуль формы

Процедура КнопкаВыполнитьНажатие(Кнопка)
    // Вставить содержимое обработчика.
КонецПроцедуры

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

Модуль общего модуля который называется исОбщегоНазначения

#Область РаботаСЗапускомВнешнихОтчетовИОбработок

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

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

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

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

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

#КонецОбласти

Пример использования выше процедур при быстром обновлении логики програмы.

Найти объект в базе по УИД

 Один из способов найти по УИДу объект в базе

Функция ПолучитьОбъектПоУИД(УИДОбъекта)  

    СсылкаНаОбъект = Неопределено;
    
    // все объекты по которым можно получить ссылку 
    СписокОбъектовМетаданных = Новый Массив;
    СписокОбъектовМетаданных.Добавить(Справочники);
    СписокОбъектовМетаданных.Добавить(Документы);
    СписокОбъектовМетаданных.Добавить(ПланыВидовХарактеристик);
    СписокОбъектовМетаданных.Добавить(ПланыСчетов);
    СписокОбъектовМетаданных.Добавить(ПланыОбмена);
    СписокОбъектовМетаданных.Добавить(БизнесПроцессы);
    СписокОбъектовМетаданных.Добавить(Задачи);
    
    Для Каждого текСтрМетаданных Из СписокОбъектовМетаданных Цикл   
        Для Каждого текСтрМенеджер Из текСтрМетаданных Цикл 
            СсылкаНаОбъект = текСтрМенеджер.ПолучитьСсылку(УИДОбъекта);
            Если СсылкаНаОбъект.ПолучитьОбъект() <> Неопределено Тогда          
                Возврат СсылкаНаОбъект //нашли
            КонецЕсли;      
        КонецЦикла;
    КонецЦикла;
    
    Возврат СсылкаНаОбъект //не нашли
    
КонецФункции

Программно добавить кнопки на форму

 Есть форма (УФ) на которой размещено две группы 

"Справочники", "Документы"

нужно вывести все справочники и документы из конфигурации в виде кнопок на эту форму в подходящую группу

Результат должен быть таким


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

Соответственно, нужно в ручном режиме добавить процедуры нажатия по примеру

&НаКлиенте
Процедура Действие_Контрагенты(Команда)
    
    ОткрытьФорму("Справочник.Контрагенты.ФормаСписка");
    
КонецПроцедуры

&НаКлиенте
Процедура Действие_Номенклатура(Команда)
    
    ОткрытьФорму("Справочник.Номенклатура.ФормаСписка");
    
КонецПроцедуры


Удалить спецсимволы

 Для удаления спецсимволов используем два подхода:

1.
Функция УбратьЛишниеСимволы(Строка1) Экспорт
    НовСтрока = "";
    ПравильныеСимволы = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnmЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮйцукенгшщзхъфывапролджэячсмитьбю";
    Для Сч = 1 по СтрДлина(Строка1) Цикл
        ТекСимв = Сред(Строка1, Сч, 1);
        Если Найти(ПравильныеСимволы, ТекСимв) > 0 Тогда
            НовСтрока = НовСтрока + ТекСимв;
        КонецЕсли;
    КонецЦикла;
    
    Возврат НовСтрока;
    
КонецФункции   

2.
Функция УбратьЛишниеСимволы(Строка1)
    
    мСпецСимволов = Новый Массив;
    мСпецСимволов.Добавить(",");
    мСпецСимволов.Добавить(".");
    мСпецСимволов.Добавить("\");
    мСпецСимволов.Добавить("=");
    мСпецСимволов.Добавить("-");
    мСпецСимволов.Добавить("_");
    мСпецСимволов.Добавить("/");
    мСпецСимволов.Добавить("!");
    мСпецСимволов.Добавить("@");
    мСпецСимволов.Добавить("#");
    мСпецСимволов.Добавить("$");
    мСпецСимволов.Добавить("%");
    мСпецСимволов.Добавить("^");
    мСпецСимволов.Добавить("&amp;");
    мСпецСимволов.Добавить("""");
    мСпецСимволов.Добавить("`");
    мСпецСимволов.Добавить("'");
    мСпецСимволов.Добавить("?");
    мСпецСимволов.Добавить("*");
    мСпецСимволов.Добавить("(");
    мСпецСимволов.Добавить(")");
    мСпецСимволов.Добавить("№");
    мСпецСимволов.Добавить(";");
    мСпецСимволов.Добавить("%");
    мСпецСимволов.Добавить("");
        
    Для Каждого СпецСимвол Из мСпецСимволов Цикл 
        Строка1 = СтрЗаменить(Строка1, СпецСимвол, " ");
    КонецЦикла;
        
    Возврат Строка1;
    
КонецФункции   


Сохранить файл через браузер

 Для сохранения файла в контексте "Управляемых форм" используя браузер используем ниже подход

&НаКлиенте
Процедура СохранитьВФайл(Команда)
      
    #Если ВебКлиент Тогда      
        // Попробуем подключить расширение работы с файлами
        РасширениеПодключено = ПодключитьРасширениеРаботыСФайлами();
        Если НЕ РасширениеПодключено Тогда
            // Расширение не установлено, пробуем установить
            НачатьПодключениеРасширенияРаботыСФайлами(Новый ОписаниеОповещения("Подключение1",ЭтаФорма,));  
        КонецЕсли;
    #КонецЕсли   
    
    // Поместим табличный документ во временной хранилище как файл MS Excel
    АдресХранилища = ПоместитьТабличныйДокументВоВременноеХранилищеНаСервере(ТабДок, "xlsx", ТипФайлаТабличногоДокумента.XLSX);
    
    Если АдресХранилища = Неопределено Тогда
        ПоказатьПредупреждение( , НСтр("ru = 'Ошибка сохранения файла'; uk = 'Помилка збереження файлу'"));
        Возврат;
    КонецЕсли;
        
    Попытка
        // Сам момент сохранения
        ПолучитьФайл(АдресХранилища, ЗаголовокДляФайла+".xlsx", Истина);
    Исключение              
        Сообщение = Новый СообщениеПользователю;
        Сообщение.Текст = "ru = 'Не удалось записать файл. Возможно, недостаточно места на диске, диск защищен от записи или не подключено расширение для работы с файлами.'; uk = 'Не вдалося записати файл. Можливо, недостатньо місця на диску, диск захищений від запису або не має з''єднання розширення для роботи з файлами.'";
        Сообщение.Сообщить();
    КонецПопытки;
    
КонецПроцедуры
&НаСервере
Функция ПоместитьТабличныйДокументВоВременноеХранилищеНаСервере(ТабличныйДокумент, Расширение, ТипФайла)
    
    АдресХранилища  = Неопределено;
    ИмяФайла        = ПолучитьИмяВременногоФайла(Расширение);
    
    Попытка
        ТабличныйДокумент.Записать(ИмяФайла, ТипФайла);
        АдресХранилища = ПоместитьВоВременноеХранилище(Новый ДвоичныеДанные(ИмяФайла));
    Исключение
        Сообщить(ОписаниеОшибки()); ВызватьИсключение;
    КонецПопытки;
    
    Возврат АдресХранилища;
    
КонецФункции
&НаКлиенте
Процедура Подключение1(Подключено,ДопПараметры)Экспорт 
    
    Если Не Подключено Тогда
        НачатьУстановкуРасширенияРаботыСФайлами();
    КонецЕсли;
    
КонецПроцедуры
&НаКлиенте
Процедура Установка2(ДопПараметры)Экспорт 
КонецПроцедуры

Обработка заполнения табличной части

 Шаблон обработки заполнения табличной части для "Управляемых форм" выглядит так

Модуль объекта должен иметь основную экспортную функцию с именем СведениеОВнешнейОбработки()

Функция СведенияОВнешнейОбработке() Экспорт
    Назначения = Новый Массив;
    Назначения.Добавить("Документ.НалоговаяНакладная");
    
    ПараметрыРегистрации = Новый Структура;
    ПараметрыРегистрации.Вставить("Вид","ЗаполнениеОбъекта");
    ПараметрыРегистрации.Вставить("Назначение", Назначения);
    ПараметрыРегистрации.Вставить("Наименование", Метаданные().Представление());
    ПараметрыРегистрации.Вставить("Версия","1.0");
    ПараметрыРегистрации.Вставить("Информация", НСтр("ru = 'Дополнительная обработка табличной части'; uk = 'Додаткова обробка табличної частини'"));
    ПараметрыРегистрации.Вставить("БезопасныйРежим", Истина);
    
    Команды = ПолучитьТаблицуКоманд();
    ДобавитьКоманду(Команды, Метаданные().Представление(),Метаданные().ПолноеИмя(),"ВызовКлиентскогоМетода",Ложь,);
    
    ПараметрыРегистрации.Вставить("Команды",Команды);
    
    Возврат ПараметрыРегистрации;   
КонецФункции
Функция ПолучитьТаблицуКоманд()
    Команды = Новый ТаблицаЗначений;
    Команды.Колонки.Добавить("Представление", Новый ОписаниеТипов("Строка"));
    Команды.Колонки.Добавить("Идентификатор", Новый ОписаниеТипов("Строка"));
    Команды.Колонки.Добавить("Использование", Новый ОписаниеТипов("Строка"));
    Команды.Колонки.Добавить("ПоказыватьОповещение", Новый ОписаниеТипов("Булево"));
    Команды.Колонки.Добавить("Модификатор", Новый ОписаниеТипов("Строка"));
    Возврат Команды;
КонецФункции    
Процедура ДобавитьКоманду(ТаблицаКоманд, Представление, Идентификатор, Использование, ПоказыватьОповещение = Ложь, Модификатор = "")
    НоваяКоманда = ТаблицаКоманд.Добавить();
    НоваяКоманда.Представление = Представление;
    НоваяКоманда.Идентификатор = Идентификатор;
    НоваяКоманда.Использование = Использование;
    НоваяКоманда.ПоказыватьОповещение = ПоказыватьОповещение;
    НоваяКоманда.Модификатор = Модификатор;
КонецПроцедуры  

В модуле формы

&НаКлиенте
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначенияМассив) Экспорт   
    БезОшибок = Истина;   
    Если БезОшибок Тогда
        ПоказатьПредупреждение(, НСтр("ru = 'Выполнено без ошибок'; uk = 'Виконано без помилок'"))
    Иначе 
        ПоказатьПредупреждение(, НСтр("ru = 'При обработке данных возникли ошибки'; uk = 'Під час обробки даних виникли помилки'")) 
    КонецЕсли;  
    //для обновления отображения
    Для Каждого стрДок Из ОбъектыНазначенияМассив Цикл 
        п = Новый Структура("Ключ", стрДок);
        Форма = ПолучитьФорму("Документ.НалоговаяНакладная.ФормаОбъекта", п);
        Форма.Прочитать();
    КонецЦикла; 
КонецПроцедуры  

Обращаю внимание на код ниже комментария
//для обновления отображения
Тут выполняется обновление табличной части, с которой был вызвана обработка заполнения
 

CopyPaste Copyright © 2017 - |- Шаблон создан O Pregador - |- Отредактирован myr4ik07