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

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

В современных конфигурациях 1С, построенных на базе Библиотеки стандартных подсистем (БСП), таких как «Комплексная автоматизация 2», «ERP 2» или «Управление торговлей 11», механизм работы с дополнительными реквизитами реализован через специальные табличные части. Часто возникают ситуации, когда при массовом заполнении данных допускаются ошибки, и эти значения необходимо программно очистить. В данной статье мы подробно разберем, как правильно работать с табличной частью дополнительных реквизитов, какие ошибки допускают разработчики и как оптимизировать процесс удаления. Для пакетного изменения данных без написания программного кода можно воспользоваться обработкой для массового управления и редактирования дополнительных реквизитов.

Понимание структуры хранения данных

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

  1. Свойство — ссылка на план видов характеристик ДополнительныеРеквизитыИСведения.
  2. Значение — само значение реквизита (может быть строкой, числом, датой или ссылкой на справочник ЗначенияСвойствОбъектов).

Если нам нужно очистить конкретный дополнительный реквизит, нам необходимо найти строку с этим свойством в табличной части объекта и удалить ее. Для интерактивной очистки строк табличных частей и реквизитов объектов базы подойдёт динамический редактор табличных частей и реквизитов объектов 1С.

Способ 1. Прямое удаление строк из табличной части (классический подход)

Рассмотрим ситуацию, когда нам нужно очистить значение конкретного реквизита (например, «Буквенный код») для всех элементов справочника СерииНоменклатуры. Разберем по шагам правильный алгоритм действий.

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


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

Теперь реализуем цикл обхода элементов справочника. Обратите внимание, что метод Удалить() должен вызываться у коллекции (табличной части), а не у самой строки. Это распространенная ошибка, на которую наткнулся автор темы на форуме.


Выборка = Справочники.СерииНоменклатуры.Выбрать();

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

В этом примере мы проанализируем ситуацию: если строк с таким свойством несколько (хотя обычно она одна), мы удаляем их все. Метод НайтиСтроки возвращает массив строк табличной части, которые мы затем передаем в метод Удалить() самой табличной части.

Оптимизация: Использование запросов и режима загрузки

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

  1. Использование запроса: Выбирать нужно только те элементы, у которых действительно заполнено данное свойство.
  2. Отключение проверок: Использование флага ОбменДанными.Загрузка = Истина позволяет обойти проверки в модуле объекта и подписки на события.

Рассмотрим оптимизированный пример кода:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ РАЗЛИЧНЫЕ
    |	СерииНоменклатурыДополнительныеРеквизиты.Ссылка КАК Ссылка
    |ИЗ
    |	Справочник.СерииНоменклатуры.ДополнительныеРеквизиты КАК СерииНоменклатурыДополнительныеРеквизиты
    |ГДЕ
    |	СерииНоменклатурыДополнительныеРеквизиты.Свойство = &Свойство";

Запрос.УстановитьПараметр("Свойство", ДопРеквизитБуквКод);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

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

Способ 2. Использование программного интерфейса БСП (рекомендуемый)

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

Рассмотрим пример использования метода ЗаписатьЗначенияСвойств. Для удаления значения достаточно передать пустую структуру или не включать данное свойство в набор для записи (в зависимости от логики задачи), но чаще всего для очистки передается неопределенное значение:


// Подготовим массив объектов, которые нужно обработать
НаборОбъектов = Новый Массив;
НаборОбъектов.Добавить(СсылкаНаОбъект);

// Подготовим таблицу значений со свойствами
ТаблицаСвойств = Новый ТаблицаЗначений;
ТаблицаСвойств.Колонки.Добавить("Свойство");
ТаблицаСвойств.Колонки.Добавить("Значение");

// Чтобы очистить значение, передаем пустую ссылку или Неопределено
НоваяСтрока = ТаблицаСвойств.Добавить();
НоваяСтрока.Свойство = ДопРеквизитБуквКод;
НоваяСтрока.Значение = Справочники.ЗначенияСвойствОбъектов.ПустаяСсылка();

// Используем программный интерфейс БСП
УправлениеСвойствами.ЗаписатьЗначенияСвойств(СсылкаНаОбъект, ТаблицаСвойств);

Этот способ предпочтительнее, так как он автоматически обрабатывает запись объекта и гарантирует целостность данных в соответствии с логикой БСП.

Очистка справочника «Значения свойств объектов»

Разберем еще один важный момент. Если тип вашего дополнительного реквизита — «Дополнительное значение», то сами варианты значений хранятся в справочнике ЗначенияСвойствОбъектов. Удаление строки из табличной части справочника СерииНоменклатуры удалит только связь (ссылку) на это значение, но само значение останется в списке выбора реквизита.

Если вы создали ошибочные значения (например, с опечатками), их нужно удалять отдельно. Посмотрим, как это сделать правильно:

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

Пример удаления «мусорных» значений самого свойства:


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

Подведение итогов

Подведем итог нашему исследованию. Для эффективного удаления значений дополнительных реквизитов мы рекомендуем:

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

← На главную