При работе с платформой 1С иногда возникает потребность в создании списков, которые не только отображают данные, но и имеют сложное, "филигранное" оформление для каждой строки, возможно, с интерактивными элементами или вложенной иерархией. Стандартные возможности динамического списка по оформлению могут оказаться недостаточными, а отказ от него ради большей свободы в отображении приводит к потере важных функций, таких как эффективная прокрутка больших объемов данных. Давайте подробно рассмотрим, как мы можем подойти к решению этой задачи, комбинируя различные механизмы платформы.
Основная сложность заключается в том, чтобы сохранить преимущества динамического списка (прокрутка, пагинация, работа с большими данными), одновременно получая возможность выводить каждую позицию в прокручиваемой области по собственному макету, например, через табличный или HTML-документ.
Начнем с анализа того, что мы хотим получить. Мы стремимся к созданию списка, который будет:
Очевидно, что стандартный динамический список имеет ограничения: в него нельзя добавить колонку с табличным или HTML-документом, и его возможности по условному оформлению, хотя и достаточно широки, не позволяют создать полноценную вложенную иерархию или произвольную разметку внутри одной строки.
Мы рассмотрим несколько основных подходов, включая практические методы доработки динамических списков, которые помогут нам приблизиться к поставленной цели, а также их комбинации.
Хотя динамический список имеет ограничения по сложности оформления, мы можем существенно расширить его возможности с помощью события ПриПолученииДанныхНаСервере и свойства ВыражениеПредставления.
Событие ПриПолученииДанныхНаСервере для динамического списка, доступное начиная с версии платформы 8.3.10, позволяет нам дополнительно обрабатывать данные, полученные для отображения. Это событие вызывается на сервере только для видимых строк списка, что обеспечивает дополнительную оптимизацию при работе с большими объемами данных.
В рамках этого события мы можем программно изменять оформление строк и ячеек динамического списка (например, реализовать флажок в динамическом списке). Например, мы можем задать цвет текста или фона для определенной колонки на основе значения какого-либо поля, которое даже не отображается в списке. Мы можем добавлять в выводимые строки данные, которых нет в базе, формируя их на лету.
&НаСервере
Процедура СписокПриПолученииДанныхНаСервере(Элемент, Данные, Отказ)
Для Каждого Строка Списка.Элементы Цикл
// Пример: Если есть поле "СтатусЗадачи"
Если Строка.СтатусЗадачи = Перечисления.СтатусыЗадач.Выполнена Тогда
// Изменяем цвет текста для всей строки
Строка.ЦветТекста = ЦветаСтиля.ЦветВыполненнойЗадачи;
// Или для конкретной ячейки
Строка.Ячейки.Наименование.ЦветТекста = ЦветаСтиля.ЦветВыполненнойЗадачи;
КонецЕсли;
// Пример: Добавляем форматированное представление для поля, которого нет в запросе
// Предположим, что в запросе есть поля "ДатаНачала" и "ДатаОкончания"
Строка.ПредставлениеПериода = "с " + Формат(Строка.ДатаНачала, "ДФ=dd.MM.yyyy") +
" по " + Формат(Строка.ДатаОкончания, "ДФ=dd.MM.yyyy");
// Это поле "ПредставлениеПериода" должно быть добавлено в колонки динамического списка
// в конфигураторе или программно.
КонецЦикла;
КонецПроцедуры
Однако важно помнить, что при использовании ПриПолученииДанныхНаСервере для формирования содержимого, высота строки динамического списка по содержимому работать не будет. У всех строк будет одинаковая высота, которую вы задали в свойствах элемента формы, или стандартная. Это является значительным ограничением для вывода сложной, многострочной информации в пределах одной ячейки.
Начиная с версии 8.3.20, у полей динамического списка появилось новое свойство ВыражениеПредставления. Если это свойство задано, динамический список использует его для формирования отображаемого текста в таблице (похожий принцип использует форматированный документ). Это позволяет нам формировать более сложное текстовое представление поля, объединяя данные из нескольких полей или применяя форматирование, без изменения основного запроса или дополнительного кода в ПриПолученииДанныхНаСервере.
Например, вместо того, чтобы выводить отдельные колонки "Фамилия", "Имя", "Отчество", мы можем создать одну колонку "ПолноеИмя" с выражением представления: [Фамилия] + " " + [Имя] + " " + [Отчество].
Для более продвинутого условного оформления мы можем использовать встроенные механизмы платформы. Они доступны как в режиме предприятия для пользователя, так и в режиме конфигуратора для разработчика. Это позволяет нам выделять строки или ячейки списка цветом, шрифтом, а также использовать различные стили (полужирный, курсив, подчеркнутый) на основе определенных условий.
ТабличноеПоле, отображающему динамический список.СтатусЗадачи = &СтатусВыполнена) и Параметры оформления (например, ЦветТекста, ЦветФона, Шрифт).Эти методы позволяют нам значительно улучшить визуальное представление динамического списка, но они все еще ограничены возможностями табличного поля и не позволяют в полной мере реализовать "филигранное" оформление с произвольной HTML-разметкой или глубокой интерактивной иерархией внутри каждой строки.
Если нам требуется действительно "филигранное" оформление, полная свобода в разметке и высокая интерактивность, то наилучшим решением является использование элемента формы Поле HTML документа. По сути, это встроенный браузерный движок Webkit, который позволяет интегрировать HTML, CSS и JavaScript, открывая широчайшие возможности для создания динамичных и интерактивных элементов интерфейса.
Поле HTML документа для отображения красивых лент взаимодействий или других сложных интерфейсов.Основная проблема при использовании Поля HTML документа вместо динамического списка для отображения большого объема данных – это прокрутка. Если мы выведем 10 000 позиций справочника сразу в HTML-документ, форма будет "тормозить" или даже зависнет. Для этого нам потребуется реализовать механизмы виртуализации или пагинации, аналогичные тем, что используются в веб-приложениях.
window.external.call("МойМетодНаКлиенте", "Параметр")), который, в свою очередь, может вызвать серверный метод.ПриИзменении этого реквизита.<a href="e1c://Объект/Справочник.Номенклатура?Ссылка=GUID_объекта">). При клике по таким ссылкам платформа 1С может обрабатывать их, открывая соответствующие формы объектов.
// Пример JavaScript-кода в HTML-документе для обработки прокрутки
// (фрагмент, требующий доработки и адаптации)
var scrollContainer = document.getElementById('myScrollableContent');
scrollContainer.onscroll = function() {
if (scrollContainer.scrollTop + scrollContainer.clientHeight >= scrollContainer.scrollHeight - 100) {
// Достигли почти конца, запрашиваем новые данные
if (window.external && window.external.call) {
window.external.call('ЗагрузитьСледующиеЭлементы', 'Параметр_для_сервера');
}
}
// Можно также отслеживать прокрутку вверх
if (scrollContainer.scrollTop < 100 && scrollContainer.dataset.hasPrevious === 'true') {
if (window.external && window.external.call) {
window.external.call('ЗагрузитьПредыдущиеЭлементы', 'Параметр_для_сервера');
}
}
};
// Функция для добавления нового HTML-контента
function addContent(htmlContent) {
scrollContainer.innerHTML += htmlContent; // Или более аккуратно вставлять
}
// Пример кода 1С для обработки вызова из JavaScript
// (в модуле формы)
&НаКлиенте
Процедура ЗагрузитьСледующиеЭлементы(Параметр) Экспорт
// Здесь можем вызвать серверный метод для получения новых данных
ПолучитьИДобавитьДанныеНаСервере(Параметр);
КонецПроцедуры
&НаСервере
Процедура ПолучитьИДобавитьДанныеНаСервере(Параметр)
// Получаем следующую порцию данных
НовыеДанные = ЗапросКБазеДанных(Параметр);
// Формируем HTML-фрагмент
НовыйHTML = СформироватьHTML(НовыеДанные);
// Передаем HTML-фрагмент на клиент и вызываем JS-функцию
Элементы.ПолеHTMLДокумента1.ВыполнитьКоманду("addContent('" + НовыйHTML + "');");
КонецПроцедуры
Это достаточно сложный подход, требующий хорошего знания как платформы 1С, так и веб-технологий (HTML, CSS, JavaScript), но он дает максимальную гибкость и контроль над отображением.
Для отображения иерархических данных, таких как задачи с подзадачами, элемент Дерево на управляемых формах является очень мощным инструментом. Он изначально предназначен для работы с иерархией и имеет встроенные механизмы для прокрутки и сворачивания/разворачивания узлов.
Дерево имеет стандартную полосу прокрутки, которая работает эффективно.Мы можем использовать дерево, заполняя его программно на сервере. При получении данных мы можем задавать различные свойства для каждой строки дерева, такие как цвет текста, фон, шрифт, а также отображать иконки, что позволит добиться определенного уровня "филигранности" оформления.
&НаСервере
Процедура ЗаполнитьДерево()
ДеревоДанных = Новый ДеревоЗначений;
ДеревоДанных.Колонки.Добавить("Задача");
ДеревоДанных.Колонки.Добавить("Статус");
ДеревоДанных.Колонки.Добавить("ЦветСтроки", Новый ОписаниеТипов("Цвет"));
// Получаем данные задач (пример)
Задачи = ПолучитьЗадачиИзБазы();
Для Каждого Задача Из Задачи Цикл
СтрокаДерева = ДеревоДанных.Добавить();
СтрокаДерева.Задача = Задача.Наименование;
СтрокаДерева.Статус = Задача.Статус;
Если Задача.Статус = Перечисления.СтатусыЗадач.Выполнена Тогда
СтрокаДерева.ЦветСтроки = ЦветаСтиля.ЦветВыполненнойЗадачи;
ИначеЕсли Задача.Статус = Перечисления.СтатусыЗадач.Просрочена Тогда
СтрокаДерева.ЦветСтроки = ЦветаСтиля.ЦветПросроченнойЗадачи;
КонецЕсли;
// Здесь же можем добавить подзадачи, если они есть
// Например: ДобавитьПодзадачи(СтрокаДерева, Задача.Ссылка);
КонецЦикла;
Элементы.Дерево1.Значение = ДеревоДанных;
КонецПроцедуры
Для отображения иерархических задач с прокруткой, дерево на управляемых формах является одним из наиболее подходящих и производительных вариантов.
Ещё один подход – это использование ТабличногоДокумента для вывода сложного макета. Мы можем сформировать каждую строку списка в виде отдельной области табличного документа, используя различные макеты.
Мы можем использовать систему компоновки данных (СКД) с оформленным макетом, чтобы сгенерировать сложный отчет, который будет представлять наш список в виде табличного документа. Затем этот ДокументРезультат (т.е. сформированный ТабличныйДокумент) мы можем вывести на форму в элементе Поле Табличного Документа.
&НаСервере
Процедура СформироватьТабличныйСписок()
МакетСКД = ПолучитьМакет("МакетСпискаЗадач"); // Макет СКД, где описан внешний вид строк
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(МакетСКД, ДанныеКомпоновки);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ТабДок = Новый ТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ТабДок);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
Элементы.ПолеТабличногоДокумента1.УстановитьДокумент(ТабДок);
КонецПроцедуры
Табличный документ позволяет очень гибко настраивать внешний вид, объединять ячейки, использовать различные шрифты и цвета, выводить картинки. Однако, как и в случае с HTML-документом, возникает проблема прокрутки для больших объемов данных. Если мы выведем все 10 000 позиций сразу в один ТабличныйДокумент, это приведет к серьезным "тормозам".
Для реализации динамической подгрузки данных в ТабличныйДокумент при прокрутке, нам потребуется использовать аналогичный подход, как и с Полем HTML документа:
Поле Табличного Документа на форме (например, через JavaScript-обработчик или средствами 1С, если такие события доступны, или косвенно через изменение видимой области).ТабличномуДокументу.Этот подход сложен, так как стандартные механизмы ТабличногоДокумента не предназначены для такой "потоковой" дозагрузки данных с сохранением прокрутки. В ЗУП (1С:Зарплата и Управление Персоналом) документ "Табель" может переключаться между форматом табличной части и табличного документа, что может дать идеи для реализации, хотя код там весьма специфичен для ЗУПа.
Также мы можем выводить произвольную расшифровку под динамическим списком для текущей активной строки ДС. Однако это не соответствует изначальной задаче, где клиенту нужно видеть "расшифровку" для каждой строки непосредственно в списке.
Независимо от выбранного подхода, нам необходимо учитывать общие рекомендации по производительности 1С:
Таким образом, для достижения "филигранного" оформления с сохранением прокрутки, мы можем комбинировать подходы: использовать ПриПолученииДанныхНаСервере и ВыражениеПредставления для улучшения оформления стандартного динамического списка. Но для более сложных, интерактивных иерархических элементов нам придется рассмотреть интеграцию Поля HTML документа с собственной логикой прокрутки и загрузки данных через JavaScript или использовать Дерево на управляемых формах для иерархических данных.