Delphi 7 Примеры Excel

Posted By admin On 25.06.19

'Delphi 4: Автоматизация приложений MS® Office® для эффективного анализа результатов' Содержание:. Глава 1: Работа с MS Excel.

  • Вот еще примеры. Что ячейка Excel пустая? Позиции и до конца текста 7, EmptyParam) do.
  • Как и любой другой язык программирования, Delphi имеет свои особенности, которые следует.

Маленькая процедурка -- на которой я тестировал вообще коннект к Excel procedure TForm1.ButtonClick(Sender: TObject); var Excel: Variant; WorkSheet: Variant; I, J: Integer; begin if OpenDialog.Execute then begin Excel:= CreateOleObject( InputBox('OleStr', 'CreateOleObject', 'Excel.Application.8') ); Excel.Visible.

Часть 1: Создание, отображение и удаление экземпляра Excel. Часть 2: Лучшее решение - шаблоны. Часть 3: Создание или открытие книги. Часть 4: Работа с листами и ячейками.

Часть 5: Передача данных разного типа. Часть 6: Передача данных используя буфер обмена и DDE. Часть 7: Пример обмена данными с Excel используя VCL и OLE. Глава 2: Работа с MS Word. Часть 1: Управление Word-ом через OLE. Часть 2: Подсчет статистики обычного текста, сносок и колонтитулов в документах. Часть 3: Открытие документа используя VCL.

Часть 4: Работа с таблицами. Часть 5: Работа с текстом, рисунками и списками. Автор статей: Евгений Старостин. Создание, отображение и удаление экземпляра Excel. Собственно, цель этой статьи мне понятна - поделиться своим опытом с народом. Итак, зачем нам, лучшим в мире программистам, нужен 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, если он, разумеется, создан? Вот здесь начинаются хитрости. Любой, читавший помощь по Excel VBA, скажет, что достаточно написать FIXLSApp.Visible:= true.

Не тут-то было. Я делаю так: Delphi 4.0 / 5.0 procedure TForm1.ShowExcel; begin if Assigned(FIXLSApp) then begin // а если он не создан? FIXLSApp.Visible0:= true; if FIXLSApp.WindowState0 = TOLEEnum(xlMinimized) then FIXLSApp.WindowState0:= TOLEEnum(xlNormal); FIXLSApp.ScreenUpdating0:= true; end; end; Зачем здесь условие на минимайз и какой-то ScreenUpdating? Давайте попробуем закомментировать эти строки, остаиви только Visible, запустить проект, создать Excel (кнопка CreateExcel), показать его (кнопка ShowExcel), минимизировать, вернуться в приложение и сделать снова ShowExcel. Да-да, Visible = true переводит фокус в минимизированный Excel, не восстанавливая размеры окна.

Это ситуация, с которой я борюсь условием на xlMinimized. Но ScreenUpdating зачем? Знающие люди говорят, что это свойство отвечает за перерисовку окон Excel.

Это все равно, что DisableControls у TDataSet. Добавляет скорости, если в нем false.

И это правда что, если выключить его во время длительных пересчетов, то быстрее пересчитается. Но мы, ведь, не выключали его.

Примеры

Зачем тогда эта строка? Делаем так: комметируем эту строку, запускаем демо, CreateExcel, ShowExcel, закрываем его (можно кнопкой с крестиком в правом верхнем углу окна, кому нравится - через меню 'Файл/Выход').

Delphi 7 Примеры Excel Ado

Знающие люди скажут, что 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.Visible0:= 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.Visible0) then begin FIXLSApp.WindowState0:= TOLEEnum(xlMinimized); FIXLSApp.Visible0:= 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.Visible0) then begin IXLSApp.WindowState0:= TOLEEnum(xlMinimized); IXLSApp.Visible0:= true; if not(csDestroying in ComponentState) then Self.SetFocus; Application.BringToFront; end; end; FreeAndNil(FIXLSApp); end; Практически тот же код. Только в D5 вы работаете уже не с интерфейсом напрямую, а с экземпляром класса TexcelApplcation. Если посмотреть его предков, то можно увидеть, что это настоящий класс, освободить который просто необходимо. Поэтому вместо присваивания в nil там написано FreeAndNil (помните такую процедуру?).

Часть 2: Лучшее решение - шаблоны. 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 добавляет после поиска книг с таким же названием в каталоге по умолчанию.

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

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

Для чистоты эксперимента (скорей из лени, великая вещь - собственная лень) я описал константный массив с тестовыми данными - TestDataArray. Создание или открытие книги. В качестве примера я беру проект из предыдущей моей статьи и стану его понемногу расширять, отвечая на вопросы, появившиеся у специалистов разного профиля и кругозора. Эти вопросы получены мною из двух 'источников': как реакция на мою статью и, извините, из переписки по XL Report Support.

Эти две вещи уж очень сильно пересекаются, поэтому я и обращаюсь к обоим источникам моего вдохновения. Я не буду последователен в своих рассуждениях, местами буду писать подробно, местами - кратко. Попросту, я опишу некоторые часто встречающиеся проблемы и решения этих проблем. Я решил совсем опустить в своем пространном (как обычно) повествовании тонкости работы с Excel в Delphi 5.0, так как считаю, что работа с импортированной библиотекой типов принципиально одинакова и в версии 4, и в версии 5. Различен, разве что, только уровень импорта этой самой библиотеки. К тому же, я уже полностью 'переехал' на Excel 2000, поэтому тестирую весь код, который приведен здесь, именно в нем.

Итак, поехали. Создание или открытие книги.

Повторюсь, не смотря на то, что я уже писал об этом в предыдущей статье. В главной форме проекта-примера я объявил свойство IWorkbook. Оно будет содержать интерфейс книги, которую мы будем создавать и использовать. Естественно, в обработчике FormDestroy я его освобождаю. Property IWorkbook: Excel8TLB.Workbook read FIWorkbook; Книгу можно создать разными способами и с разными намерениями. Если необходимо создать абсолютно чистую книгу, достаточно выполнить следующий код: if Assigned(IXLSApp) and (not Assigned(IWorkbook) ) then FIWorkbook:= IXLSApp.Workbooks.Add(EmptyParam, 0); Вопрос в том, зачем нам может понадобиться новая книга, с количеством пустых листов, выставленным по умолчанию.

Сегодня, я не могу уже ответить на этот вопрос, ибо не создаю новых пустых книг. Коллекция Workbooks содержит все открытые книги и предоставляет возможность кое-как управлять всем этим. Боже, как убоги коллекции от Microsoft, и особенно поиск в них! Я отклонюсь, но это надо видеть. Вот пример поиска книги с заданным именем, приведенный как совет в MSDN Office Developer. Public Function SheetExists(strSearchFor As String) As Boolean SheetExists = False For Each sht In ThisWorkbook.Worksheets If sht.Name = strSearchFor Then SheetExists = True End If Next sht End Function Это вам не IndexOf писать.

А я так иделаю. Метод Add этой коллекции (читай, метод интерфейса) позволяет добавить книгу к этой коллекции, пустую либо по шаблону. Первый параметр этого метода, Template (из справки по Excel VBA), может принимать имя файла с путем. Поэтому, выполнив код if Assigned(IXLSApp) and (not Assigned(IWorkbook) ) then FIWorkbook:= IXLSApp.Workbooks.Add(ExtractFilePath(ParamStr(0)) + 'Test.xls', 0); вы получите книгу, идентичную файлу 'Test.xls' с именем Test1.xls. Именно этим способом я создаю все свои отчеты, так как создаю их по заранее разработанным шаблонам. Естественно, что это шаблоны XL Report.

Если же необходимо просто открыть уже существующий файл, то используйте метод Open этой же коллекции: if Assigned(IXLSApp) and (not Assigned(IWorkbook) ) then FIWorkbook:= IXLSApp.Workbooks.Open(ExtractFilePath(ParamStr(0)) + 'Test.xls', EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, false, 0); Понимаю, что в душе нормального программиста такой код вызовет отвращение. Как-то я даже получил гневное письмо о собственной ненормальности из-за того, что использую ранее связывание и кучу EmptyParam. Впрочем, я не сильно агрессивный человек (правда, только в переписке), и отвечать не стал. В конечном итоге, раннее связывание дает мне немного преимуществ, но я за него. Я не могу помнить все методы и их параметры из Excel Type Library, поэтому получаю их (только при раннем связывании, естественно) из подсказок редактора Delphi - продуманная вещь этот редактор. А чтобы не мучаться с написанием такого количества EmptyParam, можно написать и так: if Assigned(IXLSApp) and (not Assigned(IWorkbook)) then IDispatch(FIWorkbook):= OLEVariant(IXLSApp.Workbooks).Open( FileName:= ExtractFilePath(ParamStr(0)) + 'Test.xls'); Но, мы отклонились.

Что же стоит за таким количеством параметров по умолчанию в методе Open? Да, много чего. Из этого 'громадья' я использую лишь несколько вещей.

Их я и опишу, а заинтересовавшихся остальными отсылаю к справке по Excel VBA. Вот объявление этого метода в импортированной библиотеке типов: function Open(const Filename: WideString; UpdateLinks: OleVariant; ReadOnly: OleVariant; Format: OleVariant; Password: OleVariant; WriteResPassword: OleVariant; IgnoreReadOnlyRecommended: OleVariant; Origin: OleVariant; Delimiter: OleVariant; Editable: OleVariant; Notify: OleVariant; Converter: OleVariant; AddToMru: OleVariant; lcid: Integer): Workbook; safecall; В FileName необходимо передать имя открываемого файла, желательно указав путь его нахождения. Иначе, этот файл Excel будет искать в каталоге по умолчанию. Чтобы файл был запомнен в списке последних открытых файлов, в AddToMru можно передать true. Иногда я знаю, что файл рекомендован только для чтения (не путать с 'парольной' защитой книги).

Тогда при открытии выдается соответствующее сообщение. Чтобы игнорировать его, можно передать в IgnoreReadOnlyRecommended true. Вот, пожалуй, и все мои скудные знания об этом методе.

Впрочем, с помощью его мне приходилось открывать и файлы текстовых форматов с разделителями. Но тогда я обращался к чудесному 'пишущему' плейеру VBA и записывал с его помощью макросы, затем правил их по необходимости и все отлично получалось. Этим же способом разрешать 'всяческие' тонкие вопросы рекомендую и вам. На главной форме проекта-примера я создал кнопку, с помощью которой можно открыть (или создать) файл и RadioGroup к ней, где можно указать каким из приведенных выше способов файл этот открывается. Для полного удовлетворения сюда же была добавлена обработка исключения.

Работа с листами и ячейками. Есть в VBA одна вещь, которая меня раздражает.

Это ActiveSheet и ActiveWorkbook, а также возможность работы с Cells и Range без указания, к какому листу или книге они принадлежат. Одно время я боролся сам с собой, то применяя, то совсем отказываясь от подобных конструкций. Окончательно я отказался от этого лишь после обнаружения многочисленных ошибок в анализе 'лога' моего Web-сервера, который я сделал на VBA. Благо, при работе в Delphi нет возможности написать Cells(x, y) = NewValue, подразумевая при этом какой-то неуловимый ActiveSheet. Поэтому прежде, чем работать с отдельными ячейками, я всегда получаю интерфейс на конкретный и вполне осязаемый лист книги. И делю это так: var ISheet: Excel8TLB.Worksheet.

ISheet:= IWorkbook.Worksheets.Item'Лист1' as Excel8TLB.Worksheet; Коллекция Worksheet подобна всем остальным коллекциям из Excel TLB. В ней вы можете удалять листы, вставлять новые, изменять их порядок. Но я практически никогда не делаю этого, поэтому всех нетерпеливых снова отсылаю к справке по Excel VBA. Главную же мысль свою повторю еще раз. Всегда и везде рекомендую работать с ячейками и областями в контексте их листа, получив предварительно интерфейс на этот лист вышеописанным способом. От использования свойств ActiveSheet и ActiveWorkbook можно совсем отказаться, разве что за исключением каких-то особых случаев.

Чтение данных из ячейки. Написав этот заголовок, я подумал о том, как часто я 'беру' данные из книги. Это случается весьма редко, ибо Excel я использую как средство построения отчетов. То есть, намного чаще эти данные я туда передаю.

Поэтому хотелось бы описать не столько чтение данных, сколько способы обращения к ячейкам. Я использую разные способы обращения к ячейкам от привычного в Excel Cells(x,y) до коллекции Names. Чтение данных из нескольких ячеек.

Имея ввиду все вышеописанное, можно просто организовать чтение данных из поименованной области. Я часто нахожу такой код в Сети и в книгах, приведенный в качестве примера. Поиск данных на листе. Предлагаю поискать все ячейки, содержащие строку (или подстроку) 'Text', и изменить цвет фона этих ячеек. Для этого я использовал методы Find и FindNext. Перемещение данных между листами.

Несколько раз меня спросили о том, как перемещать данные между листами. Передача данных разного типа. Как и прежде, я беру проект-пример из предыдущей своей статьи и переделываю его. Напомню, что в нем используется импортированная в Delphi 4 библиотека типов Excel (правда, исходный код я пишу уже в Delphi 5). Свои примеры я тестирую с помощью Excel 2000 с установленным пакетом обновлений Service Release 1. Впрочем, я уверен, что все примеры вы сможете откомпилировать в Delphi 4 и использовать с Excel 97 SR2 и Excel 2000 без SR1. Обращаю внимание на установку SR2 для Excel 97.

Это обязательное условие, так как без этого обновления Excel содержит очень неприятную ошибку, периодически возникающую при закрытии книг. Поэтому, пожалуйста, будьте внимательны, господа! Какие данные мы используем? Да, каждый из нас использует в своих приложениях все многообразие типов данных, с которыми способен справиться компилятор и операционная система. В принципе, можно было бы описать решение проблемы для всего этого 'многообразия'.

Я всегда утверждал и буду утверждать, что типы данных, для которых нельзя написать Cell.Value = NewValue, бесполезно использовать в Excel. Я не 'влюблен' в Excel. Но я твердо уверен в том, что Excel в сегодняшнем его состоянии - одно из мощнейших средств анализа корпоративных данных. И я до сих пор не могу найти другого применения картинкам в книгах Excel, кроме как наведение красоты. Поэтому я остановлюсь только на способах передачи целых и вещественных чисел, строк, дат и логических значений.

В общем, всего того, что так надоело нам в наш быстротекущий media-век. Проект-пример содержит одну форму, в обработчиках OnCreate и OnDestroy которой автоматически создается и освобождается Excel.Application. Причем, для этого я использовал методы из предыдущих примеров - CreateExcel, ShowExcel и ReleaseExcel. Особое внимание хочу обратить на ReleaseExcel, с помощью которого освобождается интерфейс Excel.Application. Если же необходимо закрыть Excel, вызывайте перед освобождением интерфейса метод Quit этого интерфейса (у себя я закомментировал эту строку).

На форму я поместил таблицу (TTable) из DBDEMOS - CUSTOMER.DB. Чтобы видеть хоть что-то, я использовал для этой таблицы DBGrid и навигатор. В правой части формы вы увидите кнопку со странным названием 'Send data' и группу переключателей под ней. С помощью этой группы вы сможете выбрать один из рассмотренных в этой статье вариантов передачи данных в Excel (данные я беру из вышеназванной таблицы).

После выбора варианта передачи и нажатия кнопки в Excel создается новая книга на основе шаблона Test.xls - книги, которую я прилагаю вместе с проектом. В эту книгу из таблицы переносятся значения полей из всех записей. При переносе я измеряю количество миллисекунд, затраченных на этот перенос, и помещаю это количество в ячейку A1 созданной книги. При создании примера я старался избегать лишнего кода, который в любом другом случае добавил бы законченность алгоритмам. Меня стоило бы основательно поругать за то, что я не запоминаю закладок при проходе по таблице, использую значения полей, забывая о DisplayText, и просто переношу значения в книгу без какого-либо форматирования ячеек. Наверняка, вы найдете еще несколько моментов, которые я совсем упустил из вида.

Попросту, красота кода уступила свое место желанию сосредоточиться на единственной цели - эффективной передаче данных. Единственное, что я сделал, так это избавился от возможности вмешательства пользователя в процесс переноса данных, отключив (и включив затем) у Excel свойства Interactive и ScreenUpdating, а также вызвав DisableControls для набора данных. Какие же варианты я предложу на суд читателя? Вариантов и возможностей передачи данных в Excel существует достаточно много - от очень 'заумных' (BIFF) до экзотических (сохраним в текстовый файл и затем его откроем). Все они имеют какие-то свои достоинства и недостатки. В этой статье я расскажу об одних из самых простых и эффективных решениях этой проблемы (название раздела все-таки обязывает - HelloWorld!). Правда, первый описанный здесь способ, у меня ничего кроме зубной боли не вызывает.

Не делайте так - клиническая смерть! Собственно, об этом варианте я мог бы и не писать. Во-первых, я встречал его в большинстве книг и статей, посвященных этой теме. Во-вторых, я, на самом деле, думаю, что так делать нельзя.

Речь идет о тривиальном переносе данных с помощью обычного присваивания свойству ячейки Value нового значения. Тем не менее, я надеюсь что, описывая этот вариант, мне удастся обратить ваше внимание на несколько важных вещей.

Советские фильмы. Первый переключатель на форме (с заголовком 'Value:=') скрывает за собой вызов процедуры ToNewValue. Вот ее исходный код: procedure TForm1.ToNewValue(ISheet: IxlWorksheet); var Row, Column, i: integer; begin tblCust.First; Row:= StartRow; tblCust.First; while not tblCust.EOF do begin Column:= StartColumn; for i:= 0 to tblCust.Fields.Count - 1 do begin ISheet.Cells.ItemRow, Column.Value:= FieldToVariant(tblCust.Fieldsi); Inc(Column); end; Inc(Row); tblCust.Next; end; end; Что в ней особенного? Да, это обычный проход по всей таблице (First; while not EOF do Next;) и по всем ее полям (вложенный for). Во-первых, в этом примере я всегда начинаю переносить данные с ячейки, определенной константами StartRow и StartColumn. Во-вторых, ожидаемый вами оператор присваивания 'Cell.Value:= Field.Value' я заменил на 'Cell.Value:= FieldToVariant(Field)'. То есть, в отличие от классического, 'из учебников', примера я использую свою функцию получения вариантного значения поля. Если присмотреться к исходному тексту функции FieldToVariant, function FieldToVariant(Field: TField): OLEVariant; begin Result:= '; case Field.DataType of ftString, ftFixedChar, ftWideString, ftMemo, ftFmtMemo: Result:= ' + Field.AsString; ftSmallint, ftInteger, ftWord, ftLargeint, ftAutoInc: Result:= Field.AsInteger; ftFloat, ftCurrency, ftBCD: Result:= Field.AsFloat; ftBoolean: Result:= Field.AsBoolean; ftDate, ftTime, ftDateTime: Result:= Field.AsDateTime; end; end; то можно разглядеть причину.

Кроме достаточно глупых 'AsInteger', 'AsFloat' и пр. Я добавляю в начало значений строковых полей одиночную кавычку. Вы, наверняка, помните, что ввод в формулу ячейки первым символом одиночной кавычки заставляет Excel принимать остальные символы как текст. Но, это касается формул ячеек, а не их значений!?

Попробуйте убрать добавление этой кавычки и перекомпилировать проект. Конечно, и в этом варианте все будет работать. Но (предлагаю кощунственный метод) отредактируйте поле 'Company' в первой записи таблицы, введя туда строку '3/7'. Не увидите ли вы в полученной книге вместо этой строки дату или результат деления (зависит от языковых настроек ОС)? Столь же некорректный результат будет получен и при попытке передачи строки '0001', которая будет воспринята как число 1. Благо, одиночная кавычка в начале строки решает эту проблему даже при присваивании в Value (а не в Formula). Впрочем, я не намерен долго останавливаться на этом варианте.

Все дело в значении ячейки A1 в полученной книге. На моем компьютере перенос всей таблицы занял более 4 секунд. И это на не более полусотне записей. А что было бы, если бы количество записей перевалило за пару десятков тысяч?

Кстати, повторные запуски показали колебание этого времени в пределах от трех до пяти секунд. Думаю, что такие колебания были связаны только с файловым кэшем ОС. Так что, 'Не делайте так!' Больному уже лучше.

Правда, он все еще в реанимации. На что же уходит время в предыдущем варианте? Львиная доля времени уходит на вызовы интерфейсов внешнего COM-сервера. И, не смотря на то, что мы используем ранее связывание с библиотекой типов, это так.

Еще мой любимый классик (Калверт, знаете ли) писал о нетерпимости к вызовам интерфейсов внешних OLE-серверов в больших циклах. Как видите, классик прав. Наша задача - избавиться от вызова Cell.Value в цикле. И это решаемо с помощью вариантных массивов. Совсем недавно мне пришло очередное гневное послание на тему буфера обмена - Clipboard.

XL Report очень долго использовал только буфер обмена для передачи данных из приложения в Excel. Дело в том, что при таком варианте (а я его здесь опишу) достигается практически максимальная скорость переноса данных. Дело в том, что в буфер обмена 'кладется' длинная строка, содержащая строковые значения полей набора данных (AsString), разделенные символом табуляции. Записи отделяются друг от друга переводом строки (#10). Собственно, этот формат известен в научных кругах как CSV (разделитель между значениями).

Долгое время это меня устраивало, пока XL Report использовался только нашими разработчиками и ограниченным кругом клиентов фирмы. Но тут мы решили выложить это решение в Сеть.

Я никак не беспокоился за сохранность содержимого буфера обмена. Понятное дело, это не очень правильно. Но, так было. Так есть и сейчас. Правда, по другим причинам.

Для того, чтобы 'выжать' из Excel максимальное быстродействие, приходится использовать определенные методы и свойства его интерфейсов. А их использование не оставляет ничего, кроме как уничтожение содержимого буфера обмена. В общем, сейчас я покажу максимально возможное (в этой статье!!!) решение по переносу данных - CSV. Итак: procedure TForm1.ToCSV(ISheet: IxlWorksheet); var i: integer; IR1, IR2: IxlRange; Buff: String; begin Buff:= '; tblCust.First; while not tblCust.EOF do begin for i:= 0 to tblCust.Fields.Count - 1 do begin Buff:= Buff + FieldToStr(tblCust.Fieldsi); if i.

Думаю, вы уже заметили, что один из переключателей вариантов имеет название, состоящее из зловещего сочетания букв - DDE. Первое, что вы можете почувствовать при виде этих букв, - это застоялый запах плесени и старения. Да, DDE - пережиток старого доброго времени (а, кажется, это было совсем недавно - 'как молоды мы были'), времени DOS-резидентов, командной строки, капитана Нортона и первых (не смотря на их номер - 3.0) 'форточек'. Черт, тут жизнь уже проходит, а DDE все еще жив. И слава Богу!

Ведь, мы решим 'главную' проблему - сохранение содержимого буфера обмена. Вот так: procedure TForm1.ToDDE(ISheet: IxlWorksheet); var xlDDE: TDDEClientConv; i: integer; IR1, IR2, IRange: IxlRange; Buff: string; begin Buff:= '; tblCust.First; while not tblCust.EOF do begin for i:= 0 to tblCust.Fields.Count - 1 do begin Buff:= Buff + FieldToStr(tblCust.Fieldsi); if i. В Delphi 5 и выше, для обмена данными между Вашим приложением и Excel можно использовать компонент TExcelApplication, доступный на Servers Page в Component Palette. Создаем новый проект. На форму кладем TStringGrid, заполняем его некоторыми данными и добавляем две кнопки, с названиями 'To Excel' и 'From Excel'. Так же на форму кладем компонент TExcelApplication и в свойстве 'Name' указываем 'XLApp', а свойство 'ConnectKind' меняем на 'ckNewInstance'. Когда нам необходимо работать с Excel, то обычно мы открываем ExcelApplication, затем открываем WorkBook и в конце используем WorkSheet.

Delphi 7 Примеры Excel

Итак, несомненный интерес представляет для нас листы (WorkSheets) в книге (WorkBook). Давайте посмотрим как всё это работает. Посылка данных в Excel.

Автор: Прилагается компонента ExcelView и процедуры экспорта и печати по шаблону в Excel для Delphi 2010/XE/XE2. Зачем это нужно? Excel в современном офисе фактически стал стандартом для ввода и анализа данных, создания итоговых отчетов и презентаций. В первую очередь, благодаря наглядности подхода и простоте освоения. Создать 'табличку' с нужными автоматическими расчетами, добавить промежуточные итоги по нескольким критериям и построить по этим итогам круговую диаграмму - все это можно сделать без специальной подготовки, легко и непринужденно. Поэтому вполне закономерно, что Excel широко используется и для разработки различных печатных форм.

Хотя по своим возможностям он уступает специализированным генераторам отчетов, уже практически для всех типовых документов можно найти готовые Excel-шаблоны, от коммерческого предложения до товарно-транспортной накладной по форме 1-Т Что и как экспортировать? Предполагается, что нам нужно заполнять предварительно созданные шаблоны Excel. Под шаблонами подразумеваются обычные Excel-файлы, в которых отдельные ячейки и области обозначаются именами переменных. Туда и будут вставляться наши данные.

ArrayData:= VarArrayCreate ( 1, DataSet. RecordCount, 1, FieldList. Count , varVariant ); y:= 1; while not DataSet. Eof do begin z:= 1; for i:= 0 to FieldList.

Count - 1 do begin if FieldList i = ' then ArrayData y, z := ' else begin if DataSet. FieldByName (FieldList i ).

DataType =ftFloat then ArrayData y, z := DataSet. FieldByName (FieldList i ). AsFloat else ArrayData y, z := DataSet. FieldByName (FieldList i ). Value; end; inc (z ); end; DataSet.

Jump to Дополнения - Дополнения[править| править код]. Представляют собой игровые дополнения, значительно расширяющие геймплей основной игры, а также добавляющие множество дополнительных объектов и новые города. The Sims 3 — игра, сиквел The Sims 2, анонс которой состоялся в марте 2008 года. Бесплатным среди них является только Риверсайд, который могут загрузить обладатели лицензионной копии игры The Sims 3, зарегистрированной. Для The Sims 3 было выпущено 11 дополнений и 9 каталогов. Дополнения для sims 3. Симс 3 - только лучшее дополнения для игры! В нашем каталоге The Sims 3 вы найдете большое количество контента, который максимально разнообразит ваш игровой процесс. Каталог дополнений для Симс 3. На Sims3pack.ru можно бесплатно скачать любую вещь из каталога. Список дополнений для Sims 3: такие как одежда, причёски, готовые симы знаменитости, моды, хаки, глаза и линзы, дома, участки, города, аксессуары, обувь, косметика, транспорт, картины, татуировки. Брови, усы и т.п. Для Sims 4 Симы знаменитости Sims 4 Декор для Sims 4 Техника для Sims 4 Моды для Sims 4 Позы для Sims 4 Строительство в Sims 4 Города для Sims 4 Программы для Sims 4 Скачать Sims 4 Коды для Sims 4.

Next; inc (y ); end; А потом уже вставляется в нужное место. C:= TRttiContext. Create; t:=c. GetType (cmp. ClassInfo ); p:=t.

GetProperty (PropName ); if p nil then begin IsNumeric:= false; if p. ToString = 'TStrings' then PropValue:=p. GetValue (cmp ).

Text else if p. ToString = 'Boolean' then PropValue:=BoolToStr (p. GetValue (cmp ). AsBoolean, true ) else case p. TypeKind of tkInteger, tkInt64: begin PropValue:= IntToStr (p. GetValue (cmp ). AsInteger ); IsNumeric:= true; end; tkString, tkUString, tkLString: PropValue:= p.

Delphi 7 Примеры Excel Numberformat

GetValue (cmp ). AsString; tkFloat: begin PropValue:= FloatToStr (p. GetValue (cmp ). AsExtended ); IsNumeric:= true; end; else PropValue:= '; end; if IsNumeric and (Trim (Copy (st, 1,i1 - 1 ) ) = ' ) and (Trim (Copy (st,i2 + 1,length (st ) ) ) = ' ) then Sheet. Cells Row, Col :=StrToFloat (PropValue ) else Sheet.

Delphi 7 Примеры Excel 2013

Cells Row, Col :=Copy (st, 1,i1 - 1 ) +PropValue +Copy (st,i2 + 1,length (st ) ); end; c. Free; Из за использования модулей Rtti и TypInfo компонент не работает в Delphi младше 2010. Можно либо удалить эти ссылки и весь метод ProcessProperty, либо переписать его для младших версий Delphi (см. ) ​Исходный код.