Небольшой пример программного использования схемы компоновки данных для выгрузки произвольной информации справочника или документа в табличный документ (например, в Excel).
По мере разбора задачи вы сможете самостоятельно "приготовить" внешнюю обработку. Желающие могут скачать готовую обработку за $m.
Основные вопросы, которые решаются в публикации:
- Программное создание простейшего текста запроса с использованием объектного подхода (СхемаЗапроса)
- Программное создание схемы компоновки данных с простейшей структурой (детальные записи с выводом одного поля "Ссылка")
- Использование объекта КомпоновщикНастроекКомпоновкиДанных для реализации пользовательского изменения некоторых настроек (произвольный отбор, выбор доступных полей и настройка сортировки)
- Программный вывод данных в табличный документ с использованием ранее созданной схемы компоновки данных и отредактированных настроек
Возможные варианты использования:
- как отдельный продукт для выгрузки данных в линейном виде (без иерархии)
- для проверки соответствия произвольных ссылок настроенным отборам
- реализация выборки объектов по настроенному пользователем отбору
- кастомизация обработки под свои требования (например, выгрузка сложной сложной структуры, выгрузка данных из регистров и т.д.)
Создаем новую внешнюю обработку и пустую форму обработки.
Создаем следующий список реквизитов формы:
Имя реквизита | Тип реквизита | Комментарий |
АдресСКД | Строка(0) | Временное хранилище, содержащее схему компоновки данных |
НастройкиКомпоновщика | КомпоновщикНастроекКомпоновкиДанных | Настройки компоновки данных (отбор, доступные поля, сортировка) |
ОбъектВыгрузки | Строка(0) | Имя выгружаемого справочника/документа |
Таблица | ТаблицаЗначений | Таблица выгружаемых полей |
Таблица.ИмяРеквизита | Произвольный | Для хранения идентификатора выгружаемого поля компоновки данных |
Таблица.ИмяКолонки | Строка(100) | Название колонки табличного документа, в которое будет выгружаться выбранное поле |
ТипДокумента | Произвольный | ТипФайлаТабличногоДокумента - тип табличного документа для записи в файл |
ТипОбъекта | Строка(50) | Справочник или Документ |
У реквизитов ОбъектВыгрузки, Таблица и ТипОбъекта устанавливаем проверку заполнения Выдавать ошибку
ТипОбъекта - перетаскиваем на форму одноименный реквизит, РежимВыбораИзСписка = Истина, в СписокВыбора добавляем 2 значения - "Справочники" и "Документы" (пердствление - по вкусу)
ОбъектВыгрузки - перетаскиваем на форму одноименный реквизит, РежимВыбораИзСписка = Истина
НастройкиКомпоновщикаНастройкиОтбор - перетаскиваем на форму НастройкиКомпоновщика.Настройки.Отбор, добавляем как поле:
НастройкиКомпоновщикаНастройкиПорядок - перетаскиваем на форму НастройкиКомпоновщика.Настройки.Порядок как поле
ТипДокумента - перетаскиваем на форму одноименный реквизит, РежимВыбораИзСписка = Истина
ГруппаГоризонтальная - обычная группа, ОтображатьЗаголовок = Ложь, Группировка - Горизонтальная всегда, Отображение - Нет; в эту группу добавим таблицу с доступными полями и таблицу выгружаемых данных:
- НастройкиКомпоновщикаНастройкиВыборДоступныеПоляВыбора - перетаскиваем НастройкиКомпоновщика.Настройки.Выбор.ДоступныеПоляВыбора:
- Таблица - перетаскиваем на форму одноименную таблицу значений вместе с колонками
Добавляем команду формы Выгрузить для выгрузки данных в файл и вносим ее на командную панель формы.
В итоге должен получиться примерно следующий интерфейс:
У формы создаем единственный обработчик - для события ПриСозданииНаСервере. В этом обработчике будем заполнять список выбора элемента ТипДокумента
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Для Каждого ТекТип Из ТипФайлаТабличногоДокумента Цикл
Элементы.ТипДокумента.СписокВыбора.Добавить(ТекТип);
КонецЦикла;
ТипДокумента = ТипФайлаТабличногоДокумента.XLSX;
КонецПроцедуры
У элемента ТипОбъекта добавляем обработчик события ПриИзменении. При смене типа объекта нам нужно заполнить список выбора объектов выгрузки и очистить настрйоки компоновки данных
&НаКлиенте
Процедура ТипОбъектаПриИзменении(Элемент)
ОбработатьИзменениеТипаОбъекта();
КонецПроцедуры
&НаСервере
Процедура ОбработатьИзменениеТипаОбъекта()
Элементы.ОбъектВыгрузки.СписокВыбора.Очистить();
// заполняем доступные объекты из метаданных
Для Каждого ТекущийОбъект Из Метаданные[ТипОбъекта] Цикл
Если СтрНачинаетсяС(ТекущийОбъект.Имя, "Удалить") Тогда
Продолжить;
КонецЕсли;
Элементы.ОбъектВыгрузки.СписокВыбора.Добавить(ТекущийОбъект.Имя, ТекущийОбъект.Синоним);
КонецЦикла;
// очищаем настройки компоновки и таблицу выгружаемых полей
НастройкиКомпоновщика.Инициализировать(Неопределено);
АдресСКД = "";
Таблица.Очистить();
КонецПроцедуры
У элемента ОбъектВыгрузки также добавляем обработчик события ПриИзменении: при выборе конкретного объекта выгрузки нам необходимо создать схему компоновки данных и обновить настройки компоновки
&НаКлиенте
Процедура ОбъектВыгрузкиПриИзменении(Элемент)
ИнициализироватьНастройкиКомпоновщика();
КонецПроцедуры
&НаСервере
Процедура ИнициализироватьНастройкиКомпоновщика()
Если ТипОбъекта = "Справочники" Тогда
ТипДляЗапроса = "Справочник";
ИначеЕсли ТипОбъекта = "Документы" Тогда
ТипДляЗапроса = "Документ";
Иначе
Возврат;
КонецЕсли;
// создаем схему по выбранному объекту
СхемаКомпоновки = СоздатьСхемуКомпоновкиДанных(ТипДляЗапроса, ОбъектВыгрузки);
АдресСКД = ПоместитьВоВременноеХранилище(СхемаКомпоновки, УникальныйИдентификатор);
ИсточникДоступныхНастроек = Новый ИсточникДоступныхНастроекКомпоновкиДанных(АдресСКД);
// загружаем из созданной схемы настройки по умолчанию
НастройкиКомпоновщика.Инициализировать(ИсточникДоступныхНастроек);
НастройкиКомпоновщика.Восстановить(СпособВосстановленияНастроекКомпоновкиДанных.Полное);
КонецПроцедуры
&НаСервереБезКонтекста
Функция СоздатьСхемуКомпоновкиДанных(ТипОбъекта, ИмяОбъекта, Представление = "Ссылка") Экспорт
// создаем с помощью схемы запроса текст запроса для выборки одного поля Ссылка из выбранного объекта
ИмяИсточника = ТипОбъекта+"."+ИмяОбъекта;
Схема = Новый СхемаЗапроса;
Пакет = Схема.ПакетЗапросов.Добавить(Тип("ЗапросВыбораСхемыЗапроса"));
Выборка = Пакет.Операторы[0];
Источник = Выборка.Источники.Добавить(ИмяИсточника, "ВыбираемыйОбъект");
ПолеСсылка = Выборка.ВыбираемыеПоля.Добавить("ВыбираемыйОбъект.Ссылка");
Колонка = Пакет.Колонки.Найти(ПолеСсылка);
Колонка.Псевдоним = Представление;
// программно создаем схему компоновки данных с группировкой ДетальныеЗаписи
// и двумя выбранными полями - Автополе и Ссылка
СхемаКомпоновкиДанных = Новый СхемаКомпоновкиДанных;
ИсточникДанных = СхемаКомпоновкиДанных.ИсточникиДанных.Добавить();
ИсточникДанных.Имя = "ИсточникДанных1";
ИсточникДанных.ТипИсточникаДанных = "Local";
НаборДанныхЗапросСКД = СхемаКомпоновкиДанных.НаборыДанных.Добавить(
Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
НаборДанныхЗапросСКД.Имя = "НаборДанных1";
НаборДанныхЗапросСКД.АвтоЗаполнениеДоступныхПолей = Истина;
НаборДанныхЗапросСКД.ИсточникДанных = "ИсточникДанных1";
НаборДанныхЗапросСКД.Запрос = Схема.ПолучитьТекстЗапроса();
НастройкиКомпоновки = СхемаКомпоновкиДанных.НастройкиПоУмолчанию;
ДетальныеЗаписи = НастройкиКомпоновки.Структура.Добавить(
Тип("ГруппировкаКомпоновкиДанных"));
ДетальныеЗаписи.Использование = Истина;
АвтоПоле = ДетальныеЗаписи.Выбор.Элементы.Добавить(
Тип("АвтоВыбранноеПолеКомпоновкиДанных"));
АвтоПоле.Использование = Истина;
ВыбранноеПоле = НастройкиКомпоновки.Выбор.Элементы.Добавить(
Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Использование = Истина;
ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных(Представление);
Возврат СхемаКомпоновкиДанных;
КонецФункции
Для данного элемента добавляем обработчик события Выбор - при выборе доступного поля его нужно перенести в таблицу значений Таблица и предложить пользователю ввести имя колонки табличного документа, куда будет выгружаться выбранное поле.
&НаКлиенте
Асинх Процедура НастройкиКомпоновщикаНастройкиВыборДоступныеПоляВыбораВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
// раскладываем на составляющие разыменованное выбранное поле, чтобы предложить пользователи имя колонки по умолчанию
Если СтрНайти(ВыбраннаяСтрока, ".") > 0 Тогда
МассивСоставляющих = СтрРазделить(Строка(ВыбраннаяСтрока), ".");
Подсказка = МассивСоставляющих[МассивСоставляющих.ВГраница()];
Иначе
Подсказка = Строка(ВыбраннаяСтрока);
КонецЕсли;
ЗаголовокВвода = "Введите название колонки табличного документа";
ИмяКолонки = Ждать ВвестиСтрокуАсинх(Подсказка, ЗаголовокВвода, 100, Ложь);
Нов = Таблица.Добавить();
Нов.ИмяРеквизита = ВыбраннаяСтрока;
Нов.ИмяКолонки = ИмяКолонки;
// Выделяем добавленную строку
Элементы.Таблица.ТекущаяСтрока = Нов.ПолучитьИдентификатор();
Элементы.Таблица.ТекущийЭлемент = Элементы.ТаблицаИмяКолонки;
КонецПроцедуры
Команда у нас одна - Выгрузить. Данная команда должна сформировать табличный документ и предложить пользователю сохранить его в файл, доступный с клиентского компьютера пользователя
&НаКлиенте
Асинх Процедура Выгрузить(Команда)
ОчиститьСообщения();
Если Не ПроверитьЗаполнение() Тогда
Возврат;
КонецЕсли;
Состояние("Подготовка табличного документа...");
ТабДок = СформироватьТабличныйДокументНаСервере();
Если ТабДок = Неопределено Тогда
Возврат;
КонецЕсли;
Расширение = Строка(ТипДокумента);
Режим = РежимДиалогаВыбораФайла.Сохранение;
Диалог = Новый ДиалогВыбораФайла(Режим);
Диалог.Фильтр = Расширение+"|*."+Расширение;
Диалог.Заголовок = "Выберите файл для сохранения";
Результат = Ждать Диалог.ВыбратьАсинх();
Если Результат = Неопределено Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Данные не записаны: не выбран файл для записи!";
Сообщение.Сообщить();
Возврат;
КонецЕсли;
Попытка
ТабДок.Записать(Результат[0], ТипДокумента);
ОбщегоНазначенияКлиент.СообщитьПользователю("Данные успешно записаны в файл "+Результат[0]);
Исключение
Инфо = ИнформацияОбОшибке();
Причина = ПодробноеПредставлениеОшибки(Инфо);
ОбщегоНазначенияКлиент.СообщитьПользователю("Не удалось записать данные в файл "+Результат[0]+": "+Причина);
КонецПопытки;
КонецПроцедуры
&НаСервере
Функция СформироватьТабличныйДокументНаСервере()
// Получаем из временного хранилища схему компоновки данных
СхемаОтбор = ПолучитьИзВременногоХранилища(АдресСКД);
// Получаем текущие настройки компоновщика
Настройки = НастройкиКомпоновщика.ПолучитьНастройки();
// В структуру добавляем группировку "Детальные записи" и в выбранные поля группировки автополе
ДетальныеЗаписи = Настройки.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
ДетальныеЗаписи.Использование = Истина;
АвтоПоле = ДетальныеЗаписи.Выбор.Элементы.Добавить(Тип("АвтоВыбранноеПолеКомпоновкиДанных"));
АвтоПоле.Использование = Истина;
Настройки.Выбор.Элементы.Очистить();
// Из таблицы добавляем выбранные поля
Для Каждого Строка Из Таблица Цикл
Если Строка.ИмяРеквизита = Неопределено Или Не ЗначениеЗаполнено(Строка.ИмяКолонки) Тогда
Продолжить;
КонецЕсли;
// Ищем доступное поле компоновки по идентификатору из колонки ИмяРеквизита
ДоступноеПоле = НастройкиКомпоновщика.Настройки.ДоступныеПоляВыбора.ПолучитьОбъектПоИдентификатору(Строка.ИмяРеквизита);
Если ДоступноеПоле = Неопределено Тогда
Продолжить;
КонецЕсли;
НовПоле = Настройки.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
НовПоле.Поле = ДоступноеПоле.Поле;
НовПоле.Использование = Истина;
// В качестве заголовка устанавливаем значение из колонки ИмяКолонки
НовПоле.Заголовок = Строка.ИмяКолонки;
КонецЦикла;
// Скрываем вывод настроенных отборов, устанавливаем макет оформления (без него не видна сетка ячеек) и расположение полей в отдельных колонках
Настройки.ПараметрыВывода.УстановитьЗначениеПараметра("ВыводитьОтбор", ТипВыводаТекстаКомпоновкиДанных.НеВыводить);
Настройки.ПараметрыВывода.УстановитьЗначениеПараметра("МакетОформления", "Античный");
Настройки.ПараметрыВывода.УстановитьЗначениеПараметра("РасположениеРеквизитов", РасположениеРеквизитовКомпоновкиДанных.Отдельно);
Результат = Новый ТабличныйДокумент;
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
// В компоновщик макета передаем схему и настройки с отбором, сортировкой и структурой вывода
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаОтбор, Настройки);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
// Выводим данные в табличный документ
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(Результат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
Результат.ОтображатьСетку = Истина;
Результат.Защита = Ложь;
Результат.ТолькоПросмотр = Ложь;
Возврат Результат;
КонецФункции
Добавляем функцию СведенияОВнешнейОбработке для возможности загрузки обработки в базу 1С:
Функция СведенияОВнешнейОбработке() Экспорт
Сведения = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке();
Сведения.Вставить("Вид", ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиДополнительнаяОбработка());
Сведения.Вставить("Версия", Метаданные().Комментарий);
Сведения.Вставить("Наименование", Метаданные().Синоним);
Сведения.Вставить("БезопасныйРежим", Ложь);
НоваяКоманда = Сведения.Команды.Добавить();
НоваяКоманда.Идентификатор = "ОткрытьФорму";
НоваяКоманда.Представление = Сведения.Наименование;
НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыОткрытиеФормы();
НоваяКоманда.ПоказыватьОповещение = Ложь;
Возврат Сведения;
КонецФункции
Любая конфигурация на управляемых формах с платформой 8.3.18 и выше (в обработке использованы новые методы Асинх).