Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Создание САПР на базе продуктов Autodesk


Информационный Канал Subscribe.Ru


Информационная рассылка сайта [CadDev.Narod.Ru]

(с) 2004, Калугин Сергей Сергеевич

По просьбам активистов ...

Сегодняшняя и несколько последующих рассылок будут связаны не совсем с тематикой разработки CAD.
Будут рассмотрены вопросы интеграции приложений, что тоже относится к некторым подсистемам САПР.

В этом номере:


Компоненты ADO

Дмитрий Ю. Сидоров

В Delphi 5.0 появились компоненты для работы с Microsoft® ActiveX® Data Objects (далее ADO). ADO это технология стандартного обращения к реляционным данным от Microsoft. Эта технология аналогична BDE по назначению и довольно близка по возможностям.

Следует отличать компоненты Delphi, являющиеся частью библиотеки визуальных компонентов Delphi (VCL), и интерфейсы и объекты ADO, которые в них инкапсулированы. В дальнейшем, когда упоминается компонент – это компонент Delphi, а когда объект или интерфейс – это объект или интерфейс ADO.

Обзор компонент

Для работы с ADO на вкладке компонентов ADO есть шесть компонентов: TADOConnection, TADOCommand, TADODataSet, TADOTable, TADOQuery, TADOStoredProc.

Рис. 0. Палитра компонент ADO

  • TADOConnection аналогичен компоненту BDE TDatabase и используется для указания базы данных и работы транзакциями.
  • TADOTable – таблица доступная через ADO.
  • TADOQuery – запрос к базе данных. Это может быть как запрос, в результате которого возвращаются данные и базы (например, SELECT), так и запрос, не возвращающий данных (например, INSERT).
  • TADOStoredProc – вызов хранимой процедуры. В отличие от BDE и InterBase хранимые процедуры в ADO могут возвращать набор данных, поэтому компонент данного типа является потомком от TDataSet, и может выступать источником данных в компонентах типа TDataSource*.
  • TADOCommand и TADODataSet являются наиболее общими компонентами для работы с ADO, но и наиболее сложными в работе. Оба компонента позволяют выполнять команды на языке провайдера данных (так в ADO называется драйвер базы данных).

Разница между ними в том, что команда, исполняемая через TADODataSet, должна возвращать набор данных и этот компонент позволяет работать с ними средствами Delphi (например, привязать компонент типа TDataSource). А компонент TADOCommand позволяет исполнять команды не возвращающие набор данных, но не имеет штатных средств Delphi для последующего использования возвращенного набора данных.

Очевидно, что все компоненты должны связываться с базой данных. Делается это двумя способами либо через компонент TADOConnection либо прямым указанием базы данных в остальных компонентах. К TADOConnection остальные компоненты привязываются с помощью свойства Connection, к базе данных напрямую через свойство ConnectionString.

База данных может быть указана двумя способами через файл линка к данным (файл в формате Microsoft Data Link, расширение UDL), либо прямым заданием параметров соединения.

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

Рис. 1.

При выборе “Use data link file” и нажатии на кнопку “Browse…” появляется стандартный диалог выбора файла. Этот файл можно создать в любом окне explorer-а (в этом окне открытия файла, в самом explorer, на desktop и т.д.) вызвав контекстное меню и выбрав пункт “New/Microsoft Data Link”. Потом вызовите локальное меню для созданного файла и выберите в нем пункт “Open”. После этого появится property sheet описанный чуть ниже. Эти же вкладки содержит и property sheet, вызываемый через пункт “Property” локального меню UDL файла, но в нем еще есть вкладки относящиеся к самому файлу.

Использование файлов Microsoft Data Link упрощает поддержку приложений, так как возможно использовать средства Windows для настройки приложения.

При выборе в редакторе свойства “Use connection string” и нажатии на кнопку “Build…” появляется такой же property sheet, как и при выборе “Open” для Microsoft Data Link файла.

В этом окне выбирается тип базы данных, местоположение базы и параметры соединения.

На первой странице выбирается тип базы данных или Provider, в терминах ADO.

Рис. 2.

Базы MS Access доступны как через “Microsoft Jet OLE DB Provider”, так и через “Microsoft OLE DB Provider for ODBC”.

Следующая страница зависит от выбранного типа базы, однако для всех типов есть кнопка “Test connection” позволяющая проверить правильность и полноту параметров.

Для “Microsoft Jet OLE DB Provider” она выглядит так:

Рис. 3.

Checkbox “Blank password” подавляет диалог ввода идентификатора и пароля пользователя при установлении соединения, если поле пароля пустое.

Checkbox “Allow saving password” сохраняет пароль в строке параметров соединения. Если он не отмечен, то введенный пароль будет использоваться только при выполнении тестового соединения.

Для “Microsoft OLE DB Provider for ODBC” эта страница выглядит так:

 

Рис. 4.

Радиокнопка “Use data source name” позволяет ввести предустановленный алиас ODBC, а через “Use connection string” вводится как алиасы так и тип ODBC драйвера и параметры соединения.

Параметры идентификации пользователя аналогичны выше описанным.

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

Рис. 5.

На странице “All” можно отредактировать все параметры с предыдущих страниц и параметры зависящие от провайдера, но не вошедшие на страницу “Connection”. Редактирование осуществляется в виде параметр – значение, причем в текстовой форме, никаких диалогов нет. Помощи то же нет, эти параметры описаны только в документации на провайдер. Ее можно найти в MSDN Data Access Services/Microsoft Data Access Components (MDAC) SDK/Microsoft ActiveX Data Objects (ADO)/Microsoft ADO Programmer's Reference/Using Providers with ADO.

Рис. 6.

В компоненте TADOConnection есть свойства Provider, DefaultDatabase и Mode которые являются альтернативным методом задания частей строки параметров соединения – провайдера, базы данных (например, пути до базы MS Access) и режима совместного использования файлов базы данных. Эти значение этих свойств автоматически включаются в строку соединения, если были заданы до активизации компонента и автоматически выставляются после соединения.

* Прим. ред. Компоненты StoredProc (и BDE и IB) могут возвращать набор данных, являются потомками TDataSet и могут выступать источником данных в компонентах типа TdataSource.


 

По волнам интеграции…

Евгений Старостин



Я родом из DOS. Кто-нибудь помнит, что это такое? Кто-нибудь помнит те компьютеры, на которых это крутилось? А какие усилия прилагались для того, чтобы сделать программу с минимальными требованиями к памяти и диску. Как использовали сначала EMS, а потом XMS с одной единственной целью - оптимизация. Много времени с тех пор прошло (старею что ли?).
Сейчас другие времена (наконец-то!). Кругом Win32, OLE, пара-тройка гигабайт на процесс, «безразмерные» диски. Кто сейчас придает значение лишним четырем килобайтам? Сотня килобайт - туда, сотня - сюда. Вот и я сейчас буду утверждать, что интеграция приложений (мегабайты потерь оперативной памяти) - это правильно. Да, наверно это правильно, когда ты начинаешь использовать функциональность программ, которых ты не писал. Просто, эти самые программы умеют больше, чем можешь ты сам. А аналог написать слабо - пару лет попыхтишь и на пенсию по несостоятельности (мне уже давно пора!).

А зачем оно нужно?

Собственно, цель этой статьи мне понятна - поделиться своим опытом с народом. Делюсь…

Итак, зачем нам, лучшим в мире программистам, нужен Excel, порождение "злого" гения Microsoft? Конечно, часто это лишнее - «юзать» Excel для отчетов. Напечатать «платежку» можно и в QReport-е. Но…

Есть заказчики, готовые отдать «кучищи» денег за то, что они будут знать все и всегда о своем предприятии. Да еще, чтоб это было красиво и со вкусом.

Приезжает один из моих заказчиков (немец - они повсюду! курорты Испании просто куплены ими - это знаю наверняка) на свое местное предприятие и начинает задавать интересные вопросы. Как трудились за время его отсутствия, сколько продукции выпустили, кому сколько отгрузили, в разных валютах, итого в USD и пр.? А я ему в ответ открываю отчет, неслабый такой, - сводная таблица по движению готовой продукции (посвященные знают, что это 40-ой счет в бухгалтерии). А в ней одних PageField-ов десяток. И на каждый его вопрос я начинаю отвечать не напрягаясь, потихоньку перетаскивая поля таблицы туда-сюда, фильтрую кое-что, строю диаграммы. Что, вы думаете, было потом? Он, как маленький ребенок, сидел за этой сводной таблицей несколько часов, все восхищался. И правильно, наши программисты круче ихних! Заодно и мы спокойно поработали (ему занятие нашлось). О деньгах тут вообще не говорим.

Потом я ему показал, как эту самую сводную таблицу в Сеть можно опубликовать. Сейчас просит, чтоб ему доступ из Германии сделали к этой табличке. Мы, конечно, рады стараться.

Я бы привел еще несколько примеров, но, думаю, читатели уже поняли меня. Excel - вещь практически незаменимая во всяческих анализах (не путать с поликлиникой). А для тех, кто не понял, я еще напишу. Отдельно.

Так как же с ним работать?

А просто. Создал "Excel.Application", использовал его по назначению, "убил" и готово. Вот именно об этом я и попытаюсь написать здесь.

Важно!


Параллельно с написанием статьи создавался демо-проект (точнее два - для Delphi 4 и 5), где вы сможете найти весь код примеров статьи. Проект для Delphi 4.0 использует импортированную Type Library из Excel 97. Здесь я использую ранее связывание, ибо CreateOLEObject отлично описал мой любимый классик в "Delphi 4 Unleashed" (мне ли с ним тягаться?). Кроме того, обращайтесь к комментариям в исходных текстах этого проекта. Местами там написано намного понятней, нежели здесь. Delphi 5 содержит более удобный механизм импорта библиотек типов с поддержкой событий и прекрасной генерацией ко-классов. Специально для счастливых обладателей Delphi 5 (я тоже им являюсь) я создал проект, но уже применительно к TexcelApplication (правда ли, что импортированный MS Office есть только в версии Enterprise?). Примеры кода я буду приводить сначала для Delphi 4, потом для Delphi 5. Заранее приношу прощения за дублирование информации в комментариях и в статье - писал сразу везде.
И еще. Эффективная работа с Excel-ом из Delphi-приложений немыслима без знания одной важной вещи. И имя ей - интерфейс. Мне, конечно, хотелось бы написать о принципах работы с интерфейсами здесь, в этой статье. Более того, я обещал сделать это самой Королеве. Но…
Мне ли (совсем еще не профессионалу - и это так!) пытаться сделать это лучше, чем классики этой области. Я честно признаюсь, что не смогу этого сделать быстро (в небольшом объеме) и качественно. Поэтому всякого, не знакомого еще с этой областью программирования, я с глубочайшими извинениями отсылаю к книге Чеппела "OLE Inside".
Достойную помощь (уже применительно к Delphi) может вам оказать "Delphi 4 Unleashed" Чарльза Калверта.

Создание экземпляра Excel.Application.

Модуль импортированной Excel TLB (неважно, для D4 или D5) содержит описания всех интерфейсов, которые правильные программисты из Microsoft решили выставить наружу. Там есть все необходимое: типы, константы и интерфейсы. Этого вполне достаточно для работы с Excel-ом из Delphi-приложения (во написал! а что еще нужно-то?). Я создаю Excel для последующего его использования с помощью такого кода:

Delphi 4.0

procedure TForm1.CreateExcel(NewInstance: boolean);
var IU: IUnknown;
    isCreate: boolean;
begin
  // FIXLSApp - private-поле у формы
  //            у меня в привычке добавлять букву I для всех интерфейсов
  //            понятно почему FI… ?
  if not Assigned(FIXLSApp) then begin // а зачем создавать, если уже есть?
    isCreate := NewInstance or
      (not SUCCEEDED( GetActiveObject(CLASS_Application_, nil, IU) ) );
    if isCreate then
      FIXLSApp := CreateComObject(CLASS_Application_) as _Application
    else
      FIXLSApp := IU as _Application;
  end;
end;

Этот достаточно простой код вы найдете практически во всех книгах, посвященных работе с интерфейсами. Как и везде, я напишу, что в результате выполнения этого кода создастся объект COM с CLSID-ом «{00024500-0000-0000-C000-000000000046}» (читайте и перечитывайте Калверта, это не только укрепляет сон!).

Delphi 5.0

procedure TForm1.CreateExcel(NewInstance: boolean);
begin
  if not Assigned(IXLSApp) then begin
    FIXLSApp := TExcelApplication.Create(Self);
    if NewInstance then FIXLSApp.ConnectKind := ckNewInstance;
    FIXLSApp.Connect;
  end;
end;

В отличие от предыдущих версий, Delphi 5.0 предоставляет более удобный сервис при импорте библиотек типов. Большой шаг вперед - появление класса ToleServer с поддержкой событий. Теперь работа с существующими и создание новых OLE-серверов стала намного удобней. Как видите, не приходится обращаться к низкоуровневым функциям. Впрочем, в Delphi 4.0 тоже существовал этот класс, только не от Borland. Отличная библиотека была создана Бином Ли (Binh Ly) в COM Nodes - это Threading COM Library. С легкой руки Алексея Вуколова (специальное спасибо!) я использовал ее для построения масштабируемых COM-серверов в сервисах WinNT.

Обращу ваше внимание только на параметр NewInstance. Он позволяет создать новый процесс. Я часто задаю себе вопрос - "А нужен ли NewInstance?". Одна копия процесса, все ж, требует меньше памяти. Но еще чаще я думаю - "Боже, как хорошо я сделал, когда создал новый процесс!". Почему? Если вы не хотите потерять уже открытые, но еще не сохраненные книги, экспериментируя даже с моими примерами, создавайте новый процесс. Печальный опыт научил меня использовать GetActiveObject только в случае полной уверенности в коде, который будет выполняться после. Поэтому, мой вам совет, тестируйте свои приложения только с NewInstance. Или закрывайте важные книги пред этим. Excel - хитрая программа, бывает, улетает в неизвестность, ни слова не сказав. Это не вина Microsoft. Это неудачное расположение звезд.

Как показать Excel, если он, разумеется, создан?

Вот здесь начинаются хитрости. Любой, читавший помощь по Excel VBA, скажет, что достаточно написать FIXLSApp.Visible := true. Не тут-то было. Я делаю так:

Delphi 4.0 / 5.0

procedure TForm1.ShowExcel;
begin
  if Assigned(FIXLSApp) then begin // а если он не создан?
    FIXLSApp.Visible[0] := true;
    if FIXLSApp.WindowState[0] = TOLEEnum(xlMinimized) then
      FIXLSApp.WindowState[0] := TOLEEnum(xlNormal);
    FIXLSApp.ScreenUpdating[0] := true;
  end;
end;

Зачем здесь условие на минимайз и какой-то ScreenUpdating? Давайте попробуем закомментировать эти строки, остаиви только Visible, запустить проект, создать Excel (кнопка CreateExcel), показать его (кнопка ShowExcel), минимизировать, вернуться в приложение и сделать снова ShowExcel. Да-да, Visible = true переводит фокус в минимизированный Excel, не восстанавливая размеры окна. Это ситуация, с которой я борюсь условием на xlMinimized. Но ScreenUpdating зачем?

Знающие люди говорят, что это свойство отвечает за перерисовку окон Excel. Это все равно, что DisableControls у TDataSet. Добавляет скорости, если в нем false. И это правда что, если выключить его во время длительных пересчетов, то быстрее пересчитается. Но мы, ведь, не выключали его. Зачем тогда эта строка?

Делаем так: комметируем эту строку, запускаем демо, CreateExcel, ShowExcel, закрываем его (можно кнопкой с крестиком в правом верхнем углу окна, кому нравится - через меню "Файл/Выход"). Знающие люди скажут, что Excel на самом деле не закрыт. Интерфейс мы не освободили, поэтому в TaskManager мы его и увидим. Итак, Excel по-прежнему у нас в руках. Мы имеем право сделать ему снова Show.

После такого действия у меня возникает ощущение, что я переплатил за свою видеокарту. Фокус в Excel-е, но я по-прежнему наблюдаю форму демо-проекта. Видимо, программисты из MS не рассчитывали на то, что кто-то закроет Excel, вызванный через создание Excel.Application, а потом захочет увидеть его снова. Но я-то захотел?!

Свойства Visible, WindowState и ScreenUpdating вызываются с каким-то непонятным индексом массива - 0. В модуле Excel TLB во многих свойствах и методах вы можете встретить параметр или индекс lcid. Не помню, у кого я это прочитал (Калверт или Канту), но с тех пор я туда передаю всегда 0. И все работает. LCID - это что-то насчет локализации. В MSDN написано "Indicates that the parameter is a locale ID (LCID)".

Спрячем Excel от посторонних глаз!

На свой процесс я всегда создаю один экземпляр Excel.Application. Уже пару лет все отчеты у меня - это отчеты Excel. Я написал несколько классов, которые мне очень помогают в этом. Сегодня у меня целая «отчетная» подсистема, зашитая в класс и обслуживающая непомерно большие запросы моих пользователей. В промежутках между работой с отчетами нет необходимости «мозолить глаза» лишним окном в TaskBar-е. Вот и прячу я этот Excel. Это очень просто и комментариев, думаю, не требует:

Delphi 4.0 / 5.0

procedure TForm1.HideExcel;
begin
  if Assigned(FIXLSApp) then begin
    FIXLSApp.Visible[0] := false;
  end;
end;

 

Закроем Excel корректно!

Собственно говоря, при закрытии приложения Excel сам будет закрыт, если вы там не устели чего-нибудь отредактировать. И это правильно. Программисты Borland (Inprise до сих пор мне режет слух, да и некоторым в Inprise, судя по всему, тоже) позаботились об этом. Но я еще с Delphi 3 заимел дурную привычку освобождать все самостоятельно. Освобождать обычным присваиванием в nil (это касается проекта для D4). Труда это не составляет, да и проверка на Assigned удобна. Поэтому, и еще из кое-каких соображений, я делаю так:

Delphi 4.0

procedure TForm1.ReleaseExcel;
begin
  if Assigned(FIXLSApp) then begin
    if (FIXLSApp.Workbooks.Count > 0) and (not FIXLSApp.Visible[0]) then begin
      FIXLSApp.WindowState[0] := TOLEEnum(xlMinimized);
      FIXLSApp.Visible[0] := true;
      Application.BringToFront;
    end;
 end;
  FIXLSApp := nil;
end;

Ну вот, написал только про nil, а кода - на полстраницы. Опишу ситуацию.
Вы не запускали новый процесс, вы «законнектились» к уже существовавшему. В нем была открыта книга. Попробуйте: CreateExcel, ShowExcel, HideExcel (имеем право), ReleaseExcel. Если оставить только присваивание в nil, то существовавший процесс не будет выгружен (он же существовал до запуска нашего демо), но будет спрятан от пользователя с его открытой книгой.

Delphi 5.0

procedure TForm1.ReleaseExcel;
begin
  if Assigned(IXLSApp) then begin
    if (IXLSApp.Workbooks.Count > 0) and (not IXLSApp.Visible[0]) then begin
      IXLSApp.WindowState[0] := TOLEEnum(xlMinimized);
      IXLSApp.Visible[0] := true;
      if not(csDestroying in ComponentState) then Self.SetFocus;
      Application.BringToFront;
    end;
  end;
  FreeAndNil(FIXLSApp);
end;

Практически тот же код. Только в D5 вы работаете уже не с интерфейсом напрямую, а с экземпляром класса TexcelApplcation. Если посмотреть его предков, то можно увидеть, что это настоящий класс, освободить который просто необходимо. Поэтому вместо присваивания в nil там написано FreeAndNil (помните такую процедуру?).

Лучшее решение - шаблоны

Excel, интегрированный с моими приложениями, хорош (для меня - программиста) только по одной причине. Я всегда создаю шаблоны и использую их потом при построении отчетов. Шаблоны позволяют мне избежать ручного (в исходном тексте) форматирования. В общем случае, алгоритм выглядит просто: по шаблону создается книга, каким-то образом помеченные области заполняются данными и… (а дальше все уже готово). Как я создаю книгу по шаблону:

Delphi 4.0 / 5.0

function TForm1.AddWorkbook(const WorkbookName: string): Excel8TLB._Workbook;
begin
  Result := nil;
  if Assigned(FIXLSApp) and (trim(WorkbookName) <> '') then begin
    Result := FIXLSApp.Workbooks.Add(WorkbookName, 0);
  end;
end;

В этом коде нет ничего сложного. В принципе при работе с Excel я мало находил мест, где что-либо сделать было бы сложно. Чаще достаточно прочитать справку по VBA или записать макрос (благо, Microsoft встроила в Excel хороший пишущий player). После выполнения этого метода будет добавлена книга, близнец шаблона, с именем шаблона и порядковым номером (как "Книга1.xls" или "Книга228.xls"). Правда здесь есть одна тонкость. Эти «циферки» в имя книги Excel добавляет после поиска книг с таким же названием в каталоге по умолчанию. Я несколько раз наступал на грабли (больно!), когда пытался сохранять книги в другом каталоге и создавать новую - по этому же шаблону. К сожалению, не может эта «злобная» программа держать открытыми несколько книг с одинаковыми названиями, несмотря на то, что они лежат в разных каталогах.

Data Range

Как я помечаю области, в которые необходимо разместить данные? В Excel существует возможность объединить ячейки в группу и поименовать эту группу. В терминах Microsoft это объект Range (область). Для своего проекта я создал тестовую книгу "Test.xls", в которой на листе "Лист1" разместил область "TestRange" (см. рисунок). Более того, для ячеек этой области я указал форматы вывода (Field4 - дата, Field3 - красный цвет шрифта). Я надеюсь, что после переноса тестовых данных форматы сохранятся.

Что есть шаблон без данных в нем?

Существует масса способов передать данные в Excel, начиная с DDE и заканчивая обычным присваиванием (типа Cell.Value := NewValue ). Конечно, максимальную скорость передачи данных можно получить, только используя DDE. Но я отказался от этого пути из-за некоторых ограничений и давно смущающего меня флажка в настройках Excel ("Игнорировать DDE-запросы"). Поэтому здесь я опишу менее эффективный, но работоспособный, путь решения этой проблемы. Итак, после нажатия кнопки CreateExcel имеем открытый шаблон с листом "Лист1" и областью с именем "TestRange". Для чистоты эксперимента (скорей из лени, великая вещь - собственная лень) я описал константный массив с тестовыми данными - TestDataArray. Именно эти данные я и передаю в ячейки области:

Delphi 4.0

procedure TForm1.btnDataToBookClick(Sender: TObject);
var LaunchDir: string;
    IWorkbook: Excel8TLB._Workbook;
    ISheet: Excel8TLB._Worksheet;
    IRange: Excel8TLB.Range;
    NewValueArray, V: OLEVariant;
   i: integer;
begin
  if Assigned(IXLSApp) then begin
    LaunchDir := ExtractFilePath( ParamStr(0) );
    IWorkbook := AddWorkbook( LaunchDir + 'Test.xls' );
    try
      ISheet := IWorkbook.Worksheets.Item['Лист1'] as Excel8TLB._Worksheet;
      IRange := ISheet.Range['TestRange', EmptyParam];
      NewValueArray := VarArrayCreate([0, 20, 1, 4], varVariant);
      for i := 0 to 20 do begin
        NewValueArray[i, 1] := TestDataArray[i].V1;
        NewValueArray[i, 2] := TestDataArray[i].V2;
        NewValueArray[i, 3] := TestDataArray[i].V3;
        NewValueArray[i, 4] := date + i;
      end;
      IRange.Value := NewValueArray;
    finally
      IRange := nil;
      ISheet := nil;
      IWorkbook := nil;
    end;
  end;
end;

Delphi 5.0

procedure TForm1.btnDataClick(Sender: TObject);
type
var LaunchDir: string;
    IWorkbook: Excel97.ExcelWorkbook;
    ISheet: Excel97.ExcelWorksheet;
    IRange: Excel97.Range;
    NewValueArray, V: OLEVariant;
    i: integer;
begin
  if Assigned(IXLSApp) then begin
    LaunchDir := ExtractFilePath( ParamStr(0) );
    IWorkbook := AddWorkbook( LaunchDir + 'Test.xls' );
    try
      ISheet := IWorkbook.Worksheets.Item['Лист1'] as Excel97.ExcelWorksheet;
      IRange := ISheet.Range['TestRange', EmptyParam];
      NewValueArray := VarArrayCreate([0, 20, 1, 4], varVariant);
      for i := 0 to 20 do begin
        NewValueArray[i, 1] := TestDataArray[i].V1;
        NewValueArray[i, 2] := TestDataArray[i].V2;
        NewValueArray[i, 3] := TestDataArray[i].V3;
        NewValueArray[i, 4] := date + i;
      end;
      IRange.Value := NewValueArray;
    finally
      IRange := nil;
      ISheet := nil;
      IWorkbook := nil;
    end;
  end;
end;

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

To be continue…

Excel - занимательная программа. Я давно с ней. Библиотека типов Excel громадна, как «Титаник» (хорошо, что не тонет). Я отдаю должное программистам, создавшим этот не менее замечательный, чем Delphi, продукт. И в одну статью все, что хочется написать, не вместишь (почему-то у меня уже шесть листов? Знаю, я слишком многословен). Поэтому ругайте меня и ждите продолжения…

Проект для Delphi 4. - D4Sample.zip (133 K)
Проект для Delphi 5. - D5Sample.zip (8 K)

 


http://subscribe.ru/
E-mail: ask@subscribe.ru
Отписаться
Убрать рекламу


В избранное