Как программно изменить родителя элемента справочника в 1С 7.7 при редактировании в форме списка?

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

В платформе 1С:Предприятие 7.7 разработчики часто сталкиваются с задачей автоматического перемещения элемента справочника в другую папку (группу) при изменении каких-либо реквизитов прямо в форме списка. Однако при попытке присвоить новое значение реквизиту Родитель в предопределенной процедуре ПриЗаписи() модуль формы выдает критическую ошибку: «Объект не может быть перепозиционирован!».

Рассмотрим подробно причины возникновения данной проблемы и проанализируем проверенные способы ее решения.

Почему возникает ошибка перепозиционирования?

Проанализируем механику работы формы списка справочника в 1С 7.7. Когда пользователь редактирует строку непосредственно в форме списка, элемент справочника находится в строгом контексте текущей выборки и иерархического дерева отображения.

Существуют две ключевые причины, из-за которых платформа блокирует прямую смену родителя:

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

Способ 1. Использование таймера отложенного вызова (ОбработкаОжидания)

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

Рассмотрим алгоритм реализации по шагам:

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

Посмотрим на пример кода в модуле формы списка справочника:


Перем ЭлементДляПереноса;
Перем НовыйРодитель;

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

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

Способ 2. Использование прямого SQL-запроса (UPDATE)

Для конфигураций, работающих на базе SQL-версии 1С 7.7 с использованием внешних компонент (например, 1С++ / DirectSQL), доступен вариант изменения поля родителя прямым запросом к базе данных. Этот метод обходит ограничение платформы на перепозиционирование, так как изменение происходит непосредственно на уровне СУБД.

Выясним, как формируется данный запрос:


// Пример SQL-запроса для изменения ParentID элемента
UPDATE
    $Справочник.ДолгиПередКонтрагентами AS Спр
SET
    Спр.ParentID = :ВыбРодитель
WHERE
    Спр.id = :ИскомыйЭлементСправочника

Важное примечание: при использовании прямого SQL-запроса следует учитывать, что структура иерархического дерева в самой открытой форме списка обновится только после вызова метода Форма.Обновить() или переоткрытия формы списка.

Способ 3. Перенос редактирования в форму элемента

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

Рекомендации по работе с иерархией справочников в 1С 7.7

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

← На главную