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