RAD Studio 10 Seattle Update 1

   Embarcadero Technologies выпустила первое обновление RAD Studio 10 Seattle. Оно исправляет несколько сотен ошибок, подробнее… В этой бочке мёда не обошлось без ложки дёгтя: это обновление только для владельцев RAD Studio 10 Seattle с лицензией «Update Subscription» (в менеджере лицензий в описании лицензии должен быть пункт «Is Subscription»). Таким образом, остальные покупатели RAD Studio 10 — в пролете, и после установки этого обновления будут вынуждены поставить старую версию.

Delphi 10 Seattle Web Install (includes Update 1)
C++Builder 10 Seattle Web Install (includes Update 1)
RAD Studio 10 Seattle Web Install (includes Update 1)

Читать на сайте автора.

Изучайте используемый инструментарий!

   Вчера начал разбираться с чужим проектом на Delphi 7. Система весьма сложная – несколько взаимосвязанных АРМов по 20-50 форм (а может и больше, точно не считал). Усложняет все то, что она разрабатывается уже давно и пережила смену нескольких команд разработчиков.

Читать на сайте автора.

Idera Inc покупает Embarcadero Technologies

   Слухи о том, что компания Idera, Inc покупает компанию Embarcadero Technologies, которые появились на форумах и в блогах в середине сентября подтвердились. Вчера инвестиционная компания Thoma Bravo, LLC опубликовала об этом событии свой пресс-релиз. А немного позже был опубликован и официальный пресс-релиз «Idera Announces Intent to Acquire Embarcadero, Expands Position in Database Management and Developer Tools Markets«.
   Вот и закончился семилетний период жизни нашего любимого Delphi в компании Embarcadero Technologies. За это время было сделано 11 релизов Delphi:

  • Delphi 2009 (25 августа 2008) — полная поддержка unicode; новые элементы языков программирования (например, Generics); обновление VCL…
  • Delphi 2010 (25 августа 2009) — повышение производительности; поддержка Windows 7 API, Direct2D и мультисенсорного ввода; IDE Insight; расширение RTTI…
  • Delphi XE (30 августа 2010) – новые возможности VCL, RTL и Open Tools API; доработки в редакторе кода; обновление DataSnap…
  • Delphi XE2 (1 сентября 2011) – поддержка Windows 64, Mac OS X и iOS; кросс-платформенная библиотека FireMonkey; библиотека LiveBindings; улучшения в технологии DataSnap…
  • Delphi XE3 (3 сентября 2012) – поддержка Windows 8; улучшенная поддержка Apple Mac OS X; Firemonkey 2/FM²; удалена поддержка iOS…
  • Delphi XE4 (22 апреля 2013 ) – вернулась поддержка iOS; функционал для разработки мобильных приложений (iPhone и iPad); улучшено взаимодействие с базами данных…
  • Delphi XE5 (11 сентября 2013) — поддержка разработки ПО для устройств с архитектурой ARM, работающих под управлением Android…
  • Delphi XE6 (15 апреля 2014) — исправлены сотни ошибок; новые компоненты (Application Tethering Components, Taskbar component, компоненты для работы с датчиками (акселерометр, GPS и гироскоп)…), взаимодействие с сервисами в облаках (BaaS); возможность создания приложений для Google Glass; новые иконки в IDE…
  • Delphi XE7 (2 сентября 2014) – изменения в RTL и FireMonkey, удалены компоненты для работы с BDE…
  • Delphi XE8 (7 апреля 2015) — поддержка iOS 64; в IDE интегрирована новая система контроля версий Mercurial Version Control System; добавлены два новых независящих от платформы типа данных (FixedInt и FixedUInt)…
  • Delphi 10 Seattle (31 августа 2015) — поддержка Windows 10, iOS 8.4, Android 5.1.1, API WinRT, DirectX 12; новые компоненты…

Как видите, программисты компании Embarcadero трудились над развитием Delphi в стиле «ни дня без строчки», т.е. «ни года без релиза». Для сравнения компания Borland за 13 лет (с 1995-го по 2008-й), если не считать «мертворожденных» Kylix и Delphi 8.NET, были сделаны всего 10 резов Delphi. Хотя авторство Delphi 2009 спорно, т.к. эта версия была выпущена Embarcadero всего через несколько месяцев после покупки компании Borland. По большому счету, не важно, какая компания разрабатывает Delphi (скорбим только о Borland). Важно то, чтобы команда разработчиков Delphi дружной толпой, не снижая набранного темпа, продолжила работу над своим проектом под крышей Idera, а компания Idera уделяла больше внимания и средств на дальнейшее развитие и продвижение Delphi.

Читать на сайте автора.

FastReport VCL 5. Улучшение интерактивности

   Интерактивные отчеты позволяют определить в отчёте действие, которое произойдет при щелчке мыши на каком-нибудь объекте отчета в окне предварительного просмотра. В предыдущих версиях FastReport существовало несколько способов сделать отчет интерактивным.
   Например, самый универсальный способ — это создать обработчик события OnClick. Этот обработчик может быть двух типов:

  • глобальный — обработчик события для всех объектов отчета TfrxReport.OnClickObject: TfrxClickObjectEvent;
  • локальный — обработчик события для отдельного объекта отчета TfrxReportComponent. OnPreviewClick: TfrxPreviewClickEvent.

Этот способ позволяет программным образом управлять реакцией на щелчок мыши по объектам в предварительном просмотре и ограничивается только фантазией программиста/пользователя и возможностями языка программирования.
   Сделать отчет интерактивным в FastReport можно и без написания кода. Например, можно использовать «разворачиваемые» группы. У заголовка группы есть свойство DrillDown. Включение этого свойства позволяет сделать группу интерактивной. Это означает, что группа будет реагировать на щелчок мышью в окне предварительного просмотра. Щелкнув мышью на заголовке группы, ее можно развернуть (показать все ее записи) или свернуть (скрыть все ее записи), оставив только заголовок и, при необходимости, подвал.
   В FastReport VCL 5 был добавлен еще один способ управления интерактивностью отчетов без написания кода — объекту TfrxView добавили свойство Hyperlink: TfrxHyperlink (далее «гиперссылка»). Это свойство пришло на смену свойству TfrxView.URL из FastReport 4 и расширило его возможности.
   У TfrxHyperlink есть два основных свойства — Kind и Value, и несколько вспомогательных — ValuesSeparator, ReportVariable, Expression, DetailPage, DetailReport.
   Свойство Kind — это вид гиперссылки. Оно имеет тип TfrxHyperlinkKind и может принимать следующие значения:

  • hkURL — строка для запуска в ShellExecute (ссылка на сайт, документ, программу…);
  • hkAnchor — якорь (специальная именная метка, по которой определяется номер страницы и позиция на странице для перехода по гиперссылке; ее, например, удобно использовать для создания страницы с содержанием отчета);
  • hkPageNumber — номер страницы;
  • hkDetailPage — дополнительные страницы отчета (например, скрытая страница шаблона с детальным отчетом);
  • hkDetailReport — дополнительный отчет;
  • hkCustom — свойство Hyperlink игнорируется (например, если необходимо обработать только OnPreviewClick).


   Свойство Value содержит значение, которое используется для перехода по клику на гиперссылку. Например, в нём можно указать имя якоря при Kind=hkAnchor, строку для запуска в ShellExecute при Kind=hkURL, номер страницы при Kind=hkPageNumber. Его значение может заполняться динамически с помощью формулы заданной в свойстве Expression.
   Свойство DetailPage содержит название страницы в текущем шаблоне. При Kind= hkDetailPage по клику на гиперссылку в диалоге предварительного просмотра открывается дополнительная закладка в которую загружается часть отчета, которая сформирована на основании страницы шаблона, имя которой указано в свойстве DetailPage.
   Свойство DetailReport содержит название шаблона в формате FastReport. При Kind=hkDetailReport по клику на гиперссылку в диалоге предварительного просмотра открывается дополнительная закладка, в которую загружается отчет сформированный по шаблону, указанному в свойстве DetailReport. При этом если в дополнительном отчете есть переменная с именем, указанным в свойстве ReportVariable, то ей присваивается значение свойства Value.
   Выше я писал, что свойство Hyperlink пришло на смену свойству URL, но свойство URL тоже можно использовать. Теперь изменение из скрипта свойства URL приведет к изменению свойств Kind и Value у Hyperlink по следующим правилам:

  • если первый символ свойства URL = ‘#’, то в гиперссылке будет якорь;
  • если первый символ свойства URL = ‘@’, то в гиперссылке будет номер страницы;
  • иначе в гиперссылке будет строка для запуска в ShellExecute.

Например, если в скрипте написать «Memo.URL := ‘@5’;», то свойство Memo.Kind будет равно hkPageNumber, а Memo.Value равно «5» и по клику мышкой по нему в предварительном просмотре отчета будет сделан переход на 5-ю страницу.
   Как мы видим, свойство Hyperlink в FastReport VCL 5 позволяет в предварительном просмотре с минимальными настройками управлять реакцией на щелчок мыши по объектам. Это свойство существенно расширило возможности создания интерактивных отчетов в FastReport и упростило этот процесс.

Читать на сайте автора.

FastReport. PDF-экспорт и встраивание шрифта

   В списке новшеств FastReport VCL 5 значится «В PDF-экспорт улучшено встраивание шрифтов: вместо целого шрифта встраивается только используемое в отчёте подмножество символов шрифтов. Это позволяет значительно сократить размер файла«. В своих программах я часто работаю с документами в PDF-формате, поэтому вопрос размера документа, экспортированного из FastReport в PDF-файл меня интересует.
   Много лет тому назад я делал программу, которая при добавлении записи в базу данных генерировала документ в FastRepot, экспортировала его в PDF-файл и отправляла по электронной почте. Из-за использования электронной почты передо мной стояла задача минимизации размера PDF-файла. Для этого я провел тестирование различных вариантов экспорта документа из FastReport в PDF-формат:

  1. экспорт с помощью библиотеки экспорта от сторонних производителей (например, RareFind FastReport Export Filters);
  2. экспорт с помощью входящего в FastReport класса TfrxPDFExport;
  3. экспорт с использованием библиотек для работы с PDF-файлами (например, llPDFLib).

В приведенном выше списке варианты экспорта расположены в порядке возрастания размера получаемого файла, а значит в порядке убывания ценности в рамках поставленной задачи. Поэтому мой выбор тогда пал на RareFind FastReport Export Filters. Но к моему сожалению, эта библиотека повторила судьбу многих библиотек для Delphi — она давно «умерла» (последняя версия вышла в феврале 2006). Я думаю, что в наше время и на перспективу стоит рассматривать только экспорт входящий в поставку FastReport, т.к. он «умрет» только вместе с FastReport.
   Для того, чтобы текст в PDF-документе выглядел одинаково на различных устройствах существует возможность встроить используемый шрифт в PDF-файл как ресурс. Если шрифт не встроен в PDF-документ, то Acrobat Reader попробует найти его на компьютере. Если шрифт найти не удалось, то Acrobat Reader попробует эмулировать его и текст будет читаемый, но документ будет выглядеть по-другому. Большинство программ для просмотра и печати документов в формате PDF этого делать не умеют. Поэтому единственная возможность всегда корректно отобразить PDF-документ — это встроить в него используемые шрифты. Единственным недостатком встраивания шрифта является существенное увеличение размера PDF-файла.
   TfrxPDFExport тоже умеет встраивать используемые шрифты в PDF-файл. Для этого у него есть свойство «EmbeddedFonts». Если оно True, то, согласно документации к FastReport 4, «все шрифты, использованные в отчете, будут также помещены в выходной файл PDF для корректного отображения файла на компьютере, где этих шрифтов может не быть, размер выходного файла значительно увеличивается«. Не зря автор документации выделил слова «значительно» жирным шрифтом. Экспорт в PDF со встроенными шрифтами в FastReport 3-4 увеличивал размер файла в десятки, а то и сотни раз (в зависимости от используемых шрифтов и их количества), сводя возможность его использования к нулю.
   После экскурса в теорию и историю, проверим как обстоят дела с размером файла у экспорта в PDF сейчас. Для этого я использовал три версии FastReport:

  • 4.11 — была установлена у меня на момент релиза FastReport VCL 5;
  • 4.15 — последняя версия FastReport VCL 4 на текущий момент;
  • 5.04 — текущая версия FastReport VCL 5.

   Результаты экспорта одностраничного документа, шаблон которого содержит MasterData с одним MemoView, у которого установлен шрифт «Arial» (размер файла в байтах):

Версия FastReport EmbeddedFonts=False EmbeddedFonts=True Увеличение в, раз
4.11 2 367 520 294 220
4.15 2 357 80 933 34
5.04 2 351 77 905 33

Размер полученного файла очень сильно зависит от встраиваемого шрифта. Например, если в этом шаблоне «Arial» заменить на «Times New Roman», то размер PDF-файла вырастет на 1%, а если «Arial» заменить на «Forte», то уменьшится в 10 раз.
   А вот результаты экспорта одностраничного документа, шаблон которого содержит MasterData с десятью MemoView, у каждого из которых установлен свой шрифт (размер файла в байтах):

Версия FastReport EmbeddedFonts=False EmbeddedFonts=True Увеличение в, раз
4.11 13 316 9 762 210 733
4.15 13 386 750 136 56
5.04 13 307 730 183 55

   Видно, что от версии к версии размер получаемого PDF-файла без встраивания шрифтов почти не меняется. Чего не скажешь о размере PDF-файла со встроенными шрифтами. Экспорт в FastReport 4.11 справляется с этим значительно хуже новой версии. Но почему у версий 4.15 и 5.04 получился такой похожий результат? оО Сравнив содержимое frxExportPDF.pas этих версий легко убедиться, что они почти совпадают. Оказывается, «по просьбам трудящихся» разработчики FastReport включили экспорт в PDF из первого релиза FastReport VCL 5 в последнюю версию FastReport VCL 4.
   Итак, новый экспорт документов из FastReport в формат PDF, разработанный для FastReport VCL 5, создает файлы меньшего размера, чем экспорт предыдущих версий. Если при экспорте в PDF без встраивания шрифтов, эта разница еле заметна, то при экспорте в PDF со встраиванием шрифтов файлы получаются меньше в 6,5 раз для документа с одним шрифтом и более чем в 13 раз для документа, содержащего в себе 10 шрифтов.

Читать на сайте автора.

FastReport VCL 5. Мы уже не ждали, а он припёрся

   Вчера вечером, разгребая спам, я наткнулся на письмо от FastReports, Inc с темой «Внезапно релиз FastReport VCL 5». О как! Мы уже и не ждали, а он припёрся. Тут же в голове возникла знаменитая фраза, которую сказал дедушка Ленин 7 ноября 1917 года: «Товарищи! Рабочая и крестьянская революция, о необходимости которой всё время говорили большевики, свершилась! «. Спросите: «Почему такая реакция? «. Для тех, кто не в теме расскажу предысторию этого события.
   О работе над FastReport 5 говорили еще лет 7-8 тому назад. Потом ходили только слухи о том, что работа над новой версией идёт. Но куда идёт, и какими темпами официально не сообщалось. Завеса тайны приоткрылась только в начале лета 2010 года. Был опубликован примерный функционал FastReport VCL 5 и назначен её выпуск на осень. Пришла осень…, закончился сентябрь…, октябрь…, близился к концу ноябрь…, а релиза все нет. В последний день осени вместо пресс-релиза о выпуске FastReport 5 компания FastReports, Inc сообщила:

Мы приняли решение перенести релиз FastReport VCL 5 на начало 2011-го года. Работы над FastReport VCL v.5 и FastCube VCL v.2 повлекли за собой серьёзные внутренние архитектурные изменения обоих продуктов (в том числе — для обеспечения бесшовной совместимости), в силу которых альфа-версия FastReport VCL v.5 отправлена на доработку. Мы приносим извинения за перенос сроков выпуска продукта.

   Потом у FastReports, Inc был договор с Embarcadero Technologies, Inc о включении FastReport в качестве штатного генератора в Embarcadero RAD Studio XE2. Затем последовали выпуск FastReport RAD Edition, FastReport FMX, FastReport Mono и других продуктов… Итак, не сложно догадаться, разработчикам компании было не до FastReport VCL 5. И вот, согласно народной мудрости «Обещанного три года ждут» (с 2011-го по 2014-й), читаю:

«Рады сообщить вам, что новая долгожданная версия FastReport VCL 5 выпущена!
Рассылка специально идёт 2 апреля — ведь это не шутка!
Обратите внимание на полный список нововведений:

Если вы ещё не попробовали FastReport 5 — воспользуйтесь нашим спецпредложением для наших клиентов на обновление до 5й версии: http://cp.fast-report.com/upgrades

   Надеюсь, что «Новые иконки в окне предпросмотра и в Дизайнере отчетов» — это не основное новшество в FastReport VCL 5. На следующей неделе обновлю свою версию FastReport 4 до 5-ки и узнаю, так ли это. Обещаю написать об этом в апреле (год на всякий случай не называю).

P.S. FastReports, Inc, спасибо за долгожданный релиз FastReport VCL 5! Извините, если слишком резко высказал свои мысли.

Читать на сайте автора.

Хранение массива в BLOB-поле — версия 2

    Комментарий Алексея Тимохина к моей заметке «Хранение массива в BLOB-поле» навел меня на мысль, что приведенный мной код можно значительно упростить, если выбросить из него использование TMemoryStream для временного хранения информации.
    Что бы загрузить массив в параметр query типа ftBlob можно использовать метод SetBlobData:

qInsertResearchData.Params[5].SetBlobData(aData, Length(aData) * SizeOf(aData[0]))

Чтение массива из поля типа TBlobField тоже можно записать коротко:

  // Установка размера динамического массива aData
  SetLength(aData, qResearchDATA.BlobSize div SizeOf(aData[0]));
  // Запись содержимого поля qResearchDATA типа TBlobField в массив aData
  qResearch.GetBlobFieldData(qResearchDATA.FieldNo, TBlobByteData(aData))

    Т.к. размер массива я устанавливаю равным размеру содержимого BLOB-поля, то для исключения лишних проверок в GetBlobFieldData я заменил вызов этого метода на свой код и теперь запись содержимого поля qResearchDATA типа TBlobField в массив aData выглядит так:

  With qResearch.CreateBlobStream(qResearchDATA, bmRead) do
    Try
      ReadBuffer(aData[0], qResearchDATA.BlobSize);
    Finally
      Free;
    End;

Читать на сайте автора.

Хранение массива в BLOB-поле

    Понадобилось мне хранить результаты измерений в базе данных. Просто сохранить их в таблицу не получится, т.к. количество строк с информацией в одном измерении быстро перевалит за миллион, и при сохранении их в одной транзакции пользователь успеет попить кофе. Плодить множество мелких транзакций по несколько тысяч записей тоже не сильно прибавит скорости. Скорость при последующей вычитке из базы данных миллионов строк тоже будет печальной. Поэтому единственный очевидный для меня выход — это сохранить результаты измерения в поле типа BLOB. Измерения у меня хранились в многомерном массиве, но я упрощу код и объявлю динамический одномерный массив целых чисел:

Var
  aData: Array of Integer;

Процедура записи динамического массива в базу данных получилась примерно такая:

Var
  ms: TMemoryStream;
  …
begin
  …
  Try
    ms := TMemoryStream.Create;
    // Запись содержимого массива aData в поток ms
    ms.WriteBuffer(aData[0], Length(aData) * SizeOf(aData[0]));
    // Запись содержимого потока ms в параметр query для вставки данных
    qInsertResearch.Params[5].LoadFromStream(ms, ftBlob);
  Finally
    ms.Free;
  End;
  …

А процедура чтения массива из базы данных не сложнее процедуры записи:

Var
  ms: TMemoryStream;
  …
begin
  …
  Try
    ms := TMemoryStream.Create;
    // Запись содержимого поля qResearchDATA типа TBlobField в поток ms
    qResearchDATA.SaveToStream(ms);
    // Установка размера динамического массива aData
    SetLength(aData, ms.Size div SizeOf(aData[0]));
    ms.Position := 0;
    // Запись содержимого потока ms в массив aData
    ms.ReadBuffer(aData[0], ms.Size);
  Finally
    ms.Free;
  End;
  …

Теперь на запись/чтение нескольких миллионов записей моя программа тратит секунду. Вместо размера первого элемента массива SizeOf(aData[0]) вы можете использовать размер типа элементов массива (для приведенного мной примера — SizeOf(Integer)). Но такой вариант кода будет менее универсальным, т.к. будет зависеть от используемого типа данных.

P.S. При использовании такого способа хранения данных не забывайте, что размер некоторых типов данных зависит от операционной системы, для которой скомпилирована программа. Иначе информация, которую прочтет из базы данных ваша 64-битная программа перекомпилированная из 32-битной, вас неприятно удивит.

Продолжение…

Читать на сайте автора.

О нумерации версий Delphi

  История развивается по спирали,
а пони бегает по кругу…

   Пятничные размышления, на которые натолкнуло письмо одного моего приятеля.
   Сначала разработчики Delphi нумеровали версии просто: 1, 2, 3, 4, 5, 6, 7, 8. Затем, с подачи маркетологов Microsoft перешли на нумерацию версий по годам: 2005, 2006, 2007, 2009, 2010. В 2010 году Embarcadero придумала для всех своих продуктов новый бренд — «XE». «XE» — это не «Express Edition» как у Oracle, а два понятия: «X» — гетерогенность платформы (например, доступ к различным базам данных без дополнительных затрат) и «E» — скромное «Embarcadero». Поэтому с 2010 года началась новая эра в нумерации версий Delphi: Delphi XE, Delphi XE2… Что будет дальше? А дальше:

  • Delphi XE3
  • Delphi XE4
  • Delphi XE5
  • Delphi XE6
  • Delphi XE7
  • Delphi XE8
  • Delphi XE9
  • Delphi XEA
  • Delphi XEB
  • Delphi XEC
  • Delphi XED
  • Delphi XEE

 О, XEE! Легкой перестановкой букв мы получаем название первой версии Delphi — «Delphi.EXE». Круг замкнулся… 🙂

Читать на сайте автора.

Конвертирование XLS/XLSX/XLSM в XLSB

   С появлением MS Excel 2007 на смену привычного XLS-файла пришли сразу три формата:

  • XLSX — стандартный формат файлов Excel 2007-2010 на основе XML;
  • XLSM — формат Excel 2007-2010 на основе XML с поддержкой макросов (в отличие от XLSX он позволяет сохранять код макросов MS Visual Basic для приложений (VBA) и листы макросов MS Excel 4.0 (XLM));
  • XLSB — формат двоичных файлов Excel 2007-2010 (BIFF12).

Наиболее интересным из них является формат XLSB — Excel Binary Workbook. В отличие от других форматов Excel 2007-2010, он хранит данные не в виде XML, а является двоичным. Это дает существенные преимущества при работе с большими таблицами, т.к. бинарные файлы занимают меньше места на диске и читаются/записываются быстрее.
   Ни одна из библиотек для работы с файлами Excel в Delphi не поддерживает XLSB-формат. Например, XLSReadWrite поддерживает только XLSX, а авторы TMS FlexCel вообще не могут сказать, когда у них будет поддержка формата Excel 2007 и будет ли вообще. Поэтому, что бы конвертировать файлы Excel в XLSB-формат необходимо использовать OLE:

Var
  xls: OleVariant;

Const
  // formats in Excel 2007-2010
  xlExcel12 = 50; // XLSB
  xlOpenXMLWorkbook = 51; // XLSX
  xlOpenXMLWorkbookMacroEnabled = 52; // XLSM
  xlExcel8 = 56; // XLS (export to Excel 97-2003)

Procedure XYZ.ConvertFilesToXLSB(slFiles: TStringList);
Var
  iFile: Integer;
begin
  Try
    Try
      xls := CreateOleObject(‘Excel.Application’);
      xls.DisplayAlerts := False;
      If StrToFloat(StringReplace(xls.Version, ‘.’, DecimalSeparator, [])) < 12
        then WriteToLog(‘Error! Requires Excel 2007/2010’)
        else for iFile := 0 to slFiles.Count-1 do
                ConvertToXLSB(slFiles[iFile]);
    Finally
      xls.Quit;
      xls := UnAssigned;
    End;
  Except
    on E: Exception do
      WriteToLog(E.Message);
  End;
end;

Где ConvertToXLSB:

Procedure XYZ.ConvertToXLSB(sFileName: String);
Var
  sFileNameTo: String;
begin
  sFileName := ExpandFileName(sFileName);
  sFileNameTo := ChangeFileExt(sFileName, ‘.xlsb’);
  Try
    Try
      xls.Workbooks.Open(sFileName);
      xls.ActiveWorkbook.SaveAs(Filename := sFileNameTo, FileFormat := xlExcel12);
    Finally
      xls.Workbooks.Close;
    End;
  Except
    on E: Exception do
      WriteToLog(E.Message);
  End;
end;

   Думаю, что код простой и комментировать нечего. Остановлюсь только на строке проверки версии MS Excel. xls.Version возвращает номер версии MS Excel в виде строки, где цифры разделены точкой (например, «11.0» для Excel 2003, «12.0» для Excel 2007…), поэтому, чтобы получить номер версии в виде числа его необходимо преобразовать следующим способом:

StrToFloat(StringReplace(xls.Version, ‘.’, DecimalSeparator, []))

Читать на сайте автора.