Как реализовать универсальную обработку выгрузки и загрузки данных в одной форме для разных конфигураций 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Определение контекста выполнения: в какой конфигурации мы находимся?

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

Для определения конфигурации воспользуемся обращением к свойству Метаданные.Имя. Посмотрим на пример реализации логики управления интерфейсом в обработчике ПриСозданииНаСервере:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    ИмяКонфигурации = Метаданные.Имя;
    
    Если ИмяКонфигурации = "БухгалтерияПредприятия" Тогда
        // Логика для БП
        Элементы.ГруппаЗагрузкаБП.Видимость = Истина;
        Элементы.ГруппаВыгрузкаУТ.Видимость = Ложь;
    ИначеЕсли ИмяКонфигурации = "УправлениеТорговлей" Тогда
        // Логика для УТ
        Элементы.ГруппаЗагрузкаБП.Видимость = Ложь;
        Элементы.ГруппаВыгрузкаУТ.Видимость = Истина;
    Иначе
        Сообщить("Внимание: данная конфигурация не поддерживается в полном объеме.");
    КонецЕсли;
    
КонецПроцедуры

Динамическое обращение к общим модулям через БСП

Главная проблема «универсальности» — это жесткие ссылки на общие модули в коде. Если вы напишете МодульОбмена.ВыполнитьВыгрузку(), и этого модуля не окажется в базе, форма не откроется. Выясним, как решают эту задачу разработчики фирмы «1С» в Библиотеке стандартных подсистем (БСП).

Для безопасного обращения к функционалу используется программный интерфейс модуля ОбщегоНазначения. Рассмотрим алгоритм действий:

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

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


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

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

Использование операторов Выполнить и Вычислить для абсолютной независимости

Если в вашей конфигурации не используется БСП или вы разрабатываете максимально автономную обработку, рассмотрим метод использования функций Выполнить() и Вычислить(). Это позволяет полностью скрыть вызовы специфических процедур от компилятора 1С.

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


ИмяМодуля = "МодульИнтеграцииСМаркетплейсами";
Если Метаданные.ОбщиеМодули.Найти(ИмяМодуля) <> Неопределено Тогда
    ПараметрыВызова = "Параметр1, Параметр2";
    ТекстВызова = ИмяМодуля + ".ВыполнитьЗагрузкуДанных(" + ПараметрыВызова + ")";
    
    Попытка
        Выполнить(ТекстВызова);
    Исключение
        ЗаписьЖурналаРегистрации("Ошибка универсальной обработки", 
            УровеньЖурналаРегистрации.Ошибка, , , ПодробноеОписаниеОшибки());
    КонецПопытки;
КонецЕсли;

Важно: использование Выполнить() затрудняет отладку (не работает переход по F12) и может незначительно снижать производительность при массовых вызовах, поэтому применяйте этот метод только для «точек входа» в специфический код конфигурации.

Динамическое управление составом реквизитов формы

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

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


&НаСервере
Процедура ДобавитьСпецифичноеПоле()
    
    // Проверяем наличие типа в метаданных
    Если Метаданные.Справочники.Найти("Склады") <> Неопределено Тогда
        
        // 1. Описываем новый реквизит
        МассивДобавляемыхРеквизитов = Новый Массив;
        ТипСклада = Новый ОписаниеТипов("СправочникСсылка.Склады");
        МассивДобавляемыхРеквизитов.Add(Новый РеквизитФормы("ВыбранныйСклад", ТипСклада, , "Склад выгрузки"));
        
        // 2. Добавляем реквизит на форму
        ЭтаФорма.ИзменитьРеквизиты(МассивДобавляемыхРеквизитов);
        
        // 3. Создаем элемент управления (поле ввода) для этого реквизита
        ЭлементСклад = Элементы.Добавить("ВыбранныйСклад", Тип("ПолеФормы"), Элементы.ГруппаПараметры);
        ЭлементСклад.Вид = ВидПоляФормы.ПолеВвода;
        ЭлементСклад.ПутьКДанным = "ВыбранныйСклад";
        
    КонецЕсли;
    
КонецПроцедуры

Безопасная передача данных между разными структурами

При реализации обмена между разными конфигурациями мы часто сталкиваемся с тем, что имена реквизитов совпадают, а типы или их состав — нет. Чтобы код не «падал» при обращении к несуществующему свойству объекта, рассмотрим метод ЗаполнитьЗначенияСвойств().

Этот метод является встроенным механизмом «безопасного» копирования данных. Проанализируем его преимущество: он копирует только те свойства, которые есть и в источнике, и в приемнике, игнорируя всё остальное без вызова исключений.


// Допустим, ОбъектПриемник — это ДокументОбъект в текущей базе,
// а СтруктураДанных — полученная информация из другой базы.
ЗаполнитьЗначенияСвойств(ОбъектПриемник, СтруктураДанных);
// Даже если в структуре есть поле "СтавкаНДС", а в документе его нет, ошибки не будет.

Итоги и рекомендации

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

Применяя эти методы в совокупности, вы сможете создать мощный и стабильный инструмент, который будет работать в любой современной конфигурации на платформе 1С:Предприятие 8.3.

← На главную