Comment utiliser un composant ActiveX VB pour Word Automation à partir d’Internet Explorer

Résumé

Cet article explique comment utiliser un composant ActiveX pour l’automatisation côté client de Word à partir d’une page web affichée dans Internet Explorer. L’utilisation d’un composant ActiveX à partir d’une page Web au lieu d’un script incorporé dans la page Web elle-même présente plusieurs avantages :

  • Si vous avez déjà du code Visual Basic qui automatise Microsoft Word, vous pouvez réutiliser votre code dans le navigateur en convertissant votre projet Visual Basic en une DLL ActiveX EXE ou ActiveX.
  • Word n’est pas marqué comme sécurisé pour les scripts. Selon les paramètres de sécurité dans Internet Explorer, le code Word Automation dans le script peut ne pas s’exécuter ou l’utilisateur peut être invité à recourir à un avertissement de sécurité. En supposant que votre composant ActiveX respecte certaines instructions, il peut être marqué comme sécurisé pour les scripts afin d’éviter ces problèmes de sécurité.
  • Visual Basic comporte plusieurs fonctionnalités que vous ne pouvez pas utiliser avec un script dans une page web. Par exemple, une fonctionnalité disponible pour Visual Basic, mais pas pour le script de page web est la possibilité d’appeler l’interface de programmation d’applications Windows (API).

Un scénario de développement courant consiste à présenter aux utilisateurs une interface de page web pour la création d’un document Word à l’aide de données provenant d’une source ou d’une logique externe. Bien que vous puissiez utiliser Word Automation côté serveur pour générer le document et le diffuser en continu vers le client, l’utilisation d’une approche côté serveur qui implique Word Automation présente de nombreux inconvénients. Le principal inconvénient est l’extensibilité; Word est un serveur Automation très gourmand en ressources et n’est pas recommandé pour la génération de documents sur le serveur Web.

En utilisant un composant ActiveX pour effectuer la génération de documents sur le client, vous pouvez déplacer Word Automation, qui nécessite beaucoup de ressources, du serveur Web. Il s’agit de la solution présentée par l’exemple de composant ActiveX décrit dans cet article. Bien que l’exemple soit spécifique à Word Automation, les mêmes principes peuvent être appliqués pour automatiser d’autres applications Microsoft Office, telles que Microsoft Excel.

Informations supplémentaires

Composant ActiveX Visual Basic

Le composant Visual Basic ActiveX de cet exemple interagit avec le script de page web pour générer un document de facture de commande à la demande de l’utilisateur. L’application web peut autoriser le composant ActiveX à obtenir les informations de commande pour un ID de commande donné, ou l’application web peut choisir de empaqueter les informations de commande au format XML et de les envoyer au composant ActiveX pour traitement. Dans les deux cas, une fois que le composant a obtenu les informations de commande, il peut automatiser Word pour générer et afficher le document de facture pour la commande.

Le composant ActiveX (AutomateWord) contient une seule classe, la classe Invoice, qui expose trois méthodes :

  • La méthode GetData utilise ActiveX Data Objects (ADO) pour extraire des informations sur une commande dans l’exemple de base de données Northwind. Les informations de commande sont stockées dans la variable membre privée m_Data. La méthode GetData peut être appelée pour permettre l’extraction des données côté client.
  • La méthode SendData utilise Microsoft XML (MSXML) pour remplir la variable membre privée m_Data avec les informations de commande fournies par l’appelant. SendData attend un paramètre qui représente un objet DOMDocument pour les informations de commande. La méthode SendData peut être appelée pour envoyer les informations de commande de la page Web au composant. Avec cette approche, vous pouvez utiliser ASP pour extraire les données côté serveur et présenter au client une île de données XML qui peut être utilisée pour la génération de document.
  • La méthode MakeInvoice utilise Word Automation pour créer un document qui contient les informations de commande dans la variable membre privée m_Data. Un document stocké sur le serveur Web est utilisé comme point de départ pour la facture. L’appelant peut choisir d’afficher le document Word terminé en dehors du navigateur ou d’enregistrer le document terminé sur un disque pour une utilisation ultérieure.

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

Utilisation du composant ActiveX à partir d’une page web

Autoword1.htm montre comment utiliser la méthode GetData pour permettre au composant ActiveX de récupérer les données de commande côté client et de générer le document.

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>

Le script dans Autoword1.htm utilise le composant ActiveX pour afficher le document terminé en dehors du navigateur. Vous pouvez également choisir d’enregistrer le document terminé et de l’afficher dans le navigateur ; Toutefois, pour ce faire, le document Word doit être enregistré sur un disque. Le composant peut enregistrer le document en tant que C:\Invoice.doc sur le lecteur local du client. Étant donné que le composant ActiveX est marqué comme sécurisé pour les scripts, le client est invité à confirmer l’enregistrement.

Si vous souhaitez afficher le document terminé dans le navigateur, remplacez l’appel à MakeInvoice dans Autoword1.htm par ce qui suit :

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

Autoword2.htm montre comment utiliser la méthode SendData pour envoyer les données de commande en tant qu’objet DOMDocument au composant ActiveX pour générer le document terminé. Le DOMDocument est créé à partir d’une île de données XML qui réside sur la page Web. Pour que le composant ActiveX traite correctement les informations de commande envoyées par l’appelant, le code XML doit être bien formé et structuré afin que le composant puisse les interpréter comme des informations de commande.

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>

Dans Autoword1.htm et Autoword2.htm, vous devez noter que le composant ActiveX est instancié au moyen d’une balise plutôt que de la fonction CreateObject. L’objectif de l’utilisation de la balise est d’activer le téléchargement automatique du composant ActiveX pour les utilisateurs qui n’ont pas encore installé le composant. Si un utilisateur visite l’une de ces pages et que le composant n’est pas installé, le composant est téléchargé à partir du fichier CAB (Cabinet) à l’URL indiquée dans l’attribut CODEBASE. Selon les paramètres de sécurité de l’utilisateur dans Internet Explorer, il peut d’abord recevoir une invite pour confirmer le téléchargement.

REMARQUE : Le fichier CAB inclus dans Autoword.exe a été créé avec l’Assistant Package et Déploiement pour Visual Basic. Le composant ActiveX dans le package est marqué comme sécurisé pour les scripts et l’initialisation, mais n’est pas signé numériquement.

Pour plus d’informations sur la création de téléchargements de composants Internet, la signature numérique et le marquage des composants comme sécurisés pour l’écriture de scripts et l’initialisation, consultez les sites Web Microsoft Developer Network (MSDN) suivants :

Signature et vérification du code avec Authenticode https://msdn.microsoft.com/en-us/library/ms537364.aspx

Initialisation sécurisée et script pour les contrôles ActiveX https://msdn.microsoft.com/en-us/library/Aa751977.aspx

References

Pour plus d’informations, cliquez sur les numéros d’article suivants pour afficher les articles de la Base de connaissances Microsoft :

257757 INFO : l’automatisation d’Office pour l’exécution sans assistance n’est pas recommandée ou prise en charge

(c) Microsoft Corporation 2001, Tous droits réservés. Contributions de Lori B. Turner, Microsoft Corporation.