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

Тема в разделе "Delphi - Компоненты", создана пользователем Plentiful, 29 апр 2011.

  1. Plentiful

    Plentiful Гость

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

    Код (Delphi):
    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;
    Подскажите пожалуйста в чём ошибка ???
     
  2. sinkopa

    sinkopa Well-Known Member

    Регистрация:
    17 июн 2009
    Сообщения:
    344
    Симпатии:
    9
    Смерть Кощея в яйце, яйцо в утке... ну и так далее... :)

    Короче
    Код (Delphi):
    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;
    Пример использования
    Код (Delphi):
    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;
    Рабочий проект с подробными комментариями см. в прикрепленном файле...

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

    Вложения:

  3. Plentiful

    Plentiful Гость

    uses
    OleServer, Activex, Office_TLB,Excel_TLB,Clipbrd;
    ...

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

    sinkopa Well-Known Member

    Регистрация:
    17 июн 2009
    Сообщения:
    344
    Симпатии:
    9
    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 установленной на вашем компьютере.
    Если их несколько, желательно (из соображений совместимости) брать более раннюю версию
     
  5. Plentiful

    Plentiful Гость

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

    WB := nil;
     
  6. sinkopa

    sinkopa Well-Known Member

    Регистрация:
    17 июн 2009
    Сообщения:
    344
    Симпатии:
    9
    Дайте подумаю... :KillMe:
    не... чегото не экстрасенсорится сегодня...
    Текст ошибки в студию пжалста... :)

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

Поделиться этой страницей