15. Введение в разработку систем принятия решений

15.1. Понятие многомерных данных *

15.2. Метакуб (многомерный куб) *

15.3. Динамическая фиксация числа измерений *

15.4. Обзор компонентов Delphi для разработки систем принятия решений *

15.5. Пример многомерных данных *

15.6. Использование компонента TDecisionQuery *

15.7. Редактор многомерного запроса *

15.8. Использование компонента TDecisionCube *

15.9. Использование компонента TDecisionSource *

15.10. Использование компонента TDecisionGrid *

15.10.1. Создание сетки многомерных данных *

15.10.2. Раскрытие и закрытие данных по измерениям средствами компонента TDecisionGrid *

15.10.3. Показ промежуточных сумм *

15.10.4. Исключение и включение измерения в состав показываемых в сетке данных *

15.10.5. Установка свойств показа данных по отдельному измерению *

15.10.6. Свойства и события, управляющие поведением TDecisionGrid в целом *

15.11. Использование компонента TDecisionPivot *

15.11.1. Создание переключателя активных измерений *

15.11.2. Изменение способа показа данных по измерению *

15.11.3. Фиксация значения в измерении *

15.11.4. Свойства, управляющие представлением в форме компонента TDecisionPivot *

15. Введение в разработку систем принятия решений

15.1. Понятие многомерных данных

В процессе принятия решений во многих сферах приходится анализировать многофакторную информацию о предметной области. Пусть, к примеру, организация занимается продажами товаров. При закупках товаров эта организация должна представлять, насколько устойчив спрос на товары, каковы темпы роста спроса - по товару, по региону, по конкретным организациям, каковы расходы, прибыль и многое другое.

Ситуация, когда аналитику приходится иметь дело с многофакторными данными, осложняется двумя обстоятельствами:

• во-первых, средний человек может одновременно оперировать тремя-четырьмя сущностями, учитывая при этом связи между ними;, с увеличением числа сущностей эффективность обработки информации человеком падает;

во-вторых, чисто психологически человеку, живущему в трехмерном мире, трудно представить пространство размерностью больше 3.

Математики давно оперируют с многомерными пространствами, но это абстрактный подход. В области практических применений наша способность оперировать многомерными данными, к сожалению, является ограниченной.

При возникновении необходимости обработки многофакторной информации применяют или многомерные базы данных (они остаются за рамками нашего рассмотрения), или в реляционных СУБД реализуют такие механизмы организации данных и доступа к ним, которые резко повышают эффективность анализа многофакторных данных.

15.2. Метакуб (многомерный куб)

Сущность подхода, при помощи которого Delphi позволяет оперировать с многомерными данными, состоит в следующем. Данные представляются в виде так называемого метакуба (или многомерного куба), где одному фактору соответствует свое измерение.

На рис. 15.1 приведен куб. В нем представлена информация по продажам. Одно измерение соответствует городам, в которых осуществлялись продажи;

второе измерение - фирмам, которым продавался товар; третье - временным периодам.

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

15.3. Динамическая фиксация числа измерений

При помощи компонентов Delphi, которые будут обсуждаться ниже, в источнике данных фиксируются:

• поля - измерения метакуба;

• поля, по которым должно производиться агрегирование данных (суммирование, подсчет среднего и т.д.).

Затем определяется, какие измерения показываются как столбцы, какие -как строки. После этого пользователю предоставляется таблица многомерных данных. В форме приложения может быть расположен план метакуба, то есть список измерений, где каждому измерению соответствует кнопка. Нажимая кнопку, пользователь активизирует или деактивизирует показ данных по тому или иному измерению куба.

На рис. 15.3. показана информация из пятимерного куба. Пользователь зафиксировал текущие измерения - "Покупатель", "Месяц", "Тип товара". В ячейках показывается суммарный отпуск товара.

На рис. 15.4. показан тот же куб, в котором зафиксированы три другие измерения - "Город", "Товар", "Месяц". В ячейках показывается суммарный отпуск товара.

На рис. 15.5 показан тот же куб, в котором выбраны 4 измерения - "Город". "Покупатель", "Товар", "Месяц". В ячейках показывается суммарный отпуск товара

15.4. Обзор компонентов Delphi для разработки систем принятия решений

Компоненты для разработки систем принятия решений расположены в Delphi на странице Decision Cube.

Компонент TDecisionQuery служит для определения НД, на основании которого затем будет создаваться многомерный куб. Компонент TDecisionQuery разработан специально для указанных целей, и поэтому его использование при разработке систем принятия решений является более предпочтительным, чем использование "обычных" компонентов НД - TTable и TQuery Однако и эти компоненты могут применяться для хранения данных, на которых строится метакуб.

Компонент TDecisionCube, собственно, и реализует многомерный куб данных. Он соединяется с НД (как правило, это компонент TDecisionQuery) при помощи свойства DataSet.

Компонент TDecisionSource является аналогом "источника данных", компонента TDataSource, но адаптирован для целей работы с многомерными данными. Многомерный "источник данных" соединяется с компонентом TDecisionCube при помощи свойства DecisionCube.

Компонент TDecisionPivot позволяет открывать и закрывать измерения метакуба. Для этого пользователю следует нажать (или отжать нажатую) кнопку, соответствующую конкретному измерению. Данный компонент связан с компонентом TDecisionSource при помощи свойства DecisionSource. Применение этого компонента необязательно, поскольку компонент TDecisionGrid также содержит средства для открытия и закрытия данных по измерениям куба. Это - значки "+" и "-" в заголовках столбцов и строк, соответствующих измерениям куба.

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

Компонент TDecisionGraph предназначен для показа графиков, источником которых служат многомерные данные. Он связан с компонентом TDecisionSource через свойство DecisionSource.

Ниже на примере будут показаны особенности использования названных компонентов.

15.5. Пример многомерных данных

Пусть имеем три таблицы БД.

Первая таблица Tovary.DB содержит сведения о товарах. В состав таблицы входят поля:

• Tovar-наименование товара; • Typ_Tovara - тип товара; • Ed_Izm - единица измерения товара;

• Zena - цена за единицу измерения товара.

Первичный ключ построен по полю Tovar.

Вторая таблица Pokup.DB содержит сведения о покупателях товара. В состав таблицы входят поля:

• Pokup - наименование покупателя; • Gorod - город, в котором расположена организация-покупатель.

Первичный ключ построен по полю Pokup.

Третья таблица Rashod.DB содержит сведения о расходе товара со склада. В состав таблицы входят поля:

• N_Rash - уникальный номер расхода; • Den - день; • Mes - месяц; • God - год даты расхода; • Tovar - наименование товара; • Pokup - наименование покупателя; • Kolvo - количество единиц отпущенного товара.

Первичный ключ построен по полю N_Rash. Таблица находится в отношении "многие-к-одному" с таблицами Tovary.DB и Pokup.DB. Для реализации целостности построены внешние индексы по полям Tovary и Pokup.

Необходимо построить многомерный куб для представления:

• общей суммы расхода; • средней суммы расхода;

по измерениям:

• товар; • город; • покупатель; • тип товара; • месяц из даты отпуска товара.

В процессе построения многомерных данных рассмотрим особенности компонентов, перечисленных в предыдущем разделе.

15.6. Использование компонента TDecisionQuery

Разместим в форме компонент TDecisionQuery с именем DecisionQuery1. Установим в свойство Database компонента имя базы данных (в нашем случае это loc_skld). В свойстве SQL определим оператор SELECT, в котором произведем внутреннее соединение таблиц Rashod, Tovary и Pokup:

SELECT P.GOROD, R.РОКUР,Т.TYP_TOVARA, R.TOVAR, R.MES,

SUM( R.KOLVO * T.ZENA) , AVG( R.KOLVO * T.ZENA)

FROM "Rashod.DB" R, "Pokup.DB" P, "Tovary.DB" T

WHERE R.POKUP= P.POKUP AND

T.TOVAR = R.TOVAR

GROUP BY P.GOROD, R.POKUP, TYP_TOVARA, R.TOVAR, R.MES

GROUP BY P.GOROD, R.POKUP, TYP_TOVARA, R.TOVAR, R.MES

Существуют следующие правила объявления измерений в многомерном кубе:

1. поля, по которым должны строиться измерения многомерного куба, перечисляются после ключевого слова SELECT;

2. поля, по которым измерений строить не нужно, в операторе SELECT в качестве возвращаемых полей результирующего набора данных не перечисляются;

3. только после полей-источников для измерений куба перечисляются агрегатные выражения - сумма, среднее, и число повторений;

агрегированные данные затем будут выводиться по указанным ранее измерениям;

4. обязательно использование раздела ORDER BY, где необходимо перечислить все поля, по которым строятся измерения куба, причем в том же порядке, в котором они следуют после ключевого слова SELECT.

Рассмотрим приведенный выше оператор SELECT. Измерения будут построены по полям:

1.GOROD;

2. POKUP;

3. TYP_TOVARA;

4.TOVAR;

5. MES.

В качестве данных по измерениям будет выводиться (по выбору) результат одной из следующих агрегаций:

1. суммарная стоимость отпущенного товара (KOLVO * ZENA);

2. средняя стоимость отпущенного товара (KOLVO * ZENA).

Компонент TDecisionQuery настолько "похож" на компонент TQuery, что не имеет отличных от него, уникальных свойств, методов и событий. Установим значение True в свойство компонента Active. Теперь набор многомерных данных активен в нашем приложении.

15.7. Редактор многомерного запроса

Отвлечемся на некоторое время от нашего примера и рассмотрим, как использовать еще одно средство компонента TDecisionQuery - редактор многомерного запроса - для построения SQL-оператора выборки многомерных данных. Отметим при помощи мыши компонент TDecisionQuery и нажмем правую кнопку мыши, а затем во всплывающем меню выберем элемент Decision Query Editor. Появится окно редактора многомерного запроса (рис. 15.6).

В списке List of Available Fields перечислены поля таблицы БД, чье имя выбрано в выпадающем списке Table. Используя кнопки с изображением стрелок, поля, по которым должны строиться измерения в многомерном кубе, перемещают в список Dimensions. Тем же способом в список Summaries перемещаются поля, по которым необходимо производить агрегацию. Тип агрегации запрашивается тут же. Это SUM (сумма), COUNT (счетчик повторений) и AVERAGE (среднее значение).

Закладка SQL позволяет просмотреть и, если необходимо, изменить текст SQL-оператора, построенного на основе наших действий. Кнопка Query Builder позволяет перейти в режим запроса по образцу (Query By Example) для построения оператора SELECT.

15.8. Использование компонента TDecisionCube

Вернемся к примеру. Разместим в форме компонент TDecisionCube с именем DecisionCube1. Занесем в свойство DataSet имя набора данных DecisionQuery1. Определим свойства куба. Для этого отыщем в инспекторе объектов свойство DimensionMap и в поле данных этого свойства нажмем кнопку (...). Появится окно редактора многомерного куба {Decision Cube Editor). Оно показано на рис. 15.7.

В списке Available Fields перечислены поля, по которым строятся измерения куба, и формулы для расчета агрегированных значений. Для текущего поля или формулы слева показываются параметры:

Display Name - метка, которая будет показываться для измерения в компонентах TDecisionGrid, TDecisionPivot, TDecisionGraph;

Type - тип (Dimension, Sum, Average, Count);

• Active Type - определяет показываемую информацию - As Needed (показывается, когда необходимо); Active (показывается всегда); Inactive (не показывается никогда);

Formal - формат представления значений;

Grouping - группировка по году, кварталу, месяцу и отдельному значению;

Initial Value - начальное значение.

Закладка Memory Control позволяет определить установки памяти:

•максимальное число измерений, сумм, ячеек (группа Cube Maximums);

•показывать только заголовки данных во время разработки приложения для экономии времени и ресурсов компьютера (группа Designer Data Options).

Определим названия измерений и агрегированных данных (поле Display Name).

Кратко рассмотрим свойства, методы и события компонента TDecisionCube.:

Свойства

property Capacity: Integer; определяет максимальный размер кэша в байтах для хранения многомерного массива данных куба. В случае нехватки памяти возбуждается исключение ELowCapacity Error.

property DataSet: TDataSet; содержит имя НД, который указывает данные для представления в кубе. Рекомендуется в качестве НД использовать созданный специально для указанных целей компонент TDecisionQuery.

property DimensionCount: Integer; содержит текущее число измерений в кубе.

property DimensionMap: TCubeDims; определяет параметры компонента TDecisionCube, такие как число и состав измерений куба; формат представления значений по конкретному измерению; метки, которые будут соответствовать каждому измерению в компонентах TDecisionGrid и TDecisionPivot; максимальное число измерений; состав показываемых значений. Установка указанных параметров осуществляется в редакторе куба (Decision Cube Editor), который активизируется при двойном щелчке мышью на компоненте TDecisionCube в форме приложения или при нажатии кнопки в поле данных свойства DimensionMap в инспекторе объектов.

property DimensionMapCount: Integer; содержит число полей НД, которые участвуют в формировании многомерного куба.

property MaxDimensions: Integer; содержит максимальное число измерений куба.

property MaxSummaries: Integer; содержит максимальное число сумм для куба.

property ShowProgressDialog: Boolean; определяет, нужно (True) или не нужно (False) показывать прогресс-индикатор во время формирования куба.

property SummaryCount: Integer; возвращает число полей, использованных для формирования сумм.

Метод procedure ShowCubeDialog; во время выполнения осуществляет вызов редактора куба, в котором могут быть изменены или переопределены свойства куба, установленные во время разработки. Более подробно см. свойство DimensionMap.

События

property OnLowCapacity: TCapacityErrorEvent;

TCapacityErrorEvent = procedure (var Action: TErrorAction) of object;

TErrorAction = ( eaFail, eaContinue ) ;

наступает в случае, когда не хватает памяти в кэше для хранения многомерных данных. Максимальный размер кэша устанавливается в свойстве Capacity.

property OnRefresh: TCubeRefreshEvent;

TCubeRefreshEvent = procedure(DataCube: TCustomDataStore; DimMap:

TCubeDims) of object;

наступает перед изменением плана куба. Это происходит после изменения параметров куба во время выполнения (см. метод ShowCubeDialog).

15.9. Использование компонента TDecisionSource

Компонент TDecisionSource выполняет в системах представления многомерных данных те же функции, что и компонент TDataSource в системах представления обычных данных, то есть служит "источником данных" для визуальных компонентов (TDecisionGrid, TDecisionGraph). Иными словами, TDecisionSource служит в качестве связующего звена между невизуальными компонентами многомерных данных (TDecosionCube) и визуальными компонентами.

Разместим в форме компонент TDecisionSource с именем DecisionSourcel. Установим в свойство DataSet значение имени компонента TDecisionCube, то есть DecisionCubel.

Свойства и события компонента TDecisionSource описаны ниже. Некоторые из них связаны с компонентами TDecisionPivot и TDecisionGrid, которые будет рассмотрены в следующих разделах.

Свойства

property DecisionCube: TDecisionCube; содержит имя компонента TDecisionCube.

property SparseCols: boolean; определяет, показывать или нет столбцы с пустыми значениями.

property SparseRows: boolean; определяет, показывать или нет строки с пустыми значениями.

События

property OnBeginPivot: TNotifyEvent; наступает перед изменением данных в кубе при нажатии (отжатии) кнопки, соответствующей измерению куба в компоненте TDecisionPivot, или при раскрытии/свертке данных по измерению в TdecisionGrid TNotifyEvent = procedure(Sender: TObject) of object;

property OnEndPivot: TNotifyEvent; событие вызывается той же причиной, что и событие OnBeginPivot, однако наступает после изменения данных в кубе, но до отображения этих изменений в связанных с TDecisionSource компонентах. TNotifyEvent = procedure(Sender: TObject) of object;

property OnLayoutChange: TNotifyEvent; наступает после изменения схемы данных в кубе. Событие наступает после события OnBeginPivot, но перед событием OnEndPivot и только в том случае, когда данные в кубе остаются теми же. При изменении состава измерений, которое сопровождается изменением данных в кубе, наступает событие OnNewDimensions. TNotifyEvent = procedure(Sender: TObject) of object;

property OnNewDimensions: TNotifyEvent; наступает после изменения данных в кубе.

TNotifyEvent = procedure(Sender: TObject) of object;

property OnStateChange: TNotifyEvent; наступает после изменения свойств куба (компонент TDecisionCube). TNotifyEvent = procedure(Sender: TObject) of object;

15.10. Использование компонента TDecisionGrid

15.10.1. Создание сетки многомерных данных

Компонент TDecisionGrid служит для представления многомерных данных в виде таблицы, в которой измерениям соответствуют строки и столбцы. Ячейки TDecisionGrid заполняются данными, полученными на основе расчета агрегатных функций.

Разместим в форме компонент TDecisionGrid с именем DecisionGrid1. Установим в его свойство DecisionSource имя компонента DecisionSource1 После этого произойдет визуализация многомерных данных (рис. 15.8).

Вспомним оператор SELECT, в котором определены измерения и агрегация данных в многомерном кубе:

SELECT P.GOROD, R.POKUP,Т.TYP_TOVARA, R.TOVAR, R.MES,

SUM( R.KOLVO * T.ZENA) , AVG ( R.KOLVO * T.ZENA)

FROM "Rashod.DB" R, "Pokup.DB" P, "Tovary.DB" T

WHERE R.POKUP= P.POKUP AND

T.TOVAR = R.TOVAR

GROUP BY P.GOROD, R.POKUP, TYP_TOVARA, R.TOVAR, R.MES

Согласно данному оператору, в кубе имеются измерения по полям

1. GOROD (город покупателя);

2. POKUP (название покупателя);

3. TYP_TOVARA (тип товара);

4. TOVAR (название товара);

5. MES (месяц года, в который произошел отпуск товара).

В качестве данных по измерениям будет выводиться (по выбору) результат одной из следующих агрегаций:

1. суммарная стоимость отпущенного товара (KOLVO * ZENA);

2. средняя стоимость отпущенного товара (KOLVO * ZENA).

Как видно из рис 15.8, одни измерения показываются по горизонтали, построчно ("Покупатель", "Тип товара", "Товар"), другие - вертикально, как столбцы ("Город"). По умолчанию в ячейках показываются данные той агрегатной функции, которая в списке агрегатных функций в операторе SELECT указана первой. В нашем случае - это суммарная стоимость отпущенного товара SUM( R KOLVO * T.ZENA).

15.10.2. Раскрытие и закрытие данных по измерениям средствами компонента TDecisionGrid

Каждому измерению в сетке данных соответствует знак "+" или "-" Он указывается в ячейке, в которой содержится название предыдущего измерения Например, знак для измерения "Тип товара" находится в ячейке, в которой показывается название предыдущего измерения - "Покупатель".

Знак "+" сообщает, что информация по измерению в сетке данных не показывается. Знак "-", наоборот, свидетельствует о том, что данные по измерению показываются Если щелкнуть на значке мышью, значок переходит в противоположное состояние (с "+" на "-" и наоборот). При этом данные по измерению также переходят в противоположное состояние визуализации - если они показывались в сетке, то прячутся, и наоборот.

Важно помнить, что сокрытие данных по какому-либо измерению ведет к сокрытию данных по измерениям, расположенным правее от него. На рис 15 9 показан результат сокрытия данных по измерению "Тип товара" Как видно из рисунка, скрыты не только данные по измерению "Тип товара", но и по измерению"Товар".

15.10.3. Показ промежуточных сумм

Как видно из рис. 15 8, для каждого значения данных по измерению показываются промежуточные суммы. Их показ можно устранить. Для этого нужно щелкнуть по компоненту TDecisionGrid правой кнопкой мыши и во всплывающем меню выбрать Subtotals on/off. Повторный выбор данного элемента меню приведет к включению промежуточных сумм в сетку

Подобного же эффекта, но для конкретного измерения, можно добиться, если выбрать мышью ячейку заголовка конкретного измерения и нажать правую кнопку Выбор элемента Display Data and Subtotals приводит к показу промежуточных сумм Выбор элемента Display Data Only устраняет показ промежуточных сумм для измерения.

Те же действия осуществимы и для конкретного значения по измерению. Если щелкнуть правой кнопкой мыши по ячейке данных, соответствующих нужному измерению, то появится меню, в котором к элементам Display Data and Subtotals и Display Data Only добавится элемент Display Subtotals Only. Выбор этого элемента приводит к показу только промежуточных сумм. Установка одного из названных режимов показа относится не к измерению в целом, а к данным, касающимся того значения измерения, которое показывается в ячейке.

Все возможности, о которых идет речь в данном подразделе, доступны как во время разработки приложения, так и во время его выполнения

15.10.4. Исключение и включение измерения в состав показываемых в сетке данных

То или иное измерение может быть исключено из сетки данных или вновь добавлено в нее - как во время разработки, так и во время выполнения приложения.

Выше нами рассмотрено использование значков "+" и "-" Однако сворачивание и раскрытие данных в случае использования этих значков затрагивает и соседние измерения, расположенные справа. Механизм, о котором пойдет речь в этом подразделе, позволяет исключать или вновь включать в сетку данные, соответствующие конкретному измерению, не затрагивая при этом данных по другим измерениям

Для того чтобы скрыть данные по измерению, можно воспользоваться двумя способами.

Первый способ - щелкнуть правой кнопкой мыши по ячейке данных измерения, которое показывается построчно, и во всплывающем меню выбрать элемент Drill in to this value

Второй способ - нажать правую кнопку мыши:

• над заголовком измерения,

над пустой ячейкой в ряду ячеек сетки, расположенным над рядом, в котором показываются названия измерений;

над крайним левым (пустым) столбцом сетки, в списке измерений снять отметку с необходимого измерения.

Чтобы включить измерение в состав показываемых, нужно воспользоваться вторым способом и установить отметку у необходимого измерения.

15.10.5. Установка свойств показа данных по отдельному измерению

Свойство property Dimensions: TDisplayDims; представляет собой коллекцию компонентов TDisplayDim, каждый из которых позволяет управлять представлением данных, соответствующих конкретному измерению.

Рассмотрим свойства компонента TDisplayDims:

• property Count: Integer; возвращает число измерений в TDecisionGrid, то есть число компонентов TDisplayDim в коллекции TDisplayDims.

property Items[Index: Integer]: TDisplayDim; возвращает компонент TDisplayDim с индексом Index. TDisplayDim соответствует серии данных по одному измерению. Значение Index лежит в диапазоне 0..Count-1.

Рассмотрим свойства компонента TDisplayDim, то есть серии данных по конкретному измерению в TDecisionGrid:

•• property Alignment: TAlignment; определяет выравнивание.

•• property Color: TColor; определяет цвет фона в ячейках.

•• property DisplayName: String; определяет текст заголовка.

•• property FieldName: String; определяет имя поля, по которому строится измерение.

•• property Format: String; определяет формат представления значений в ячейках.

•• property Subtotals: Boolean; определяет, следует ли (True) или нет (False) показывать значения промежуточных сумм по измерению.

На этапе конструирования программы значения приведенных выше свойств можно установить, выбрав в инспекторе объектов свойство Dimensions. После этого на экране появится список измерений и агрегированных значений (рис. 15.10). Сделав текущим нужное измерение или агрегированное значение, в инспекторе объектов можно переопределить принятые по умолчанию значения его свойств.

15.10.6. Свойства и события, управляющие поведением TDecisionGrid в целом

Свойства

property CaptionColor: TColor; определяет цвет фона для заголовков столбцов и строк.

property CaptionFont: TFont; определяет шрифт для заголовков столбцов и строк.

property CelIs[ACol, ARow: Integer]: String; возвращает в строковом виде содержимое ячейки на пересечении столбца АСоl и строки ARow.

ro property ColCount: Integer; возвращает текущее число столбцов.

property DataCoIor: TColor; определяет цвет фона во всех ячейках.

property DataFont: TFont; определяет шрифт во всех ячейках.

property DataSumColor: TColor; определяет цвет фона - только в ячейках, где показываются суммы.

property DecisionSource: TDecisionSource; содержит имя компонента TDecisionSource.

property DefauItColWidth: Integer; определяет умалчиваемую ширину (в пикселях) всех ячеек TDecisionGrid. Установка нового значения этого свойства приводит к изменению ширины сразу всех ячеек компонента.

property DefaultRowHeight: Integer; определяет высоту (в пикселях) всех ячеек TDecisionGrid Установка нового значения свойства приводит к изменению высоты сразу всех ячеек компонента.

property FixedCols:Integer; возвращает число столбцов, используемых для показа заголовков измерений и меток данных, то есть для показа служебной информации.

property FixedRows:Integer; возвращает число строк, используемых для показа служебной информации.

property GridLineColor: TColor; определяет цвет линий, отделяющих ячейки друг от друга.

property GridLineWidth: Integer; определяет в пикселях ширину линий, отделяющих ячейки друг от друга.

property LabelColor: TColor; определяет цвет фона ячеек, в которых показываются заголовки столбцов и строк.

property LabelFont: TFont; определяет шрифт ячеек, в которых показываются заголовки столбцов и строк.

property LabelSumColor: TColor; определяет цвет фона ячеек, в которых показываются заголовки сумм.

property Options: TDecisionGridOptions; TDecisionGridOptions = set of TDecisionGridOption; представляет собой множество, которое определяет параметры показа в TDecisionGrid. В множество могут входить значения:

cgGridLines - выводятся вертикальные и горизонтальные линии, отделяющие ячейки друг от друга.

cgOutliner - заголовки измерений куба содержат знаки "+" и "-", которые позволяют открывать или закрывать измерения без помощи компонента TDecisionPivot.

cgPivotable - разрешается перетаскивать измерения способом darg and drop.

ro property RowCount:Integer; возвращает число строк в TDecisionGrid.

property Totals: Boolean; определяет, показываются (True) или нет (False) значения подсумм по измерениям.

События

TDecisionDrawCeIlEvent = procedure (Sender: TObject; Col, Row: Longint;

var Value: string; var AFont: TFont; var AColor: TColor; AState: TGridDrawState;

ADrawState: TDecisionDrawState) of Object;

наступает при прорисовке ячейки в TDecisionGrid. Параметры:

Соl - номер столбца;

Row - номер строки;

Value - символьное представление значения, показываемого в ячейке;

AFont - шрифт, которым показывается значение в ячейке;

A Color - цвет фона в ячейке;

AState - состояние ячейки. TGridDrawState = set of (gdSelected, gdFocused, gdFixed);

A DrawState - множество, определяющее вид показываемых в ячейке данных. Может включать в себя значения:

dsGroupStart - ячейка - первая строка или первый столбец для измерения. В этом случае в множество ADrawState входят также значения dsRow Value или dsCol Value.

dsRowCaption - в ячейке показывается заголовок строки, то есть имя измерения, значения которого показываются горизонтально.

dsColCaption - в ячейке показывается заголовок столбца, то есть имя измерения, значения которого показываются вертикально.

dsSum - в ячейке показывается метка или значение промежуточной суммы. В этом случае в множество ADrawState входят также значения dsRow Value, dsCol Value и dsData.

• dsRow Value - в ячейке показывается одно из значений измерения (метка), а не собственно данные. Название измерения в этом случае расположено в ячейке слева.

• dsColValue - в ячейке показывается одно из значений измерения (метка), а не собственно данные. Название измерения в этом случае расположено в ячейке сверху.

dsData - в ячейке показываются только данные.

dsOpenAfter - ячейка имеет знак "+" в правой части, использующийся для раскрытия данных по следующему измерению. В этом случае в множество ADrawState входят также значения dsRowCaption, dsColCaption, dsRow Plus и dsColPlus.

• dsCloseAfter - ячейка имеет знак "-" в правой части, использующийся для сокрытия данных по следующему измерению. В этом случае в множество ADrawState входят также значения dsRowCaption, dsColCaption, dsRowPlus и dsColPlus.

• dsRowIndicator - ячейка используется только для показа знаков "+" или "-" и располагается в самом левом столбце TDecisionGrid. dsColIndicalor - ячейка используется только для показа знаков "+" или "-" и располагается в самой верхней строке TDecisionGrid.

dsRowPlus - ячейка, определяемая dsRowIndicator, содержит значение "+". Появляется только совместно с dsRowIndicator.

• dsColPlus - ячейка, определяемая dsColIndicator, содержит значение "+". Появляется только совместно с dsColIndicator.

• dsNone - у ячейки нет никакого предназначения.

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

procedure TForm1.DecisionGrid1DecisionDrawCell (Sender: TObject; Col, Row: Integer; var Value: String; var aFont: TFont; var aColor:

TColor;

AState: TGridDrawState; aDrawState: TDecisionDrawState) ;

begin

IF dsData in aDrawState THEN begin

IF Value = " THEN Value := '0';

IF not(gdFocused in AState)AND (StrToInt(Value) > 2000) THEN

AColor := cIRed;

END;//if

end;

property OnDecisionExamineCell: TDecisionExamineCellEvent;

TDecisionExamineCellEvent = procedure (Sender: TObject; ICol, IRow: Longint; ISum: Integer; const ValueArray: TSmallIntArray) of Object;

наступает, когда пользователь, находясь в ячейке данных, нажимает правую кнопку мыши. Параметры:

ICol - номер столбца ячейки;

IRon - номер строки ячейки;

ISum - номер текущей суммы;

ValueArray - массив координат в координатной сетке TDecisionSource (а не TDecisionGrid). Для получения имени измерения, соответствующего конкретному элементу массива, следует использовать метод GetDimensionName.

property OnTopLeftChanged: TNotifyEvent; наступает при скроллинге данных в сетке TDecisionGrid.

TNotifyEvent = procedure(Sender: TObject) of object;

15.11. Использование компонента TDecisionPivot

15.11.1. Создание переключателя активных измерений

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

Разместим в форме компонент TDecisionPivot (имя DecosionPivot1) Установим в его свойство DecisionSource имя компонента DecisionSource1.

Общий вид окна приложения показан на рис.15 11

15.11.2. Изменение способа показа данных по измерению

Из рисунка 15.11 видно, что кнопки в компоненте TDecisionPivot размещены в трех областях

В левой области размещена кнопка "Стоимость (сумма)". Это кнопка предназначена для выбора агрегатных функции По умолчанию в качестве текущей агрегатной функции берется первая из функций, определенных в операторе SELECT (компонент TDecisionQuery). Чтобы сменить агрегатную функцию, нужно нажать кнопку и из появившегося списка выбрать нужную функцию

Средняя область компонента TDecisionPivot содержит кнопки измерений, данные по которым показываются построчно. В нашем случае это кнопки, соответствующие измерениям "Тип товара", "Покупатель", "Товар", "Месяц".

Правая часть компонента TDecisionPivot содержит кнопки измерений, данные по которым показываются в виде столбцов. В нашем случае это кнопка, соответствующая измерению "Город".

Для того чтобы перевести кнопку из одной области в другую, следует щелкнуть по ней правой кнопкой мыши и в всплывающем меню выбрать элемент Move to roh Area (при переводе измерения в построчный показ) или Move to Column Area (при переводе измерения в показ по столбцу).

15.11.3. Фиксация значения в измерении

По умолчанию по измерению показываются все его данные. Например, по измерению "Покупатель" показываются все покупатели. Однако часто бывает необходимо показывать данные не по всем, а по конкретному покупателю. Для этого следует переместить указатель мыши на кнопку соответствующего измерения и нажать правую кнопку мыши, а затем выбрать элемент всплывающего меню Drilled in.

Кнопка "Покупатель" изменит свой заголовок на "Покупатель. All Values". Теперь, чтобы зафиксировать конкретного покупателя, следует нажать правую кнопку мыши и в появившемся списке выбрать название конкретного покупателя. При этом его имя будет показываться в кнопке, соответствующей измерению "Покупатель", а данные в кубе будут сечением по координате измерения "Покупатель", соответствующей конкретному покупателю (рис.15.12).

Для того чтобы вновь показывать все значения по измерению (например, всех покупателей по измерению "Покупатель"), следует установить указатель мыши на кнопку, соответствующую измерению, нажать правую кнопку мыши и во всплывающем меню снять отметку с режима Drilled in.

 

15.11.4. Свойства, управляющие представлением в форме компонента TDecisionPivot

property ButtonAutoSize: Boolean;

указывает, следует ли автоматически согласовывать размеры кнопок, соответствующих измерениям куба в компоненте TDecisionPivot, с размером самого компонента TDecisionPivot (значение True) или, независимо от размеров компонента, всегда поддерживать одни и те же размеры кнопок (значение False).

property ButtonHeight: Integer; определяет высоту (в пикселях) кнопок в компоненте TDecisionPivot (только для случая, когда свойство ButtonAutoSize = False).

property ButtonSpacing: Integer; определяет расстояние (в пикселах) между кнопками. property ButtonWidth: Integer;

определяет ширину (в пикселях) кнопок в компоненте TDecisionPivot (только для случая, когда свойство ButtonAutoSize = False).

property DecisionSource: TDecisionSource; содержит имя компонента TDecisionSource.

property GroupLayout: TDecisionButtonPosition; TDecisionButtonPosition = (xtHorizontal, xtVertical, xtLeftTop); определяет способ расположения кнопок измерений в компоненте TDecisionPivot:

xtHorizontal - горизонтальное;

xtVertical - вертикальное;

xtLeftTop - кнопки, соответствующие измерениям, которые выводятся в виде строк, помещаются слева внизу; кнопки, соответствующие измерениям-столбцам - вверху и кнопки, соответствующие суммам - вверху слева.

property Groups: TDecisionPivotOptions;

TDecisionPivotOptions = set of TDecisionPivotOption;

TDecisionPivotOption = (xtRows, xtColumns, xtSummaries);

множество, которое определяет, какие кнопки входят в TDecisionPivot. В состав множества могут входить значения:

xtRows - кнопки измерений куба, которые выводятся как строки;

xtColumns - кнопки измерений куба, которые выводятся как столбцы;

xtSummaries - кнопки, соответствующие суммам. property GroupSpacing: Integer;

определяет расстояние (в пикселах) между группами кнопок, соответствующих измерениям по строкам, по столбцам и суммам.