Документ Корректировка записей регистров в конфигурации «Управление торговлей 10.3» (и других на базе обычных форм) является универсальным инструментом. Он не имеет привычных табличных частей для хранения данных, а выступает в роли «контейнера» или оболочки для движений по практически любым регистрам системы. В процессе эксплуатации, особенно после свертки базы, часто возникает необходимость программно «почистить» такие документы — например, удалить записи по неиспользуемым типам цен или обнулить остатки товаров, которые ошибочно попали в корректировку.
В этой статье мы подробно разберем, как программно изменять состав движений этого документа, рассмотрим нюансы работы с наборами записей и выясним, как правильно удалять ненужные строки, не нарушая логику работы системы.
Прежде чем приступать к написанию кода, проанализируем ситуацию. У документа КорректировкаЗаписейРегистров нет реквизитов, в которых хранятся данные регистров. Вместо этого он напрямую управляет наборами записей. При открытии документа в интерфейсе система динамически считывает данные из регистров, по которым данный документ является регистратором, и выводит их на соответствующие закладки.
Существует два основных способа программного изменения данных в таком документе:
Движения.НаборЗаписей конкретного регистра с отбором по документу-регистратору.Разберем каждый из этих способов подробнее.
Этот метод удобен, когда вы уже работаете с объектом документа (например, в процессе его создания или модификации других реквизитов). Проанализируем алгоритм действий:
// Получаем объект документа
ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();
// Выбираем конкретный регистр, который нужно отредактировать
НаборДвижений = ДокОбъект.Движения.ЦеныНоменклатуры;
// Читаем текущие движения из базы в память
НаборДвижений.Прочитать();
// Проходим циклом с конца, чтобы безопасно удалять строки
Индекс = НаборДвижений.Количество() - 1;
Пока Индекс >= 0 Цикл
ТекущаяСтрока = НаборДвижений[Индекс];
// Условие: например, удаляем записи с определенным типом цен
Если ТекущаяСтрока.ТипЦен.ПометкаУдаления Тогда
НаборДвижений.Удалить(Индекс);
КонецЕсли;
Индекс = Индекс - 1;
КонецЦикла;
// Устанавливаем флаг записи для коллекции
НаборДвижений.Записывать = Истина;
// Записываем сам документ, при этом запишутся и измененные движения
ДокОбъект.Записать();
Важный нюанс: при использовании этого метода свойство Записывать = Истина сообщает системе, что при вызове метода Записать() объекта документа необходимо принудительно обновить данные в соответствующем регистре. Если этот флаг не установить, изменения в коллекции Движения будут проигнорированы.
Если задача стоит в массовом редактировании тысяч строк или очистке данных по конкретному регистру без изменения самого объекта документа, работа через НаборЗаписей является более производительной и гибкой. Выясним причину: в этом случае нам не нужно блокировать и считывать весь объект документа со всеми его движениями по другим регистрам.
Рассмотрим пример удаления записей из регистра сведений ЦеныНоменклатуры, где тип цены помечен на удаление:
// 1. Создаем набор записей для нужного регистра
НаборЗаписей = РегистрыСведений.ЦеныНоменклатуры.СоздатьНаборЗаписей();
// 2. Устанавливаем жесткий отбор по регистратору (нашему документу)
НаборЗаписей.Отбор.Регистратор.Установить(СсылкаНаДокумент);
// 3. Читаем данные
НаборЗаписей.Прочитать();
// 4. Выгружаем данные в Таблицу Значений для быстрой обработки
ТЗ = НаборЗаписей.Выгрузить();
// 5. Ищем строки, которые НЕ нужно удалять (оставляем валидные данные)
ПараметрыОтбора = Новый Структура;
// Здесь может быть сложная логика фильтрации через Запрос или перебор
// В данном примере просто удалим лишнее из ТЗ в цикле
КоллекцияДляУдаления = Новый Массив;
Для Каждого СтрокаТЗ Из ТЗ Цикл
Если СтрокаТЗ.ТипЦен.ПометкаУдаления Тогда
КоллекцияДляУдаления.Добавить(СтрокаТЗ);
КонецЕсли;
КонецЦикла;
Для Каждого СтрокаДляУдаления Из КоллекцияДляУдаления Цикл
ТЗ.Удалить(СтрокаДляУдаления);
КонецЦикла;
// 6. Очищаем набор, загружаем обновленную ТЗ и записываем
НаборЗаписей.Загрузить(ТЗ);
НаборЗаписей.Записать();
Обратите внимание: если вам нужно полностью очистить все записи документа по конкретному регистру, достаточно просто установить отбор по регистратору и вызвать НаборЗаписей.Записать() без предварительного чтения и добавления строк. Пустой набор при записи сотрет все старые данные в базе по данному регистратору.
Проанализируем техническую особенность документа КорректировкаЗаписейРегистров. В нем существует скрытая служебная табличная часть (или свойство) под названием ТаблицаРегистров. В этой таблице перечисляются имена регистров, по которым документ делает движения.
Если вы программно полностью удалили все записи из какого-то регистра (например, очистили ПартииТоваровНаСкладах), крайне желательно удалить соответствующую строку из ТаблицаРегистров объекта документа. Рассмотрим, как это сделать:
ОбъектДок = СсылкаНаДокумент.ПолучитьОбъект();
СтрокаРегистра = ОбъектДок.ТаблицаРегистров.Найти("ПартииТоваровНаСкладах", "Имя");
Если СтрокаРегистра <> Неопределено Тогда
ОбъектДок.ТаблицаРегистров.Удалить(СтрокаРегистра);
ОбъектДок.Записать();
КонецЕсли;
Если этого не сделать, в интерфейсе документа останется пустая закладка регистра, что может запутать пользователя или привести к ошибкам при ручном перепроведении, которые можно исключить с помощью платформы для создания программных роботов.
Если ваша задача — корректировка остатков товаров в организации (как описано в ситуации со сверткой), следует учитывать следующие моменты:
Активность. Если вы хотите, чтобы корректировка перестала влиять на отчеты, но данные физически остались в документе «для истории», можно просто программно установить Активность = Ложь.ТоварыНаСкладах и ПартииТоваровНаСкладах). При программном удалении строк из одного регистра обязательно проверяйте необходимость удаления из связанных, иначе возникнут расхождения в управленческом балансе.ВидДвижения (Приход или Расход). При программном формировании новых записей в корректировке важно соблюдать логику: положительные остатки обычно вводятся через ВидДвиженияНакопления.Приход.Разберем ситуацию, когда документов корректировки сотни, а записей в них — тысячи. Чтобы процесс не затянулся на часы, придерживайтесь следующих правил: например, для автоматического создания архивов и обслуживания баз применяется программа для тихого архивирования и тестирования 1С.
ТаблицаЗначений, добавьте индексы по ключевым полям поиска и только потом обрабатывайте.НачатьТранзакцию() / ЗафиксироватьТранзакцию()). Однако помните о блокировках: если база активно используется, делайте фиксацию транзакции каждые 10-50 документов.Таким образом, мы выяснили, что программное редактирование документа Корректировка записей регистров сводится к управлению наборами записей. Это мощный инструмент, требующий аккуратности: всегда делайте резервную копию базы перед выполнением подобных обработок, так как прямая правка движений напрямую влияет на все отчеты и остатки в системе.