Programmieren mit dBASE PLUS: Kommunikation mit anderen Programmen


Allgemeines zum Zugriff auf externe Programme Bearbeiten

Mit dBase ist es seit Version 5 möglich, mit anderen Programmen über OLE zu kommunizieren, die eine OLE-Schnittstelle bereitstellen. Dadurch wird eine andere Anwendung quasi ferngesteuert. Die Möglichkeiten der Fernsteuerung sind abhängig davon, welche Funktionen die Anwendung für den Zugriff über OLE bereitstellt. In Microsoft Word oder Microsoft Excel kann eigentlich die komplette Anwendung gesteuert werden. Die Möglichkeiten entsprechen denen der Word und Excel Makrosprache.

Die Klasse OLEAUTOCLIENT Bearbeiten

Um eine Verbindung mit einer anderen Anwendung zu initiieren, wird die Klasse OLEAUTOCLIENT() verwendet. Als Parameter erwartet die Klasse den Classname der Anwendung und gibt ein OLE-Objekt zurück, über das die Anwendung gesteuert werden kann.

Der Classname findet sich z.B. in der Registrierdatenbank von Windows unter HKEY_CLASSES_ROOT. Allerdings sind nicht alle dort eingetragenen Klassennamen für die Verwendung mit OLE ausgelegt.

In dieser Beschreibung wollen wir uns mit den zwei Anwendungen befassen, die wahrscheinlich am meisten verwendet werden. Microsoft Word und Excel. Diese beiden Programme bieten eine solche Vielfalt an Möglichkeiten, dass hier exemplarisch verschiedene Methoden des Umgangs mit OLEAUTOCLIENT aufgezeigt werden können. Diese können dann auch als Grundlage für Versuche mit anderen Programmen dienen.

Ein einfaches Beispiel mit Word und Excel Bearbeiten

Um den Grundsätzlichen Umgang mit OLE-Objekten zu verdeutlichen hier ein kleines Beispiel um in Word ein Dokument zu öffnen:

Anmerkung: Um die Beispiele übersichtlicher zu machen, verzichte ich auf Fehlerprüfungen wie z.B. im folgenden die vorherige Überprüfung ob das Dokument überhaupt existiert. Solche Prüfungen sollten bei produktiv eingesetzten Programmen natürlich immer gemacht werden um Fehlermeldungen aus den OLE-Anwendungen zu vermeiden!'

oWord = NEW OLEAUTOCLIENT("word.application")
oWord.Documents.Open("c:\test.doc")
oWord.visible = true 
oExcel = NEW OLEAUTOCLIENT("excel.application")
oExcel.Workbooks.Open("c:\test.xls")
oExcel.visible = true 

In beiden Beispielen wird in der ersten Zeile die OLE-Verbindung zur Anwendung aufgebaut, in der zweiten Zeile wird die Datei geöffnet und in der dritten Zeile wird die Anwendung angezeigt.

Es wird schon deutlich, dass sich der Umgang mit OLE-Objekten nicht wesentlich mit dem Umgang mit dBase-Objekten unterscheidet. Es gibt auch hier Eigenschaften und Methoden, die auch eine vergleichbare Syntax haben.

Anmerkung: Die Variablennamen oWord und oExcel können natürlich frei gewählt werden. Ich verwende jedoch möglichst immer sprechende Namen mit einem Kleinbuchstaben am Anfang, der den Typ der Variablen anzeigt.

Ermitteln von Funktionen der OLE-Anwendung Bearbeiten

Um festzustellen, welche Funktionen eine Anwendung zur Verfügung stellt, gibt es einige Möglichkeiten.

  • Evtl. vorhandene Dokumentation
  • Evtl. vorhandener Makroeditor
  • Inspect() Funktion aus dBASE
  • Jemanden fragen, der es vielleicht weiß
  • Ausprobieren

Da wir uns mit Word und Excel beschäftigen ist die Verwendung des Makroeditors der jeweiligen Anwendung zu empfehlen.

Zuerst sollte klar sein, was eigentlich in der Anwendung gemacht werden soll, dann wird ein Makro erstellt, das genau das tut. Schließlich kann das Makro im Quelltext studiert werden um die verwendeten Eigenschaften und Methoden zu ermitteln.

Das hört sich auf den ersten Blick nicht sehr kompliziert an, wird es aber, wenn komplexere Aktionen in der Anwendung ausgeführt werden sollen. Auch ist eine 1:1 Adaption in dBase manchmal nicht oder nur über Umwege möglich. Doch das wird beim Testen schnell deutlich.

Grundsätzlich ist es auch nicht verkehrt sich einmal mit dem Objekt-Modell von Word oder Excel zu befassen. Auch dort gibt es wie in dBase Objekte mit Unterobjekten und Unter-Unterobjekten. Und alle diese Objekte und Unterobjekte haben eigene Eigenschaften und Methoden.

Bei anderen Anwendungen hilft oftmals nur ausprobieren, da Dokumentationen solcher Funktionen meist dünn gesät sind - wenn es überhaupt welche gibt.

Direkter Zugriff oder Befehlsbibliothek? Bearbeiten

Wenn mit einem neuen Kapitel in der Programmierung begonnen wird - was die OLE-Programmierung auf jeden Fall ist - dann geht beim Testen und dem Glücksgefühl über die ersten Erfolge oft die Struktur baden. Da auch meist alles schnell gehen muss, wird dann in der Anwendung schnell die funktionierende Routine eingebaut und alles ist gut.

Spätestens aber, wenn mal wieder ein Wechsel der Word-Version ansteht und dabei vielleicht die Makrosprache verändert wurde - wie das beim Sprung von den 6er-Version auf die 2000er Version war - muss der komplette Quellcode durchforstet werden und dort die entsprechenden Anpassungen durchgeführt werden. Und wenn dann auch noch unterschiedliche Kunden mit verschiedenen Word- oder Excelversionen das gleiche Programm verwenden, wird es richtig aufwändig.

Aus diesem Grund rate ich dringend dazu, alle OLE-Befehle, die in der eigenen Applikation verwendet werden, in einer Funktionsbibliothek oder einer eigenen Klasse unterzubringen. Wir haben dazu zwei Funktionsbibliotheken erstellt (word.prg und excel.prg), die mit entsprechenden Parametern aufgerufen werden. In den Bibliotheken wird dann die Version von Word oder Excel überprüft und es werden entsprechend unterschiedliche Befehle ausgeführt, je nach Version. Dadurch können dann auch die Befehle einer neuen Version an einer zentralen Stelle zugefügt werden, ohne die eigentliche Applikation verändern zu müssen.

Natürlich kann das auch in einer cc-Klasse gemacht werden. Ich habe das in prg-Dateien weil - wie sollte es auch anders sein - das über Jahre gewachsen ist!

Aufbau einer Bibliothek Bearbeiten

Wie bereits erwähnt, verwende ich eine prg-Datei und werde im folgenden auch kurz die Verwendung einer solchen Datei erläutern.

Als Parameter werden übergeben das OLE-Objekt, der auszuführende Befehl und eine unterschiedliche Anzahl von Parametern für die eigentlichen Aktionen. Eine Besonderheit ist dabei noch, dass zumindest beim Aufruf der OLE-Anwendung bekannt sein muss, ob es sich beispielsweise um Word 6 oder Word 97/2000/XP handelt. Ich habe dies durch eine globale _app Variable gelöst (auch wenn globale Variablen nicht zum guten Stil gehören, halte ich dies hier für sinnvoll). In dieser wird festgelegt welche Version verwendet wird. In den einzelnen Funktionen wird dann auch anhand dieser Versionsnummer unterschiedlich verzweigt.

/* word.prg 
   Bibliothek OLE-Zugriff auf Microsoft Word
*/
PARAMETERS oWd, cAktion, oOpt

IF EMPTY(cAktion)
  // Keine Aktion übergeben
  return
ENDIF

// Welche Word-Version ? 
IF TYPE("_app.wordversion") # "U"
   nVersion = 8
ELSE
   nVersion = _app.wordversion
ENDIF

objRueckgabe = NULL
cAktion = UPPER(cAktion)

DO CASE
   CASE cAktion == "START"
		DO CASE
			CASE nVersion = 6
				 objRueckgabe = NEW OLEAUTOCLIENT("word.basic")
			OTHER
				 objRueckgabe = NEW OLEAUTOCLIENT("word.application")
		ENDCASE
		
   CASE cAktion == "OEFFNEN"
        DO CASE
           CASE nVersion = 6
                oWd.DateiÖffnen(oOpt)
           OTHER
			    oWd.Documents.Open(oOpt)
        ENDCASE
   CASE cAktion == "ANZEIGEN"
        DO CASE
           CASE nVersion = 6
                cTmp = TRIM(oWd.fenstername())
                IF NOT EMPTY(cTmp)
                   oWd.aktivieren(cTmp)
                ENDIF
           OTHER
			    oWd.visible = true
			    oWd.activate()
        ENDCASE
ENDCASE

Im obigen Beispiel ist exemplarisch an drei Funktionen dargestellt wie die Bibliothek aufgebaut ist. Sinnvoll ist natürlich im Kopf oder bei den einzelnen Funktionen eine Beschreibung, sowie die benötigten Parameter einzufügen. Teilweise werden mehr als ein Parameter gebraucht. In diesem Fall übergebe ich ein Array mit Parametern, die in der jeweiligen Funktion ausgewertet werden.

Aus einem dbase-Programm sähe der Aufruf dann folgendermassen aus:

oWord = word("","START")
word(oWord,"OEFFNEN","c:\test.doc")
word(oWord,"ANZEIGEN")


Alternativ dazu kann die Bibliothek auch als Klasse programmiert werden:

/* word.cc
   Bibliothek OLE-Zugriff auf Microsoft Word
*/
class word() of object custom

local oWord

try
  oWord = new oleautoclient("word.application")
catch (exception e)
  oWord = new oleautoclient("word.basic")
endtry
this.oWord = oWord
this.nVersion = oWord.version


function OEFFNEN(oOpt)
  DO CASE
    CASE this.nVersion == 6
      this.oWord.DateiÖffnen(oOpt)
    OTHERWISE
      this.oWord.Documents.Open(oOpt)
  ENDCASE
return

function ANZEIGEN()
  DO CASE
    CASE this.nVersion = 6
      IF NOT EMPTY(TRIM(this.oWord.fenstername()))
        this.oWord.aktivieren(TRIM(this.oWord.fenstername()))
      ENDIF
    OTHERWISE
      this.oWord.visible = true
      this.oWord.activate()
    ENDCASE
return

function release
  this.oWord.quit()
  this.oWord = null
return

endclass

Der Aufruf in dBase sieht dann leicht geändert aus:

set procedure to word.cc additive
oWord = new word()
oWord.OEFFNEN("c:\test.doc")
oWord.ANZEIGEN()

Steuerung von Word Bearbeiten

In diesem Abschnitt sollen einige Beispiele für die Verwendung mit Word gezeigt werden. Alle Beispiele beziehen sich auf Word 2000, funktionieren aber auch mit Word 97 bis Word XP. Es werden immer nur die Beispiele für den direkten Aufruf verwendet, nicht für die Verwendung einer Bibliothek. Diese sollte sich - wie bereits im letzten Abschnitt erwähnt - jede/r nach eigenen Anforderungen erstellen.

Starten, Anzeigen und Beenden von Word Bearbeiten

oWord = NEW OLEAUTOCLIENT("word.application")  // Erstellen der OLE-Instanz
oWord.visible = true // Word anzeigen
oWord.activate() // Word aktivieren
oWord.quit() // Word schliessen

Dokument: Neu, Öffnen, Speichern, Drucken, Schließen Bearbeiten

Neues Dokument
oWord.Documents.Add()

Wenn eine Dokumentvorlage verwendet werden soll, kann diese als Parameter übergeben werden:
oWord.Documents.Add("c:\vorlagen\vorlage.dot")

Dokument öffnen
oWord.Documents.Open("c:\text.doc")

Dokument speichern
Speichern unter einem Dateinamen
oWord.ActiveDocument.SaveAs("c:\test1.doc")

Nur Speichern (Falls noch kein Dateiname vorhanden, wird ein entsprechendes Word-Dialogfeld gezeigt)
oWord.ActiveDocument.Save()

Dokument drucken
oWord.activedocument.printout()

Dokument schließen
Mit Speichern (Wenn Änderungen am Dokument gemacht wurden kommt das entsprechende Word-Dialogfeld)
oWord.activedocument.close(-1)

Text einfügen, Textmarken, Navigation im Text Bearbeiten

Text an der Cursorposition einfügen
oWord.selection.typetext("Texttext")

Textmarke an der Cursorposition einfügen oWord.ActiveDocument.Bookmarks.add("textmarke1")

Zu Textmarke springen

IF oWord.activedocument.bookmarks.exists("textmarke1") = true
  oWord.ActiveDocument.Bookmarks.item("textmarke1").select()
ENDIF

Navigation im text
Zum Anfang des Textes
oWord.Selection.FirstKey(6)

Zum Ende des Textes
oWord.Selection.EndKey(6)

Ein Zeichen nach links
oWord.Selection.MoveLeft()

Ein Zeichen nach rechts
oWord.Selection.Moveright()

Ein Zeichen nach unten
oWord.Selection.MoveDown()

Ein Zeichen nach oben
oWord.Selection.MoveUp()

Backspace-Taste
oWord.Selection.TypeBackspace()

ENTF-Taste
oWord.Selection.Delete()

Text formatieren Bearbeiten

Markierter Text kann beliebig formatiert werden. Es ist auch möglich vor dem Einfügen von Text eine Schriftart oder Größe einzustellen und nach dem Einfügen wieder zurückzustellen:

Schriftart und Schrifteigenschaften festlegen.

oWord.Application.Selection.Font.Name = "Verdana" // Schriftart
oWord.Application.Selection.Font.Size = 11 // Schriftgröße 11 Punkt
oWord.Application.Selection.Font.Bold = 1 // Fett
oWord.Application.Selection.Font.Italic = 1 // Kursiv
oWord.Application.Selection.Font.Underline = 0 // Nicht Unterstrichen
oWord.Application.Selection.Font.Underline = 3 // Doppelt Unterstrichen
oWord.Application.Selection.Font.Underline = 1 // Einfach Unterstrichen
oWord.Application.Selection.Font.Hidden = 1 // Versteckt
oWord.Application.Selection.Font.StrikeThrough = 1 // Durchgestrichen


Farben für Schriften:

  • 0 = Automatisch
  • 1 = Schwarz
  • 2 = Blau
  • 3 = Türkis
  • 4 = Hellgrün
  • 5 = Pink
  • 6 = Rot
  • 7 = Gelb
  • 8 = Weiß
  • 9 = Dunkelblau
  • 10 = Dunkeltürkis (teal)
  • 11 = Grün
  • 12 = Violett
  • 13 = Dunkelrot
  • 14 = Dunkelgelb
  • 15 = 50% Grau
  • 16 = 25% Grau


oWord.Application.Selection.Font.ColorIndex = 6 // Rot 


Absätze formatieren Bearbeiten

Neuen Absatz einfügen

oWord.selection.TypeParagraph()

Ausrichtung

  • 0 = Links
  • 1 = Zentriert
  • 2 = Rechts
  • 3 = Blocksatz
  • 4 = Distribute (letzte Zeile Größer)
  • 5 = Blocksatz mittlerer Abstand
  • 7 = Blocksatz weiter Abstand
  • 8 = Blocksatz kleiner Abstand

oWord.selection.ParagraphFormat.Alignment = 1 // Zentriert

Zeilenabstand in Punkten

oWord.selection.ParagraphFormat.LineSpacing = 20

Zeilenabstand einfach oder mehrfach

  • 0 = Einfach
  • 1 = 1 1/2 fach
  • 2 = Doppelt

oWord.selection.ParagraphFormat.LineSpacingRule = 1

Absatzabstand

oWord.selection.ParagraphFormat.SpaceBefore = 10 // 10 Punkte Abstand von oben
oWord.selection.ParagraphFormat.SpaceAfter = 10 // 10 Punkte Abstand zum nächsten Absatz
oWord.selection.ParagraphFormat.RightIndent = 15 // 15 Punkte Einzug von Rechts
oWord.selection.ParagraphFormat.LeftIndent = 15 // 15 Punkte Einzug von Links
oWord.selection.ParagraphFormat.FirstLineIndent = -15 // Erste Zeile -15 Punkte Einzug von Links (hängender Einzug)

Dokument formatieren / Markierungen Bearbeiten

Seitenränder festlegen

oWord.Activedocument.pageSetup.topMargin = 25 // Rand oben in Punkte
oWord.Activedocument.pageSetup.bottomMargin = 25 // Rand unten in Punkte
oWord.Activedocument.pageSetup.leftMargin = 25 // Rand links in Punkte
oWord.Activedocument.pageSetup.rightMargin = 25 // Rand rechts in Punkte

Hoch / Querformat

oWord.Activedocument.pageSetup.Orientation = 0 // Hochformat
oWord.Activedocument.pageSetup.Orientation = 1 // Querformat

Komplettes Dokument markieren

oWord.selection.WholeStory()

Tabellen Bearbeiten

Die Arbeit mit Tabellen in Word ist etwas komplexer, aber durchaus möglich. Text in Tabellenfelder einfügen funktioniert mit dem bereits besprochenen oWord.selection.Typetxt("Text"). Auch die anderen Funktionen für Formatierung etc. funktionieren in einer Tabelle

Neue Tabelle erstellen
Benötigt wird die Anzahl der Zeilen und Spalten

oWord.ActiveDocument.Tables.add(oWord.selection.range,nZeilen,nSpalten)

Eine Zelle weiterspringen

oWord.Selection.MoveRight()

Eine neue Zeile nach der aktuellen Zeile einfügen

oWord.Selection.SelectRow() // Zuerst die Zeile markieren 
oWord.Selection.EndKey() // Dann ans Ende der Zeile gehen 
oWord.Selection.MoveRight(12) // Neue Zeile einfügen

Zelle markieren

oWord.Selection.SelectRow()

Tabelle markieren

oWord.Selection.Tables(1).Select() 

Optimale Breite der kompletten Tabelle einstellen

oWord.Selection.Tables(1).Select()
oWord.Selection.Tables(1).AutoFitBehavior(1)

Breite einer Zelle in cm einstellen

oWord.selection.cells.setwidth(ROUND((5.25*72)/2.54,2),0)

Der fettgedruckte Wert ist die cm-Angabe

Höhe einer Zelle in cm einstellen

oWord.Selection.Rows.HeightRule = 2
oWord.Selection.Rows.Height = ROUND((5.25*72)/2.54,2)

Der fettgedruckte Wert ist die cm-Angabe

Höhe einer Zelle auf automatisch einstellen

oWord.Selection.Rows.HeightRule = 0


Rahmen für Tabellen oder Zellen einstellen
Wenn eine ganze Tabelle mit Rahmen formatiert werden soll, dann muss die Tabelle vorher markiert werden (siehe oben). Ansonsten wird der Rahmen für die Zelle eingestellt, in der sich der Cursor befindet.
Anhand dieses Beispiels wird auch der Umgang mit Objekten verdeutlicht, die mehrere Parameter gleichzeitig zugewiesen bekommen müssen. Hier ist die Verfahrensweise analog dBase mit einem with / endwith Konstrukt. Zum einen erfordert dieses Konstrukt weniger Tipparbeit, zum anderen hat die Rahmenformatierung anders nicht funktioniert :-).
Für die Formatierung von Rahmen sind verschiedene Parameter möglich.

  • Position des Rahmens
    • 1 = oben
    • 2 = links
    • 3 = unten
    • 4 = rechts
    • 5 = vertikale Gitternetzlinien (bei markierung mehrerer Zellen)
    • 6 = horizontale Gitternetzlinien (bei markierung mehrerer Zellen)
  • Art der Linie
    • 1 = Linie
    • 4 = unterbrochene Linie
    • 7 = doppelte Linie
    • andere Werte ergeben noch andere Linienformen - einfach ausprobieren

Im folgenden Beispiel wird eine doppelte (7 fett) Linie unten (3 fett) eingestellt:

with oWord.Selection.Borders(3)
     Visible = true 
     LineStyle = 7
endwith

Im folgenden Beispiel wird eine einfache (1 fett) Linie links (2 fett) eingestellt:

with oWord.Selection.Borders(2)
     Visible = true 
     LineStyle = 1
endwith

Im folgenden Beispiel werden alle Linien entfernt:

oWord.Selection.cells.Borders.Enable = false 
oWord.Selection.paragraphformat.rightindent=0

Im folgenden Beispiel wird ein kompletter Rahmen mit Gitternetz erstellt:

oWord.Selection.Rows.borders.enable = 1

Schattierung für Tabellen oder Zellen einstellen
Die Einrichtung von Schattierungen erfordert wieder Parameter für die Stärke der Schattierung.

  • Stärke der Schattierung
    • 50 = 5%
    • 100 = 10%
    • 500 = 50 %
    • usw.

Im folgenden Beispiel wird eine 10%ige Schattierung (100 fett) eingestellt:

oWord.Selection.shading.texture = 100

Grafik einfügen Bearbeiten

Das Einfügen von Grafiken ist auch wieder eine etwas komplexere Geschichte. Es gibt zur Gestaltung einige Parameter, die gesetzt werden können, um beispielsweise die Höhe und Breite einzustellen :

Grafik einfügen

oWord.Selection.InlineShapes.AddPicture("C:\grafik.jpg")

Grafik einfügen und Höhe und Breite definieren

oWord.Selection.InlineShapes.AddPicture("C:\grafik.jpg")
oWord.selection.Extend() // Markierung erweitern
oWord.selection.moveleft(1) // Grafik markieren
oWord.application.Selection.InlineShapes(1)
    height = 50 // Höhe einstellen
    width = 100 // Breite einstellen
endwith
oWord.selection.EscapeKey() // Markierungserweiterung aufheben
oWord.selection.moveRight(1) // Eins nach rechts neben die Grafik

Serienbriefe erstellen Bearbeiten

Auch die Erstellung von Serienbriefen in Word ist aus dBase kein Problem:

Serienbrief erstellen - und Datenquelle zuordnen

oWord.ActiveDocument.MailMerge.MainDocumentType=0 
oWord.ActiveDocument.MailMerge.OpenDataSource("C:\steuerdatei.doc")
oWord.ActiveDocument.MailMerge.ViewMailMergeFieldCodes = 0 

Seriendruckfeld an aktueller Position einfügen

oWord.ActiveDocument.MailMerge.Fields.Add(oWord.selection.range,"FELD1")

Steuerung von Excel Bearbeiten

In diesem Abschnitt sollen einige Beispiele für die Verwendung mit Excel gezeigt werden. Alle Beispiele beziehen sich auf Excel 2000, funktionieren aber auch mit Excel 97 bis Excel XP. Es werden immer nur die Beispiele für den direkten Aufruf verwendet, nicht für die Verwendung einer Bibliothek. Diese sollte sich - wie bereits im letzten Abschnitt erwähnt - jede/r nach eigenen Anforderungen erstellen.

Starten, Anzeigen und Beenden von Excel Bearbeiten

oExcel = NEW OLEAUTOCLIENT("excel.application")  // Erstellen der OLE-Instanz
oExcel.visible = true // Excel anzeigen
oExcel.activate() // Excel aktivieren
oExcel.quit() // Excel schliessen

Dokument: Neu, Öffnen, Speichern, Drucken, Schließen Bearbeiten

Neue Arbeitsmappe

oExcel.Workbooks.Add() 

Arbeitsmappe öffnen

oExcel.Workbooks.Open("c:\test.xls")

Arbeitsmappe speichern
Speichern unter einem Dateinamen

oExcel.ActiveWorkbook.SaveAs("c:\test1.xls",1)

Nur Speichern (Falls noch kein Dateiname vorhanden, wird ein entsprechendes Dialogfeld gezeigt)

oExcel.ActiveWorkbook.Save()

Arbeitsmappe drucken

oExcel.ActiveWorkbook.printout()

Arbeitsmappe schließen
Mit Speichern (Wenn Änderungen am Dokument gemacht wurden erscheint das entsprechende Dialogfeld)

oExcel.ActiveWorkbook.close()

Ohne Speichern und ohne Nachfrage

oExcel.ActiveWorkbook.close(0)

Arbeitsmappe bearbeiten: Werte einfügen, auslesen, löschen Bearbeiten

Wert an aktueller Position einfügen

oExcel.ActiveCell.value = "Wert"

Wert an aktueller Position auslesen

cWert = oExcel.ActiveCell.value

Wert an aktueller Position löschen

cWert = oExcel.ActiveCell.clearContents()

Wert an bestimmter Position einfügen

oExcel.Range("A2").Select
oExcel.ActiveCell.value = "Wert"

Wert an bestimmter Position auslesen

oExcel.Range("A2").Select
cWert = oExcel.ActiveCell.value

Formatierung Arbeitsmappe, Tabellenoperationen Bearbeiten

Kopfzeile der Arbeitsmappe beschriften
Im folgenden Beispiel soll der Wert "Seite &S von &A" auf der linken Seite der Kopfzeile in der Schriftart Courier 8 angezeigt werden.

oExcel.ActiveSheet.PageSetup.leftHeader = '&"Courier New"&8Seite &S von &A' 

Der zu übergebende String ist so aufgebaut, dass zuerst ein & und die Schriftart in Hochkommas geschrieben wird. Direkt darauf folgt wieder ein & und die Schriftgröße in Punkt. Danach dirkt anschließend der eigentliche Text. Der Text wird nicht in Hochkommas geschrieben sondern direkt drangehängt. Natürlich kann die Beschriftung auch an eine andere Position der Kopfzeile oder in die Fusszeile gesetzt werden. Das Prinzip ist dabei das selbe.

oExcel.ActiveSheet.PageSetup.leftHeader
oExcel.ActiveSheet.PageSetup.rightHeader
oExcel.ActiveSheet.PageSetup.centerHeader
oExcel.ActiveSheet.PageSetup.leftFooter
oExcel.ActiveSheet.PageSetup.rightFooter
oExcel.ActiveSheet.PageSetup.centerFooter

Seitenausrichtung der Arbeitsmappe
Hochkant, Querformat, Vertikal und Horizontal zentrieren, Gitternetz etc.

oExcel.ActiveSheet.PageSetup.orientation = 1 // Hochkant
oExcel.ActiveSheet.PageSetup.orientation = 2 // Quer
oExcel.activesheet.PageSetup.CenterHorizontally = true // Horizontal zentrieren
oExcel.activesheet.PageSetup.CenterVertically = true // Vertikal zentrieren
oExcel.activesheet.PageSetup.PrintGridLines = true // Gitternetzlinien anzeigen

Seitenränder - die cm-Werte mit 28 multiplizieren um auf die Punkt-Zahl zu kommen

oExcel.ActiveSheet.PageSetup.TopMargin = 56 // ca. 2 cm Rand von oben 
oExcel.ActiveSheet.PageSetup.BottomMargin = 56 // ca 2 cm Rand von unten 
oExcel.ActiveSheet.PageSetup.LeftMargin = 56 // ca 2 cm Rand von links
oExcel.ActiveSheet.PageSetup.RightMargin = 56 // ca 2 cm Rand von rechts 
oExcel.ActiveSheet.PageSetup.HeaderMargin = 56 // ca 2 cm Rand der Kopfzeile 
oExcel.ActiveSheet.PageSetup.FooterMargin = 56 // ca 2 cm Rand der Fusszeile 

Tabelle benennen

oExcel.ActiveSheet.name = "Tabellenname"

Tabelle auswählen

oExcel.Sheets("Tabellenname").select()

Formatierung von Zellen Bearbeiten

Zeichenformatierung

oExcel.selection.font.name = "Courier New"  // Schriftart
oExcel.selection.font.size = 12  // Schriftgröße
oExcel.selection.font.bold = true  // Fett (false = Normal)
oExcel.selection.font.italic = true  // Kursiv (false = Normal)
oExcel.selection.font.underline = 2  // Unterstrichen (-4142 = Normal)
oExcel.selection.font.underline = -4119  // Doppelt Unterstrichen (-4142 = Normal)
oExcel.selection.font.underline = 4  // Einfach Unterstrichen Buchhaltung (-4142 = Normal)
oExcel.selection.font.underline = 5  // Doppelt Unterstrichen Buchhaltung (-4142 = Normal)
oExcel.selection.font.strikethrough = true  // Durchgestrichen (false = Normal)
oExcel.selection.font.subscript = true  // Tiefgestellt (false = Normal)
oExcel.selection.font.superscript = true  // Hochgestellt (false = Normal)
oExcel.selection.font.colorindex = 0  // Schriftfarbe automtisch
1 = Schwarz, 2 = weiss, 3 = rot, 4 = grün, 5 = blau, 6 = gelb, 7 = magenta ...

Format des Zelleninhalts
In Excel können Zellen bestimmte Nummern, Text und andere Formate besitzen. So können beispielsweise Zahlen mit 1000er Punkten und zwei Stellen hinter dem Komma angezeigt werden.

oExcel.Selection.NumberFormat = "General"  // Standard
oExcel.Selection.NumberFormat = "@" // Text
oExcel.Selection.NumberFormat = "#,##0.00" // 1000er Punkte mit zwei Dezimalstellen hinter dem Komma
oExcel.Selection.NumberFormat = "0"  // Ganzzahl
oExcel.Selection.NumberFormat = "#.##0,00 €"  //Zwei Dezimalstellen mit 1000er Punkten und EUR-Symbol

Zellinhalt als Hyperlink formatieren
Wenn eine Zelle eine URL enthält wird diese zunächst als Text dargestellt und ist nicht klickbar. Der folgende Code macht den Zellinhalt zu einem aktiven Hyperlink, so dass per Mausklick die betreffende URL (z.B. eine Webadresse) geöffnet wird. Im Beispiel wird der ursprüngliche Zellinhalt durch den Text "Hier klicken" ersetzt.

cURL = oExcel.ActiveCell.value
oExcel.ActiveSheet.Hyperlinks.Add(oExcel.ActiveCell, cURL)
oExcel.ActiveCell.value = "Hier klicken" 

Zeichenausrichtung
Horizontal

oExcel.selection.HorizontalAlignment = 1  // Standard
oExcel.selection.HorizontalAlignment = 2  // Links
oExcel.selection.HorizontalAlignment = 3  // Zentriert
oExcel.selection.HorizontalAlignment = 4  // Rechts
oExcel.selection.HorizontalAlignment = 6  // Blocksatz

Vertikal

oExcel.selection.VerticalAlignment = 1  // Oben
oExcel.selection.VerticalAlignment = 2  // Zentriert
oExcel.selection.VerticalAlignment = 3  // Unten
oExcel.selection.VerticalAlignment = 4  // Blocksatz

Zeilenumbruch in der Zelle

oExcel.selection.WrapText = true 


Hintergrundfarben
In Excel gibt es 56 Farbwerte die als Hintergrundfarbe genommen werden können.

oExcel.selection.Interior.ColorIndex = 0  // Keine Farbe (weiss)

Mit folgender Funktion kann ein Farbmuster in Excel erstellt werden. Daraus kann dann die gewünschte Farbe abgelesen werden:

xExcel = 1
yExcel = 1
FOR IExcel = 0 TO 56
    IF xExcel = 9
       xExcel = 1
       yExcel++
    ENDIF
    oOpt = CHR(64 + xExcel) + STR(yExcel,1)
    oExcel.activesheet.range(oOpt).select
    oExcel.activecell.value = IExcel
    oExcel.selection.Interior.ColorIndex = IExcel
    xExcel++
ENDFOR

Rahmen
Ein Rahmen für eine Zelle oder einen Bereich besteht immer aus den einzelnen Strichen oben, unten, rechts, links etc. Es existiert in Excel ein Borders-Objekt mit einem Index für jeden Strich. Im folgenden sind die jeweiligen Werte zu sehen:

  • 1 = links (jede Zelle)
  • 2 = rechts (jede Zelle)
  • 3 = oben (jede Zelle)
  • 4 = unten (jede Zelle)
  • 5 = diagonal links oben nach rechts unten (jede Zelle)
  • 6 = diagonal linkt unten nach rechts oben (jede Zelle)
  • 7 = Kasten links (um Markierung)
  • 8 = Kasten oben (um Markierung)
  • 9 = Kasten unten (um Markierung)
  • 10 = Kasten rechts (um Markierung)
  • 11 = Gitternetz Vertikal (um Markierung)
  • 12 = Gitternetz Horizontal (um Markierung)

Um nun einen Rahmen zuzuweisen und die Funktion nicht mehrmals aufrufen zu müssen kann man sich mit einem Array behelfen, dass die Index-Werte beinhaltet, für die ein Rahmen gesetzt werden soll.

oOpt = {1,2,3,4}  // Rahmen um die aktive Zelle
FOR excelI = 1 TO oOpt.size
    with oExcel.selection.borders(oOpt[excelI])
         LineStyle = 1  // Linie
         ColorStyle = -4105 // schwarz
         weight = 2 // Standard-Dicke
    endwith
ENDFOR

Um einen Rahmen zu entfernen, ist es am besten jeden Index wieder zu deaktivieren :

FOR excelI = 1 TO 12
    with oExcel.selection.borders(excelI)
         ColorStyle = -4142
         LineStyle = -4142
         weight = 2
    endwith
ENDFOR

Spaltenbreite und Zeilenhöhe
Um die Breite einer Spalte festzulegen, kann die Spalte in der Form ("A:A" - erste Spalte "B:B" - zweite Spalte etc...) angegeben werden. Ansonsten wird die aktuell aktive Spalte verwendet.

oExcel.Columns("B:B").Select
oExcel.Selection.ColumnWidth = 8 // Wert * 10 = Pixel

Um die Höhe einer Zeile festzulegen, kann die Zeile in der Form ("1:1" - erste Zeile "2:2" - zweite Zeile etc...) angegeben werden. Ansonsten wird die aktuell aktive Zeile verwendet.

oExcel.Rows("2:2").Select
oExcel.Selection.RowHeight = 10 // Wert * 1,66666 = Pixel

Um die Spaltenbreite und Zeilenhöhe automatisch festzulegen, muss der komplette Bereich markiert werden. Dazu gibt es für das Auffinden der letzten Zelle mit Inhalt eine spezielle Funktion.

oExcel.ActiveCell.SpecialCells(11).Select  // Letzte Zelle mit Inhalt auswählen
cExObjTmp =  oExcel.selection.address  // Index der letzten Zelle in eine Variable speichern
oExcel.activesheet.range("A1:"+cExObjTmp).select  // Markieren vom Anfang bis zur letzte Zelle
oExcel.Selection.Columns.AutoFit() // Automatische Spaltenbreite
oExcel.Selection.Rows.AutoFit() // Automatische Zeilenhöhe

Markieren und sortieren Bearbeiten

Markierung einer einzelnen Zelle:

oExcel.activesheet.range("A1").select

Markierung aller Zellen (Siehe auch vorhergehender Abschnitt automatische Breite/Höhe):

oExcel.ActiveCell.SpecialCells(11).Select  // Letzte Zelle mit Inhalt auswählen
cExObjTmp =  oExcel.selection.address  // Index der letzten Zelle in eine Variable speichern
oExcel.activesheet.range("A1:"+cExObjTmp).select  // Markieren vom Anfang bis zur letzte Zelle
// Nach Spalte A sortieren, ab Zeile 2 wegen Überschrift
// 2. Parameter: 1 - aufsteigend sortieren, 2 - absteigend sortieren
oExcel.selection.sort(oExcel.range("A2"),1)


Hervorheben durch spezielle Formatierungen Bearbeiten

dreiteilige Ampel

(Ein Wert einer Zelle (hier (7,2) wird symbolisch als Ampeldarstellung charakterisiert: In den Zellen (6,1) und (7,1) und (8,1) entsteht eine Ampel, wobei jeweils einer der Inhalte in rot, gelb oder grün erscheint. Die jeweils beiden anderen sind dann grau. Es erscheinen drei ausgefüllte Kreise untereinander - eine Ampel eben!

  //Ampelformatierung in dreiteiliger Form
  oCell=e.activeSheet.cells(8,1)
  oCell.formula := [']+"n"
  oCell.Font.Name = "Webdings"
  oCell.IndentLevel=1
  //
  if e.activeSheet.cells(7,2).value >0   //rot
  oCell.Font.ColorIndex = 3
  else
  oCell.Font.ColorIndex = 15
  endif
  //
  //
  oCell=e.activeSheet.cells(7,1)
  oCell.formula := [']+"n"
  oCell.Font.Name = "Webdings"
  oCell.IndentLevel=1
  //
  if e.activeSheet.cells(7,2).value =0  //gelb
  oCell.Font.ColorIndex = 6
  else
  oCell.Font.ColorIndex = 15
  endif
  //
  //
  oCell=e.activeSheet.cells(6,1)
  oCell.formula := [']+"n"
  oCell.Font.Name = "Webdings"
  oCell.IndentLevel=1
  //
  if e.activeSheet.cells(7,2).value <0   //grün
  oCell.Font.ColorIndex = 4
  else
  oCell.Font.ColorIndex = 15
  endif


einteilige Ampel

(der Wert in einer Zelle (i,2) bewirkt die Darstellung der Zelle (i,1) als ausgefüllten Kreis in der Farbe rot, gelb oder grün entsprechend der abgeforderten Bedingung)

  //Spalte Ampel formatieren
  //Ampelformatierung in einteiliger Form
  oCell=e.activeSheet.cells(i,1)
  oCell.formula := [']+"n"
  oCell.Font.Name = "Webdings"
  oCell.IndentLevel=1
  //
  if e.activeSheet.cells(i,2).value >0   //grün
  oCell.Font.ColorIndex = 4
  endif
  if e.activeSheet.cells(i,2).value =0   //gelb
  oCell.Font.ColorIndex = 6
  endif
  if e.activeSheet.cells(i,2).value <0   //rot
  oCell.Font.ColorIndex = 3
  endif


Namen definieren Bearbeiten

dBASE kann über ODBC auf Excel-Tabellen lesend zugreifen. Dafür muss in der Excel-Tabelle für den gewünschten Datenbereich ein Name definiert werden. In Excel geschieht das über das Menü Einfügen > Namen > Definieren. Über OLE funktioniert das Einfügen des Namens wie folgt.

Zunächst wird wieder die letzte Zelle mit Inhalt ermittelt. Dann wird für den Bereich von "A1" bis zur letzten Zelle ein Namen hinzugefügt (im Beispiel "Tabelle1").

oExcel.ActiveCell.SpecialCells(11).Select  // Letzte Zelle mit Inhalt auswählen
cExObjTmp =  oExcel.selection.address  // Index der letzten Zelle in eine Variable speichern
// Namen definieren für den gesamten Bereich von Zelle "A1" bis Ende
oExcel.ActiveWorkbook.Names.Add("Tabelle1", oExcel.activesheet.range("A1:"+cExObjTmp))

Wenn ein entsprechender ODBC-DSN eingerichtet ist (Treiber: "Microsoft Excel-Treiber (*.xls)"), der auf die Excel-Datei zeigt (Pfad und Dateiname, z.B. "c:\Excel\MeineDatei.xls"), kann die Excel-Datei direkt aus dBASE geöffnet werden.

Fazit Bearbeiten

In diesem Abschnitt wurde anhand häufig verwendeter Funktionen exemplarisch dargestellt, was so alles mit Word und Excel möglich ist. Natürlich geht da noch vieles mehr. Besonders hingewiesen sei noch einmal auf die inspect()-Funktion, mit dem man sich die möglichen Eigenschaften und Befehle, die von Word und Excel bereitgestellt werden, anschauen kann. Hier sind auch die Zahlen zu sehen, die bei bestimmten Aktionen als Parameter zu übergeben sind. Allerdings sind die Parameter der Methoden hier nicht aufgeführt. Hierzu kann auch die VBA-Hilfe von Word und Excel verwendet werden. Ansonsten hilft auch die bereits beschriebene Makro-Variante und eben Ausprobieren.