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