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