среда, 27 июля 2011 г.

Работа с элементами формы полей отбора СКД

... на самом деле для работы с элементом формы отбора СКД нам нужно всего 3 поля - Использование, ЛевоеЗначение И ПравоеЗначениеДляКраткогоОтображенияЭлемента. 
Когда необходимо назначить назначить свои обработчики проще всего это делать динамически

Процедура ПриОткрытии()

    // Определение типов данных
    // Так как метод Получить() работает только спо индексу элемента необходимо использовать перебор
    Для Каждого ЭлементОтбора Из КомпоновщикНастроек.Настройки.Отбор.Элементы Цикл
        Если Строка(ЭлементОтбора.ЛевоеЗначение) = "Дирекция" Тогда
            Элемент.ОграничениеТипа = Новый ОписаниеТипов("СправочникСсылка.ЗначенияСвойствОбъектов");
            Элемент.Значение = Элемент.ОграничениеТипа.ПривестиЗначение(Неопределено);
        КонецЕсли;
    КонецЦикла;

    // Установление обработчика колонке
    КолонкаПравоеЗначение = ЭлементыФормы.Отбор.Колонки.Найти("ПравоеЗначениеДляКраткогоОтображенияЭлемента");

    ДействиеНачалоВыбора = Новый Действие("ОтборПравоеЗначениеДляКраткогоОтображенияЭлементаНачалоВыбора");
    Колонка.ЭлементУправления.УстановитьДействие("НачалоВыбора", ДействиеНачалоВыбора);

    ДействиеОкончаниеВвода = Новый Действие("ОтборПравоеЗначениеДляКраткогоОтображенияЭлементаОкончаниеВводаТекста")
    Колонка.ЭлементУправления.УстановитьДействие("ОкончаниеВводаТекста", ДействиеОкончаниеВвода);

КонецПроцедуры

Процедура ОтборПравоеЗначениеДляКраткогоОтображенияЭлементаНачалоВыбора(Элемент, СтандартнаяОбработка)

    ПолеКомпоновкиДанных = ЭлементыФормы.Отбор.ТекущаяСтрока.ЛевоеЗначение;

    Если Строка(ПолеКомпоновкиДанных) = "Дирекция" Тогда
        Элемент.ВыборПоВладельцу = ПВХДирекция;
    КонецЕсли;

КонецПроцедуры

Процедура ОтборПравоеЗначениеДляКраткогоОтображенияЭлементаОкончаниеВводаТекста(Элемент, Текст, Значение, СтандартнаяОбработка)

    ПолеКомпоновкиДанных = ЭлементыФормы.Отбор.ТекущаяСтрока.ЛевоеЗначение;
    Если Строка(ПолеКомпоновкиДанных) = "Дирекция" Тогда
        СтандартнаяОбработка = Ложь;
        ОбработкаОкончанияВводаТекста(Элемент, Текст, Значение, СтандартнаяОбработка);
    КонецЕсли;

КонецПроцедуры

Процедура ОбработкаОкончанияВводаТекста(Элемент, Текст, Значение, СтандартнаяОбработка)

    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    |   ЗначенияСвойствОбъектов.Ссылка
    |ИЗ
    |   Справочник.ЗначенияСвойствОбъектов КАК ЗначенияСвойствОбъектов
    |ГДЕ
    |   ЗначенияСвойствОбъектов.Владелец = &Владелец
    |   И ЗначенияСвойствОбъектов.Наименование ПОДОБНО &Наименование + ""%""";

    Запрос.УстановитьПараметр("Владелец", ПВХДирекция);
    Запрос.УстановитьПараметр("Наименование", Текст);

    Результат = Запрос.Выполнить();
    Если НЕ Результат.Пустой() Тогда
        Список = Новый СписокЗначений;
        Список.ЗагрузитьЗначения(Результат.Выгрузить().ВыгрузитьКолонку("Ссылка"));
        ЭлСписка = ЭтаФорма.ВыбратьИзСписка(Список, Элемент);
        Если ЭлСписка <> Неопределено Тогда
            Значение = ЭлСписка.Значение;
        КонецЕсли;
    Иначе
        Элемент.ОграничениеТипа = Новый ОписаниеТипов("СправочникСсылка.ЗначенияСвойствОбъектов");
        Элемент.Значение = Элемент.ОграничениеТипа.ПривестиЗначение(Неопределено);
    КонецЕсли;

КонецПроцедуры

Динамическое добавление полей во внешнем наборе СКД

Система компоновки данных отлично выводит результат группировки таблицу значений, но она не умеет выводить результат таблицы значений. В таком случае можно получить детальные записи, а таблицу значений собрать уже при выводе в другой СКД

Процедура ВывестиНаборДанных(НаборДанных);

    ВнешниеНаборыДанных = Новый Структура;
    ВнешниеНаборыДанных.Вставить("НаборДанных", НаборДанных);

    СхемаКомпоновкиДанныхДляВывода = ПолучитьМакет("МакетДляВывода");
    Настройки = СхемаКомпоновкиДанныхДляВывода.НастройкиПоУмолчанию;

    // {{ динамическое добавление колонок валютных сумм
    Валюты = НаборДанных.Скопировать();
    Валюты.Свернуть("Валюта", "СуммаУпр");
    Валюты.Сортировать("СуммаУпр Убыв");

    Для Каждого Валюта Из Валюты Цикл
        ИмяПоля         = "Сумма" + Валюта.Валюта.Наименование;
        ЗаголовокПоля   = "Сумма, " + Валюта.Валюта.Наименование;

        // добавить в набор данных
        НоваяКолонка = НаборДанных.Колонки.Добавить(ИмяПоля, ОМОбщегоНазначения.ПолучитьОписаниеТиповЧисла(10, 2));

        // добавить в поля данных
        ПоляДанных = СхемаКомпоновкиДанныхДляВывода.НаборыДанных[0].Поля;
        НовоеПолеДанных = ПоляДанных.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
        НовоеПолеДанных.Поле = ИмяПоля;
        НовоеПолеДанных.Заголовок = ЗаголовокПоля;
        НовоеПолеДанных.ТипЗначения = ОМОбщегоНазначения.ПолучитьОписаниеТиповЧисла(10, 2);

        // добавить в ресурсы
        НовоеПолеИтога = СхемаКомпоновкиДанныхДляВывода.ПоляИтога.Добавить();
        НовоеПолеИтога.ПутьКданным = ИмяПоля;
        НовоеПолеИтога.Выражение   = "Сумма(" + ИмяПоля + ")";

        // добавить в настройки
        НовоеПоле = СхемаКомпоновкиДанныхДляВывода.НастройкиПоУмолчанию.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
        НовоеПоле.Поле = Новый ПолеКомпоновкиДанных(ИмяПоля);
        НовоеПоле.Заголовок = ЗаголовокПоля;
        НовоеПоле.Использование = Истина;
    КонецЦикла;

    // переместить ресурсы по порядку
    ЭлементыНастройки = СхемаКомпоновкиДанныхДляВывода.НастройкиПоУмолчанию.Выбор.Элементы;
    Для Каждого ПолеНастройка Из ЭлементыНастройки Цикл
        Если Строка(ПолеНастройка.Поле) = "КатегорияА" Тогда
            ПолеКатегорияА = ПолеНастройка;
        ИначеЕсли Строка(ПолеНастройка.Поле) = "КатегорияВ" Тогда
            ПолеКатегорияВ = ПолеНастройка;
        ИначеЕсли Строка(ПолеНастройка.Поле) = "КатегорияС" Тогда
            ПолеКатегорияС = ПолеНастройка;
        КонецЕсли;
    КонецЦикла;

    ЭлементыНастройки.Сдвинуть(ПолеКатегорияА, ЭлементыНастройки.Количество() - ЭлементыНастройки.Индекс(ПолеКатегорияА));
    ЭлементыНастройки.Сдвинуть(ПолеКатегорияВ, ЭлементыНастройки.Количество() - ЭлементыНастройки.Индекс(ПолеКатегорияВ));
    ЭлементыНастройки.Сдвинуть(ПолеКатегорияС, ЭлементыНастройки.Количество() - ЭлементыНастройки.Индекс(ПолеКатегорияС));

    // заполнить валюты
    Для Каждого Строка Из НаборДанных Цикл
        Строка["Сумма" + Строка.Валюта.Наименование] = Строка.Сумма;
    КонецЦикла;
    // }} динамическое добавление колонок валютных сумм

    ДанныеРасшифровки = Новый ДанныеРасшифровкиКомпоновкиДанных;
    ДанныеРасшифровки.Настройки = Настройки;

    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанныхДляВывода, Настройки, ДанныеРасшифровки);

    ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных, ДанныеРасшифровки);

    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(ЭлементыФормы.ДокументРезультат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);

КонецПроцедуры

Вывод параметров и результата в разных СКД

При написании отчетов самым простым и эффективным инструментом является СКД. Но иногда система компоновки не в силах внести в таблицу значений необходимую информацию. В то же время создавать форму с множеством отборов не очень удобно(отборы, пожалуй являются одним из самых ценных методов СКД), в таком случае я получаю данные в одной системе компоновки, преобразую их и вывожу через другую систему компоновки. При этом в результирующем табличном документе параметры и отборы выводятся в первой, а таблица с данными или диаграмма во второй системе компоновки.

Процедура СформироватьОтчет()

    НаборДанных = ПолучитьНаборДанных();
    ВывестиНаборДанных(НаборДанных);

КонецПроцедуры
 
Функция ПолучитьНаборДанных()

    // Установка параметров формирования
    УстановитьПараметр("НачалоПериода", НачалоДня(НачалоПериода));
    УстановитьПараметр("КонецПериода", КонецДня(КонецПериода));

    // Вывод результата в таблицу значений
    КомпоновщикНастроек.Настройки.Структура[0].Использование = Истина;

    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;

    НаборДанных = Новый ТаблицаЗначений;
    ПроцессорВывода.УстановитьОбъект(НаборДанных);

    МакетКомпоновкиДанных = КомпоновщикМакета.Выполнить(ОтчетОбъект.СхемаКомпоновкиДанных,
        ЭтотОбъект.КомпоновщикНастроек.Настройки,,,Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));

    ПроцессорКомпоновки.Инициализировать(МакетКомпоновкиДанных);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);

    // {{ вывод результата в табличный документ
    КомпоновщикНастроек.Настройки.Структура[0].Использование = Ложь; 
    Настройки = ЭтотОбъект.КомпоновщикНастроек.Настройки;

    ДанныеРасшифровки = Новый ДанныеРасшифровкиКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);

    ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки,, ДанныеРасшифровки);

    ЭлементыФормы.ДокументРезультат.Очистить();

    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(ЭлементыФормы.ДокументРезультат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);
    // }} вывод результата в табличный документ

    Возврат НаборДанных;

КонецФункции


Процедура ВывестиНаборДанных(НаборДанных);

    ВнешниеНаборыДанных = Новый Структура;
    ВнешниеНаборыДанных.Вставить("НаборДанных", НаборДанных);

    СхемаКомпоновкиДанныхДляВывода = ПолучитьМакет("МакетДляВывода");
    Настройки = СхемаКомпоновкиДанныхДляВывода.НастройкиПоУмолчанию;

    ДанныеРасшифровки = Новый ДанныеРасшифровкиКомпоновкиДанных;
    ДанныеРасшифровки.Настройки = Настройки;

    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанныхДляВывода, Настройки, ДанныеРасшифровки);

    ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных, ДанныеРасшифровки);

    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(ЭлементыФормы.ДокументРезультат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);

КонецПроцедуры