Использование компонентов Microsoft Office в приложениях

Часть 1. Компоненты Chart и Spreadsheet

Алексей Федоров

Как известно, одной из новинок в Microsoft Office 2000 является введение понятия офисных Web-компонентов — компонентов ActiveX, которые можно использовать в составе HTML-страниц или обычных приложений. Эти компоненты реализуют некоторые функции программ, входящих в семейство Microsoft Office. Помимо их непосредственного использования для создания некоторого класса решений на базе Microsoft Office, эти компоненты применяются в тех случаях, когда мы сохраняем офисные документы в виде «активных» Web-документов. Естественно, что офисные Web-компоненты не предназначены для распространения по Internet. Они используются в рамках внутренней корпоративной сети — Intranet — и могут располагаться как на сервере, так и на клиентских компьютерах.

В этой статье мы рассмотрим некоторые примеры использования компонентов Microsoft Office в приложениях, созданных средствами Delphi.

Введение

Компонент Chart

   Построение графиков на основе статических данных

   Вариантные массивы

   Использование компонента Chart

   Построение графиков на основе данных из СУБД

   Построение графиков на основе данных из электронной таблицы

Компонент Spreadsheet

Заключение

Введение

Для программирующих на Delphi интерес представляют три офисных компонента: Spreadsheet Component, Chart Component и PivotTable Component. В табл. 1 приведена основная информация об этих компонентах.

Таблица 1

Компонент

ActiveX

Объект

TLB

Справка

Spreadsheet Component

Spreadsheet

Spreadsheet

MSOWC.DLL

MSOWCVBA.CHM

Chart Component

Chart

ChartSpace

MSOWC.DLL

MSOWCVBA.CHM

PivotTable Component

PivotTable List

PivotTable

MSOWC.DLL

MSOWCVBA.CHM

 

Кроме того, существуют компоненты DataSourceControl, RecordNavigationControl и ExpandControl. В Delphi с ролью компонента DataSourceControl успешно справляются компоненты ADOExpress (мы увидим это в приведенных ниже примерах), компонент RecordNavigationControl интересен только с точки зрения дизайна и при необходимости может быть заменен на «родной» DBNavigator. Компонент ExpandControl вообще не документирован.

Поскольку все офисные компоненты доступны через единую библиотеку типов (MSOWC.DLL), подключение этой библиотеки к проекту приводит к тому, что становятся доступны все компоненты. Использование офисных компонентов в Delphi нужно начинать с подключения соответствующей библиотеки типов. Для этого следует выполнить команду Project | Import Type Library. В списке доступных библиотек типов выберем библиотеку Microsoft Office Web Components 9.0 Version 1.0 (рис. 1).

Далее, поскольку мы имеем дело с компонентами ActiveX, следует отметить опцию Generate Component Wrapper и нажать кнопку Install. Таким образом на указанной нами палитре компонентов появятся новые компоненты — ChartSpace, Spreadsheet, DataSourceControl, RecordNavigationControl, ExpandControl и PivotTable (рис. 2).

в начало

в начало

Компонент Chart

Компонент Chart предназначен для графического представления данных, получаемых из других офисных компонентов – Spreadsheet, PivotTable, путем представления статических данных или путем динамического представления данных, например из ADO-источников. Ниже мы рассмотрим три способа использования данного компонента в Delphi-приложениях:

  1. построение графиков на основе статических данных;
  2. построение графиков на основе данных из СУБД;
  3. построение графиков на основе данных из электронной таблицы.
в начало

в начало

Построение графиков на основе статических данных

Компонент Chart позволяет строить графики на основе статических данных. В этом случае все данные предоставляются во время работы самим приложением. В Delphi-приложениях такие данные хранятся либо в статических вариантных массивах, создаваемых с помощью функции VarArrayCreate, либо в динамических вариантных массивах, реализуемых через функцию VarArrayOf.

в начало

в начало

Вариантные массивы

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

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

Динамический вариантный массив не связывается с переменной какого-либо типа — для создания такого массива служит функция VarArrayOf. Вот пример использования этой функции:

VarArrayOf([
104737, 50952, 78128, 117797,
52902, 80160, 47491, 62435
]));

Функция VarArrayOf возвращает одномерный вариантный массив, содержащий элементы типа Variant.

в начало

в начало

Использование компонента Chart

Использование компонента Chart состоит из ряда шагов. Работа начинается с очищения содержимого графика. Далее мы добавляем новый график в коллекцию Charts компонента Chart. Компонент может содержать до 16 графиков. Затем можно задать заголовок нового графика (свойство Title) и указать данные, которые содержатся в сериях — коллекции Series объекта Chart. Этот объект также поддерживает оси (Axes) и «легенду» (свойство Legend). Базовая иерархия объектов компонента Chart показана на рис. 3.

Ознакомившись с основными правилами использования компонента Chart, рассмотрим практический пример — построение графика на основе статических данных.

Начнем с объявления переменных:

var
Chart : WCChart; // График
Series : WCSeries; // Серия
XValues : Variant; // Значения для оси Х

После этого можно приступить к манипуляциям с компонентом. Сначала очистим содержимое текущего графика

ChartSpace1.Clear;
ChartSpace1.Refresh;

А теперь создадим новый график — добавим новый объект в коллекцию Charts компонента Chart. Так как мы добавляем первый график, индекс нового объекта указывается равным 0.

Chart := ChartSpace1.Charts.Add(0);

Собственно построение графика начнем с того, что зададим текст его заголовка.

Chart.HasTitle := True;
Chart.Title.Caption := ‘Sales By Category’;

Затем мы должны описать данные для оси Х, в нашем примере это будет статический вариантный массив:

XValues := VarArrayCreate([0,7], varVariant);
XValues[0] := ‘Beverages’;
XValues[1] := ‘Condiments’;
XValues[2] := ‘Confections’;
XValues[3] := ‘Dairy Products’;
XValues[4] := ‘Grains & Cereals’;
XValues[5] := ‘Meat & Poultry’;
XValues[6] := ‘Produce’;
XValues[7] := ‘Seafood’;

Теперь можно задать данные для построения графика, но прежде добавим серию — новый объект Series в коллекции SeriesCollection (листинг 2).

В приведенном выше коде мы добавляем новую серию, задаем ее заголовок, указываем данные (статический и динамический вариантные массивы), а также указываем тип графика для данной серии — столбиковая диаграмма.

Далее мы можем добавить еще одну серию и наложить новый график на уже существующий:

Series := Chart.SeriesCollection.Add(1);
With Series do
Begin
   Caption := ‘1999’;
      SetData(chDimCategories, chDataLiteral, XValues);
// Данные для оси Y - динамические
   SetData(chDimValues, chDataLiteral,
      VarArrayOf (
      [20000, 15000, 36000, 56000, 40000, 18000, 
20000, 33000]
      ));
   Type_ := chChartTypeLineMarkers;
End;

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

Для достижения конечной цели нам осталось совсем немного: надо лишь добавить ось со значениями для второй серии:

Chart.Axes.Add(Chart.Axes[chAxisPositionLeft].Scaling,
   chAxisPositionRight, chValueAxis);

оформить оси в соответствии со значениями данных графика:

Chart.Axes[chAxisPositionLeft ].NumberFormat
 := ‘$#,##0’;
Chart.Axes[chAxisPositionRight].NumberFormat
 := ‘0’;
Chart.Axes[chAxisPositionLeft ].MajorUnit := 
20000;
Chart.Axes[chAxisPositionRight].MajorUnit := 
20000;

и добавить «легенду» в нижней части построенного графика

Chart.HasLegend := True;
Chart.Legend.Position := chLegendPositionBottom;

Результат работы нашей программы показан на рис. 4.

Как видно из рисунка, мы получили два графика, наложенных один на другой и построенных на основе статических данных. В следующем примере мы покажем, как для построения графика использовать данные, хранимые в СУБД.

в начало

в начало

Построение графиков на основе данных из СУБД

При использовании данных, хранимых в СУБД, для построения графика с использованием компонента Chart у нас есть две опции. Мы можем использовать либо офисный Web-компонент DataSource (для этого следует добавить на форму компонент DataSourceControl, созданный при загрузке библиотеки типов офисных компонентов), либо какой-либо ADO-совместимый источник данных. Во всем остальном последовательность действий с компонентом Chart остается точно такой же, как и в предыдущем примере. Итак, обратимся к коду примера и рассмотрим, как строить графики на данных, хранимых в СУБД.

Начнем с того, что объявим переменные. Сначала — для случая с Web-компонентом DataSource:

var
RSD : RecordsetDef;
BarChart : WCChart;
PieChart : WCChart;

После этого мы описываем источник данных и SQL-запрос для их извлечения (листинг 3).

Здесь мы используем базу данных Access Northwind и представление Category Sales for 1997. Далее очищаем содержимое графика и указываем источник данных:

With ChartSpace1 do
Begin
   Clear;
   Refresh;
// !!
 DataSource := DataSourceControl1.DefaultInterface as
 MSDATASRC_TLB.DataSource;
// !!
 DataMember := RSD.Name;
End;

Обратите внимание на строку, выделенную жирным шрифтом: поскольку свойство DataSource компонента Chart имеет тип DataSource, объявленный как интерфейс на основе IUnknown (в модуле MSDATASRC_TLB), то мы используем показанную выше конструкцию. Отметим, что в Visual Basic все намного проще: можно присвоить свойству DataSource значение DataSourceControl1 — в этом случае интерфейс по умолчанию будет извлечен автоматически.

Прежде чем рассматривать последовательность действий дальше (она будет одинаковой для источников данных обоих типов, воспользуемся ADO-совместимым источником данных. В этом случае мы будем использовать компоненты ADO Express — ADOConnection (для задания источника данных и установки типа курсора) и ADOCommand (для извлечения данных по SQL-запросу). Здесь потребуется новая переменная:

var 
 RS : _Recordset;

а код для извлечения данных и ассоциации их с компонентом Chart будет выглядеть так:

RS := ADOCommand1.Execute;
With ChartSpace1 do
Begin
 Clear;
 Refresh;
 DataSource := RS as MSDATASRC_TLB.DataSource;
 DataMember := ‘’;
End;

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

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

В приведенном выше коде мы создали второй график, описали данные, добавили «легенду», заголовок, изменили шрифт заголовка и тип отображения данных (в нашем примере данные отображаются как проценты). На рис. 5 показан результат работы нашей программы.

Далее мы рассмотрим построение графиков на основе данных из электронной таблицы.

в начало

в начало

Построение графиков на основе данных из электронной таблицы

Начнем с того, что добавим к нашей форме компонент Spreadsheet, который будет использоваться как источник данных для графика. Отметим, что в этом случае график будет динамически меняться при изменении данных в электронной таблице.

Объявим переменные, которые будем использовать в нашем коде.

var
   Sheet : WorkSheet;
   Chart : WCChart;

Далее заполним ячейки электронной таблицы данными:

Sheet := Spreadsheet1.ActiveSheet;
 With Sheet do
 Begin
   Range[‘A1’, ‘A10’].Set_Formula(‘=Row()’);
   Range[‘B1’, ‘B10’].Set_Formula(‘=A1^2’);
   Range[‘A12’,’A12'].Set_Formula(‘=Max(A1:A10)’);
   Range[‘B12’,’B12'].Set_Formula(‘=Max(B1:B10)’);
End;

В колонку А мы занесли номера рядов (от 1 до 10), а в колонку B — значения квадратов от значений соответствующей ячейки колонки A. В ячейки A12 и B12 мы занесли максимальные значения соответствующей колонки.

Обратите внимание на то, что компонент Spreadsheet позволяет использовать формулы, знакомые нам по Microsoft Excel, — это не случайно, так как оба этих продукта используют единое программное ядро. Более того, можно использовать компонент Spreadsheet для выполнения каких-либо вычислений. В этом случае сам компонент можно даже не отображать на экране.

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

Как и в предыдущем примере, мы используем приведение к типу MSDATASRC_TLB.DataSource, указывая интерфейс по умолчанию компонента Spreadsheet.

Теперь можно задать заголовки осей и их тип:

 With Chart do
 Begin
//
// Покажем заголовки осей
//
 With Axes[chAxisPositionBottom] do
 Begin
  HasTitle := True;
  Title.Caption := ‘X’;
  Title.Font.Set_Size(8);
  MajorUnit := 1;
 End;
 With Axes[chAxisPositionLeft] do
 Begin
  HasTitle := True;
  Title.Caption := ‘X Squared’;
  Title.Font.Set_Size(8);
  MajorUnit := 10;
 End;

Теперь мы можем установить максимальные и минимальные значения по осям, а также изменить некоторые стили:

 Scalings[chDimXValues].Maximum :=
  Sheet.Range[‘A12’, ‘A12’].Value;
 Scalings[chDimXValues].Minimum := 1;
 Scalings[chDimYValues].Maximum :=
  Sheet.Range[‘B12’, ‘B12’].Value;
// Изменим стили
 With SeriesCollection.Item[0] do
 Begin
  Marker.Style := chMarkerStyleDot;
  Marker.Size := 6;
  Line.Set_Weight(1);
 End

На рис. 6 представлен результат работы нашей программы.

Напомню, что в последнем примере, за счет того что данные берутся непосредственно из офисного компонента — компонента Spreadsheet, их изменение приведет к немедленной перерисовке графика.

Итак, мы продемонстрировали, как использовать компонент Spreadsheet в качестве источника данных для построения графика на основе компонента Chart, а теперь рассмотрим, как можно использовать компонент Spreadsheet сам по себе.

в начало

в начало

Компонент Spreadsheet

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

Объектная модель компонента Spreadsheet состоит из свойства ActiveSheet, обеспечивающего доступ к единственной электронной таблице, объектов Pane (окно таблицы), Range (диапазон ячеек), TitleBar (заголовок) и Worksheet (сама таблица). Базовая иерархия объектов компонента Spreadsheet показана на рис. 7.

Компонент Spreadsheet предоставляет несколько способов для занесения данных в электронную таблицу. Например, можно вводить данные вручную, копировать их через область обмена данными из Excel, документа Word или текстового файла, импортировать данные из текстового файла, расположенного локально или на Web-узле, и т.п.

Чтобы загрузить данные из текстового файла, используется метод LoadText, для которого в качестве параметров указывается:

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

Например:

   SpreadSheet1.LoadText(‘c:\data\employee.txt’, 
Chr(9),
   False, ‘“‘);

Собственно, вызова указанного метода вполне достаточно, чтобы заполнить электронную таблицу данными. Также можно задавать данные через свойства CSVData (данные, разделенные запятыми) или HTMLData (данные в формате HTML). Все эти свойства доступны и для чтения, и для записи, но к свойству CSVData можно обратиться только в том случае, если данные были заданы именно как CSV.

Поскольку данные в формате HTML хранятся в Excel-совместимом формате, это можно использовать для того, чтобы обмениваться данными между компонентом Spreadsheet и Excel.

Здесь мы используем компонент ADOCommand для загрузки данных из таблицы Employees базы данных Northwind. После того как данные извлечены, используем цикл по всем записям, в каждой итерации которого данные заносятся в соответствующую ячейку электронной таблицы.

После занесения данных их можно отформатировать. Ниже показано, как изменить шрифт у первой строки таблицы:

With Spreadsheet1.Range[Spreadsheet1.Cells.Item[1, 1], Spreadsheet1.Cells.Item[1,RS.Fields. 
  Count]].Font do
Begin
 Set_Name(‘Arial Narrow’);
 Set_Bold(True);
 Set_Size(11);
End;

а также задать автоматическое изменение ширины колонок и выравнивание текста влево:

With Spreadsheet1.Range[Spreadsheet1.Cells.Item[1, 1],Spreadsheet1.Cells.Item[NumRecs, 
  RS.Fields.Count]] do
Begin
 AutoFitColumns;
 Set_HAlignment(ssHAlignLeft);
End;

Результат работы нашей программы — на рис. 8.

В завершение рассмотрения офисных компонентов скажем несколько слов об установке цветов. Если мы захотим изменить цвет какого-либо элемента, то столкнемся с тем, что свойство Color доступно только для чтения — это происходит из-за ошибки в генераторе интерфейса к библиотеке типов в Delphi. Поэтому вместо изменения значения свойства Color следует использовать метод Set_Color. Второй нюанс заключается в том, что данный метод ожидает параметр типа POleVariant1; этот тип описан как указатель на OLEVariant (^OleVariant). Ниже показано, как воспользоваться методом Set_Color:

C : OLEVariant;
...
// Можно использовать либо предопределенные цвета
C := OLEVariant(‘CornSilk’);
// либо указать их как шестнадцатеричный RGB-код
C := OLEVariant(RGB($C0, $C0, $C0));
Spreadsheet1.ActiveSheet.UsedRange.Interior.
Set_Color(@C);
в начало

в начало

Заключение

В этом обзоре мы ознакомились с двумя офисными Web-компонентами — Chart и Spreadsheet — и привели примеры использования этих компонентов в Delphi-приложениях. Завершая наш обзор, следует сказать и о лицензировании офисных Web-компонентов. Для использования этих компонентов необходима лицензия на Microsoft Office 2000, которую вы получаете, приобретая такие продукты, как Office 2000 Premium, Office 2000 Professional, Office 2000 Small Business, Office 2000 Standard, Office 2000 Developer или Microsoft Access 2000. Офисные компоненты распространяются только в составе вышеперечисленных продуктов и должны использоваться только на тех компьютерах, где установлен пакет Microsoft Office 2000.

КомпьютерПресс 11'2000