Почему не отображаются движения документа после программного добавления в 1С?

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

Мы часто сталкиваемся с ситуацией, когда программно формируем движения документа в регистрах, но они по какой-то причине не видны в базе данных или на форме документа. Давайте вместе разберем эту проблему и найдем ее решение, проанализировав основные причины и методы работы с движениями в 1С.

Понимание основ: Наборы записей и Движения документа

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

В 1С существует два основных способа программного формирования и записи движений:

  1. Способ 1: Через свойство "Движения" объекта документа

    У каждого объекта документа есть свойство Движения, которое представляет собой коллекцию наборов записей по всем регистрам, с которыми данный документ может взаимодействовать. Если мы добавляем записи таким способом и для соответствующего набора записей устанавливаем свойство Записывать = Истина, то при записи (или проведении) самого документа платформа 1С автоматически сохраняет все модифицированные наборы записей. Этот метод часто используется в обработчиках проведения документов. Чтобы быстро получить готовый шаблон такого алгоритма, можно использовать средства генерации кода создания объекта по ссылке, которые поддерживают и формирование кода движений.

    
    // Получаем объект документа, если у нас есть только ссылка
    МДок = Строка.Док.ПолучитьОбъект(); 
    
    // Обращаемся к коллекции движений для конкретного регистра
    ДвижРегистра = МДок.Движения.НужныйРегистр;
    
    // Очищаем текущие движения документа по этому регистру (если нужно перезаписать)
    ДвижРегистра.Очистить(); 
    
    // Добавляем новые записи в коллекцию ДвижРегистра
    НоваяЗапись = ДвижРегистра.Добавить();
    НоваяЗапись.Измерение1 = "Значение1";
    НоваяЗапись.Ресурс1 = 100;
    // ... и так далее для всех нужных полей
    
    // Устанавливаем флаг, чтобы движения были записаны при записи документа
    ДвижРегистра.Записывать = Истина; 
    
    // Если документ не проводится автоматически, но нам нужно сохранить движения,
    // можно вызвать запись всего документа или непосредственно коллекции движений.
    
  2. Способ 2: Через менеджер регистра (РегистрыНакопления.<ИмяРегистра>.СоздатьНаборЗаписей())

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

Основные причины, по которым движения могут быть не видны, и их решения

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

  1. Отсутствие или некорректная установка отбора по регистратору

    Для регистров, подчиненных регистратору (например, регистры накопления), крайне важно установить отбор по регистратору. Без этого 1С не сможет понять, к какому именно документу относятся наши манипуляции с движениями. Если отбор не установлен, метод Записать() на пустом наборе записей приведет к удалению всех записей из регистра, а не только записей конкретного документа. А при добавлении записей без отбора они могут быть записаны, но без связи с документом-регистратором.

    Правильный способ установки отбора:

    
    // Создаем набор записей для нужного регистра
    НаборЗаписей = РегистрыНакопления.НужныйРегистр.СоздатьНаборЗаписей(); 
    
    // Устанавливаем отбор по регистратору, используя метод Установить()
    НаборЗаписей.Отбор.Регистратор.Установить(СсылкаНаДокумент); 
    
  2. Неправильное использование методов Прочитать(), Очистить() и Записать()

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

    Ситуация 1: Удаление существующих движений документа и запись новых

    Предположим, наша задача — полностью перезаписать движения документа в регистре. В этом случае нам не нужно вызывать метод Прочитать(). Нам достаточно создать пустой набор записей, установить для него отбор по регистратору и вызвать Записать().

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

    Ситуация 2: Загрузка существующих движений, их модификация и перезапись

    Если нам нужно не полностью перезаписать движения, а, например, изменить только некоторые записи, тогда нам обязательно потребуется метод Прочитать(). Он загружает в наш объект НаборЗаписей все существующие движения, соответствующие отбору.

  3. Неустановленное свойство "Записывать" для движений документа

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

  4. Необновление формы после программных изменений

    Даже если мы корректно записали движения в базу данных, они могут быть не видны на форме документа из-за кеширования. Для визуализации изменений после отработки программного кода можно в коде формы вызвать ЭтаФорма.Прочитать().

Дополнительные рекомендации и лучшие практики

Чтобы наша работа с движениями была максимально эффективной и без ошибок, давайте рассмотрим еще несколько полезных моментов.

  1. Особенности метода Записать() с параметром Замещать

    Метод Записать() имеет параметр Замещать (по умолчанию Истина). Если вы используете расширения для изменения логики проведения, стоит убедиться в отсутствии конфликтов.

  2. Избегайте чтения и записи наборов записей в цикле

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

  3. Получение объекта документа

    Если вам нужна только ссылка для установки отбора, не вызывайте ПолучитьОбъект(). Это лишняя нагрузка на систему. Используйте саму ссылку: НаборЗаписей.Отбор.Регистратор.Установить(СсылкаНаДокумент).

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

← На главную