Come usare un componente ActiveX VB per l'automazione di Word da Internet Explorer

Riepilogo

Questo articolo illustra come usare un componente ActiveX per l'automazione lato client di Word da una pagina Web di cui viene eseguito il rendering in Internet Explorer. L'uso di un componente ActiveX da una pagina Web invece di uno script incorporato nella pagina Web stessa offre diversi vantaggi:

  • Se si dispone già di codice Visual Basic che automatizza Microsoft Word, è possibile riutilizzare il codice nel browser convertendo il progetto di Visual Basic in un EXE ActiveX o in una DLL ActiveX.
  • Word non è contrassegnato come sicuro per la creazione di script. A seconda delle impostazioni di sicurezza in Internet Explorer, è possibile che il codice di Automazione di Word nello script non venga eseguito o che all'utente venga richiesto un avviso di sicurezza. Supponendo che il componente ActiveX soddisfi determinate linee guida, potrebbe essere contrassegnato come sicuro per la creazione di script per evitare questi problemi di sicurezza.
  • Visual Basic include diverse funzionalità che non è possibile usare con lo script in una pagina Web. Ad esempio, una funzionalità disponibile per Visual Basic ma non per lo script di pagina Web è la possibilità di chiamare l'API (Application Programming Interface) di Windows.

Uno scenario di sviluppo comune consiste nel presentare agli utenti un'interfaccia di pagina Web per la creazione di un documento di Word usando dati provenienti da un'origine o da una logica esterna. Anche se è possibile usare Automazione Word sul lato server per generare il documento e trasmetterlo al client, esistono molti svantaggi nell'uso di un approccio lato server che prevede Automazione di Word. Lo svantaggio principale è la scalabilità; Word è un server di automazione a elevato utilizzo di risorse e non è consigliato per la generazione di documenti nel server Web.

Usando un componente ActiveX per eseguire la generazione di documenti nel client, è possibile spostare l'automazione di Word a elevato utilizzo di risorse dal server Web. Questa è la soluzione presentata dal componente ActiveX di esempio illustrato in questo articolo. Sebbene l'esempio sia specifico di Automazione di Word, è possibile applicare gli stessi principi per l'automazione di altre applicazioni di Microsoft Office, ad esempio Microsoft Excel.

Ulteriori informazioni

Componente ActiveX di Visual Basic

Il componente ActiveX di Visual Basic in questo esempio interagisce con lo script della pagina Web per generare un documento di fattura ordine su richiesta dell'utente. L'applicazione Web può consentire al componente ActiveX di ottenere le informazioni sull'ordine per un determinato ID ordine oppure l'applicazione Web può scegliere di creare il pacchetto delle informazioni sull'ordine come XML e inviarle al componente ActiveX per l'elaborazione. In entrambi i casi, dopo che il componente ha ottenuto le informazioni sull'ordine, può automatizzare Word per compilare e visualizzare il documento di fattura per l'ordine.

Il componente ActiveX (AutomateWord) contiene una singola classe, la classe Invoice, che espone tre metodi:

  • Il metodo GetData usa ActiveX Data Objects (ADO) per estrarre informazioni su un ordine nel database di esempio Northwind. Le informazioni sull'ordine vengono archiviate nella variabile membro privato m_Data. È possibile chiamare il metodo GetData per consentire l'estrazione dei dati sul lato client.
  • Il metodo SendData usa Microsoft XML (MSXML) per riempire il m_Data variabile membro privato con le informazioni sull'ordine fornite dal chiamante. SendData prevede un parametro che rappresenta un oggetto DOMDocument per le informazioni sull'ordine. È possibile chiamare il metodo SendData per inviare le informazioni sull'ordine dalla pagina Web al componente. Con questo approccio, è possibile usare ASP per estrarre il lato server dati e presentare al client un'isola di dati XML che può essere usata per la generazione di documenti.
  • Il metodo MakeInvoice usa Automazione Word per compilare un documento contenente le informazioni sull'ordine nella variabile membro privata m_Data. Un documento archiviato nel server Web viene usato come punto di partenza per la fattura. Il chiamante può scegliere di visualizzare il documento di Word completato all'esterno del browser o di salvare il documento completato in un disco per un uso successivo.

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

Uso del componente ActiveX da una pagina Web

Autoword1.htm illustra come usare il metodo GetData per consentire al componente ActiveX di recuperare il lato client dei dati dell'ordine e compilare il documento.

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>

Lo script in Autoword1.htm usa il componente ActiveX per visualizzare il documento completato all'esterno del browser. È anche possibile scegliere di salvare il documento completato e visualizzarlo nel browser; In questo modo, tuttavia, è necessario salvare il documento di Word in un disco. Il componente può salvare il documento come C:\Invoice.doc nell'unità locale del client. Poiché il componente ActiveX è contrassegnato come sicuro per lo scripting, al client viene richiesto di confermare il salvataggio.

Per visualizzare il documento completato nel browser, modificare la chiamata a MakeInvoice in Autoword1.htm come segue:

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

Autoword2.htm illustra come utilizzare il metodo SendData per inviare i dati dell'ordine come oggetto DOMDocument al componente ActiveX per la generazione del documento completato. DOMDocument viene creato da un'isola di dati XML che si trova nella pagina Web. Affinché il componente ActiveX elabori correttamente le informazioni sull'ordine inviate dal chiamante, il codice XML deve essere ben formato e strutturato in modo che il componente possa interpretarlo come informazioni sull'ordine.

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>

Sia in Autoword1.htm che in Autoword2.htm, è necessario notare che il componente ActiveX viene creato tramite un tag anziché la funzione CreateObject. Lo scopo dell'uso del tag consiste nell'abilitare il download automatico del componente ActiveX per gli utenti che non hanno già installato il componente. Se un utente visita una di queste pagine e il componente non è installato, il componente viene scaricato dal file CAB nell'URL indicato nell'attributo CODEBASE. A seconda delle impostazioni di sicurezza dell'utente in Internet Explorer, può prima ricevere una richiesta per confermare il download.

NOTA: il file CAB incluso in Autoword.exe è stato creato con la Creazione guidata pacchetto e distribuzione per Visual Basic. Il componente ActiveX nel pacchetto è contrassegnato come sicuro per la creazione di script e l'inizializzazione, ma non è firmato digitalmente.

Per altre informazioni sulla creazione di download di componenti Internet, sulla firma digitale e sul contrassegno dei componenti come sicuri per la creazione di script e l'inizializzazione, vedere i seguenti siti Web microsoft developer network (MSDN):

Firma e controllo del codice con Authenticode https://msdn.microsoft.com/en-us/library/ms537364.aspx

Inizializzazione e scripting sicuri per i controlli ActiveX https://msdn.microsoft.com/en-us/library/Aa751977.aspx

Riferimenti

Per altre informazioni, fare clic sui numeri degli articoli seguenti per visualizzare gli articoli della Microsoft Knowledge Base:

257757 INFO: l'automazione di Office per l'esecuzione automatica non è consigliata o supportata

(c) Microsoft Corporation 2001, Tutti i diritti riservati. Contributi di Lori B. Turner, Microsoft Corporation.