Вывод графика из Excel в Image

  • Автор темы Plentiful
  • Дата начала
P

Plentiful

Гость
#1
Народ помогите пожалуйста !!!! Вот программный код:

Код:
procedure TForm1.Button1Click(Sender: TObject);
var
fXL: TExcelApplication;
Sheet: _Worksheet;
Book: _Workbook;
Chart: ChartObject;
lcid: THandle;
begin
lcid := GetUserDefaultLCId;
fXL := TExcelApplication.Create(nil); 
try
fXL.ConnectKind := ckNewInstance;
fXL.DisplayAlerts[lcid] := False;
fXL.AutoQuit := false;						 <--------- после того как я нажал на кнопку у меня программа выдаёт ошибку вот в этой строке !!!
fXL.Visible[lcid] := true;

fXL.Connect;

Book := fxl.Workbooks.Add('I:\Учёба\Информатика\2 семестр\Мои работы\Курсовая работа\1 ', lcid);
Sheet := (Book.ActiveSheet as _Worksheet);
Chart := Sheet.ChartObjects(1,lcid) as ChartObject;
Chart.CopyPicture(xlscreen,xlbitmap);

if Clipboard.HasFormat(CF_BITMAP)
then Image1.Picture.Bitmap.Handle:=Clipboard.GetAsHandle(CF_bitmap);

except
ShowMessage('Ошибка');
end;
Подскажите пожалуйста в чём ошибка ???
 

sinkopa

Well-Known Member
#2
Народ помогите пожалуйста !!!! Вот программный код:
...
Подскажите пожалуйста в чём ошибка ???
Смерть Кощея в яйце, яйцо в утке... ну и так далее... :)

Короче
Код:
uses
OleServer, Activex, Office_TLB,Excel_TLB,Clipbrd;
...

var
Charts: TStringList; // Список Графиков (они же чарты, они же диаграммы)

function GetExcelChartImages(exlFileName: string;  // Имя файла из которого вынимаем Графики
ChartList: TStrings;  // В items кладем имена гравиков, в objects витмапы
StartExcelNewInstance: Boolean=False // True - Если мы хотим "собственный" экземпляр Excel
// False (по умолчанию) - Пытаемся прицепиться к
// запущенному Excel. Если такого нет - Запускаем
): Boolean;

implementation


function GetExcelChartImages(exlFileName: string; ChartList: TStrings; StartExcelNewInstance: Boolean=False): Boolean;
var
ExcelApp: TExcelApplication;
WB: _Workbook;
WBName: string;
xCharts: ChartObjects;
xChart: ChartObject;
Crt: OleVariant;
i,j: Integer;
BMP: TBitmap;
NeedCloseWb: Boolean;
begin
NeedCloseWb := False;
WBName := ExtractFileName(exlFileName); // берем имя рабочей книги откуда будем вынимать графики

ExcelApp := TExcelApplication.Create(nil); // Создаем объект TExcelApplication

if StartExcelNewInstance then
ExcelApp.ConnectKind := ckNewInstance
else
ExcelApp.ConnectKind := ckRunningOrNew;

ExcelApp.Connect; // Подключаемся

WB := nil;

try
if (ExcelApp.Workbooks.Count > 0) then
begin
// Ищем рабочую книгу с заданным именем
for i := 1 to ExcelApp.Workbooks.Count do
begin
if (ExcelApp.Workbooks.Item[i].Name = WBName) then
begin
WB := ExcelApp.Workbooks.Item[i] as _Workbook;
Break;
end;
end;
end;

if (WB = nil) then  // Если не нашлась - открываем
begin
WB := ExcelApp.Workbooks.Open(exlFileName, EmptyParam, EmptyParam, EmptyParam,
EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam,
EmptyParam, EmptyParam, EmptyParam, False, EmptyParam, EmptyParam, 0);
NeedCloseWb := True; // Раз сами открыли, сами и закроем
end;

xCharts := nil;

for i := 1 to WB.Worksheets.Count do // Обходим страницы рабочей книги, собираем Графики
begin
xCharts := ((WB.Worksheets.Item[i] as _Worksheet).ChartObjects(EmptyParam, 0) as ChartObjects);

if Assigned(xCharts) then
begin
xChart := nil;
for j := 1 to xCharts.Count do // Обходим все меющиеся на странице графики
begin
xChart := xCharts.Item(j) as ChartObject;

if Assigned(xChart) then
begin
ClipBoard.Clear;						// чистим буфер обмена (на всякий случай)
xChart.CopyPicture(xlScreen,xlBitmap); // копируем график в буфер обмена как битмар

BMP := TBitmap.Create;				 // Забираем график из буфера обмена
BMP.LoadFromClipboardFormat(CF_BITMAP,ClipBoard.GetAsHandle(cf_Bitmap), 0);

Crt := xChart.Chart;
if (Crt.HasTitle = True) then		  // Если у графика есть собственное название
// В список кладем это название
ChartList.AddObject(Crt.ChartTitle.Text,BMP)
else									// Иначе в список кладем "рабочее имя" графика
ChartList.AddObject(Crt.Name,BMP);
end;
BMP := nil;
xChart := nil;
end;

end;
xCharts := nil;
end;

if NeedCloseWb then							 // Если нужно - закрываем рабочую книгу
WB.Close(False,EmptyParam,EmptyParam,0);

finally
ClipBoard.Clear;								 // чистим за собой буфер обмена
Result := (ChartList.Count > 0);

if StartExcelNewInstance then				  // Если мы запускали собственный экземпляр Excel
begin										  // Мы должны его "потушить"
if Assigned(ExcelApp) then
begin
if (ExcelApp.Workbooks.Count > 0) and (not ExcelApp.Visible[0]) then
begin
ExcelApp.WindowState[0] := TOLEEnum(xlMinimized);
ExcelApp.Visible[0] := true;
Application.BringToFront;
end;
end;
FreeAndNil(ExcelApp);
end
else										 // Если цеплялись к запущенному - просто отключаемся
begin
ExcelApp.Disconnect;
ExcelApp.Free;
end;
end;
end;
Пример использования
Код:
procedure TForm1.Button1Click(Sender: TObject);
var
BMP: TBitmap;
i: Integer;
begin
if GetExcelChartImages('I:\Учёба\Информатика\2 семестр\Мои работы\Курсовая работа\1.xls',Charts) then
begin
i := Charts.IndexOf('Диаграмма расхода колбасных обрезков'); // Пытаемся отыскать диаграмму с заданным именем
if (i < 0) then i := 0;				 // Если не нашлась - покажем первую в списке

BMP := TBitmap(Charts.Objects[i]);	  // Достали из Objects битмам
Image1.Picture.Bitmap := BMP;			 // Показываем
end;
end;
Рабочий проект с подробными комментариями см. в прикрепленном файле...

А... чуть не забыл... :)
Ошибка про которую Вы спрашивали возникает потому что Вы пытаетесь "рулить" Экселем ДО ТОГО как к нему собственно подключились...
 

Вложения

P

Plentiful

Гость
#3
uses
OleServer, Activex, Office_TLB,Excel_TLB,Clipbrd;
...

А почему когда я написал модули Office_TLB,Excel_TLB delphi мне в них выдаёт ошибку ?
 

sinkopa

Well-Known Member
#4
uses
OleServer, Activex, Office_TLB,Excel_TLB,Clipbrd;
...
А почему когда я написал модули Office_TLB,Excel_TLB delphi мне в них выдаёт ошибку ?
1. Меню: Project->Import Type Library...
2. Находим в списке "Microsoft Office 1.х Object Library"
3. Жмем Create Unit.
4. Находим в списке "Microsoft Excel 1х.0 Object Library".
5. Жмем Create Unit.

Примечание: х - цифра зависит от версии Office установленной на вашем компьютере.
Если их несколько, желательно (из соображений совместимости) брать более раннюю версию
 
P

Plentiful

Гость
#5
а тепер всё запускает, а когда я нажимаю на кнопку, то он мне выдаёт лшибку вот в этой строчке:

WB := nil;
 

sinkopa

Well-Known Member
#6
а тепер всё запускает, а когда я нажимаю на кнопку, то он мне выдаёт лшибку вот в этой строчке:

WB := nil;
Дайте подумаю... :KillMe:
не... чегото не экстрасенсорится сегодня...
Текст ошибки в студию пжалста... :)

Примечание (на всякий случай... если кто не знает)
Хоть мы, крутые парни, программный код всегда пишем правильно...
Так ведь? Все присутствующие меня поддержат? :)
тем не менее... подлые компиляторы периодически нам выдают непонятные сообщения, называя их при этом "ошибками"... хотя с чего бы им взятся?
Я это вот к чему. Чтобы поделиться с другом "текстом подлой выходки" компилятора достаточно сделать следующее:
1. Установить фокус на форму сообщения (кликнуть в окошке с мессагой).
2. Скопировать в буффер. т.е. Нажать "Ctrl+C" (или Ctrl+Insert - кто как больше привык).
3. Переключиться в текстовый редактор.
4. Вставить из буффера. т.е. Нажать "Ctrl+V" (или Shiftl+Insert - кто как больше привык).
Вуаля :)
Тоже самое, кстати, можно проделывать со всеми стандартными окошками сообщений виндовс... (с кастомными диалогами и формами, это не пройдет к сожалению).