В современных конфигурациях 1С, построенных на базе Библиотеки стандартных подсистем (БСП), таких как «Комплексная автоматизация 2», «ERP 2» или «Управление торговлей 11», механизм работы с дополнительными реквизитами реализован через специальные табличные части. Часто возникают ситуации, когда при массовом заполнении данных допускаются ошибки, и эти значения необходимо программно очистить. В данной статье мы подробно разберем, как правильно работать с табличной частью дополнительных реквизитов, какие ошибки допускают разработчики и как оптимизировать процесс удаления. Для пакетного изменения данных без написания программного кода можно воспользоваться обработкой для массового управления и редактирования дополнительных реквизитов.
Прежде чем приступать к удалению, проанализируем, где именно хранятся данные. В отличие от стандартных реквизитов, дополнительные реквизиты хранятся в табличной части самого объекта (справочника или документа), которая обычно называется ДополнительныеРеквизиты. Эта таблица состоит из двух ключевых колонок:
ДополнительныеРеквизитыИСведения.ЗначенияСвойствОбъектов).Если нам нужно очистить конкретный дополнительный реквизит, нам необходимо найти строку с этим свойством в табличной части объекта и удалить ее. Для интерактивной очистки строк табличных частей и реквизитов объектов базы подойдёт динамический редактор табличных частей и реквизитов объектов 1С.
Рассмотрим ситуацию, когда нам нужно очистить значение конкретного реквизита (например, «Буквенный код») для всех элементов справочника СерииНоменклатуры. Разберем по шагам правильный алгоритм действий.
Для начала нам нужно получить ссылку на само свойство, которое мы будем удалять:
ДопРеквизитБуквКод = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Буквенный код");
Теперь реализуем цикл обхода элементов справочника. Обратите внимание, что метод Удалить() должен вызываться у коллекции (табличной части), а не у самой строки. Это распространенная ошибка, на которую наткнулся автор темы на форуме.
Выборка = Справочники.СерииНоменклатуры.Выбрать();
Пока Выборка.Следующий() Цикл
ОбъектСерия = Выборка.ПолучитьОбъект();
ПараметрыОтбора = Новый Структура;
ПараметрыОтбора.Вставить("Свойство", ДопРеквизитБуквКод);
// Ищем строки, соответствующие нашему свойству
НайденныеСтроки = ОбъектСерия.ДополнительныеРеквизиты.НайтиСтроки(ПараметрыОтбора);
Если НайденныеСтроки.Количество() > 0 Тогда
Для Каждого СтрокаТЧ Из НайденныеСтроки Цикл
// Правильное удаление строки из коллекции
ОбъектСерия.ДополнительныеРеквизиты.Удалить(СтрокаТЧ);
КонецЦикла;
// Важно не забыть записать объект после изменений
ОбъектСерия.Записать();
КонецЕсли;
КонецЦикла;
В этом примере мы проанализируем ситуацию: если строк с таким свойством несколько (хотя обычно она одна), мы удаляем их все. Метод НайтиСтроки возвращает массив строк табличной части, которые мы затем передаем в метод Удалить() самой табличной части.
Если справочник содержит десятки тысяч элементов (как это часто бывает с сериями номенклатуры), использование метода Выбрать() и запись каждого объекта будут работать крайне медленно. Выясним причину: программа тратит время на чтение всех элементов и выполнение всех проверок при записи. Чтобы ускорить процесс, проанализируем следующие шаги:
ОбменДанными.Загрузка = Истина позволяет обойти проверки в модуле объекта и подписки на события.Рассмотрим оптимизированный пример кода:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| СерииНоменклатурыДополнительныеРеквизиты.Ссылка КАК Ссылка
|ИЗ
| Справочник.СерииНоменклатуры.ДополнительныеРеквизиты КАК СерииНоменклатурыДополнительныеРеквизиты
|ГДЕ
| СерииНоменклатурыДополнительныеРеквизиты.Свойство = &Свойство";
Запрос.УстановитьПараметр("Свойство", ДопРеквизитБуквКод);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
Объект = Выборка.Ссылка.ПолучитьОбъект();
// Ускоряем запись объекта
Объект.ОбменДанными.Загрузка = Истина;
// Очистка через поиск строк
МассивСтрок = Объект.ДополнительныеРеквизиты.НайтиСтроки(Новый Структура("Свойство", ДопРеквизитБуквКод));
Для Каждого Строка Из МассивСтрок Цикл
Объект.ДополнительныеРеквизиты.Удалить(Строка);
КонецЦикла;
Если МассивСтрок.Количество() > 0 Тогда
Объект.Записать();
КонецЕсли;
КонецЦикла;
В конфигурациях на БСП существует специальный общий модуль УправлениеСвойствами. Проанализируем его возможности: он позволяет записывать значения свойств без ручного манипулирования табличными частями. Этот метод более надежен, так как он самостоятельно определяет, где хранится свойство (в реквизитах или в сведениях).
Рассмотрим пример использования метода ЗаписатьЗначенияСвойств. Для удаления значения достаточно передать пустую структуру или не включать данное свойство в набор для записи (в зависимости от логики задачи), но чаще всего для очистки передается неопределенное значение:
// Подготовим массив объектов, которые нужно обработать
НаборОбъектов = Новый Массив;
НаборОбъектов.Добавить(СсылкаНаОбъект);
// Подготовим таблицу значений со свойствами
ТаблицаСвойств = Новый ТаблицаЗначений;
ТаблицаСвойств.Колонки.Добавить("Свойство");
ТаблицаСвойств.Колонки.Добавить("Значение");
// Чтобы очистить значение, передаем пустую ссылку или Неопределено
НоваяСтрока = ТаблицаСвойств.Добавить();
НоваяСтрока.Свойство = ДопРеквизитБуквКод;
НоваяСтрока.Значение = Справочники.ЗначенияСвойствОбъектов.ПустаяСсылка();
// Используем программный интерфейс БСП
УправлениеСвойствами.ЗаписатьЗначенияСвойств(СсылкаНаОбъект, ТаблицаСвойств);
Этот способ предпочтительнее, так как он автоматически обрабатывает запись объекта и гарантирует целостность данных в соответствии с логикой БСП.
Разберем еще один важный момент. Если тип вашего дополнительного реквизита — «Дополнительное значение», то сами варианты значений хранятся в справочнике ЗначенияСвойствОбъектов. Удаление строки из табличной части справочника СерииНоменклатуры удалит только связь (ссылку) на это значение, но само значение останется в списке выбора реквизита.
Если вы создали ошибочные значения (например, с опечатками), их нужно удалять отдельно. Посмотрим, как это сделать правильно:
ЗначенияСвойствОбъектов, где владельцем является ваше свойство.Пример удаления «мусорных» значений самого свойства:
ВыборкаЗначений = Справочники.ЗначенияСвойствОбъектов.Выбрать(ДопРеквизитБуквКод);
Пока ВыборкаЗначений.Следующий() Цикл
ОбъектЗначение = ВыборкаЗначений.ПолучитьОбъект();
// Проверяем условие (например, неправильное наименование)
Если ОбъектЗначение.Наименование = "НеверныйКод" Тогда
ОбъектЗначение.Удалить(); // Или УстановитьПометкуУдаления(Истина)
КонецЕсли;
КонецЦикла;
Подведем итог нашему исследованию. Для эффективного удаления значений дополнительных реквизитов мы рекомендуем:
Удалить() вызывается у табличной части: Объект.ДополнительныеРеквизиты.Удалить(Строка).ОбменДанными.Загрузка = Истина для массовых операций записи.ДополнительныеСведения.Соблюдение этих правил позволит вам быстро и корректно управлять данными в любой современной конфигурации 1С.