Как правильно снять с регистрации набор записей в плане обмена 1С:Разбор типичных ошибок и методов оптимизации

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

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

Анализируем исходную проблему

Типичный сценарий: программист создает набор записей для независимого периодического регистра сведений, устанавливает фильтры по всем измерениям и периоду, а затем вызывает метод УдалитьРегистрациюИзменений. Однако после выполнения кода записи в таблице регистрации (которую можно увидеть через консоль запросов или обработку «Регистрация изменений для обмена», также может быть полезна регистрация или удаление объектов из плана обмена с формы) никуда не исчезают.

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


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

На первый взгляд все логично, но здесь кроется несколько архитектурных и логических ловушек, которые мы сейчас подробно разберем.

Ошибка №1: Лишний вызов метода Прочитать()

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

Когда вы вызываете Прочитать(), система обращается к основной таблице регистра, считывает данные в память сервера. Это создает лишнюю нагрузку на дисковую подсистему и СУБД, особенно если записей много. Для удаления регистрации достаточно просто установить значения в Отбор.

Ошибка №2: Коварство типа Дата и точность периода

Это самая частая причина «тихого» отказа в удалении регистрации. В периодических регистрах сведений Период является ключевым полем. Если в базе данных запись зарегистрирована с точностью до миллисекунд (например, 12.10.2023 14:55:01.456), а в ваш фильтр из запроса или из внешнего источника пришло значение 12.10.2023 14:55:01 (без миллисекунд), то для системы 1С это разные моменты времени.

Рассмотрим подробнее: метод УдалитьРегистрациюИзменений выполняет поиск в таблице изменений по точному совпадению. Если совпадение не найдено, ошибка не выдается — система просто считает, что удалять нечего. Всегда проверяйте в отладчике, совпадает ли тип и значение периода в Товар.Дата с тем, что реально записано в таблице регистрации изменений.

Ошибка №3: Состав измерений и «Основной отбор»

Проанализируем структуру регистра. Если у измерений в конфигураторе установлена галочка «Основной отбор», эти измерения обязаны присутствовать в фильтре набора записей. Если вы пропустите хотя бы одно такое измерение, метод удаления регистрации может отработать некорректно или проигнорировать команду.

Также важно помнить: метод Установить() у элементов отбора автоматически взводит флаг Использование = Истина. Повторно прописывать эти строки в коде не нужно, это только загромождает текст программы.

Оптимальный алгоритм снятия с регистрации

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


// Создаем набор записей один раз вне цикла для экономии ресурсов
НаборЗаписей = РегистрыСведений.ЦеныНоменклатуры.СоздатьНаборЗаписей();

Для Каждого СтрокаДанных из ТаблицаОбработанныхЗаписей Цикл
    // Сбрасываем старые фильтры
    НаборЗаписей.Отбор.Сбросить();
    
    // Устанавливаем новые фильтры. 
    // ВАЖНО: значения должны в точности соответствовать измерениям в базе
    НаборЗаписей.Отбор.Период.Установить(СтрокаДанных.Период);
    НаборЗаписей.Отбор.Номенклатура.Установить(СтрокаДанных.Номенклатура);
    НаборЗаписей.Отбор.Характеристика.Установить(СтрокаДанных.Характеристика);
    НаборЗаписей.Отбор.ВидЦен.Установить(СтрокаДанных.ВидЦен);
    
    // Удаляем регистрацию без вызова Прочитать()
    ПланыОбмена.УдалитьРегистрациюИзменений(УзелОбмена, НаборЗаписей);
КонецЦикла;

Продвинутый подход: Удаление по номеру сообщения

Рассмотрим более профессиональный способ управления регистрацией, который рекомендует фирма «1С». Вместо того чтобы вручную перебирать каждую запись и мучиться с фильтрами по периоду, используйте механизм подтверждения сообщений.

Как это работает:

  1. При выгрузке данных вы используете метод ПланыОбмена.ВыбратьИзменения(Узел, НомерСообщения). Все выгруженные записи помечаются этим номером.
  2. Вы отправляете данные принимающей стороне.
  3. Когда принимающая сторона присылает подтверждение (квитанцию) о том, что пакет №Х успешно загружен, вы вызываете один-единственный метод: ПланыОбмена.УдалитьРегистрациюИзменений(Узел, НомерСообщения).

Этот способ работает в десятки раз быстрее, так как СУБД удаляет записи одним запросом по индексу номера сообщения, не анализируя сложные фильтры по измерениям и периодам. Это исключает ошибки «несовпадения миллисекунд» и значительно повышает надежность обмена.

Особенности планов обмена в расширениях

Если вы работаете с планом обмена, добавленным через расширение конфигурации, помните о следующих нюансах:

Подводя итог, можно сказать: если УдалитьРегистрациюИзменений не срабатывает — в 99% случаев проблема в неточном соответствии фильтра и данных в таблице изменений. Тщательная проверка значений через отладчик, отказ от лишних методов вроде Прочитать() и переход на удаление по номеру сообщения помогут вам создать стабильный и быстрый механизм обмена данными.

← На главную