Chart, ChartObject, Shape, Picture
Пожалуй, самым популярным использованием Excel является применение его для построения диаграмм (Chart). Это заметно по большому количеству примеров, статей и различных FAQ в Интернете по этой теме.
Chart Object
ChartObject Object Model
Shapes Collection Object Model
Chart Class
Как добавить Chart в отдельный лист книги? Как внедрить Chart в лист книги?
Chart может существовать как отдельный лист книги, так и как внедренный в лист объект ChartObject. Принципиальная разница только в том, ChartObject — это уже объект Shape, содержащий в себе Chart.
Чтобы добавить Chart как отдельный лист книги, нужно воспользоваться методом Add коллекции Sheets.
var
oChart: _Chart;
oSheet: _Worksheet;
...
oChart := XL.Sheets.Add(EmptyParam, oSheet, 1, xlChart, lcid) as _Chart;
Внимание! Не пытайтесь добавить Chart, используя коллекцию Charts — вы получите OLE исключение, т.к. Charts — это коллекция-подмножество Sheets, содержащее ссылки на листы Chart.
Чтоб добавить Chart, как внедренный в лист объект, можно воспользоваться методом Add коллекции листа ChartObjects (здесь существует возможность сразу задать координаты и размеры внедряемого Chart, как будто это объект Shape).
oChart := (oSheet.ChartObjects(EmptyParam, lcid)
as ChartObjects).Add(
oSheet.Range['B9', EmptyParam].Left,
oSheet.Range['B9', EmptyParam].Top + 8,
oSheet.Range['I9', EmptyParam].Left - oSheet.Range['B9', EmptyParam].Left,
oSheet.Range['B30', EmptyParam].Top - oSheet.Range['B9', EmptyParam].Top).Chart
as _Chart;
Внимание! При преобразовании Chart в ChartObject (или наоборот) лист Chart (или объект ChartObject) исчезнет (будет утерян), поэтому необходимо всегда получать ссылку на новый объект Chart, возвращаемый функцией Locate.
Charts
Location Method
How to: Add Chart Controls to Worksheets
Как указать источник данных объекту Chart?
Для указания источника данных, можно воспользоваться методом SetSourceData объекта Chart или (мне кажется, что это даже удобнее) методом ChartWizard.
var oRng: ExcelRange;
...
oRng := oSheet.Range['E2:H6', EmptyParam];
// Указываем источник данных методом SetSourceData
with oChart do begin
SetSourceData(oRng, xlColumns); // источник данных и PlotBy
ChartType := xl3dColumn; // тип диаграммы
end;
// Указываем источник методом ChartWizard, в котором можно сразу
// задать многие параметры диаграммы
oChart.ChartWizard(
oRng, // Source: OleVariant;
xl3dColumn, // Gallery: OleVariant;
EmptyParam, // Format: OleVariant;
// данные серий - в колонках
xlColumns, // PlotBy: OleVariant;
EmptyParam, // CategoryLabels: OleVariant;
EmptyParam, // SeriesLabels: OleVariant;
True, // HasLegend: OleVariant;
'Sales', // Title: OleVariant;
EmptyParam, // CategoryTitle: OleVariant;
'у.е.', // ValueTitle: OleVariant;
EmptyParam, // ExtraTitle: OleVariant;
lcid);
SetSourceData Method
ChartWizard Method
Как получить доступ к ряду (series) Chart?
Например, в цикле присвоим всем сериям новое имя.
for i := 1 to (oChart.SeriesCollection(EmptyParam, lcid) as SeriesCollection).Count do
(oChart.SeriesCollection(i, lcid) as Series).Name := Format('="Q%d"', [i]);
Обратиться к серии (ряду) можно не только по индексу, но и по имени, например
(oChart.SeriesCollection('Q1', lcid) as Series).Interior.Color := RGB(0, 0, 255);
SeriesCollection Collection Object
Series Object
Как добавить новый ряд (Series) в Chart?
with (oChart.SeriesCollection(EmptyParam, lcid) as SeriesCollection).NewSeries do
begin
Values := oSheet.Range['H2', 'H6'];
Name := '="Q4"';
end;
Также можно воспользоваться методом Extend, который "расширяет" область данных диаграммы.
NewSeries Method
Extend Method
Как изменить цвет серии в Chart?
with (oChart.SeriesCollection(1, lcid) as Series).Interior do begin
Color := RGB(0, 0, 255);
Pattern := xlSolid;
end;
Interior Property
Border Property
Fill Property
Как изменять заголовки Chart и его осей?
Например, так:
// Заголовок диаграммы
HasTitle[lcid] := True;
ChartTitle[lcid].Characters[EmptyParam, EmptyParam].Text := 'Sales';
// Ось Х - заголовка нет
(Axes(xlCategory, xlPrimary, lcid) as Axis).HasTitle := False;
// Оси Y - заголовок "у.е."
(Axes(xlValue, xlPrimary, lcid) as Axis).HasTitle := True;
(Axes(xlValue, xlPrimary, lcid) as Axis).AxisTitle.
Characters[EmptyParam, EmptyParam].Text := 'у.е.';
(Axes(xlValue, xlPrimary, lcid) as Axis).AxisTitle.Orientation := xlUpward;
Axes Method
Как назначить подписи значениям оси Х (ось категорий) из области ячеек?
Для отображения подписей оси X предназначено свойство XValues объекта Series.
// значения по категориям
(oChart.SeriesCollection(1, lcid) as Series).XValues :=
oSheet.Range['C2:C6', EmptyParam];
XValues Property
Как убрать легенду из Chart?
Легенду можно просто "спрятать", указав, что ее "нет". Также вы можете изменять любые атрибуты легенды (Font, Interior и другие), получив доступ к свойству Legend объекта Chart.
oChart.HasLegend[lcid] := False;
Legend Object
HasLegend
Как добавить в лист объект Shape и записать в него текст?
Объект Shape — это контейнер для многих других объектов, таких как TextBox, PolyLine, ChartObject и др. Также и свойство Comment объекта Range, по возможностям и набору свойств, можно отнести к Shape. Все объекты-наследники Shape содержатся в коллекции Shapes листа.
Внимание! Не забудьте явно указать namespace при присвоении типа объекта Shape, т.к. возможен конфликт с объектом Shape namespace Office:
var
AShape: ExcelXP.Shape;
// или
AShape: Excel2000.Shape;
Примеры:
// Rectangle
AShape := ASheet.Shapes.AddShape(
msoShapeRectangle,
ASheet.Range['A1', EmptyParam].Width / 2,
ASheet.Range['A1', EmptyParam].Height,
ASheet.Range['D1', EmptyParam].Left - ASheet.Range['A1', EmptyParam].Width / 2,
ASheet.Range['D9', EmptyParam].Top - ASheet.Range['A1', EmptyParam].Height
);
AShape.TextFrame.Characters(EmptyParam, EmptyParam).Text := 'Rectangle';
// Oval
AShape := ASheet.Shapes.AddShape(
msoShapeOval,
ASheet.Range['E1', EmptyParam].Left,
ASheet.Range['F2', EmptyParam].Top,
ASheet.Range['I1', EmptyParam].Left - ASheet.Range['E1', EmptyParam].Left,
ASheet.Range['F12', EmptyParam].Top - ASheet.Range['F2', EmptyParam].Top
);
AShape.TextFrame.Characters(EmptyParam, EmptyParam).Text := 'Oval';
AShape.TextFrame.HorizontalAlignment := xlCenter;
AShape.TextFrame.VerticalAlignment := xlCenter;
// TextBox
AShape := ASheet.Shapes.AddShape(
msoTextOrientationVerticalFarEast,
ASheet.Range['B1', EmptyParam].Left,
ASheet.Range['B11', EmptyParam].Top,
ASheet.Range['E1', EmptyParam].Left - ASheet.Range['B1', EmptyParam].Left,
ASheet.Range['B18', EmptyParam].Top - ASheet.Range['B10', EmptyParam].Top
);
AShape.TextFrame.Characters(EmptyParam, EmptyParam).Text := 'Rhombus';
AShape.TextFrame.HorizontalAlignment := xlCenter;
AShape.TextFrame.VerticalAlignment := xlCenter;
// Hedgehog
AShape := ASheet.Shapes.AddShape(
msoShape32pointStar,
ASheet.Range['D1', EmptyParam].Left,
ASheet.Range['E19', EmptyParam].Top,
ASheet.Range['G1', EmptyParam].Left - ASheet.Range['D1', EmptyParam].Left,
ASheet.Range['E30', EmptyParam].Top - ASheet.Range['E19', EmptyParam].Top
);
AShape.TextFrame.Characters(EmptyParam, EmptyParam).Text := 'Hedgehog';
AShape.TextFrame.HorizontalAlignment := xlCenter;
AShape.TextFrame.VerticalAlignment := xlCenter;
AShape.TextFrame.Orientation := msoTextOrientationUpward; // 2
Shapes Collection
Shapes
Shape Object
TextFrame Property
ShapeRange Collection
Как изменить цвет линии и фона Shape?
Delphi:
(AShape.Fill as FillFormat).ForeColor.SchemeColor := 41;
(AShape.Line as LineFormat).ForeColor.SchemeColor := 62;
C#:
AShape.Fill.ForeColor.SchemeColor = 43;
AShape.Line.ForeColor.SchemeColor = 53;
Fill Property
Line Property
Как сгруппировать несколько объектов Shape на листе?
// Сгруппируем все объекты Shapes на листе
AShape := (ASheet.DrawingObjects(EmptyParam, lcid)
as DrawingObjects).ShapeRange.Group;
AShape.Name := 'MyGroup1';
// группировка через вариантный массив
V := VarArrayCreate([1, 2], varVariant); // !!!
// сгруппируем 2-й и 4-й Shape
V[1] := 2;
V[2] := 4;
AShape := ASheet.Shapes.Range[V].Group;
AShape.Name := 'MyGroup2';
// Если заранее известно, какие Shape будут сгруппированы,
// то можно и так
AShape := ASheet.Shapes.Range[VarArrayOf([2, 4])].Group;
AShape.Name := 'MyGroup3';
// Теперь, на закуску, через Selection
// Выберем 2-й, 3-й и 4-й Shape
ASheet.Shapes.Item(2).Select(True);
ASheet.Shapes.Item(3).Select(False);
ASheet.Shapes.Item(4).Select(False);
// сгруппируем выделенные Shape
AShape := (XL.Selection[lcid] as DrawingObjects).ShapeRange.Group;
AShape.Name := 'MyGroup4';
// Разгруппировать
AShape.Ungroup;
Заметьте, что после того, как объекты Shape были сгруппированы, их количество на листе (Shapes.Count) уменьшится. После "группировки" можно обратиться к отдельному Shape, включенному в группу, используя коллекцию GroupItems объекта Shape, полученного в результате группировки.
Group Method
Regroup Method
Ungroup Method
GroupItems Property
Как вставить в лист картинку?
var
AShape: Excel_TLB.Shape;
APic: Picture; // Excel_TLB
Img: TImage; // ExtCtrls
MyFormat: Word; // для копирования картинки в БО
AData: THandle; // для копирования картинки в БО
APalette: HPALETTE; // для копирования картинки в БО
...
// Первый метод
// Вставляем картинку из файла с "нулевым" размером в
// позицию ячейки B2. "Нулевой" размер потому, что
// мы не знаем заранее размера картинки
with ASheet.Range['B2', EmptyParam] do
AShape := ASheet.Shapes.AddPicture(ExpandFileName('common.gif'),
msoFalse, msoTrue, Left, Top, 0, 0);
// После вставки получаем ссылку на объект Shape, содержащий
// нашу картинку. "Реанимируем" оригинальный размер картинки
AShape.ScaleHeight(1, msoTrue, EmptyParam);
AShape.ScaleWidth(1, msoTrue, EmptyParam);
AShape.Name := 'Picture1';
// Второй метод - вставляем в выделенную ячейку
ASheet.Range['C7', EmptyParam].Select;
APic := (ASheet.Pictures(EmptyParam, lcid)
as Pictures).Insert(ExpandFileName('common.gif'), EmptyParam);
APic.Name := 'Picture2';
// Третий метод - вставка через буфер обмена
// Загрузим картинку с диска в TImage
Img.Picture.LoadFromFile(ExpandFileName('common.bmp'));
MyFormat := CF_PICTURE;
AData := Img.Picture.Bitmap.Handle;
APalette := Img.Picture.Bitmap.Palette;
// и помещаем в буфер обмена
Img.Picture.SaveToClipboardFormat(MyFormat, AData, APalette);
Clipboard.SetAsHandle(MyFormat, AData);
// из буфера обмена вставим в ячейку D12
ASheet.Paste(ASheet.Range['D12', EmptyParam], EmptyParam, lcid);
Все добавленные картинки будут включены в коллекцию Shapes листа.
AddPicture Method
Worksheet.Pictures Method
Paste Method
Как изменить размер картинки и вписать ее в размер определенной области ячеек?
Если пытаться изменять размер картинки, то она, по умолчанию, будет менять размер пропорционально. Такую особенность задает свойство LockAspectRatio объекта Shape. Если установить LockAspectRatio равным msoFalse, то картинка будет менять размеры непропорционально.
// Картинка будет вписана в область D12:J18 с сохранением пропорций
AShape.Width := ASheet.Range['K12', EmptyParam].Left -
ASheet.Range['D12', EmptyParam].Left;
AShape.Height := ASheet.Range['D19', EmptyParam].Top -
ASheet.Range['D12', EmptyParam].Top;
// Картинка будет вписана во всю область D12:J18 без сохранения пропорций
AShape.LockAspectRatio := msoFalse;
AShape.Width := ASheet.Range['K12', EmptyParam].Left -
ASheet.Range['D12', EmptyParam].Left;
AShape.Height := ASheet.Range['D19', EmptyParam].Top -
ASheet.Range['D12', EmptyParam].Top;
LockAspectRatio Property
Как изменить яркость или контрастность картинки?
(AShape.PictureFormat as PictureFormat).Brightness := 0.25; // 25% яркости
(AShape.PictureFormat as PictureFormat).Contrast := 0.75; // 75% контрастность
PictureFormat Property
Как добавить картинке гиперссылку?
Смотрите " Как добавить URL? Как сделать гиперссылку для рисунка?"
Hyperlink Property
Полезные ссылки
Creating Charts in Excel 2003 Using Visual Basic for Applications Code
How To Create Excel Chart w/OLE Automation from Visual Basic
Microsoft Excel Charting FAQs
Excel Charts and Graphs Help from Mr Excel
Excel Chart Tips
How to automate Microsoft Excel from Microsoft Visual C# .NET
How To Automate Excel from an HTML Web Page Using JScript
VBA Samples for Working with Excel 2003 Worksheets
XL97: How to Create a GIF File from a Microsoft Excel Chart
COM Tips & Tricks