Как записать в регистр сведений только те записи, которые были отредактированы на форме?

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

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

Метод 1. Использование служебного реквизита (Флаг изменения)

Это самый простой и распространенный способ. Мы добавим в таблицу на форме «невидимый» для пользователя признак, который будет сигнализировать системе, что строка была изменена. Разберем по шагам, как это реализовать:

  1. Добавление реквизита: В объекте, который выводит таблицу на форму (это может быть ТаблицаЗначений или ДанныеФормыКоллекция), создадим колонку Изменена с типом Булево.
  2. Настройка формы: Разместим эту колонку в таблице на форме, но установим ей свойство Видимость = Ложь.
  3. Отслеживание правок: Для каждого элемента управления в строке таблицы (например, поле ввода количества или цены) создадим событие ПриИзменении.

Проанализируем пример кода для этого события:


&НаКлиенте
Процедура ТоварыКоличествоПриИзменении(Элемент)
    ТекущаяСтрока = Элементы.Товары.ТекущиеДанные;
    Если ТекущаяСтрока <> Неопределено Тогда
        ТекущаяСтрока.Изменена = Истина;
    КонецЕсли;
КонецПроцедуры

Теперь при нажатии кнопки сохранения нам достаточно перебрать строки и выбрать только те, где Изменена = Истина. Рассмотрим, как программно сформировать записи в регистре:


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

Метод 2. Сравнение с копией данных (контрольная Таблица Значений)

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

При открытии формы (в событии ПриСозданииНаСервере) мы сохраняем текущее состояние таблицы в скрытый реквизит формы типа ТаблицаЗначений. Рассмотрим алгоритм:

  1. Создаем реквизит формы КопияДанных (тип ТаблицаЗначений), полностью повторяющий структуру основной таблицы.
  2. При загрузке формы заполняем его: КопияДанных.Загрузить(Объект.Товары.Выгрузить());.
  3. При сохранении сравниваем строки по индексам или по уникальным ключам.

Посмотрим на пример функции сравнения:


&НаСервере
Процедура СохранитьОтличия()
    ТаблицаТекущая = Объект.Товары.Выгрузить();
    ТаблицаСтарая = РеквизитФормыВЗначение("КопияДанных");
    
    Для Индекс = 0 По ТаблицаТекущая.Количество() - 1 Цикл
        СтрокаТекущая = ТаблицаТекущая[Индекс];
        СтрокаСтарая = ТаблицаСтарая[Индекс];
        
        // Сравниваем только значимые поля, например, Количество
        Если СтрокаТекущая.Количество <> СтрокаСтарая.Количество Тогда
            ЗаписатьВРегистр(СтрокаТекущая);
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

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

Особенности регистров, подчиненных регистратору

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

Чтобы изменить только одну строку в подчиненном регистре, нужно придерживаться следующей логики:

  1. Прочитать весь существующий набор записей по данному регистратору в объект РегистрСведенийНаборЗаписей.
  2. Найти в наборе нужную запись (по измерениям).
  3. Изменить значения ресурсов в этой записи.
  4. Записать весь набор обратно.

Пример работы с набором:


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

Для Каждого Запись Из Набор Цикл
    Если Запись.Номенклатура = ИзмененныйТовар Тогда
        Запись.Количество = НовоеКоличество;
    КонецЕсли;
КонецЦикла;

Набор.Записать();

Метод 3. Использование механизма «История данных»

Если ваша основная задача — знать, кто и когда изменил данные, и вы используете современную платформу (8.3.11 и выше), рекомендуем рассмотреть системный механизм История данных. Рассмотрим его преимущества:

Для включения этого механизма достаточно в свойствах объекта метаданных (например, документа или регистра) установить свойство История данных = Использовать.

Архитектурная рекомендация

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

Резюмируем: Для быстрой реализации используйте скрытую колонку-флаг. Для обеспечения максимальной точности при сложных манипуляциях с таблицей — сравнение с копией данных. А если нужно отслеживать действия пользователей для аудита — выбирайте системную Историю данных.

← На главную