При разработке интерфейсов в 1С:Предприятии 7.7 часто возникает задача вывести в форме списка справочника расчетные показатели — например, умножить количество минут опоздания на тариф штрафа. Если добавить на форму текстовую колонку с формулой, платформа рассчитает значение для каждой строки. Однако при попытке сложить эти значения и вывести общий итог разработчик сталкивается с ограничениями платформы. Разберем по шагам, почему так происходит и какими способами можно реализовать корректный подсчет итогов.
Платформа 1С 7.7 устроена таким образом, что многострочная часть списка справочника или журнала документов не хранит всю выборку данных в оперативной памяти клиента. Выясним ключевые причины:
Итог() реализован только для табличных частей документов и объектов типа ТаблицаЗначений. Для списков справочников встроенной агрегации колонок не предусмотрено.Рассмотрим рабочие способы решения этой задачи в зависимости от архитектурных требований.
Если необходимо оставить данные в справочнике и отображать итоговую сумму непосредственно на форме списка, вынесем на форму отдельный элемент диалога типа Текст и свяжем его с переменной, например ВсегоСумма. Для расчета напишем процедуру, которая выполняет явный обход записей с учетом установленного отбора.
Разберем пример кода для модуля формы списка справочника:
Процедура ПересчитатьИтог()
ВсегоСумма = 0;
Спр = СоздатьОбъект("Справочник.Опоздания");
// Если используется отбор по сотруднику (владельцу или реквизиту)
Если ПустоеЗначение(ВыбСотрудник) = 0 Тогда
Спр.ИспользоватьВладельца(ВыбСотрудник);
КонецЕсли;
Спр.ВыбратьЭлементы();
Пока Спр.ПолучитьЭлемент() = 1 Цикл
// Проверяем условия отбора, например период
Если (Спр.ДатаОпоздания >= ВыбНачПериода) И (Спр.ДатаОпоздания <= ВыбКонПериода) Тогда
СуммаСтроки = Спр.КоличествоМинут * Спр.Тариф;
ВсегоСумма = ВсегоСумма + СуммаСтроки;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Вызов процедуры ПересчитатьИтог() необходимо привязать к ключевым событиям формы:
ПриОткрытии() для инициализации начального значения.ПриЗаписи() элемента справочника, чтобы при ручной корректировке минут итоговая сумма сразу актуализировалась.Если справочник содержит большой объем данных, простой цикл ВыбратьЭлементы() может выполняться медленно. В таких случаях эффективнее использовать встроенный язык запросов 1С 7.7. Запрос агрегирует числовые данные на уровне движка базы.
Посмотрим на пример реализации расчета через запрос:
Функция РассчитатьИтогЗапросом(ТекСотрудник, ДатаНач, ДатаКон)
ТекстЗапроса = "
|Период с (ДатаНач) по (ДатаКон);
|Сотр = Справочник.Опоздания.Владелец;
|Минуты = Справочник.Опоздания.КоличествоМинут;
|Функция ВсегоМинут = Сумма(Минуты);
|Группировка Сотр;
|Условие(Сотр = ТекСотрудник);
|";
Запрос = СоздатьОбъект("Запрос");
Если Запрос.Выполнить(ТекстЗапроса) = 1 Тогда
Если Запрос.Группировка(1) = 1 Тогда
// Умножаем общее количество минут на установленный тариф
Возврат Запрос.ВсегоМинут * Константа.ТарифШтрафа;
КонецЕсли;
КонецЕсли;
Возврат 0;
КонецФункции
Если сотруднику требуется возможность интерактивно просматривать список, корректировать минуты и сразу видеть мгновенный пересчет общей суммы по документному принципу, наилучшим решением является создание специализированной обработки с элементом диалога ТаблицаЗначений.
Разберем по шагам, как устроен этот механизм:
ТаблицаЗначений с идентификатором ТЗ.ТЗ.Итог("СуммаШтрафа"), который моментально возвращает точную сумму по всем строкам таблицы без повторных обращений к базе данных.Пример программного расчета по таблице значений:
Процедура ПриИзмененииМинут()
ТекСтр = ТЗ.ТекущаяСтрока();
Если ТекСтр > 0 Тогда
ТЗ.ПолучитьСтрокуПоНомеру(ТекСтр);
ТЗ.СуммаШтрафа = ТЗ.КоличествоМинут * ТЗ.Тариф;
// Мгновенный пересчет общего итога
ИтогоШтраф = ТЗ.Итог("СуммаШтрафа");
КонецЕсли;
КонецПроцедуры
С точки зрения методологии учета в 1С 7.7 факты хозяйственной деятельности (опоздания, начисления, удержания) правильнее регистрировать документами, а не справочниками. Документ содержит полноценную табличную часть, в которой стандартно поддерживаются:
Итог("ИмяРеквизита").Таким образом, если задача требует интерактивного расчета и суммирования строк с формулами, следует отказаться от попыток агрегации колонок в форме списка справочника и применить явную выборку, обработку с таблицей значений либо документную модель учета.