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