Как записать количество строк табличной части в ресурс регистра накопления 1С?

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

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

Разберем, как правильно спроектировать регистр накопления и какими способами можно записать количество строк табличной части в его ресурс.

Архитектура регистра накопления: типичные ошибки и правильная структура

Перед написанием программного кода проанализируем структуру регистра накопления. Для решения задачи агрегирования числовых показателей (выработки) подходит оборотный регистр накопления (свойство Вид регистра = Обороты).

Рассмотрим состав метаданных регистра:

  1. Измерения: реквизит Монтажник (тип: ссылка на справочник).
  2. Ресурсы: числовой реквизит КоличествоПриборов (тип: Число(10, 0), неотрицательное).

Частая ошибка: добавление отдельного измерения Дата для хранения дня выполнения работ. В любом регистре накопления 1С уже присутствует системный реквизит Период. Добавление собственного измерения даты избыточно — оно увеличивает размер таблиц и замедляет выборку итогов. Для учета выработки за конкретный день достаточно записывать дату выполнения работ напрямую в реквизит Период движения.

Способ 1. Формирование движения через обращение к свойствам объекта

Рассмотрим базовый вариант формирования записей в модуле документа в процедуре ОбработкаПроведения. Если в документе реквизит ДатаВыполненияРабот задан в шапке, а каждая строка табличной части Приборы представляет собой одну единицу оборудования, мы можем вычислить общее число строк методом Количество().

Посмотрим на пример кода:


Процедура ОбработкаПроведения(Отказ, Режим)
    
    // Проверяем наличие строк, чтобы не создавать пустых записей
    Если ТабличнаяЧастьПриборы.Количество() = 0 Тогда
        Возврат;
    КонецЕсли;
    
    // Инициализируем запись в регистр
    Движение = Движения.ВыработкаМонтажников.Добавить();
    
    // Приводим дату выполнения работ к началу дня
    Движение.Период = НачалоДня(ДатаВыполненияРабот);
    Движение.Монтажник = Монтажник;
    
    // Записываем общее количество строк табличной части
    Движение.КоличествоПриборов = ТабличнаяЧастьПриборы.Количество();
    
КонецПроцедуры

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

Способ 2. Формирование движений через запрос к табличной части (рекомендуемый)

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

Разберем по шагам реализацию через запрос:


Процедура ОбработкаПроведения(Отказ, Режим)
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   НАЧАЛОПЕРИОДА(Док.ДатаВыполненияРабот, ДЕНЬ) КАК Период,
        |   Док.Монтажник КАК Монтажник,
        |   КОЛИЧЕСТВО(Док.НомерСтроки) КАК КоличествоПриборов
        |ИЗ
        |   Документ.УстановкаОборудования.Приборы КАК Док
        |ГДЕ
        |   Док.Ссылка = &Ссылка
        |СГРУППИРОВАТЬ ПО
        |   НАЧАЛОПЕРИОДА(Док.ДатаВыполненияРабот, ДЕНЬ),
        |   Док.Монтажник";
        
    Запрос.УстановитьПараметр("Ссылка", Ссылка);
    
    РезультатЗапроса = Запрос.Выполнить();
    Если Не РезультатЗапроса.Пустой() Тогда
        Движения.ВыработкаМонтажников.Загрузить(РезультатЗапроса.Выгрузить());
    КонецЕсли;
    
КонецПроцедуры

В этом запросе функция КОЛИЧЕСТВО() автоматически подсчитывает число строк для каждой уникальной комбинации периода и исполнителя, а метод Загрузить() мгновенно переносит результат в набор записей регистра.

Получение накопленных данных из регистра

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

Рассмотрим пример запроса для получения итогов:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   ВыработкаОбороты.Период КАК ДатаРабот,
    |   ВыработкаОбороты.Монтажник КАК Монтажник,
    |   ВыработкаОбороты.КоличествоПриборовОборот КАК ВсегоПриборов
    |ИЗ
    |   РегистрНакопления.ВыработкаМонтажников.Обороты(&НачалоДня, &КонецДня, День, ) КАК ВыработкаОбороты
    |ГДЕ
    |   ВыработкаОбороты.Монтажник = &Монтажник";

Запрос.УстановитьПараметр("НачалоДня", НачалоДня(ТекущаяДата()));
Запрос.УстановитьПараметр("КонецДня", КонецДня(ТекущаяДата()));
Запрос.УстановитьПараметр("Монтажник", ВыбранныйМонтажник);

Результат = Запрос.Выполнить().Выгрузить();

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

Практические рекомендации

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