C++ Builder Snippets  


MS-Word Dokument basierend auf einer Vorlage erzeugen, ausfüllen, speichern, drucken:
 
Screenshot des Beispielprojekts Die Frage "wie kann ich die Word-Vorlagen für Protokolle, Berichte oder Serienbriefe aus meinem Programm heraus mit Daten füttern und anschließend ausdrucken oder speichern ? " gehört inzwischen zu den FAQs in jedem Programmierforum.

Eine solche Funktionalität hat mehrere Vorteile: sie lässt sich verhältnismäßig einfach in ein Programm einbinden, erspart eigene (oft programmierintensive) Ausdrucksroutinen, generiert auf vielen Systemen lesbare Dateien und bietet dem Anwender eine hohe Flexibilität bei der Gestaltung des Dokuments.

Das nachfolgende Beispiel zeigt, wie MS-Word via OLE-Schittstelle gesteuert werden kann. Word muss auf Ihrem System natürlich installiert sein. Das Programm initialisiert zunächst den Word OLE-Server, erzeugt ein neues Dokument basierend auf der zuvor erstellten Vorlage (Datei "Vorlage.doc" im Quellcode-Archiv), springt der Reihe nach alle in der Vorlage definierte Textmarken an und trägt die Inhalte der entsprechenden Eingabefeldern an den Textmarkenpositionen ein. Anschließend wird das Dokument gespeichert oder gedruckt und Word beendet (nur wenn das Programm nicht schon vorher aktiv war).

Gespeichert wird das generierte Dokument in der Datei "Brief.doc" im Programmverzeichnis.

Hinweis zum Erstellen der Word-Vorlage: die Textmarken werden mit Hilfe des Menüpunktes " Einfügen > Textmarke" definiert bzw. gelöscht. Vor dem Setzen der Textmarke muss der aus ihrem Programm heraus zu überschreibende Textabschnitt selektiert sein !

Durch die Verwendung der späten Bindung (zur Programmlaufzeit) ist der Code mit allen Word-Versionen ab 95 lauffähig, es müssen keine Type Libraries eingebunden werden. Das Beispielprogramm wurde mit Word 97, 2000 und 2002 (Office XP) getestet.



Programm-Quellcode:

Header-Datei FormMain.h zum Hauptformular der Anwendung:
//---------------------------------------------------------------------------
#ifndef FormMainH
#define FormMainH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ComObj.hpp>
#include <utilcls.h>

// Definition der Variablen für die
// Übergabe an "GoTo"-Funktion
typedef enum WdGoToItem
{
  wdGoToBookmark = 0xFFFFFFFF,
  wdGoToSection = 0,
  wdGoToPage = 1,
  wdGoToTable = 2,
  wdGoToLine = 3,
  wdGoToFootnote = 4,
  wdGoToEndnote = 5,
  wdGoToComment = 6,
  wdGoToField = 7,
  wdGoToGraphic = 8,
  wdGoToObject = 9,
  wdGoToEquation = 10,
  wdGoToHeading = 11,
  wdGoToPercent = 12,
  wdGoToSpellingError = 13,
  wdGoToGrammaticalError = 14,
  wdGoToProofreadingError = 15
} WdGoToItem;

//---------------------------------------------------------------------------
// Hauptfenster der Anwendung
//---------------------------------------------------------------------------
class TfrmMain : public TForm
{
__published:  // Von der IDE verwaltete Komponenten
  TButton *btnCreateAndSaveDoc;
  TEdit *editAnrede;
  TLabel *Label1;
  TEdit *editEmpfaenger;
  TLabel *Label2;
  TEdit *editAnschrift;
  TLabel *Label3;
  TLabel *Label4;
  TEdit *editPLZ_Ort;
  TLabel *lblBetreff;
  TEdit *editBetreff;
  TMemo *memoText;
  TLabel *Label6;
  TLabel *Label7;
  TEdit *editErsteller;
  TButton *btnCreateAndPrintDoc;
  void __fastcall btnCreateAndSaveDocClick(TObject *Sender);
  void __fastcall btnCreateAndPrintDocClick(TObject *Sender);

private:  // Anwender-Deklarationen

  // Initialisierung des Word OLE-Servers
  bool __fastcall InitOleServer(Variant &vOLEWord);

  // Word-Dokument erzeugen, ggf. speichern und/oder drucken
  void __fastcall CreateDocument(Variant &vOLEWord,
    AnsiString slTemplateFile, AnsiString slSaveFile, bool blPrint);

  // Beenden des Word OLE-Servers
  void __fastcall TerminateOleServer(Variant &vOLEWord);

public:    // Anwender-Deklarationen
  __fastcall TfrmMain(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TfrmMain *frmMain;
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
// Hauptfenster der WordControl-Beispielanwendung
// http://rad.bytesandmore.de, Serge Kreutzmann, 2002
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "FormMain.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TfrmMain *frmMain;
//---------------------------------------------------------------------------
__fastcall TfrmMain::TfrmMain(TComponent* Owner)
  : TForm(Owner)
{
}

//---------------------------------------------------------------------------
// Initialisierung des Word OLE-Servers
//---------------------------------------------------------------------------
bool __fastcall TfrmMain::InitOleServer(Variant &vOLEWord)
{
  vOLEWord = Unassigned;
  try
  {
    // vielleicht läuft Word ja bereits (wenn nicht, wird hier
    // eine Exception generiert - aber die ist ja behandelt :)
    vOLEWord = GetActiveOleObject("Word.Application");
    return false;
  }
  catch(...)
  {
     try
     {
       // vielleicht läuft Word ja bereits...
       vOLEWord = CreateOleObject("Word.Application");
       return true;
     }
     catch(Exception& e)
     {
        // Wahrscheinlich kein Word auf dem Rechner...
        Application->MessageBox(e.Message.c_str(),"OLE-Error",MB_ICONERROR);
        vOLEWord = Unassigned;
     }
  }
  return true;
}

//---------------------------------------------------------------------------
// Beenden des Word OLE-Servers
//---------------------------------------------------------------------------
void __fastcall TfrmMain::TerminateOleServer(Variant &vOLEWord)
{
  // Word OLE-Server beenden:
  if(!vOLEWord.IsEmpty())
  {
    vOLEWord.OlePropertyGet("Application").OleProcedure("Quit");
    vOLEWord = Unassigned;
  }
}

//---------------------------------------------------------------------------
// Word-Dokument erzeugen, ggf. speichern und/oder drucken
//---------------------------------------------------------------------------
void __fastcall TfrmMain::CreateDocument(Variant &vOLEWord,
  AnsiString slTemplateFile, AnsiString slSaveFile, bool blPrint)
{
  try
  {
    // falls Word-Fenster sichtbar sein soll,
    // muss folgende Zeile aktiviert werden:
    // vOLEWord.OlePropertySet("Visible", true);

    // Falls die Vorlagen-Datei nicht existiert, schimpfen und beenden:
    if(!FileExists(slTemplateFile))
    {
      Application->MessageBox("Vorlagendatei nicht gefunden !",
        "Abbruch",MB_ICONERROR);
      return;
    }

    // Referenz auf die "Documents"-Eigenschaft besorgen
    Variant vDokuments = vOLEWord.OlePropertyGet("Documents");
    // neues Dokument mit slTemplateFile als Dokumentenvorlage erzeugen:
    vDokuments.Exec(Procedure("Add") << slTemplateFile << 0);

    //--------------------------------------------------
    // Formular-Felder ausfüllen
    //--------------------------------------------------

    // Referenz auf die "Selection"-Eigenschaft besorgen
    Variant vSelection = vOLEWord.OlePropertyGet("Selection");

    // Zu Textmarke "Empfaenger" gehen:
    vSelection.Exec(Procedure("GoTo") << (int)wdGoToBookmark <<
       0 << 0 << "Empfaenger");
    // den Text aus dem Eingabefeld eintragen:
    vSelection.OleProcedure("TypeText",(VARIANT)
      ((Variant)editEmpfaenger->Text.c_str()));

    // Zu Textmarke "Anschrift" gehen:
    vSelection.Exec(Procedure("GoTo") << (int)wdGoToBookmark <<
       0 << 0 << "Anschrift");
    // den Text aus dem Eingabefeld eintragen:
    vSelection.OleProcedure("TypeText",(VARIANT)
      ((Variant)editAnschrift->Text.c_str()));

    // Zu Textmarke "PLZ_Ort" gehen:
    vSelection.Exec(Procedure("GoTo") << (int)wdGoToBookmark <<
       0 << 0 << "PLZ_Ort");
    // den Text aus dem Eingabefeld eintragen:
    vSelection.OleProcedure("TypeText",(VARIANT)
      ((Variant)editPLZ_Ort->Text.c_str()));

    // Zu Textmarke "Betreff" gehen:
    vSelection.Exec(Procedure("GoTo") << (int)wdGoToBookmark <<
       0 << 0 << "Betreff");
    // den Text aus dem Eingabefeld eintragen:
    vSelection.OleProcedure("TypeText",(VARIANT)
     ((Variant)editBetreff->Text.c_str()));

    // Zu Textmarke "Anrede" gehen:
    vSelection.Exec(Procedure("GoTo") << (int)wdGoToBookmark <<
       0 << 0 << "Anrede");
    // den Text aus dem Eingabefeld eintragen:
    vSelection.OleProcedure("TypeText",(VARIANT)
      ((Variant)editAnrede->Text.c_str()));

    // Zu Textmarke "Text" gehen:
    vSelection.Exec(Procedure("GoTo") << (int)wdGoToBookmark <<
       0 << 0 << "Text");
    // den Text aus dem Eingabefeld eintragen:
    vSelection.OleProcedure("TypeText",(VARIANT)
      ((Variant)memoText->Lines->Text.c_str()));

    // Zu Textmarke "Ersteller" gehen:
    vSelection.Exec(Procedure("GoTo") << (int)wdGoToBookmark <<
       0 << 0 << "Ersteller");
    // den Text aus dem Eingabefeld eintragen:
    vSelection.OleProcedure("TypeText",(VARIANT)
      ((Variant)editErsteller->Text.c_str()));

    // ggf. drucken:
    if(blPrint)
      vOLEWord.OlePropertyGet("Application").OleProcedure("PrintOut");

    // ggf. speichern:
    Variant vActiveDocument = vOLEWord.OlePropertyGet("ActiveDocument");
    if(slSaveFile != EmptyStr)
      vActiveDocument.Exec(Procedure("SaveAs") << slSaveFile << 0 << 0
        << "" << 1 << "" << 0 << 0 << 0 << 0 << 0 );

    // "gespeichert"-Flag in Word setzen, damit keine Nachfragen kommen
    vActiveDocument.OlePropertySet("Saved", true);

    // Datei schließen:
    vActiveDocument.Exec(Procedure("Close"));
  }
  catch(Exception& e)
  {
    Application->MessageBox( e.Message.c_str(),"OLE-Error",MB_ICONERROR);
  }
}

//---------------------------------------------------------------------------
// Dokument erzeugen und speichern
//---------------------------------------------------------------------------
void __fastcall TfrmMain::btnCreateAndSaveDocClick(TObject *Sender)
{
  // OLE-Server initialisieren, die Variable blWordStarted
  // wird auf true gesetzt falls Word nicht bereits aktiv war
  Variant vOLEWord;
  bool blWordStarted = InitOleServer(vOLEWord);

  // Falls die Initialisierung des OLE-Servers erfolgreich,
  // Dokument erzeugen und speichern:
  if(!vOLEWord.IsEmpty())
    CreateDocument(vOLEWord, ExtractFilePath(ParamStr(0))+"vorlage.doc",
      ExtractFilePath(ParamStr(0))+"Brief.doc", false);

  // Word nur beenden, wenn es von uns zuvor gestartet wurde:
  if(blWordStarted) TerminateOleServer(vOLEWord);
}

//---------------------------------------------------------------------------
// Dokument erzeugen und drucken
//---------------------------------------------------------------------------
void __fastcall TfrmMain::btnCreateAndPrintDocClick(TObject *Sender)
{
  // OLE-Server initialisieren, die Variable blWordStarted
  // wird auf true gesetzt falls Word nicht bereits aktiv war
  Variant vOLEWord;
  bool blWordStarted = InitOleServer(vOLEWord);

  // Falls die Initialisierung des OLE-Servers erfolgreich,
  // Dokument erzeugen und drucken:
  if(!vOLEWord.IsEmpty())
    CreateDocument(vOLEWord, ExtractFilePath(ParamStr(0))+"vorlage.doc",
      EmptyStr, true);
  // Word nur beenden, wenn es von uns zuvor gestartet wurde:
  if(blWordStarted) TerminateOleServer(vOLEWord);
}
//---------------------------------------------------------------------------

  Download BCB5
Projekt-Quellcode
Download
Demo-Exe

© '99-2002 by S. Kreutzmann