Как массово обновить или очистить реквизит справочника в 1С по выбранной группе

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

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

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

Постановка задачи и логика решения

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

Алгоритм работы обработки:

  1. Пользователь выбирает на форме группу (папку) номенклатуры.
  2. Программа находит все элементы, которые находятся внутри этой группы и всех её подпапок.
  3. Для каждого найденного элемента происходит получение объекта, очистка реквизита и запись изменений.

Шаг 1: Подготовка формы и реквизитов

Для начала создадим внешнюю обработку. Нам понадобятся следующие элементы:

Шаг 2: Написание запроса к базе данных

Самый эффективный способ получить список элементов из конкретной папки — использовать механизм запросов 1С. Рассмотрим, почему важно использовать оператор В ИЕРАРХИИ. Если мы используем простое равенство, программа выберет только те элементы, которые лежат непосредственно в указанной папке. Оператор В ИЕРАРХИИ позволяет «спуститься» на любую глубину вложенности.

Проанализируем пример правильного текста запроса:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   Номенклатура.Ссылка КАК Ссылка
    |ИЗ
    |   Справочник.CMS1C_Номенклатура КАК Номенклатура
    |ГДЕ
    |   Номенклатура.Ссылка В ИЕРАРХИИ(&ГруппаНоменклатуры)
    |   И НЕ Номенклатура.ЭтоГруппа
    |   И НЕ Номенклатура.ПометкаУдаления";

Запрос.УстановитьПараметр("ГруппаНоменклатуры", ГруппаНоменклатуры);

Важные моменты в запросе:

  1. Условие НЕ Номенклатура.ЭтоГруппа: Нам нужно менять реквизиты только у товаров (элементов), а не у самих папок.
  2. Условие НЕ Номенклатура.ПометкаУдаления: Обычно не имеет смысла тратить ресурсы на обработку помеченных на удаление объектов.
  3. Параметры: Никогда не вставляйте ссылки напрямую в текст запроса, всегда используйте УстановитьПараметр для безопасности и стабильности кода.

Шаг 3: Обработка результатов запроса и запись объектов

После выполнения запроса мы получаем выборку ссылок. Однако Ссылка в 1С предназначена только для чтения. Чтобы изменить данные, нам необходимо получить полноценный объект с помощью метода ПолучитьОбъект().

Разберем итоговый программный код процедуры выполнения:


&НаСервере
Процедура ВыполнитьНажатие(Элемент)
    
    // Проверка на заполнение группы
    Если ГруппаНоменклатуры.Пустая() Тогда
        Сообщить("Пожалуйста, выберите группу номенклатуры!");
        Возврат;
    КонецЕсли;

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

    Запрос.УстановитьПараметр("ГруппаНоменклатуры", ГруппаНоменклатуры);

    РезультатЗапроса = Запрос.Выполнить();
    Выборка = РезультатЗапроса.Выбрать();

    Пока Выборка.Следующий() Цикл
        
        // Получаем объект для редактирования
        ЭлементОбъект = Выборка.Ссылка.ПолучитьОбъект();
        
        // Очищаем реквизит. В модуле объекта при записи сработает 
        // стандартный алгоритм генерации URL из наименования.
        ЭлементОбъект.url = ""; 
        
        Попытка
            ЭлементОбъект.Записать();
            Сообщить("Обновлен URL для: " + ЭлементОбъект.Наименование);
        Исключение
            Сообщить("Ошибка при записи объекта: " + ОписаниеОшибки());
        КонецПопытки;
        
    КонецЦикла;

    Сообщить("Обработка завершена!");
    
КонецПроцедуры

Разбор типичных ошибок

В процессе обсуждения на форуме автор столкнулся с несколькими проблемами, которые полезно рассмотреть подробнее:

  1. Ошибка «Поле объекта не обнаружено (Выгрузить)»: Она часто возникает, если попытаться вызвать метод Выгрузить() не у результата запроса, а ошибиться в синтаксисе. Правильно использовать Запрос.Выполнить().Выгрузить(), если вам нужна Таблица Значений, но для простого обхода лучше использовать Выбрать() и Следующий() — это экономит оперативную память.
  2. Ошибка «Ожидается выражение ВЫБРАТЬ»: Это происходит, если вы определили строковую переменную с текстом запроса (например, ТекстЗапроса = "..."), но забыли присвоить её свойству Запрос.Текст.
  3. Работа с иерархией: Если справочник связан с другим справочником (например, CMS1C_Номенклатура имеет владельцем стандартную Номенклатуру), в условии ГДЕ нужно указывать Владелец В ИЕРАРХИИ(&Группа).

Оптимизация производительности

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

Таким образом, мы выяснили, что для решения задачи достаточно грамотно составить запрос с учетом иерархии и организовать цикл по объектам справочника. Данный подход является универсальным для любых задач по массовому изменению данных в 1С.

← На главную