Glengamoi (Forum) · AspHeute · .NET Heute (RSS-Suche) · AspxFiles (Wiki) · .NET Blogs

Mit ASP ein Word Dokument am Server generieren

Geschrieben von: Christian Holm
Kategorie: ASP Tricks

This printed page brought to you by AlphaSierraPapa

Mit dem Microsoft Word Object Modell lassen sich z.B. Word Dokumente auf einem Server generieren, die dann von einem Client weiter verwendet werden können. Dies kann sich bei der Generierung von Flyern, Intranetdokumenten oder Produktdaten als sehr nützlich erweisen. Der Weg durch den Word Object "Dschungel" ist aber bei anspruchsvolleren Aufgaben oftmals steinig.

Damit die Beispiele auf Ihrem Web Server laufen, müssen einige Vorbereitungen getroffen werden. Zuerst einmal muß natürlich Microsoft Word am Server installiert sein. Die Permissions für den Schreibzugriff und das Ausführen von Scripts müssen ebenfalls für das Web Server Verzeichnis gegeben sein.

Falls Sie beim Ausführen der Beispiele die sinnvolle Fehlermeldung Error 800A175D - Could Not Open Macro Storage erhalten, finden Sie im KB Artikel Q224338 auf der Microsoft MSDN Site die nötige Abhilfe um diesen zu beseitigen. Die Bemerkung "sinnvoll" habe ich mir deshalb erlaubt, da die Meldung nicht eindeutig auf das Problem hinweist, sondern von mehreren Ursachen folgen kann.

Das 101er Beispiel

Das erste Beispiel ist sehr einfach gehalten. Es wird lediglich ein Word Dokument erstellt, ein unformatierter Text eingefügt und dann im Web Server Verzeichnis gespeichert. Die Schritte, die hierfür nötig sind zeigt das nun folgende Listing der GenWord101Sample.asp Datei:

<%
   Set objWordApp = Server.CreateObject("Word.Application")
   
   objWordApp.Documents.Add
   
   objWordApp.Selection.TypeText "This is a plain text that you'll see in word."
   
   objWordApp.ActiveDocument.SaveAs Server.MapPath("MyDocument.doc")   
   objWordApp.Quit
   
   Set objWordApp = Nothing
%>

Wenn Sie die aus diesem Script generierte Datei MyDocument.doc in Word öffnen, können Sie den durch die TypeText Methode erstellten Text sehen. Da dies aber noch nicht alles ist, werden wir die Aufgabenstellung erweitern.

Ergebnisse aus einer Datenbankabfrage in Word darstellen

Natürlich können Sie wie mit Microsoft Excel auch eine Datenbankabfrage ausführen und das Ergebnis dem Word Objekt übergeben. Als Datenbank habe ich die MS Access Northwind Datenbank (wird standardmäßig mit Access oder mit dem SQL Server mitinstalliert) herangezogen, die sich für Übungszwecke hervorragend eignet. Damit sich die retournierten Datensätze in Grenzen halten, habe ich eine spezielle Auswahl mittels SQL Statements erstellt. Die Daten werden im Word Dokument in einer Tabelle gespeichert. Zweckmäßig verwendet das Script eine Dokumentenvorlage (POView01.dot) die eine formatierte Kopf- und Fußzeile beinhaltet.

Im Script (GenWordSample.asp) beginne ich mit der Datenbankabfrage. Ich hole mir die durch das SQL Statement bestimmten Daten aus der Northwind Datenbank:

Set objConn = Server.CreateObject("ADODB.Connection")
Set objRS = Server.CreateObject("ADODB.Recordset") 

strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source="
strConn = strConn & Server.MapPath("Northwind.mdb") 
strSQL ="SELECT Products.ProductName, Products.UnitPrice "
strSQL = strSQL & "FROM Products "
strSQL = strSQL & "WHERE Products.UnitPrice <= 15 "
strSQL = strSQL & "ORDER BY Products.ProductName ASC"

objConn.Open strConn

objRS.Open strSQL, objConn

If Not objRS.EOF and Not objRS.BOF Then
  arrData = objRS.GetRows()
End If 

objRS.Close
objConn.Close
Set objRS = Nothing
Set objConn = Nothing

Die Trennung von Datenbeschaffung und Word Dokument Generierung hat den Sinn, daß wenn bei der Datenbeschaffung etwas schief geht, ich leicht die weiterfolgende Instanzierung des Word Objekts verhindern kann. So wird auch vermieden, daß das Word Objekt untätig im Speicher verbleibt und auf die Daten wartet. Wenn Sie dies nicht beachten, können sich schnell mehrere Instanzen - durch folgende Requests auf die ASP Seite - des Word Objektes im Speicher sammeln und den Web Server in die Knie zwingen oder gar zum Absturz bringen.

Die angeforderten Daten speichere ich in einem Array namens arrData. Daher kann ich nach erfolgreicher Beendigung der Datenbankfrage die hierfür benötigten Objekte wieder freigeben.

Als nächstes wird das Word Dokument mit den Daten befüllt. Da Word mehrere Konstanten verwendet, die in VBScript als Zahlenwerte anzugeben sind, deklariere ich zunächst diese. Natürlich könnte man dort, wo sie benötigt werden auch sofort ihre Zahlenwerte einsetzen. Um aber später Änderungen leichter durchführen zukönnen, gebe ich diese lieber so an:

Const wdAlignParagraphCenter = 1
Const wdAlignParagraphLeft = 0
Const wdParagraph = 4
Const wdHorizontalPositionMargin = 0
Const wdTableLeft = -999998
Const wdCollapseEnd = 0

Nun ist es Zeit das Word Objekt mithilfe von Server.CreateObject zu instanzieren, ein neues Dokument zu erstellen und die Dokumentvorlage (POView01.dot) anzugeben:

Set WdApp = Server.CreateObject("Word.Application")
WdApp.Application.Visible = False

Set objDocument = WdApp.Documents.Add(Server.MapPath("POView01.dot"))

Mithilfe des erstellten Range Objektes (objRange) können wir das Dokumentschriftbild dezent formatieren:

Set objRange = objDocument.Range

With objRange
    .ParagraphFormat.Alignment = wdAlignParagraphCenter
    .Font.Size = 12
    .Font.Name = "Arial"
    .InsertAfter("Current Sales Report")
    .MoveEnd(wdParagraph)
    .Collapse(wdCollapseEnd)
End With

Es sind nun alle Vorbereitungen getroffen. Die Daten, die in dem Array arrData gespeichert sind können nun eingefügt werden. Um sie wie gesagt übersichtlicher darzustellen, schreiben wir sie in eine Tabelle. Dazu müssen wir ein neues Tabellenobjekt namens objTable erstellen:

Set objTable = WdApp.ActiveDocument.Tables.Add (objRange, Ubound(arrData,2), 2,1,1)

Die Tabelle wird innerhalb des im Range-Objekt objRange angegebenen Bereichs erstellt. Hierbei können auch die vorherig definierten Formatoptionen übernommen werden. Die Tabelle wird dann mit der Add Methode der Tables Collection erstellt.

Um nicht zuviel oder zuwenig Tabellenreihen zu erstellen, finde ich mit der UBound Function die obere Grenze des Arrays, in dem die Daten gespeichert sind. Dieser Wert bestimmt die maximale Reihenanzahl der Tabelle. Die letzten beiden optionalen Parameter sind DefaultTableBehavior und AutoFitBehavior:

DefaultTableBehavior gibt an, ob Word die Zellen der Tabelle an ihren Inhalt anpassen soll (AutoFit). AutoFitBehavior setzt die AutoFit Regeln fest, die von Word angeboten werden.

Jetzt wird der Inhalt des Arrays arrData in die Tabelle eingefügt:

For i = 0 To Ubound(arrData,2)
   objTable.Cell(i,1).Range.InsertAfter(arrData(0,i))
   objTable.Cell(i,2).Range.InsertAfter(arrData(1,i))
Next

Abschließend kann nun das Dokument im Web Server Verzeichnis gespeichert und dann die Applikation beendet werden:

objDocument.SaveAs Server.MapPath("Sales.doc")
objDocument.Close 

WdApp.Application.Quit

Schlußbemerkung

Dies war eine kleine Einführung in die vielen Möglichkeiten, die das Word Objekt bietet. So einfach dies auch klingen mag, durch die Möglichkeit der Verwendung von zwei unterschiedlichen Sprachformen (VBA und VBScript) mit diesem Objekt, passieren oft für einen Web Server fatale Fehler.

Wenn man aber die hier angeführten Hinweise beachtet, kann man sich viele Stunden in der Programmierung und später durch die Verwendung des Scriptes sparen.

This printed page brought to you by AlphaSierraPapa

Download des Codes

Klicken Sie hier, um den Download zu starten.
http://www.aspheute.com/code/20010319.zip

Verwandte Artikel

Ein Excel-Sheet am Server generieren und zum Client schicken
http:/www.aspheute.com/artikel/20010305.htm
Serverdaten clientseitig in Exceltemplates importieren
http:/www.aspheute.com/artikel/20020128.htm
Verwendung von XML-Schemas (XSD)
http:/www.aspheute.com/artikel/20010925.htm
Wordfiles richtig öffnen!
http:/www.aspheute.com/artikel/20020122.htm

Links zu anderen Sites

PRB: Error 800A175D - Could Not Open Macro Storage
http://support.microsoft.com/support/kb/articles/Q224/3/38.ASP

 

©2000-2006 AspHeute.com
Alle Rechte vorbehalten. Der Inhalt dieser Seiten ist urheberrechtlich geschützt.
Eine Übernahme von Texten (auch nur auszugsweise) oder Graphiken bedarf unserer schriftlichen Zustimmung.