Внедрение и автоматизация документов Office с помощью Visual Basic
Аннотация
При разработке приложения, использующего данные в документе Office, может быть полезно, чтобы эти данные были представлены непосредственно в приложении Visual Basic, чтобы пользователь могли просматривать и редактировать данные без необходимости переключения на приложение Office. Это можно сделать в Visual Basic с помощью элемента управления контейнером OLE.
В этой статье показано, как динамически создавать и автоматизировать документ Office с помощью элемента управления контейнерами OLE.
Дополнительная информация
Возможность вставки документа Office в Visual Basic предоставляется технологией компоновки и внедрения объектов (OLE) корпорации Майкрософт. OLE позволяет одному приложению разместить объект, принадлежащий другому приложению, удобным для конечного пользователя способом, но не требует, чтобы участвующие в нем приложения знали внутренние сведения другого приложения. Visual Basic предоставляет элемент управления контейнером OLE, позволяющий программистам Visual Basic добавлять объекты OLE в форму.
После внедрения объекта большинство серверов OLE поддерживают автоматизацию, чтобы позволить хост-приложению программно изменять объект или управлять им из кода. Чтобы получить ссылку на объект службы автоматизации, используйте свойство Object контейнера OLE. Это свойство возвращает объект службы автоматизации, который тесно соответствует внедренному определенному элементу.
Создание приложения Visual Basic, в котором размещается книга Excel
Запустите Visual Basic и создайте новый стандартный проект. Form1 создается по умолчанию.
На панели элементов управления добавьте три кнопки команд в Form1. Затем добавьте экземпляр элемента управления контейнера OLE. Когда элемент управления "Контейнер OLE" помещается в форму, он запрашивает тип объекта, который нужно вставить. В этом примере необходимо динамически добавить объект, поэтому нажмите кнопку "Отмена", чтобы закрыть диалоговое окно без добавления объекта.
В окне кода для Form1 добавьте следующий код:
Option Explicit Dim oBook As Object Dim oSheet As Object Private Sub Command1_Click() On Error GoTo Err_Handler ' Create a new Excel worksheet... OLE1.CreateEmbed vbNullString, "Excel.Sheet" ' Now, pre-fill it with some data you ' can use. The OLE.Object property returns a ' workbook object, and you can use Sheets(1) ' to get the first sheet. Dim arrData(1 To 5, 1 To 5) As Variant Dim i As Long, j As Long Set oBook = OLE1.object Set oSheet = oBook.Sheets(1) ' It is much more efficient to use an array to ' pass data to Excel than to push data over ' cell-by-cell, so you can use an array. ' Add some column headers to the array... arrData(1, 2) = "April" arrData(1, 3) = "May" arrData(1, 4) = "June" arrData(1, 5) = "July" ' Add some row headers... arrData(2, 1) = "John" arrData(3, 1) = "Sally" arrData(4, 1) = "Charles" arrData(5, 1) = "Toni" ' Now add some data... For i = 2 To 5 For j = 2 To 5 arrData(i, j) = 350 + ((i + j) Mod 3) Next j Next i ' Assign the data to Excel... oSheet.Range("A3:E7").Value = arrData oSheet.Cells(1, 1).Value = "Test Data" oSheet.Range("B9:E9").FormulaR1C1 = "=SUM(R[-5]C:R[-2]C)" ' Do some auto formatting... oSheet.Range("A1:E9").Select oBook.Application.Selection.AutoFormat Command1.Enabled = False Command2.Enabled = False Command3.Enabled = True Exit Sub Err_Handler: MsgBox "An error occurred: " & Err.Description, vbCritical End Sub Private Sub Command2_Click() On Error GoTo Err_Handler ' Create an embedded object using the data ' stored in Test.xls.<?xm-insertion_mark_start author="v-thomr" time="20070327T040420-0600"?> If this code is run in Microsoft Office ' Excel 2007, <?xm-insertion_mark_end?><?xm-deletion_mark author="v-thomr" time="20070327T040345-0600" data=".."?><?xm-insertion_mark_start author="v-thomr" time="20070327T040422-0600"?>change the file name to Test.xlsx.<?xm-insertion_mark_end?> OLE1.CreateEmbed "C:\Test.xls" Command1.Enabled = False Command2.Enabled = False Command3.Enabled = True Exit Sub Err_Handler: MsgBox "The file 'C:\Test.xls' does not exist" & _ " or cannot be opened.", vbCritical End Sub Private Sub Command3_Click() On Error Resume Next ' Delete the existing test file (if any)... Kill "C:\Test.xls" ' Save the file as a native XLS file... oBook.SaveAs "C:\Test.xls" Set oBook = Nothing Set oSheet = Nothing ' Close the OLE object and remove it... OLE1.Close OLE1.Delete Command1.Enabled = True Command2.Enabled = True Command3.Enabled = False End Sub Private Sub Form_Load() Command1.Caption = "Create" Command2.Caption = "Open" Command3.Caption = "Save" Command3.Enabled = False End Sub
Нажмите клавишу F5, чтобы запустить программу. Нажмите кнопку Создать. Это внедряет новый лист и автоматизирует Excel для добавления данных непосредственно на лист. Обратите внимание, что если дважды щелкнуть объект, он активируется на месте и пользователь может редактировать данные напрямую. Теперь нажмите кнопку "Сохранить", чтобы сохранить данные в файл и закрыть объект OLE. Кнопка "Открыть" позволяет открыть копию ранее сохраненного файла.
Создание приложения Visual Basic, в котором размещается документ Word
Запустите Visual Basic и создайте новый стандартный проект. Form1 создается по умолчанию.
На панели элементов управления добавьте три кнопки команд в Form1. Затем добавьте экземпляр элемента управления контейнера OLE. Когда элемент управления "Контейнер OLE" помещается в форму, он запрашивает тип объекта, который нужно вставить. В этом примере необходимо динамически добавить объект, поэтому нажмите кнопку "Отмена", чтобы закрыть диалоговое окно без добавления объекта.
В окне кода для Form1 добавьте следующий код:
Option Explicit Dim oDocument As Object Private Sub Command1_Click() On Error GoTo Err_Handler ' Create a new Word Document... OLE1.CreateEmbed vbNullString, "Word.Document" ' Add some text to the document. The OLE.Object ' property returns the document object... Set oDocument = OLE1.object oDocument.Content.Select With oDocument.Application.Selection ' Add a heading at the top of the document... .Style = oDocument.Styles("Heading 1") .Font.Color = &HFF0000 .TypeText "Blue Sky Airlines" .ParagraphFormat.Alignment = 1 '[wdAlignParagraphCenter] .TypeParagraph .TypeParagraph ' Now add some text... .TypeText "Dear Mr. Smith," .TypeParagraph .TypeParagraph .TypeText "Thank you for your interest in our current fares " & _ "from Oakland to Sacramento. We guarantee to be " & _ "the lowest price for local flights, or we'll " & _ "offer to make your next flight FREE!" .TypeParagraph .TypeParagraph .TypeText "The current fare for a flight leaving Oakland " & _ "on October 4, 1999 and arriving in Sacramento " & _ "the same day is $54.00." .TypeParagraph .TypeParagraph .TypeText "We hope you will choose to fly Blue Sky Airlines." .TypeParagraph .TypeParagraph .TypeText "Sincerely," .TypeParagraph .TypeParagraph .TypeParagraph .TypeText "John Taylor" .TypeParagraph .Font.Italic = True .TypeText "Regional Sales Manager" .TypeParagraph End With ' Zoom to see entire document... OLE1.SizeMode = 3 OLE1.DoVerb -1 Command1.Enabled = False Command2.Enabled = False Command3.Enabled = True Exit Sub Err_Handler: MsgBox "An error occurred: " & Err.Description, vbCritical End Sub Private Sub Command2_Click() On Error GoTo Err_Handler ' Create an embedded object using the data ' stored in Test.doc.<?xm-insertion_mark_start author="v-thomr" time="20070327T040719-0600"?> If this code is run in Microsoft Office ' Word 2007, change the file name to Test.docx.<?xm-insertion_mark_end?><?xm-deletion_mark author="v-thomr" time="20070327T040717-0600" data=".."?> OLE1.CreateEmbed "C:\Test.doc" Command1.Enabled = False Command2.Enabled = False Command3.Enabled = True Exit Sub Err_Handler: MsgBox "The file 'C:\Test.doc' does not exist" & _ " or cannot be opened.", vbCritical End Sub Private Sub Command3_Click() On Error Resume Next ' Delete the existinf test file (if any)... Kill "C:\Test.doc" ' Save the file as a native Word DOC file... oDocument.SaveAs "C:\Test.doc" Set oDocument = Nothing ' Close the OLE object and remove it... OLE1.Close OLE1.Delete Command1.Enabled = True Command2.Enabled = True Command3.Enabled = False End Sub Private Sub Form_Load() Command1.Caption = "Create" Command2.Caption = "Open" Command3.Caption = "Save" Command3.Enabled = False End Sub
Нажмите клавишу F5, чтобы запустить программу. Нажмите кнопку Создать. Это внедряет новый документ и автоматизирует Word для добавления данных непосредственно в документ. Обратите внимание, что если дважды щелкнуть объект, он активируется на месте и пользователь может редактировать данные напрямую. Теперь нажмите кнопку "Сохранить", чтобы сохранить данные в файл и закрыть объект OLE. Кнопка "Открыть" позволяет открыть копию ранее сохраненного файла.
Рекомендации по использованию контейнера OLE
При внедрении из существующего файла данные, отображаемые в контейнере OLE, являются копией данных в файле. Любые внесенные изменения не сохраняются в одном файле автоматически. Хотя для сохранения результатов в определенный файл можно использовать метод, аналогичный приведенному выше, не все серверы OLE поддерживают эту возможность. Это не считается обычным поведением объекта OLE.
Если выполняется связывание с файлом, то объект не может быть активирован на месте. Вместо этого, когда пользователь дважды щелкает объект, объект открывается в окне серверного приложения. На месте можно активировать только внедренные объекты.
Элемент управления "Контейнер OLE" учитывает привязку данных. Если у вас есть база данных Access 97 или Access 2000, вы можете привязать элемент управления к полю объекта OLE в базе данных. При отображении формы данные извлекаются из базы данных и отображаются для изменения пользователем. Все изменения, внесенные пользователем, автоматически сохраняются в базе данных при закрытии объекта OLE.
Чтобы сделать контейнер OLE-контейнер привязанным к данным, добавьте элемент управления данными Visual Basic и задайте для его свойства DatabaseName путь к базе данных. Затем задайте для RecordSource существующую таблицу в базе данных. Используйте свойство DataSource элемента управления OLE для привязки элемента управления к элементу управления данными Visual Basic, а затем задайте для свойства DataField значение, указывающее на определенное поле в наборе записей, содержащего объект OLE. Visual Basic выполняет все остальное.
Размер и положение штриховки границы, которая отображается, когда контейнер активен на месте, определяется размером объекта и выбранными для элемента управления OLE. Эта граница отображается для пометки границ окна редактирования. Границы окна редактирования часто не соответствуют границам самого контейнера OLE; Это нормальное поведение для объекта OLE. Окно редактирования не может быть программно изменено из Visual Basic.
Некоторые методы автоматизации могут не работать правильно, если объект не был активен на месте. Чтобы программно активировать объект OLE, используйте метод DoVerb и укажите vbOLEShow (-1) в качестве команды.
Вы можете определить, отображается ли меню связанного или внедренного объекта в форме контейнера, настроив свойство NegotiateMenus формы. Если свойству NegotiateMenus дочерней формы присвоено значение True, а для контейнера определена строка меню, меню объекта помещаются в строку меню контейнера при активации объекта. Если в контейнере нет строки меню или свойству NegotiateMenus задано значение False, меню объекта не отображаются при его активации. Обратите внимание, что свойство NegotiateMenus не применяется к формам MDI, поэтому меню формы MDI невозможно объединить с меню активируемого объекта. Чтобы проиллюстрировать согласование меню, попробуйте сделать следующее с примером приложения, созданного в предыдущем разделе:
- Запустите приложение и нажмите кнопку "Создать", чтобы внедрить новый документ в контейнер OLE.
- Щелкните правой кнопкой мыши контейнер OLE и выберите команду "Изменить на месте", чтобы активировать объект. Обратите внимание, что меню для приложения объекта отображаются, так как свойство NegotiateMenus формы Form1 по умолчанию имеет значение True.
- Закройте форму, чтобы завершить приложение.
- Выбрав form1, щелкните "Редактор меню" в меню "Сервис".
- Создайте меню верхнего уровня с заголовком "Файл" и именем mnuFile. Задайте для свойства NegotiatePosition этого меню значение "1 Слева". Создайте пункт меню с заголовком "Открыть" и именем mnuOpen.
- Нажмите кнопку "ОК", чтобы закрыть редактор меню.
- Снова запустите приложение и нажмите кнопку "Создать", чтобы внедрить новый документ в контейнер OLE.
- Щелкните правой кнопкой мыши контейнер OLE и выберите команду "Изменить на месте", чтобы активировать объект. Обратите внимание, что меню для Form1 было объединено с меню для приложения объекта.
Visual Basic не позволяет управлять процессом слияния меню или вносить изменения в элементы меню сервера при добавлении. Однако вы можете изменить меню приложения Office с помощью службы автоматизации с помощью следующего кода:
' This code disables the Insert|Object item on the merged menu... Dim oMenuBar As Object Set oMenuBar = oBook.Application.CommandBars("Worksheet Menu Bar") oMenuBar.Controls("&Insert").Controls("&Object...").Enabled = False
Обратите внимание, что перед активным размещением объекта может потребоваться внести некоторые изменения. В противном случае изменения могут не отображаться в объединенном меню.
Примечание Этот маркер не применяется к Microsoft Office Excel 2007 или Microsoft Office Word 2007.
Visual Basic в настоящее время не поддерживает назначение пространства панели инструментов. Таким образом, закрепленные панели инструментов обычно не отображаются при активации объекта. Однако можно отобразить плавающее окно инструментов с автоматизацией:
OLE1.DoVerb -1 '[vbOLEShow] With oBook.Application.CommandBars("Standard") .Position = 4 '[msoBarFloating] .Visible = True End With
Примечание Этот маркер не применяется к Microsoft Office Excel 2007 или Microsoft Office Word 2007.
Для программ, для которых требуется, чтобы объект всегда оставалась активным на месте, корпорация Майкрософт предоставила технологию Документов ActiveX. Не все серверы OLE являются серверами документов ActiveX; Microsoft Word, Microsoft Excel и Microsoft PowerPoint являются серверами документов ActiveX.
Visual Basic не поддерживает собственный элемент управления для размещения документов ActiveX. Однако элемент управления WebBrowser, который поставляется с Internet Explorer (версии 3.0 и более поздних версий), поддерживает эту форму автономных функций на месте. Этот элемент управления можно использовать для открытия документа Office в качестве документа ActiveX. Дополнительные сведения об использовании элемента управления WebBrowser см. в следующей статье:
243058 Как использовать элемент управления WebBrowser для открытия документа Office
Метод SaveToFile контейнера OLE создает файл, который можно открыть в контейнере OLE. Однако файлы, сохраненные с помощью метода SaveToFile контейнера OLE, невозможно открыть непосредственно в соответствующем приложении Office. Если вы хотите сохранить внедренный документ на диск, чтобы его можно было открыть в целевом приложении, используйте метод SaveAs документа приложения:
OLE1.object.SaveAs ("C:\MyNewFile.doc")