Für Applikationen die einen COM-Server zur Verfügung stellen, bietet CONZEPT 16 eine Schnittstelle, mit der eine Kommunikation auf Basis des „Component Object Models“ durchgeführt werden kann. In dem Artikel Component Object Model COM lag der Schwerpunkt in der Beschreibung der Architektur dieser Schnittstelle.
In dem heutigen Beitrag steht die praktische Umsetzung im Mittelpunkt. Als Beispiel haben wir das Auslesen von Daten einer Excel-Datei gewählt. Folgende Verarbeitungsschritte werden dabei durchlaufen:
- Starten eine Instanz von Excel (CONZEPT 16-Funktion
ComOpen()
) - Öffnen einer bestehenden Excel-Datei (Excel-Methode „Open„)
- Ermitteln des aktiven Arbeitsblattes (Excel-Eigenschaft „ActiveSheet„)
- Abfragen des verwendeten Bereiches innerhalb des Datenblattes (Excel-Eigenschaft „UsedRange„)
- Anzahl Zeilen und Spalten des verwendeten Bereichs ermitteln (Excel-Eigenschaften „Rows„, „Columns“ und „Count„)
- Daten des verwendeten Bereiches abfragen (Excel-Eigenschaften „Value„)
- Array durchlaufen, dabei Typ und Inhalt der Zelle auslesen (CONZEPT 16-Eigenschaften „cpiItemType“ und „cp<Datentyp>Item„.
- Beenden von Excel (Excel-Methode „Quit„)
Beispiel:
define
{
mWorksheet : _Sys->spPathMyDocuments + '\MyWorksheet.xls'
}
try
{
// Excel starten
tApp # ComOpen('Excel.Application',_ComAppCreate);
// Arbeitsmappe öffnen
tWorkbook # tApp->ComCall('Workbooks.Open',mWorksheet);
// Aktives Arbeitsblatt ermitteln
tActiveSheet # tWorkbook->cphActiveSheet;
// Verwendeter Bereich im Arbeitsblatt abrufen
tRange # tActiveSheet->cphUsedRange;
// Anzahl der mit Daten belegten Zeilen ermitteln
tRows # tRange->cphRows;
tMaxRow # tRows->cpiCount;
// Anzahl der mit Daten belegten Spalten ermitteln
tColumns # tRange->cphColumns
tMaxColumn # tColumns->cpiCount;
// Daten des verwendeten Bereichs abrufen
tArray # tRange->cphValue;
// Array verarbeiten
if (tArray > 0)
{
// Zeilen
for tRow # 1
loop inc(tRow)
while (tRow <= tMaxRow)
{
// Spalten
for tColumn # 1
loop inc(tColumn)
while (tColumn <= tMaxColumn)
{
// Datentyp der Zelle ermitteln
switch (tArray->cpiItemType(tRow,tColumn))
{
// Inhalt der Zelle auslesen
case _TypeAlpha : tVal # tArray->cpaItem(tRow,tColumn);
case _TypeFloat : tVal # CnvAF(tArray->cpfItem(tRow,tColumn),0);
case _TypeInt : tVal # CnvAI(tArray->cpiItem(tRow,tColumn),0);
...
...
}
}
}
}
}
if (tApp > 0)
{
// Excel beenden
tApp->ComCall('Application.Quit');
// COM-Objekt freigeben
tApp->ComClose();
}
Im obigen Beispiel wird das aktive Arbeitsblatt der Excel-Datei verarbeitet. Unter Umständen liegt eine Excel-Datei vor, die aus mehreren Arbeitsblättern mit Daten besteht. Um alle Daten einer Arbeitsmappe verarbeiten zu können, muss zuerst die Anzahl der Arbeitsblätter ermittelt werden. Die Eigenschaft „Worksheets“ des Workbook-Objekts gibt eine Auflistung aller Arbeitsblätter zurück. Über die Eigenschaft „Count“ des Auflistungs-Objekts lässt sich anschließend die Anzahl der Arbeitsblätter ermitteln.
Beispiel:
// Excel starten
tApp # ComOpen('Excel.Application',_ComAppCreate);
// Arbeitsmappe öffnen
tWorkbook # tApp->ComCall('Workbooks.Open',mWorksheet);
// Sheets-Auflistung
tSheets # tWorkbook->cphWorkSheets;
// Alle Arbeitsblätter durchlaufen und deren Namen ermitteln
for tCnt # 1
loop inc(tCnt)
while (tCnt <= tSheets->cpiCount)
{
tSheet # tWorkbook->cphWorksheets(tCnt);
// Name des Arbeitsblattes
tName # tSheet->cpaName
}
Um ein bestimmtes Arbeitsblatt für die Bearbeitung auszuwählen, wird im Index der Eigenschaft Worksheets die Indexnummer oder der Name des Arbeitsblattes angegeben. Die Indexnummer entspricht der Position des Arbeitsblattes innerhalb der Arbeitsmappe. Die Zählung beginnt von links.
Beispiel:
// Arbeitsblatt über Indexnummer auswählen
tSheet # tWorkbook->cphWorksheets(2);
// Arbeitsblatt über Namen auswählen
tSheet # tWorkbook->cphWorksheets('Tabelle2');
Eine Antwort
Ein Nachteil des Auslesens direkt aus Excel ist, das Excel pro Feld den Datentyp bestimmt, und es passieren kann, das Textfelder plötzlich als Float oder Datum erkannt werden (und man keine Chance hat den Original-Textwert auszulesen)
Ich persönlich bevorzuge es daher die Excel-Datei als CSV-Datei zu
speichern und dann über FsiRead einzulesen.