Как перехватить и обработать интерактивное копирование записи регистра сведений

Программист IT и автоматизация бизнеса
← На главную

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

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

Метод 1: Использование обработчика ПриСозданииНаСервере в форме записи

Самый распространенный и быстрый способ перехватить момент копирования — это анализ параметров формы в обработчике ПриСозданииНаСервере. Платформа 1С при интерактивном копировании передает в форму специальный параметр ЗначениеКопирования. Проанализируем, как это работает на практике.

Важно понимать, что в параметре ЗначениеКопирования для регистра сведений передается не сама запись, а КлючЗаписи копируемого объекта. Чтобы определить, является ли создание записи процессом копирования, мы можем проверить этот параметр на заполненность.

Посмотрим на пример кода, который следует разместить в модуле формы записи регистра:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

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

    // Дополнительная проверка: является ли запись новой в принципе
    // Если ИсходныйКлючЗаписи пустой — значит запись еще не существует в базе
    ЭтоНоваяЗапись = Запись.ИсходныйКлючЗаписи.Пустой();

КонецПроцедуры

В данном примере мы используем свойство Запись (которое является основным реквизитом формы типа РегистрСведенийМенеджерЗаписи). Обратите внимание, что проверка через Запись.ИсходныйКлючЗаписи.Пустой() помогает нам отличить новую запись от редактирования существующей, но именно параметр ЗначениеКопирования говорит нам о том, что данные были подтянуты из другой записи.

Метод 2: Архитектурно правильный подход через ОбработкаЗаполнения

Хотя работа в форме записи решает задачу визуального отображения, с точки зрения архитектуры платформы 1С, логику инициализации объектов правильнее выносить в модули объектов. У регистра сведений для этих целей существует Модуль менеджера записи и обработчик ОбработкаЗаполнения.

Этот метод хорош тем, что он сработает не только при интерактивном нажатии F9, но и при программном создании записи на основании ключа, если вызывается метод Заполнить(). Проанализируем реализацию в модуле менеджера записи:


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

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

Метод 3: Перехват в форме списка (СписокПередНачаломДобавления)

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

Рассмотрим пример кода в форме списка:


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

Использование параметра ЗначениеЗаполнения (FillingValues) — это "типовой" способ передачи данных в новую форму. Платформа автоматически применит эти значения к полям записи после её инициализации.

Особенности для различных типов регистров

Проанализируем нюансы, которые зависят от настроек регистра:

  1. Периодические регистры: При копировании платформа всегда пытается сохранить Период исходной записи. Если ваш регистр имеет периодичность "В пределах дня", а вы копируете старую запись, крайне важно принудительно устанавливать ТекущаяДата(), иначе пользователь может случайно создать запись в далеком прошлом.
  2. Независимые регистры: Здесь все измерения доступны для редактирования. При копировании важно проверять уникальность комбинации измерений. Если вы изменили Период или ключевое измерение (например, Организация), риск получить ошибку "Запись с такими ключевыми полями существует" снижается.
  3. Подчиненные регистры (по регистратору): Копирование записи такого регистра напрямую невозможно, так как она жестко привязана к документу-регистратору. В этом случае копируется сам документ, а записи регистра пересчитываются при его проведении.

Рекомендации по реализации

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

  1. Если логика простая и касается только визуального интерфейса — используйте ПриСозданииНаСервере в форме записи, проверяя Параметры.ЗначениеКопирования.
  2. Если логика должна работать всегда (включая программный вызов) — используйте ОбработкаЗаполнения в модуле менеджера записи.
  3. Для получения данных исходной записи всегда помните, что в параметрах копирования передается КлючЗаписи. Чтобы получить значения ресурсов, необходимо выполнить метод Прочитать() через созданный менеджер записи.
  4. Всегда используйте ТекущаяДатаСеанса() вместо ТекущаяДата(), чтобы избежать проблем с разницей часовых поясов между сервером и клиентом.

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

← На главную