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

Аннотация

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

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

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

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

Дополнительная информация

Компонент ActiveX в Visual Basic

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

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

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

Invoice.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 на диск. Компонент может сохранить документ как C:\Invoice.doc на локальном диске клиента. Так как компонент ActiveX помечен как безопасный для создания скриптов, клиенту предлагается подтвердить сохранение.

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

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

Autoword2.htm показано, как с помощью метода SendData отправить данные заказа в качестве объекта 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 он может сначала получить запрос на подтверждение загрузки.

ПРИМЕЧАНИЕ. CAB-файл, включенный в Autoword.exe, был создан с помощью мастера упаковки и развертывания для Visual Basic. Компонент ActiveX в пакете помечен как безопасный для создания скриптов и инициализации, но не имеет цифровой подписи.

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

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

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

Ссылки

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

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

(c) Microsoft Corporation 2001, все права зарезервированы. Участие: Лори Б. Тертер (Lori B. Turner), корпорация Майкрософт.