При разработке конфигураций на платформе 1С часто возникает задача отображения в списке документов суммы, пересчитанной по курсу валюты на дату каждого конкретного документа. Поскольку Динамический список — это мощный, но специфический инструмент, прямое использование виртуальной таблицы СрезПоследних внутри запроса списка может привести к проблемам с производительностью. Давайте разберем основные подходы к решению этой задачи.
Если вы хотите избежать сложных изменений в структуре данных, можно воспользоваться механизмом оформления данных динамического списка. В управляемых формах для этих целей существует событие ПриПолученииДанныхНаСервере.
Суть метода заключается в том, что платформа при выводе строк списка на экран вызывает этот обработчик, позволяя нам «дообогатить» данные каждой строки. Мы можем получить ссылку на документ, считать его дату, затем выполнить запрос к регистру сведений КурсыВалют и записать результат в оформление строки.
Преимущества: Гибкость, отсутствие необходимости модификации метаданных или создания временных таблиц.
Недостатки: Высокая нагрузка на сервер при прокрутке длинных списков, так как запрос к регистру будет выполняться для каждой порции отображаемых данных.
Чтобы список работал максимально быстро, профессионалы стараются избегать вычислений непосредственно при открытии формы. Один из эффективных методов — обеспечение полноты данных в регистре сведений.
КурсыВалют, даже если курс не изменился (дублирование записи).Левое соединение основной таблицы документа с таблицей регистра по полю Период.Такой подход превращает сложный запрос с поиском «последнего» значения в обычное соединение по ключу даты, что выполняется базой данных практически мгновенно.
Если необходимо получить срез данных для множества дат в рамках одного отчета или сложного запроса, можно сгенерировать таблицу дат программно. Это полезно, если в вашем регистре есть «дыры» (пропуски дат). Рассмотрим пример формирования такой таблицы:
ВЫБРАТЬ 0 КАК Цифра ПОМЕСТИТЬ ВТ_Цифры ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ 5 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ 7 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 8 ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ 9;
ВЫБРАТЬ ВТ_Цифры1.Цифра + 10 * ВТ_Цифры2.Цифра + 100 * ВТ_Цифры3.Цифра + 1000 * ВТ_Цифры4.Цифра КАК ПолеЧисло
ПОМЕСТИТЬ ВТ_Числа
ИЗ ВТ_Цифры КАК ВТ_Цифры1, ВТ_Цифры КАК ВТ_Цифры2, ВТ_Цифры КАК ВТ_Цифры3, ВТ_Цифры КАК ВТ_Цифры4;
ВЫБРАТЬ ДОБАВИТЬКДАТЕ(&ДатаНачала, ДЕНЬ, ВТ_Числа.ПолеЧисло) КАК ДатаЧисло
ИЗ ВТ_Числа КАК ВТ_Числа
ГДЕ ДОБАВИТЬКДАТЕ(&ДатаНачала, ДЕНЬ, ВТ_Числа.ПолеЧисло) МЕЖДУ &ДатаНачала И &ДатаОкончания;
Этот код позволяет получить сплошной список дат, к которому затем можно эффективно присоединить данные о курсах.
Наиболее производительным методом является хранение результата. Создайте дополнительный регистр сведений, в который при проведении документа записывается сумма в валюте. Это переносит нагрузку с этапа чтения (отображения списка) на этап записи (проведения документа).
Важные рекомендации при реализации:
ЕСТЬNULL в запросах. Если курс на дату документа не найден, NULL может привести к ошибкам в расчетах или визуальным дефектам.Кратности валюты. В 1С курс часто выражается как «сумма валюты за X единиц», поэтому деление на Кратность является обязательным для корректности расчетов.Выбирая решение, анализируйте объем данных. Для небольших списков достаточно обработки ПриПолученииДанныхНаСервере. Если же список содержит тысячи и более строк, используйте предварительный расчет и сохранение данных в регистр сведений — это сэкономит ресурсы сервера и обеспечит быструю работу интерфейса для пользователей.