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

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия
← На главную

При работе с обменом данными между различными базами 1С, например, между типовой конфигурацией "Бухгалтерия предприятия 3.0" и самописной базой, часто возникает необходимость выборочной миграции данных. Представим ситуацию, когда нам требуется переносить не всех контрагентов и их договоры, а только тех, которые помечены специальным образом. В типовых конфигурациях существует механизм дополнительных реквизитов, который позволяет добавлять произвольные поля к объектам без изменения конфигурации. Возникает логичный вопрос: можно ли использовать такой дополнительный реквизит для отбора объектов в правилах регистрации обмена данными в "Конвертации данных 2.0"?

Мы столкнулись с задачей, когда из "Бухгалтерии 3.0" в самописную базу нужно перенести только часть контрагентов и их договоров. Чтобы не переносить всех, мы решили добавить в справочники "Контрагенты" и "Договоры контрагентов" дополнительный реквизит, например, "Участвует в обмене ИмяСамописнойБазы" типа "Булево". Цель этого реквизита — служить флагом для регистрации объектов к обмену.

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

На первый взгляд кажется, что это просто. Однако, при попытке настроить отбор в правилах регистрации по свойствам объекта (ПРОБ) мы сталкиваемся с несколькими ограничениями:

  1. Отсутствие дополнительного реквизита в списке свойств: В интерактивном режиме настройки правил регистрации дополнительные реквизиты не всегда доступны для прямого выбора в качестве свойства объекта для отбора.
  2. Ограниченные виды сравнения: Часто доступны только базовые виды сравнения, такие как "Равно" и "Не равно", отсутствует, например, "В", что усложняет реализацию сложной логики отбора.

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

Решение 1: Программная обработка в правилах регистрации

Самым гибким и мощным способом реализации сложной логики отбора является использование программного кода непосредственно в правилах регистрации обмена данными. Механизм "Конвертации данных 2.0" позволяет писать код, который выполняется в момент регистрации объекта к обмену.

Реализация отбора с помощью программного кода

Мы можем использовать обработчик события, которое выполняется при регистрации объекта. В этом обработчике мы получаем доступ к объекту, который регистрируется, и можем проанализировать значение его дополнительного реквизита. Если дополнительный реквизит указывает, что объект не должен участвовать в обмене, мы устанавливаем параметр Отказ = Истина. Это прервет регистрацию текущего объекта.

Рассмотрим пример кода, который можно поместить в событие "При регистрации объекта" (или аналогичное, в зависимости от версии КД и конкретного правила):


// Предполагаем, что имя нашего дополнительного реквизита "УчаствуетВОбмене"
// и он имеет тип Булево.

// Получим Объект, который регистрируется.
// Например, в событии "При регистрации объекта" переменная Объект уже доступна.

// Поиск дополнительного реквизита по наименованию (лучше по ссылке на ПВХ)
// Но для демонстрации используем наименование.
// Важно: имя реквизита может храниться в ПВХ "ДополнительныеРеквизитыИСведения".

ЗначениеДопРеквизита = Ложь;

Для Каждого ДопРеквизитИзКоллекции Из Объект.ДополнительныеРеквизиты Цикл
    Если ДопРеквизитИзКоллекции.Свойство.Имя = "УчаствуетВОбмене" Тогда // Пример имени, замените на фактическое
        ЗначениеДопРеквизита = ДопРеквизитИзКоллекции.Значение;
        Прервать;
    КонецЕсли;
КонецЦикла;

Если ЗначениеДопРеквизита = Ложь Тогда
    Отказ = Истина;
КонецЕсли;

В этом коде мы перебираем коллекцию дополнительных реквизитов объекта, находим наш реквизит по имени и проверяем его значение. Если оно Ложь (то есть объект не участвует в обмене), мы устанавливаем Отказ = Истина.

"Интересный эффект" и его решение

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

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

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

Давайте посмотрим на исправленный и рабочий вариант кода, который использовал пользователь:


// В обработчике правил регистрации, например, "При регистрации объекта"

// Переменная "Объект" уже содержит текущий регистрируемый объект
// Имя нашего дополнительного реквизита, например, "УчаствуетВОбмене"

Отказ = Ложь; // По умолчанию регистрируем

// Найдем сам элемент ПВХ "ДополнительныеРеквизитыИСведения" по имени
// Это более надежный способ, чем строковое сравнение имени свойства
// В реальном коде лучше сохранить ссылку на нужный элемент ПВХ в константе или параметре
// или получить ее один раз при инициализации.

ИмяРеквизита = "УчаствуетВОбмене..."; // Полное имя реквизита из плана видов характеристик

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

Если СсылкаНаДопРеквизит <> Неопределено Тогда
    // Получаем коллекцию дополнительных реквизитов объекта
    // и ищем в ней наш реквизит по найденной ссылке
    ДопРеквизитКоллекции = Объект.ДополнительныеРеквизиты.Найти(СсылкаНаДопРеквизит);

    Если ДопРеквизитКоллекции <> Неопределено Тогда
        // Проверяем значение доп. реквизита
        Если НЕ ДопРеквизитКоллекции.Значение Тогда // Если значение Ложь, то не участвует
            Отказ = Истина;
        КонецЕсли;
    Иначе
        // Если доп. реквизит отсутствует (например, не добавлен для объекта),
        // можно принять решение о регистрации или отказе по умолчанию.
        // В нашем случае, если реквизита нет, считаем, что объект не должен участвовать.
        Отказ = Истина; 
    КонецЕсли;
Иначе
    // Если описание доп. реквизита не найдено в ПВХ, 
    // это может быть ошибка или признак того, что объект не требует отбора.
    // Примем решение не регистрировать по умолчанию, чтобы избежать неконтролируемого переноса.
    Отказ = Истина; 
КонецЕсли;
```

В этом коде мы сначала находим сам элемент ПланаВидовХарактеристик ДополнительныеРеквизитыИСведения по имени нашего дополнительного реквизита. Затем, используя этот элемент, обращаемся к коллекции Объект.ДополнительныеРеквизиты.Найти(СсылкаНаДопРеквизит). Этот подход гарантирует, что мы получаем актуальное значение дополнительного реквизита, даже если оно было только что изменено пользователем и еще не до конца записано в базу данных. Таким образом, проблема с несвоевременным чтением значения была успешно решена.

Решение 2: Использование расширений конфигурации

Альтернативным способом, который позволяет избежать изменения основной конфигурации (и, соответственно, снятия ее с поддержки), является использование расширений конфигурации. Расширения — это мощный инструмент для доработки типовых решений 1С, который становится все более гибким с каждой новой версией платформы.

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

Мы можем создать расширение для нашей типовой "Бухгалтерии 3.0" и в этом расширении добавить новый, обычный реквизит к нужным справочникам (например, "Контрагенты" и "Договоры контрагентов"). Этот реквизит будет храниться в таблицах расширения, но при этом будет доступен как обычный реквизит для объектов основной конфигурации.

  1. Создаем новое расширение в конфигураторе.
  2. Добавляем в расширение нужные справочники (например, "Справочник.Контрагенты").
  3. К добавленным справочникам в расширении добавляем новый реквизит, например, "МойРеквизитУчаствуетВОбмене" типа "Булево".
  4. Для того чтобы пользователи могли заполнять этот реквизит, нам необходимо добавить в расширение формы этих справочников и вынести новый реквизит на форму. Это может потребовать некоторой работы с формами расширений, включая их синхронизацию при обновлении основной конфигурации, о чем справедливо упоминается в обсуждении. Однако современные версии платформы 1С значительно упрощают работу с расширениями форм.

Использование реквизита из расширения в правилах обмена

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

В событии "Перед выгрузкой" для соответствующего правила конвертации объектов (ПКО) мы можем написать следующий код:

// В событии "Перед выгрузкой" для ПКО "Контрагенты" // Переменная "Объект" ссылается на выгружаемый объект "Контрагент" // Предполагаем, что наш реквизит называется "МойРеквизитУчаствуетВОбмене" Если Объект.МойРеквизитУчаствуетВОбмене = Ложь Тогда Отказ = Истина; // Отказываем в выгрузке, если реквизит установлен в Ложь КонецЕсли; // Или более кратко: // Отказ = (Объект.МойРеквизитУчаствуетВОбмене = Ложь);

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

Решение 3: Использование стандартного механизма "Дополнительные реквизиты и сведения" (БСП)

Самым рекомендуемым и наименее инвазивным способом для добавления новых полей в типовые конфигурации 1С (основанных на Библиотеке Стандартных Подсистем – БСП) является использование встроенного механизма "Дополнительные реквизиты и сведения". Этот механизм позволяет создавать дополнительные реквизиты прямо в режиме "1С:Предприятие", без необходимости заходить в конфигуратор.

Порядок создания дополнительного реквизита через БСП

  1. Перейдите в раздел "Администрирование" -> "Общие настройки".
  2. Найдите пункт "Дополнительные реквизиты и сведения" и откройте его.
  3. Выберите объект, для которого вы хотите добавить реквизит (например, "Справочник Контрагенты").
  4. Нажмите кнопку "Создать" и выберите "Новый реквизит".
  5. Укажите наименование реквизита (например, "УчаствуетВОбмене"), выберите тип значения (например, "Булево") и настройте другие параметры.
  6. После создания, этот дополнительный реквизит автоматически появится на формах соответствующих объектов (в специальной группе "Дополнительные реквизиты"), без необходимости модифицировать формы через конфигуратор или расширение.

Использование дополнительного реквизита БСП в правилах обмена

Дополнительный реквизит, созданный через механизм БСП, является частью объекта и хранится в нем. Поэтому мы можем использовать его точно так же, как в Решении 1, обращаясь к коллекции Объект.ДополнительныеРеквизиты. Код для отбора будет аналогичным:


// В обработчике правил регистрации или "Перед выгрузкой" ПКО

// Предполагаем, что наш реквизит называется "УчаствуетВОбмене"
// и он имеет тип Булево.

Отказ = Ложь; 

// Получаем ссылку на элемент ПВХ, который описывает наш доп. реквизит
СсылкаНаДопРеквизит = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоРеквизиту("Имя", "УчаствуетВОбмене");

Если СсылкаНаДопРеквизит <> Неопределено Тогда
    ДопРеквизитКоллекции = Объект.ДополнительныеРеквизиты.Найти(СсылкаНаДопРеквизит);

    Если ДопРеквизитКоллекции <> Неопределено Тогда
        Если НЕ ДопРеквизитКоллекции.Значение Тогда 
            Отказ = Истина;
        КонецЕсли;
    Иначе
        Отказ = Истина; 
    КонецЕсли;
Иначе
    Отказ = Истина; 
КонецЕсли;

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

Выводы и рекомендации

Мы рассмотрели несколько подходов к использованию дополнительных реквизитов для отбора объектов при регистрации обмена данными в 1С:

  1. Программная обработка в правилах регистрации с прямым доступом к Объект.ДополнительныеРеквизиты. Это самый прямой и гибкий способ, если дополнительный реквизит уже создан (например, через БСП) и требуется сложная логика отбора. Важно учитывать нюансы момента записи и чтения данных.
  2. Использование расширений конфигурации для добавления обычного реквизита. Отличный вариант, если штатный механизм дополнительных реквизитов БСП не подходит (например, если требуется особый тип данных или нестандартное расположение на форме). Требует работы с формами в расширении.
  3. Использование стандартного механизма "Дополнительные реквизиты и сведения" (БСП) в режиме 1С:Предприятие. Наиболее простой и безопасный способ для добавления реквизитов в типовых конфигурациях без снятия с поддержки и без конфигуратора. После создания реквизита его можно использовать как в программной обработке, так и в более простых сценариях обмена.

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

← На главную