Использование компонента ActiveX VB для автоматизации Word из Internet Explorer

Сводка

В этой статье показано, как можно использовать компонент ActiveX для клиентской автоматизации Word с веб-страницы, отображаемой в Internet Explorer. Существует несколько преимуществ использования компонента ActiveX на веб-странице, а не сценария, встроенного в веб-страницу.

  • Если у вас уже есть код Visual Basic, автоматизирующий Microsoft Word, вы можете повторно использовать код в браузере, преобразовав проект Visual Basic в файл ActiveX EXE или библиотеку DLL ActiveX.
  • Word не помечен как безопасный для сценариев. В зависимости от параметров безопасности в Internet Explorer код автоматизации Word в сценарии может не запускаться, или пользователь может получать предупреждение о безопасности. Предполагается, что компонент ActiveX соответствует определенным рекомендациям, поэтому он может быть помечен как безопасный для сценариев, чтобы избежать этих проблем с безопасностью.
  • В Visual Basic есть несколько функций, которые нельзя использовать с скриптом на веб-странице. Например, одной из функций, доступных в Visual Basic, но не в скрипте веб-страницы, является возможность вызова программного интерфейса Windows (API).

Типичный сценарий разработчика — предоставление пользователям интерфейса веб-страницы для создания документа Word с использованием данных из внешнего источника или логики. Несмотря на то что вы можете использовать автоматизацию Word на стороне сервера для создания документа и потоковой передачи его обратно клиенту, существует множество недостатков использования серверного подхода, включающего автоматизацию слов. Основной недостаток — масштабируемость; Word является очень ресурсоемким сервером автоматизации и не рекомендуется для создания документов на веб-сервере.

Используя компонент ActiveX для создания документа на клиенте, можно переместить средство автоматизации Word, интенсивно использующее ресурсы, с веб-сервера. Это решение, которое представляет пример компонента ActiveX, рассмотренного в этой статье. Несмотря на то, что пример относится только к автоматизации Word, для автоматизации других приложений Microsoft Office, таких как Microsoft Excel, можно применять одни и те же принципы.

Дополнительные сведения

Компонент ActiveX для Visual Basic

Компонент ActiveX Visual Basic в этом примере взаимодействует с скриптом веб-страницы для создания документа с накладной заказа по запросу пользователя. Веб-приложение может разрешить компоненту ActiveX получить сведения о заказе для данного идентификатора заказа, или веб-приложение может упаковать сведения о заказе в формате XML и отправить его компоненту ActiveX для обработки. В обоих случаях после того, как компонент получает сведения о заказе, он может автоматизировать Word для создания и отображения документа счета для заказа.

Компонент ActiveX (Аутоматеворд) содержит один класс, класс Invoice, предоставляющий три метода:

  • Метод GetData использует объекты данных ActiveX (ADO) для извлечения сведений о заказе в образце базы данных Northwind. Сведения о заказе хранятся в закрытой переменной-члене m_Data. Метод GetData можно вызвать для того, чтобы извлечение данных происходило на стороне клиента.
  • Метод Сенддата использует Microsoft XML (MSXML) для заполнения закрытой переменной члена m_Data сведениями о заказе, предоставленными вызывающим абонентом. Сенддата ожидает один параметр, представляющий объект DOMDocument для сведений о заказе. Метод Сенддата может быть вызван для отправки сведений о заказе с веб-страницы в компонент. Благодаря этому подходу вы можете использовать ASP для извлечения данных на стороне сервера и представления клиента с островом XML-данных, который можно использовать для создания документа.
  • Метод Макеинвоице использует Word Automation для создания документа, который содержит сведения о заказе в частной переменной члена m_Data. Документ, хранящийся на веб-сервере, используется в качестве отправной точки для счета. Вызывающий абонент может отобразить заполненный документ Word вне браузера или сохранить готовый документ на диске для последующего использования.

Счет. CLS

Option Explicit

Private Type InvoiceData
    OrderID As String
    OrderDate As Date
    CustID As String
    CustInfo As String
    ProdInfo As Variant
End Type

Private m_Data As InvoiceData

Public Sub GetData(sOrderID As Variant, sConn As Variant)

Dim oConn As Object, oRS As Object

'Connect to the Northwind database.
    Set oConn = CreateObject("ADODB.Connection")
    oConn.Open sConn

'Obtain the Customer ID and Order Date.
    Set oRS = CreateObject("ADODB.Recordset")
    oRS.Open "Select [OrderDate], [CustomerID] from Orders where " & _
             "[OrderID]=" & sOrderID, oConn, 3 'adOpenStatic=3
    m_Data.OrderID = sOrderID
    m_Data.OrderDate = CDate(oRS.Fields("OrderDate").Value)
    m_Data.CustID = oRS.Fields("CustomerID").Value
    oRS.Close

'Obtain Customer information.
    Set oRS = CreateObject("ADODB.Recordset")
    oRS.Open "Select * from Customers Where CustomerID='" & _
             m_Data.CustID & "'", oConn, 3 'adOpenStatic=3
    m_Data.CustInfo = oRS.Fields("CompanyName").Value & vbCrLf & _
                      oRS.Fields("City") & " "
    If Not (IsNull(oRS.Fields("Region"))) Then
       m_Data.CustInfo = m_Data.CustInfo & oRS.Fields("Region").Value & " "
    End If
    m_Data.CustInfo = m_Data.CustInfo & oRS.Fields("PostalCode").Value & _
                      vbCrLf & oRS.Fields("Country").Value
    oRS.Close

'Obtain Product information.
    Set oRS = CreateObject("ADODB.Recordset")
    oRS.Open "Select ProductName, Quantity, [Order Details].UnitPrice," & _
             "Discount from Products Inner Join [Order Details] on " & _
             "Products.ProductID = [Order Details].ProductID " & _
             "Where OrderID = " & sOrderID, oConn, 3 'adOpenStatic=3
    m_Data.ProdInfo = oRS.GetRows
    oRS.Close

'Close the connection to the database.
    oConn.Close

End Sub

Public Sub SendData(oXML As Variant)

'Extract the information from the DOMDocument object oXML and store
    'it in the private member variable m_Data.

m_Data.OrderID = oXML.getElementsByTagName("OrderID").Item(0).Text
    m_Data.OrderDate = oXML.getElementsByTagName("OrderDate").Item(0).Text
    m_Data.CustID = oXML.getElementsByTagName("CustID").Item(0).Text
    m_Data.CustInfo = oXML.getElementsByTagName("CustInfo").Item(0).Text

Dim oItems As Object, oItem As Object
    Set oItems = oXML.getElementsByTagName("Items").Item(0)
    ReDim vArray(0 To 3, 0 To oItems.childNodes.Length - 1) As Variant
    Dim i As Integer
    For i = 0 To UBound(vArray, 2)
        Set oItem = oItems.childNodes(i)
        vArray(0, i) = oItem.getAttribute("Desc")
        vArray(1, i) = oItem.getAttribute("Qty")
        vArray(2, i) = oItem.getAttribute("Price")
        vArray(3, i) = oItem.getAttribute("Disc")
    Next
    m_Data.ProdInfo = vArray

End Sub

Public Sub MakeInvoice(sTemplate As Variant, Optional bSave As Variant)

Dim oWord As Object
    Dim oDoc As Object
    Dim oTable As Object

If IsMissing(bSave) Then bSave = False

'Open the document as read-only.
    Set oWord = CreateObject("Word.Application")
    Set oDoc = oWord.Documents.Open(sTemplate, , True)

'Fill in the bookmarks.
    oDoc.Bookmarks("Customer_Info").Range.Text = m_Data.CustInfo
    oDoc.Bookmarks("Customer_ID").Range.Text = m_Data.CustID
    oDoc.Bookmarks("Order_ID").Range.Text = m_Data.OrderID
    oDoc.Bookmarks("Order_Date").Range.Text = m_Data.OrderDate

'Fill in the table with the product information.
    '** Note that the table starts out with three rows -- the first row
    '   contains headers for the table, the second row is for
    '   the first set of product data, and the third row contains a total.
    '   New rows are added for additional products before the "total row".

Set oTable = oDoc.Tables(1)
    Dim r As Integer, c As Integer
    For r = 1 To UBound(m_Data.ProdInfo, 2) + 1
        If r > 1 Then oTable.Rows.Add (oTable.Rows(oTable.Rows.Count))
        For c = 1 To 4
            oTable.Cell(r + 1, c).Range.Text = _
               m_Data.ProdInfo(c - 1, r - 1)
        Next
        oTable.Cell(r + 1, 5).Formula _
            "=(B" & r + 1 & "*C" & r + 1 & ")*(1-D" & r + 1 & ")", _
            "#,##0.00"
    Next

'Update the field for the grand total and protect the document.
    oTable.Cell(oTable.Rows.Count, 5).Range.Fields.Update
    oDoc.Protect 1 'wdAllowOnlyComments=1

If bSave Then
        'Save the document as "c:\invoice.doc" and quit Word.
        Dim nResult As Long
        nResult = MsgBox("Are you sure you wish to create the document" & _
             " ""c:\invoice.doc""? If this document already exists, " & _
             "it will be replaced", vbYesNo, "AutomateWord")
        If nResult = vbYes Then oDoc.SaveAs "c:\invoice.doc"
        oDoc.Close False
        oWord.Quit
    Else
        'Make Word visible.
        oWord.Visible = True
    End If

End Sub

Использование компонента ActiveX на веб-странице

В Autoword1. htm показано, как можно использовать метод GetData, чтобы позволить компоненту ActiveX получать клиентские данные заказа и создавать документ.

Autoword1. htm

<HTML>
<HEAD>
   <OBJECT ID="AutoWord"
    CLASSID="CLSID:32646EBA-0919-4C2F-94D6-599F46DC34F2"
    CODEBASE="https://YourWebServer/invoice/package/AutomateWord.CAB#version=1,0,0,0">
   </OBJECT>
</HEAD>
<BODY>
Enter an order id between 10248 and 11077 and click the button to view the invoice for the order:
<P/><INPUT TYPE="text" VALUE="10500" ID="OrderID">
<P/><BUTTON ID="InvoiceButton">Create Invoice</BUTTON>
</BODY>

<SCRIPT Language="VBScript">

Function InvoiceButton_OnClick()
      Dim sConn
      sConn = "Provider=sqloledb;Data Source=YourSQLServer;Initial Catalog=Northwind;UID=sa;"
      AutoWord.GetData OrderID.Value, sConn
      AutoWord.MakeInvoice "https://YourWebServer/invoice/invoice.doc"
   End Function

</SCRIPT>
</HTML>

Сценарий в Autoword1. htm использует компонент ActiveX для отображения завершенного документа вне браузера. Вы также можете сохранить готовый документ и отобразить его в браузере; Тем не менее, для этого необходимо сохранить документ Word на диске. Компонент может сохранить документ как К:\инвоице.док на локальном диске клиента. Так как компонент ActiveX помечен как безопасный для сценариев, клиенту предлагается подтверждение сохранения.

Если вы хотите отобразить заполненный документ в браузере, замените вызов Макеинвоице в Autoword1. htm на следующий:

      AutoWord.MakeInvoice "https://YourWebServer/invoice/invoice.doc", True
      window.navigate "c:\invoice.doc"

В Autoword2. htm показано, как можно использовать метод Сенддата для отправки данных заказа в качестве объекта DOMDocument в компонент ActiveX для создания готового документа. DOMDocument создается из острова данных XML, расположенного на веб-странице. Чтобы компонент ActiveX правильно обрабатывал сведения о заказах, отправленных вызывающим абонентом, XML-код должен быть правильно сформированным и структурированным, чтобы компонент мог интерпретировать его как информацию о заказах.

Autoword2. htm

<HTML>
<HEAD>
   <OBJECT ID="AutoWord"
    CLASSID="CLSID:32646EBA-0919-4C2F-94D6-599F46DC34F2"
    CODEBASE="https://YourWebServer/invoice/package/AutomateWord.CAB#version=1,0,0,0">
   </OBJECT>
</HEAD>
<BODY>
   <BUTTON ID="InvoiceButton">Create Invoice</BUTTON>
   <XML ID="DataXML">
     <Order>
        <OrderID>10700</OrderID>
        <OrderDate>10/10/2000</OrderDate>
        <CustID>SAVEA</CustID>
        <CustInfo>Save-a-lot
Markets Boise ID 83720
USA</CustInfo>
        <Items>
           <Product Desc="Chai" Qty="5" Price="18" Disc="0.2"/>
           <Product Desc="Sasquatch Ale" Qty="12" Price="14" Disc="0.2"/>
           <Product Desc="Scottish Longbreads" Qty="40" Price="12.5" Disc="0.2"/>
           <Product Desc="Flotemysost" Qty="60" Price="21.5" Disc="0.2"/>
        </Items>        
     </Order>
   </XML>
</BODY>

<SCRIPT Language="VBScript">

Function InvoiceButton_OnClick()
      AutoWord.SendData DataXML.XMLDocument
      AutoWord.MakeInvoice "https://YourWebServer/invoice/invoice.doc"
   End Function

</SCRIPT>
</HTML>

В Autoword1. htm и Autoword2. htm Обратите внимание на то, что компонент ActiveX создается с помощью тега, а не функции CreateObject. Цель использования тега состоит в том, чтобы включить автоматическую загрузку компонента ActiveX для пользователей, на которых еще не установлен компонент. Если пользователь посещает одну из этих страниц и компонент не установлен, то компонент загружается из CAB-файла по URL-адресу, указанному в атрибуте CODEBASE. В зависимости от параметров безопасности пользователя в Internet Explorer они могут сначала получить запрос на подтверждение загрузки.

NOTE: CAB-файл, включенный в файл автотекста. exe, был создан с помощью мастера пакетов и развертывания для Visual Basic. Компонент ActiveX в пакете помечен как безопасный для выполнения сценариев и инициализации, но не подписан цифровой подписью.

Для получения дополнительных сведений о создании загружаемых компонентов, цифровой подписи и пометке компонентов как безопасных для написания сценариев и инициализации посетите следующий веб-сайт сети MSDN:

Подписание и проверка кода с помощью Authenticodehttps://msdn.microsoft.com/en-us/library/ms537364.aspx

Безопасная инициализация и сценарии для элементов управления ActiveXhttps://msdn.microsoft.com/en-us/library/Aa751977.aspx

Ссылки

Чтобы получить дополнительные сведения, щелкните следующие номера статей базы знаний Майкрософт:

257757 Info: Автоматизация Office для автоматического выполнения не рекомендуется или не поддерживается

(c) корпорация Майкрософт (Microsoft Corporation) 2001, все права защищены. Вклады Лори B. Турнер, корпорация Майкрософт.