В одной из статей, посвященных работе с Excel в Delphi читатель с ником Kanti задал весьма не тривиальную задачку - как добраться до диаграммы Excel, внедренной в документ Word и работать с ней. За что Kanti большое человеческое спасибо - приятно, когда читатели интересуются жизнью блога и предлагают новые темы и идеи.
На первый взгляд задача довольно не простая. Однако решение для неё есть. Я пошел немного дальше в решении проблемы и сегодня расскажу вам:
- как работать с объектом Excel, внедренном в документ Word
- как работать с документом Word, внедренным в Excel.
Прежде, чем начать изложение основного материала, следует упомянуть некоторые моменты работы с Word, т.к. в блоге я их не касался, но эти основы пригодятся для освоения основного материала статьи.
1. Азы работы с MS Word в Delphi
Запуск MS Word в принципе ни чем не отличается от запуска MS Excel за одним небольшим исключением - меняется параметр функции CreateOLEObject:
MyWord:=CreateOleObject('Word.Application');
Но, чтобы не повторяться дважды я расскажу ещё один дополнительный момент, который Вам пригодиться для дальнейшей работы: как подключиться к уже выполняющемуся приложению MS Office, чтобы не создавать лишних копий процессов.
Для того, чтобы подключиться к уже запущенному приложению достаточно использовать функцию GetActiveOleObject, единственным параметром которой является имя класса. Например, чтобы подключиться к запущенному приложению MS Word необходмо выполнить:
MyExcel:=GetActiveOleObject('Word.Application')
Соответственно, чтобы не гадать запущена или не запущена та или иная программа пакета MS Office достаточно воспользоваться связкой двух функций:
try
MyWord:=GetActiveOleObject('WordApplication');
except
MyWord:=CreateOleObject('Word.Application');
end;
Для того, чтобы открыть уже имеющийся документ Word необходимо воспользоваться методом Open объекта Documents, например так:
MyWord.Documents.Open('myword.doc');
После того как документ открыт, Вы можете его редактировать, изменять текст, параметры страницы и т.д., но сегодня нам это не важно. Главное сегодня - научиться работать с объектами. И с этого момента начинается решение первой задачи.
2. Как работать с объектом Excel, внедренном в документ Word
Каждый документ Word имеет коллекцию Shapes, которая позволяет добавлять в документ объекты, созданные и отображаемые с помощью программ-серверов OLE (OLE-серверов). OLE-объекты в документах Word могут отображаться также, как они отображаются в приложениях, предназначенных для их создания и редактирования. Все наверно пользовались редактором формул Math Type? Вот вам простой OLE-сервер. Добавляете OLE-объект формулы в документ - открывается окно Math Type где вы вводите то, что хотите увидеть и потом формула отображается в документе Word.
Другое дело, когда Вы пробуете вставить в документ Word, например файл mp3. В этом случае объект будет отображен в документе в виде ярлыка, но, тем не менее будет внесен в коллекцию Shapes и до него можно будет добраться из Delphi.
Теперь попробуем посмотреть как выглядит добавление OLE-объектов. В простейшем случае Вы открываете Word, создаете документ и выбираете "Правка - Вставить - Объект" и перед Вами открывается окно с перечнем всех OLE-объектов, которые Вы можете использовать в документе. Выбираете объект, вставляете в документ - работаете. Обратите внимание на рисунок - в окне на рисунке как раз отображены всевозможные объекты нашего с Вами исследования.
Для того, чтобы вставить OLE-объект в документ Word из Delphi необходимо воспользоваться методом AddOleObject коллекции Shapes, который имеет следующий вид:
Shapes.AddOleObject(ClassType, FileName, LinkToFile, DisplayAsIcon, IconFileName, IconIndex, IconLabel, Range)
ClassType - имя, используемое для включения указанного объекта OLE. Например, чтобы вставить в документ Word диаграмму Excel следует использовать
ClassType:='Excel.Chart'
для добавления листа Excel, соответственно:
ClassType:='Excel.Sheet'
и так далеею В принципе ничего сложного нет - вставить можно, что угодно, хоть exe-файл :)
FileName - имя файла, из которого должен быть создан объект. Если этот аргумент опущен, то используется текущая папка. Вы должны указать либо ClassType либо FileName, но никак не одновременно оба параметра.
LinkToFile - True для того, чтобы связать OLE-объект с файлом, из которого он был создан. False, чтобы сделать объект OLE-объект независимым от копии файла, т.е. включить объект в документ Word. Если Вы определили значение для ClassType, аргумент LinkToFile должны быть ложными. Значение по умолчанию False.
DisplayAsIcon - True для отображения объекта OLE в виде значка. Значение по умолчанию False.
IconFileName - Файл, который содержит значок для отображения объекта OLE.
IconIndex -индекс иконки отображения из IconFileName. Значение по умолчанию - ноль.
IconLabel - подпись к иконке объекта.
Range - диапазон, где объект OLE будет размещен в тексте. Объект OLE заменяет выбранный диапазон. Если этот аргумент опущен, объект вставляется автоматически (в текущую позицию курсора в документе).
Давайте теперь продемонстрируем использование этого метода на практике и, заодно, приготовим плацдарм для дальнейшей работы. Рассмотрим как можно вставить чистый лист Excel в документ Word. Причем вставим лист в нужные нам координаты и зададим ему (листу) длину и ширину:
var MyWord: OLEVariant;
begin
MyWord:=CreateOleObject('Word.Application');
MyWord.Visible:=true;
MyWord.Documents.Open(doc);
MyWord.ActiveDocument.Shapes.AddOLEObject(ClassType:='Excel.Sheet',Left:=10, Top:=10, Width:=400, Height:=300);
end;
Как видите, вместо того, чтобы указать объект Range мы просто расписали его параметры Left, Top, Width и Height. После выполнения этих операций в документе doc аккурат в верху страницы вставиться лист Excel.
Теперь, когда лист вставлен, можно приступать к дальнейшему изучению "глубин" OLE-серверов Microsoft.
Создадим новую переменную, в которой будем хранить ссылку на OLE-объект.
MyOLE: OLEVariant;
и сразу получим ссылку на наш лист Excel в Word'е:
MyOLE:=MyWord.ActiveDocument.Shapes.Item(1);
Так будет проще разбираться и избавит нас от лишней писанины.
Представим себе, что мы ничего абсолютно не знаем про то, что лежит в MyOLE. Знаем только то, что это элемент из коллекции Shapes и все. Как определить, что мы получили ссылку именно на объект Excel, а не на автофигуру или, ещё хуже, не на файл mp3?
Для того, чтобы получить всю необходимую информацию об OLE-объекте достаточно обратиться к объекту MS Word под названием OLEFormat.
OLEFormat имеет следующие свойства:
| Свойство | Описание |
|---|---|
| Application | Возвращает имя приложения к которому относится объект. В нашем случае вернет "Microsoft Word" |
| ClassType | Возвращает или устанавливает тип класса для указанного объекта OLE, фотографии или поля. |
| Creator | Возвращает 32-битное целое число, которое указывает на приложение в котором был создан объект. |
| DisplayAsIcon | True, если указанный объект отображается в виде значка. Свойство для чтения/записи |
| IconIndex | Возвращает или устанавливает индекс иконки, используемой если DisplayAsIcon True. |
| IconLabel | Возвращает или устанавливает подпись к иконке OLE-объекта. |
| IconName | Возвращает или устанавливает файл программы, в которой хранится икона для объекта OLE. |
| IconPath | Возвращает путь к файлу, в котором хранится иконка для объекта OLE |
| Label | Возвращает строку, которая используется, чтобы определить часть исходного файла для связывания объектов |
| Object | Возвращает объект, который представляет собой объект верхнего уровня интерфейса указанного объекта OLE |
| Parent | Возвращает объект, который представляет собой родительский объект указанного объекта OLEFormat |
| ProgID | Возвращает программный идентификатор (ProgID) для указанного объекта OLE. |
Теперь, используя эти свойства, попробуем получить всю необходимую нам информацию об OLE-объекте.
Вызовем последовательно свойства ClassType и ProgID:
ShowMessage(MyOle.OLEFormat.ClassType); ShowMessage(MyOle.OLEFormat.ProgID);
В моем случае, результатом выполнения операций были две одинаковых строки "Excel.Sheet.12" Так как у меня установлен Office 2007 то версия 12, что и отразилось в сообщениях. У Вас это могут быть 10, 11 или как у меня 12 версии. С помощью номера версии можно будет определять - возможно ли в принципе изменять такие объекты на машине пользователя или нет.
Идем дальше. Итак, мы определили, что объект представляет собой лист Excel. Как получить доступ к Excel? И причем сделать это так, чтобы можно было наш OLE-объект изменить?
Обратимся к свойству Object. Согласно описанию, свойство должно вернуть нам ссылку на объект верхнего уровня. Следовательно, применительно к нашей ситуации - это будет ссылка на объект Excel. Чтобы убедиться в сказанном, сделаем так:
ShowMessage(MyOle.OLEFormat.Object.Application.Name);
то есть получим имя приложения в котором был создан объект. В результате получим сообщение в виде строки "Microsoft Excel".
Ну, а теперь развязка вопроса - используя ссылку на Excel попробуем написать что-нибудь на листе, например, избитую фразу "Hello World!":
MyOle.OLEFormat.Object.Application.ActiveSheet.Range['A1'].Value:='Hello World!';
Можете проверить - в ячейку А1 запишется строка. Здесь следует обратить внимание на то, что при записи в Excel мы не использовали свойства ActiveWorkBook, которое обычно предшествует свойству ActiveSheet. Все дело в том, что среди объектов OLE Office нет такого OLE-объекта - вставляется только лист либо диаграмма. По сути диаграмма - это два листа Sheet где на одном находится сам график, а на втором - данные к нему.
Вот таким простым и достаточно понятным способом можно добавлять, изменять и удалять OLE-объекты. Кстати, на досуге можете потренироваться вставлять, активировать, редактировать сразу несколько различных OLE-объектов - принцип работы тот же. Получаете Object и используете его функции.
3. Как работать с документом Word, внедренным в Excel.
Надо сказать, что разработчики в Microsoft весьма неплохо потрудились, чтобы запутать бедных разработчиков :). В начале все просто - как в Word. Есть Shapes у которого в свою очередь есть метод AddOLEObject, с практически теме же параметрами.
Далее, по логике вещей, у Shapes должно быть свойство-объект OLEFormat. Проверяем - действительно есть, но...свойства другие, точнее одно из свойств другое, а большинства вообще нет. Но, мы люди не гордые - будем управляться с тем, что есть:
| Свойство | Описание |
|---|---|
| Application | При использовании без классификатора объектов, это свойство возвращает объект приложения, представляющий приложение Microsoft Excel. При использовании с объектом Qualifier, это свойство возвращает объект приложения, которое использовалось для создания объекта |
| Object | Возвращает OLE Automation объект ассоциированный с OLE объектом |
| Parent | Возвращает объект, который представляет собой родительский объект указанного объекта OLEFormat |
| progID | Возвращает программный идентификатор (ProgID) для указанного объекта OLE. |
Как видите свойств не много. Главное, что осталось свойство Object - вот его мы и попробуем использовать в своих корыстных целях.
За что следует, наверное, сказать спасибо разработчикам Excel, так это за то, что они предусмотрели сразу объект OLEObjects предоставляющий нам в распоряжение все OLE-объекты листа. Используя этот объект мы минуем использование Shapes. Например так:
MyExcel.ActiveWorkBook.ActiveWorkSheet.OLEObjects.Count
Мы получаем число OLE-объектов документа.
MyExcel.ActiveWorkBook.ActiveWorkSheet.OLEObjects(1)
соответственно даст доступ к первому из OLE-объектов документа, а уж с ним-то нам и предстоит работать. Итак, рассмотрим следующую задачку: необходимо вставить в документ Excel пустой документ Word и написать в нем любую строку.
Чтобы не повторяться в применениях метода - вставим в Excel уже готовый документ Word из файла:
...
MyExcel.ActiveWorkBook.ActiveSheet.OLEObjects.Add(FileName:=doc, Left:=10, Top:=10, Width:=300, Height:=300);
MyOLE:=MyExcel.ActiveWorkBook.ActiveSheet.OLEObjects.item(1);
MyOLE.Activate;
ShowMessage(MyOle.ProgID); //убедимся, что объект относится к Word
ShowMessage(MyOle.Object.Application.Name); //запросим имя приложения
MyOle.Object.Application.ActiveDocument.Range.InsertAfter('Привет');
....
Обратите внимание, в данном случае мы использовали для работы с OLE-объектом не Shapes, а OLEObjects. Попробуйте воспроизвести те же самые действия как в случае работы с Excel из Word, т.е. воспользоваться свойством Object у объекта ObjectFormat. Думаю Вы будите "приятно" удивлены, т.к. в результате запроса имени приложения Вам вернется не Word как ожидалось, а Excel - следовательно работать с OLE-объектом становится невозможно.
Также следует отметить, что прежде, чем приступать к редактированию OLE-объекта, следует его предварительно активировать.
Вот так можно работать с Excel из Word и с Word из Excel и при этом не выходить из Delphi :). Ну, а для чего это использовать - решать Вам. Я только показал Вам возможности работы в Delphi с программами Word и Excel.
Одним из способов отдохнуть от сидячей работы программиста является Сплав по реке - активный вид отдыха. Отвлекитесь на время и потом работать станет намного проще.
Мой блог находят по следующим фразам
- delphi 21 вариант
- компоненты по 2010 Delphi
- Alpha skin для delphi 2007
- delphi без лицензии
- delphi авторизация google
- Synapse.tc
- Delphi в Internet
| Делись! | Загружай! | Плюсуй! |
| | |









19 Сен 2009 в 9:58 пп
Редактируем объекты Excel, содержащиеся в документах Word, не выходя из Delphi…
Thank you for submitting this cool story — Trackback from progg.ru…