Подписка

Проекты

Сборник идей для разработок в Delphi и использования их в Интернет. Участвуй в работе коллективного разума!

Google API в Delphi - проект с открытым исходным кодом.


А тут я коплю на лицензию Delphi 2011. Сумма пожертвования не фиксирована.

Друзья блога

Блоги и сообщества

DelphiFeeds.ru - Все Delphi-блоги Рунета О раскрутке блога по программированию Сообщество умных людей VR-Online.RU Бесплатный журнал для программистов и всех, кто интересуется IT Статьи и уроки по Delphi Статьи по Delphi

Счётчики


Анализ веб сайтов

Рейтинг блогов




Система Orphus

  • 27Aug

    Видимо любители экономить килобайты оперативной памяти могут меня закидать помидорами или ещё чем по-хуже, но все-таки я скажу, что интеграция приложений (мегабайты оперативы) – это большой плюс нынешней разработки приложений.
    Как ни крути, а время DOS и килобайтов оперативной памяти прошло. Врядли кто-то всерьез сейчас задумывается над тем куда это с винчестера пропал мегабайт? Да и использование в своих приложениях функциональности программ, которых ты не писал, но которые выполняют что-то лучше – это всё-таки больший прогресс, нежели корпеть год-два над программой, а потом узнать, что время-то прошло. ' '
    Итак, цель сегодняшней статьи – поделиться с Вами опытом работы с Microsoft Excel в приложениях, написанных на Delphi.
    Вспомнился сейчас один случай. Когда я только начинал работать по своей специальности, пригласили меня написать программу-расчётник для экологов нашего нефтезавода. В принципе ничего серьёзного – программа считает выброс от нагревательной печи и выдает табличку результатов, которую необходимо распечатать и уложить в толстую папку с отчётами. Естественно, что в области разработки подобных приложения я далеко не пионер, поэтому дали взглянуть на аналог будущей программы, который работал ещё под DOS и печатались отчёты на дико скрипящем матричном принтере с 12-ю иголками. Ну посмотрел, элементарная таблица, расчёт немного запутан, но жить можно – начал по-тихоньку писать. И попалась мне тогда на глаза статейка про работу с Excel в Delphi. Вот я и решил попробовать выдавать отчёт не только на форму приложения, а ещё и скидывать весь ход расчёта с формулами и прочим делом в Excel…Надо сказать более сильно детской радости начальника отдела я не видел до сих пор :). Люди, всю жизнь проработавшие в DOS увидели как тот же самый расчёт может выглядеть в современных условиях. Вот теперь при определении технических заданий на каждую новую программу, обязательно присутствует пункт, гласящий, что программа должна передавать данные либо в MS Word либо в MS Excel.Соответственно и цена на разработку возрастает, иногда значительно.

    Отсюда можно сделать простой и однозначный вывод – заказчики готовы пожертвовать лишними деньгами только для того, чтобы всё в программе было красиво. Excel может дать вашему приложению ту самую красоту и удобство.

    Ну, а для того, чтобы каждый раз не утруждать себя выполнением однотипных операций, я разработал небольшой модуль для работы с Excel. Этот же модуль я в настоящее время дорабатываю под ещё одну задачу, но об этом после. Сегодня основы основ работы с Excel в Delphi.

    1. Как проверить установлен ли Excel на компьютере пользователя?

    Создаем новый модуль (unit) и подключаем в uses следующие модули:

    uses ComObj, ActiveX, Variants, Windows, Messages, SysUtils, Classes;

    теперь объявляем глобальную переменную:

    var MyExcel: OleVariant;

    Одну константу (для удобства):

    const ExcelApp = 'Excel.Application';

    И пишем простенькую функцию:

    function CheckExcelInstall:boolean;
    var
      ClassID: TCLSID;
      Rez : HRESULT;
    begin
    // Ищем CLSID OLE-объекта
      Rez := CLSIDFromProgID(PWideChar(WideString(ExcelApp)), ClassID);
      if Rez = S_OK then  // Объект найден
        Result := true
      else
        Result := false;
    end;

    Если функция CLSIDFromProgID находит CLSID OLE-объекта, то, соответственно – Excel установлен.

    Но проверка на наличие установленного Excel – это только часть необходимых операций перед началом работы. Другой немаловажной проверкой является проверка на наличие уже запущенного экземпляра Excel. Если этого не делать, то может случиться такая нехорошая ситуация, когда в системе будет зарегистрировано …дцать процессов Excel и все оперативная память волшебным образом утекет “в трубу” – за такое могут и по ушам надавать. Но мы-то свои уши бережем. Пишем вторую функцию проверки.

    2. Определяем запущен ли Excel

    function CheckExcelRun: boolean;
    begin
      try
        MyExcel:=GetActiveOleObject(ExcelApp);
        Result:=True;
      except
        Result:=false;
      end;
    end;

    Думаю тут лишних объяснений не потребуется? Всё предельно просто – если есть активный процесс Excel, то му просто получаем на него ссылку и можем использовать Excel для своих корыстных целей. Главное – не забыть проверить – может кто-то этот самый Excel забыл закрыть, но это другой момент. Будем считать, что Excel в нашем полном распоряжении.

    3. Как запустить Excel?

    Одно дело, когда мы получаем в распоряжение уже запущенный Excel, другое – когда Excel требуется запустить из Delphi. Напишем функцию запуска Excel:

    function RunExcel(DisableAlerts:boolean=true; Visible: boolean=false): boolean;
    begin
      try
    {проверяем установлен ли Excel}
        if CheckExcelInstall then
          begin
            MyExcel:=CreateOleObject(ExcelApp);
    //показывать/не показывать системные сообщения Excel (лучше не показывать)
            MyExcel.Application.EnableEvents:=DisableAlerts;
            MyExcel.Visible:=Visible;
            Result:=true;
          end
        else
          begin
            MessageBox(0,'Приложение MS Excel не установлено на этом компьютере','Ошибка',MB_OK+MB_ICONERROR);
            Result:=false;
          end;
      except
        Result:=false;
      end;
    end;

    Здесь мы в начале проверяем, установлен ли Excel в принципе и, если он все же установлен, запускам. При этом мы можем сразу показать окно Excel пользователю – для этого необходимо выставить параметр Visible в значение True.

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

    Переходим к следующему этапу работы – созданию рабочей книги.

    4. Создаем пустую рабочую книгу Excel

    Для создания пустой рабочей книги я обычно использую вот такую функцию:

    function AddWorkBook(AutoRun:boolean=true):boolean;
    begin
      if CheckExcelRun then
        begin
          MyExcel.WorkBooks.Add;
          Result:=true;
        end
      else
       if AutoRun then
         begin
           RunExcel;
           MyExcel.WorkBooks.Add;
           Result:=true;
         end
       else
         Result:=false;
    end;

    Т.е. сразу проверяю запущен ли Excel и, если он не запущен, то либо запускаю и добавляю книгу, либо просто выхожу – всё зависит от ситуации.

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

    function GetAllWorkBooks:TStringList;
    var i:integer;
    begin
      try
        Result:=TStringList.Create;
        for i:=1 to MyExcel.WorkBooks.Count do
          Result.Add(MyExcel.WorkBooks.Item[i].FullName)
      except
        MessageBox(0,'Ошибка перечисления открытых книг','Ошибка',MB_OK+MB_ICONERROR);
      end;
    end;

    Функция возвращает список TStringList всех рабочих книг Excel открытых в данный момент. Обратите внимание, что в отличие от Delphi Excel присваивает первой книге индекс 1, а не 0 как это обычно делается в Delphi при работе, например, с теми же индексами в ComboBox’ах.

    Ну, и наконец, после того, как поработали с книгами – их требуется закрыть. Точнее сохранить, а потом уж закрыть.

    5. Сохраняем рабочую книгу и закрываем Excel

    Для того, чтобы сохранить рабочую книгу, я использовал такую функцию:

    function SaveWorkBook(FileName:TFileName; WBIndex:integer):boolean;
    begin
      try
        MyExcel.WorkBooks.Item[WBIndex].SaveAs(FileName);
        if MyExcel.WorkBooks.Item[WBIndex].Saved then
          Result:=true
        else
          Result:=false;
      except
        Result:=false;
      end;
    end;

    Если у Вас открыто 10 книг – просто вызываете функцию 10 раз, меняя значение параметра WBIndex и имени файла и дело в шляпе.

    А закрывается Excel вот так:

    function StopExcel:boolean;
    begin
      try
        if MyExcel.Visible then MyExcel.Visible:=false;
        MyExcel.Quit;
        MyExcel:=Unassigned;
        Result:=True;
      except
        Result:=false;
      end;
    end;

    Вот набор тех основных функций с которых начинается вся интеграция Excel в приложения написанные на Delphi. В следующий раз займемся работой с конкретной книгой – научимся записывать и читать данные из книг. А пока я готовлю новый материал, можете узнать, что такое свадьба в одессе.

    Файлы для загрузки

    Модуль uMyExcel

    Related posts:

    1. Excel в Delphi. Методы объекта WorkSheet (лист).
    2. Excel в Delphi. Работа с объектом Range (диапазон)
    3. Excel в Delphi. Работа со свойствами документа.
    4. Диаграммы Excel в Delphi. Общие сведения.
    5. Excel в Delphi. Свойства объекта WorkSheet.

    Автор Vlad в 5:57 pm

    Метки: ,

15 Comments

WP_Cloudy
  • Социальная сеть для блоггеров sloger.net пишет:

    Работа с Excel в Delphi. Основы основ. | Delphi в Internet…

    Рассматриваем основные функции для работы с Excel из Delphi…

  • webveter пишет:

    Если документ простой, но объемный – это будет медленно. А при большом количестве таких документов – жизнь пройдет мимо.
    Вывести в Excel можно и проще.
     

  • Vlad пишет:

    Что конкретно будет медленно? :) Запуск Excel или проверка установки Excel? Так тут ускорить процесс негде. Вывода в Excel-то пока в статье нет. Забегая вперед, могу сказать – выводить по-отдельности каждую ячейку – долго, муторно и не верно, но есть вариант как ускорить процесс в несколько десятков, а то и сотен раз.
    Да, и ещё – оставлять в комментариях ссылки не стоит. Блог и так DoFollow, кому надо – тот перейдет на ваш блог.

  • Иван пишет:

    Очень хорошие статьи. Разобрался во всём с первого раза ))) Понравилась схема в mind42 )))
    Автору остаётся сказать только спасибо!

  • Vlad пишет:

    не за что, Иван. Всегда рад помочь)

  • Алекс пишет:

    Все хорошо. Но если Excel не запущен – возникает исключение. Что с этим делать? function CheckExcelRun выбрасывает сообщение и все…Хотя по смыслу должно было вернуть False

  • Vlad пишет:

    Странно. Если Excel запущен, то должна создаваться вторая копия приложения без исключений. Код в студию :)

  • Мария пишет:

    Насчет процедуры CheckExcelRun. Если программа запускается из под Delphi и Excel не запущен, то выскакивает ошибка: Операция GetActiveOleObject недоступна. Если програма запускается не из под Delphi то все в порядке. Наверное эту проблему имел ввиду Алекс. Как решение можно при отладке программы когда возникает исключение нажимать F9.

  • underchronos пишет:

    Собственное говоря, а как при таком связывании отследить “сообщения” от Excel? Например, юзер “случайным” образом закрывает рабочую книгу, а программа все еще “хочет” работать с ней.

  • Vlad пишет:

    Честно говоря, никогда не задумывался о том как отловить сообщение от Excel и возможно ли то сдела вообще. Обычно в случае работы с книгами Excel или документами Word просто не забывал пользоваться try..except..end :) По-моему в данном случае можно покапаться в событиях Excel.

  • Динар пишет:

    произвожу экспорт в excel из delphi, все проходит как бы ровно. а неровность заключается в том что после экспорта остается жить процесс “excel.exe”. пытался юзать (Excel.Quit; Excel:=Unassigned;) не хочет помогать. помогите плиз люди добрые

  • Vlad пишет:

    Вы точно один раз запускаете процесс?
    Excel.Quit; – выход из приложения
    Excel:=Unassigned; – освобождение переменной
    Этих строк 100% достаточно, чтобы завершить процесс правильно.

  • Виноградная Лиса пишет:

    Вобще очень крутая статья! Долго мучался очень я)
    Не компилируется функция Save, “FileName:TFileName” вот этот кусок. Откуда это берется?

  • SeregaAltmer пишет:

    По сабжу пока не работал, но скорее всего либо перменная FileName уже объявлена, либо тип TFileName из модуля SysUtils, где-то переопределен.

    Сообщение компилятора приведите без него только догадки строить остается.

  • SeregaAltmer пишет:

    Готовый модуль скачать не удалось… какието глюки на айфолдерс.
    Написал по “инструкции” в посте. Все работает без проблем.

Ваш ответ

Внимание: Все комментарии модерируются, и это может вызвать задержку их публикации. Отправлять комментарий заново не требуется.

Пожалуйста, заключайте исходный код в тэги [code][/code].