SpreadsheetML

In diesem Artikel soll nun aufgezeigt werden, wie in den Content-Parts die Tabellen von Excel-Dokumenten dargestellt werden. Bei dem Tabellenformat handelt es sich um die Kernaufgabe von Excel, das zur Beschreibung der Tabellen SpreadsheetML in den entsprechenden Parts verwendet. SpreadsheetML ist im ersten Teil des OOXML-Standards beschrieben.

Folgende Parts sind zur Tabellendarstellung notwendig:

  • /xl/workbook/sheet[i].xml

  • /xl/styles.xml

  • /xl/workbook.xml

Weitere Parts können hinzugefgt werden:

  • /xl/sharedStrings.xml

  • /xl/calcChain.xml

Konstruktionen, die in einem Tabellenmodell umgesetzt sein müssen, sind überspannende Zellen, Darstellung der Zellen in verschiedenen Styles und Typisierung der Zelleninhalte. Angaben, die für ganze Zeilen bzw. Spalten (Breite bzw. Höhe, ggf. Styles) gemacht werden, sind ebenfalls notwendig. Bei der Tabellenkalkulation kommen noch Formeln hinzu, die den Wert einer Tabellenzelle berechnen.

 

Workbook

Der workbook-Part dient hauptsächlich als Verweis auf die Tabellenblätter, für die Benennung der Tabellenblätter und für die Festlegung der Blattreihenfolge sowie für allgemeine Einstellungen des Dokumentes. Folgendes Beispiel zeigt die rudimentärste Version dieses Parts:

<workbook>
   <sheets>
      <sheet name="Tabelle 1" sheetId="1" r:id="rId1"/>
      <sheet name="Tabelle 2" sheetId="2" r:id="rId2"/>
      <sheet name="Tabelle 3" sheetId="3" r:id="rId3"/>
   </sheets>
</workbook>

Das <sheets>-Element enthält für jedes Tabellenblatt ein <sheet>-Kindelement. Die Reihenfolge der <sheet>-Elemente entscheidet über die Reihenfolge der Tabellenblätter in Excel. Dem <sheet>-Element wird mit dem name-Attribut der Tabellenblattname, mit dem sheetId-Attribut eine eindeutige ID und mit dem r:id-Attribut ein Relationship aus dem zugehörigen Relationship-Part, der zum sheet-Part des Tabellenblattes führt, zugewiesen.

 

Tabellenblatt

Als Einstieg soll zunächst mit SpreadsheetML eine einfache Tabelle gemäß der Abbildung 4 dargestellt werden.

Abb. 4: Einfache Excel-Tabelle

Abb. 4: Einfache Excel-Tabelle

Das folgende Code-Beispiel stellt den Part /xl/worksheets/sheet1.xml dar, der die Inhalte dieser Tabelle enthält:

<worksheet>
   <sheetViews>
      <sheetView workbookViewId="0"/>
   </sheetViews>
   <sheetData>
      <row r="1">
         <c r="A1" t="s">
            <v>1</v>
         </c>
         <c r="B1" t="s">
            <v>2</v>
         </c>
      </row>
      <row r="2">
         <c r="A2">
            <v>1</v>
         </c>
         <c r="B2">
            <v>1</v>
         </c>
      </row>
      <row r="3">
         <c r="A3">
            <v>2</v>
         </c>
         <c r="B3">
            <v>4</v>
         </c>
      </row>
       [...]
      <row r="11">
         <c r="A11">
            <v>10</v>
         </c>
         <c r="B11">
            <v>100</v>
         </c>
      </row>
   </sheetData>
</worksheet>

Anhand dieses Beispiels werden nun die grundsätzlichen Elemente von SpreadsheetML erläutert.

 

Grundstruktur

Das Wurzelelement <worksheet> enthält neben Meta-Informationen mit dem <sheetData>-Element die Tabellenstruktur dieses Tabellenblattes. Der Inhalt von <sheetData> besteht aus Zeilen-Elementen der Tabelle. Da eine Excel-Tabelle stets über 1 Millionen leere Tabellenzeilen hat, werden hier nur Zeilen gespeichert, die Daten enthalten. In einem leeren Tabellenblatt ist das <sheetData>-Element somit ebenfalls leer.

Tabellenzeile

Eine Zeile wird als <row>-Element dargestellt:

<row r="3">
   [Tabellenzellen dieser Zeile]
</row>

Das r-Attribut gibt dabei die Zeilennummer an, wenn sie von der automatischen Zeilennummer abweicht. Diese Zeile ist somit die dritte Zeile dieser Tabelle. Gibt es keine <row>-Elemente mit den Attributen r="1" und r="2", bleiben die ersten beiden Zeilen leer. Die automatische Zeilennummer wird anhand der Position im <sheetData>-Element ermittelt. Sofern dem <row>-Element mit dem r-Attribut keine Zeilennummer zugewiesen wurde, ist die Zeilennummer dieser Zeile gegenüber der Zeilennummer der vorstehenden Zeile um eins erhöht. Gibt es keine vorstehende Zeile, ist die automatische Zeilennummer 1.

Tabellenzelle

Für Tabellenzellen gilt das gleiche Prinzip wie bei Zeilen. Leere Zellen innerhalb einer Zeile werden nicht dargestellt. Zellen werden durch <c>-Elemente erzeugt:

<c r="B3">
   [Inhalt der Tabellenzelle]
</c>

Abb. 5: Zellname einer Tabelle

Abb. 5: Zellname einer Tabelle

Hier gibt das r-Attribut den Zellennamen an, der mit dem in Excel angezeigten Zellennamen übereinstimmt. Der Name der Zelle (hier: B3) setzt sich aus dem Spaltennamen (B) und der Zeilennummer (3) zusammen. Die Zeilennummer von jedem <c>-Element muss dabei mit der Zeilennummer des <row>-Elements übereinstimmen, in dem sich das <c>-Element befindet. Dies gilt auch, wenn die Zeilennummer für das <row>-Element automatisch ermittelt wird.

Wie bei den <row>-Elementen ist beim <c>-Element das r-Attribut optional. Die automatische Ermittlung erfolgt auf die gleiche Art: Das erste <c>-Element wird, wenn kein Zellenname manuell festgelegt ist, der Spalte A zugeordnet. Für alle folgenden Zellen ohne manuellen Namen wird die Spalte anhand der vorstehenden Zelle ermittelt.

 

Zelleninhalt

Beim Inhalt der Zellen unterscheidet SpreadsheetML anhand der Struktur zwischen unterschiedlichen Inhaltstypen. Im einfachsten Fall enthält die Zelle den Typ Number. Sie könnte jedoch u.a. auch einen String oder einen booleschen Wert enthalten. Für die Zuweisung des Inhalttyps erhält das <c>-Element ein t-Attribut. Im Folgenden soll nun aufgezeigt werden, wie diese unterschiedlichen Typen in SpreadsheetML umgesetzt werden.

Typ: Number

Da die Kernaufgabe von Excel-Tabellen der Umgang mit Zahlen ist, ist der numerische Typ Number der Default-Typ einer Tabellenzelle. Zellen, die kein t-Attribut erhalten, sind folglich numerischen Typs. Explizit kann ihnen aber mit dem Wert n für das t-Attribut der Typ Number zugewiesen werden:

<c r="B3" t="n">
     <v>4</v>
</c>

Tabellenzellen numerischen Typs erhalten ein Kindelement <v>, das den Wert dieser Zelle in Form einer Dezimalzahl enthält. Dabei wird die amerikanische Schreibweise mit dem Punkt als Dezimaltrennzeichen verwendet:

<v>4.5</v>

Typ: String

Strings haben in Excel-Dokumenten die Besonderheit, dass es zwei Möglichkeiten gibt, diese darzustellen. Dabei verwendet Excel standardmäßig die komplexere Variante, alle Strings im sharedStrings-Part in einer ungeordneten Sammlung auszulagern. In diesem Part werden die Strings aller Tabellenblätter gesammelt. Mit Verweisen in den Tabellenzellen auf die einzelnen Strings dieser Sammlung wird die Zuordnung aufrechterhalten. Da diese Arbeit als Ziel ein Transformationsszenario von XML zu XLSX hat, wäre eine generische Erzeugung eines sharedStrings-Parts von erheblich großem Aufwand. In SpreadsheetML gibt es eine wesentlich einfachere Variante zur Darstellung von Strings, die diesen Aufwand vermeidet. Die Beschreibung des sharedStrings-Parts soll hier deshalb nicht erfolgen.

Stattdessen wird die Möglichkeit aufgezeigt, Strings auch direkt in die Zelle zu schreiben. Hierzu dient der Typ inlineStr als Wert für das t-Attribut. Wird dieser Typ für eine Zelle gewählt, muss das entsprechende <c>-Element als Kindelement ein <is>-Element erhalten. Für einen einfachen String ohne Inline-Formatierungen enthält dieses <is>-Element ein <t>-Element, das den entsprechenden String enthält:

<c r="A1" t="inlineStr">
     <is>
         <t>x</t>
     </is>
</c>
Inzeilige Auszeichnung

Formatierungen, die nur Teile eines Strings innerhalb einer Zelle betreffen, also inzeilige Formatierungen, kommen in kalkulatorischen Tabellen äußerst selten vor. Da das Prinzip hierfür von WordML übernommen wurde, soll an dieser Stelle nur auf den Artikel WordML - Inzeilige Elemente verwiesen werden.

Typ: Boolean

Soll ein boolescher Wert in die Zelle geschrieben werden, muss im t-Attribut der Wert b angegeben werden. Als Kindelement erhält die Zelle, wie beim numerischen Typ, ein <v>-Element. Allerdings mit der Einschränkung, dass dieses nur noch die Werte 1 (logisch WAHR) oder 0 (logisch FALSCH) enthalten darf:

<c r="A1" t="b">
   <v>1</v>
</c>

Überspannende Zellen

Teil eines Tabellenmodells ist auch der Umgang mit überspannenden Tabellenzellen. Dabei wird zwischen Spalten und Zeilen überspannenden Zellen unterschieden. Verschmilzt eine Zelle mit benachbarten Zellen innerhalb der gleichen Zeile, überspannt sie Spalten. Geschieht dies innerhalb einer Spalte, ist sie folglich eine Zeilen überspannende Zelle. Von den verschmolzenen Zellen wird nur die oberste bzw. links außen liegende Zelle als überspannende betrachtet. Sie überspannt die Zellen, die sich rechts oder unterhalb von ihr befinden (bei europäischer Schreibrichtung). Eine Zelle kann sowohl Spalten als auch Zeilen überspannen.

Es hängt nun vom Tabellenmodell ab, wie diese Eigenschaften von Tabellenzellen beschrieben werden. In Excel ist das, zieht man die gängigen Modelle zum Vergleich heran, etwas eigentümlich umgesetzt.

Während die meisten Tabellenmodelle die Überspannungseigenschaften direkt mit der überspannenden Zelle verknüpfen, ist bei SpreadsheetML diese Information vollständig von den Tabellenzellen getrennt. Im Top-Level-Element <mergeCells> des sheet-Parts, das direkt dem <sheetData>-Element folgt, wird für jede Zell-Verbindung ein <mergeCell>-Element angelegt.

<sheetData> [...] </sheetData>
<mergeCells>
   <mergeCell ref="A2:B11"/>
</mergeCells>

Das ref-Attribut des <mergeCell>-Elements gibt dabei einen Zellen-Bereich an, der die überspannende Zelle mit allen überspannten Zellen enthält.

Ein Bereich von Zellen wird in Excel durch zwei Zellennamen, getrennt durch den Doppelpunkt, definiert (Zellenname1:Zellenname2), die so ein eindeutiges Rechteck beschreiben. Dabei gibt der erste Zellenname den Namen der obersten am weitesten links gelegenen Zelle des Bereiches an und der zweite die unterste am weitesten rechts gelegene Zelle. Der Bereich A2:B11 beinhaltet so die Zellen A2, B2, A3, B3, [usw.] bis A11 und B11.

Beim Überspannen ist zu beachten, dass Excel nicht berücksichtigt, ob innerhalb des zu überspannenden Bereiches bereits Zellen definiert wurden, die möglicherweise Inhalt enthalten. Es wird nur noch der Inhalt der überspannenden Zelle dargestellt.

<sheetData>
     <row>
          <c r="A1" t="inlineStr">
              <is>
                  <t>x</t>
              </is>
          </c>
          <c t="inlineStr">
              <is>
                  <t>y</t>
              </is>
          </c>
     </row>
     […]
</sheetData>
<mergeCells>
     <mergeCell ref="A1:B1"/>
</mergeCells>

Abb. 6: Überspannende Zelle

Abb. 6: Überspannende Zelle

In diesem Beispiel überspannt die Zelle A1 die Zelle B1. Dabei wird der Inhalt der Zelle B1 (y) überdeckt und somit nicht dargestellt. Dies geschieht, obwohl der Zelle ohne einem r-Attribut kein expliziter Name zugewiesen wurde, was bedeutet, dass die automatische Zuweisung von Zellennamen die Überspannung von Zellen nicht berücksichtigt.

Soll die überdeckte Zelle in der Spalte C dargestellt werden, muss dies entweder über einen expliziten Zellennamen (C1) oder durch eine eingefügte leere Zelle zwischen den beiden Zellen erfolgen.

 

Formeln

Ein wichtiger Bestandteil von Excel-Tabellen sind Formeln, die den Wert einer Tabellenzelle meist anhand von anderen Zellen berechnen. In Excel erfolgt die Eingabe einer Formel für eine Zelle, indem die Eingabe des Zellenwertes mit einem Gleichheitszeichen (=) begonnen wird. Der darauf folgende String stellt nun die Formel dar. Wie genau die Formel aussehen muss, um das entsprechende Ergebnis zu erhalten, soll hier jedoch nicht behandelt werden. Entscheidend ist aber, dass die Formel in der gleichen Form, nur ohne das Gleichheitszeichen, in SpreadsheetML eingefügt wird. Ausnahme sind hier Funktionsnamen, falls Excel in einer anderen Sprache als Englisch verwendet wird. In SpreadsheetML werden stets die englischen Namen für Excel-Funktionen verwendet (beispielsweise AVERAGE() statt MITTELWERT()).

f-Element

Als Beispiel soll die einfache Formel =A3*A3 dienen. Das <c>-Element einer Zelle, die das Ergebnis dieser Berechnung enthalten soll, erhält ein Kindelement <f>, dessen Inhalt die Formel ist:

<c r="B3">
   <f>A3*A3</f>
</c>

Optional kann für eine bessere Performance der resultierende Wert zusätzlich noch in das <c>-Element geschrieben werden:

<c r="B3">
   <f>A3*A3</f>
   <v>4</v>
</c>

Gemeinsam genutze Formeln

Oftmals sollen alle Zellen einer Tabellenspalte die gleiche Formel erhalten, die jedoch abhängig vom Kontext der Zelle ist. (Z.B.: quadriere die benachbarte Zelle.) In Excel wird dies realisiert, indem in die erste Zelle die entsprechende Formel eingetragen wird, die Zelle kopiert und in den anderen Zellen der Spalte eingefügt wird (siehe Abb. 7).

Abb. 7: Erzeugung gemeinsam genutzter Formeln in Excel

Abb. 7: Erzeugung gemeinsam genutzter Formeln in Excel

Dabei erfolgt ein relatives Kopieren. Die Formel wird nicht identisch übertragen, sondern umgerechnet, sodass die Beziehungen zwischen den referenzierten Zellen innerhalb der Formel und der Zelle, in der die Formel kopiert wird, erhalten bleiben.

Die Darstellung in SpreadsheetML richtet sich nach dieser Vorgehensweise. Die Formel steht in einer Zelle und alle Zellen, für die die Beziehungen dieser Formel auch gelten sollen, referenzieren auf diese Formel. Gekennzeichnet wird eine solche mehrfach verwendete Formel mit einem Attribut t="shared". Zudem wird mit dem si-Attribut eine ID mitgegeben und im ref-Attribut wird angegeben, in welchem Bereich eine solche Referenz auf diese Formel vorkommen darf:

<row r="2">
 [...]
   <c r="B2">
      <f t="shared" ref="B2:B11" si="0">A2*A2</f>
   </c>
</row>

Eine Referenz auf diese Formel darf nur innerhalb der Zellen des Bereiches B2:B11 stehen, könnte aber auch beispielsweise nur in der Zelle B3 stehen. Der Bereich darf also größer sein, als es notwendig wäre.

Soll nun in einer Zelle dieses Bereiches auf die Formel referenziert werden, wird dem <c>-Element ein leeres <f>-Element zugefügt. Es erhält ebenfalls das Attribut t="shared" und ein si-Attribut mit der referenzierten ID als Wert.

<row r="3">
 [...]
   <c r="B3">
      <f t="shared" si="0"/>
   </c>
</row>

Der calcChain-Part

Die bisherigen Beschreibungen der Formeln im sheet-Part sind noch nicht ausreichend, ein fehlerfreies Dokument zu erzeugen. Excel benötigt im calcChain-Part eine Liste aller Tabellenzellen dieses Excel-Dokumentes, deren Wert kalkulatorisch ermittelt wird. Die Liste ist nicht hierarchisch strukturiert, wie man es in einem XML-Dokument erwarten würde, sondern eine Sequenz von <c>-Elementen. Jede Zelle, die in die Liste aufgenommen werden soll, erhält hier ein <c>-Element mit einem r-Attribut mit dem entsprechenden Zellennamen als Wert:

<calcChain>
   <c r="B2" i="1"/>
   <c r="B3"/>
   <c r="B4"/>
   <c r="B5"/>
     [...]
</calcChain>

Zwischen einzelnen Tabellenblättern wird durch die Reihenfolge der <c>-Elemente unterschieden. Das erste <c>-Element, das auf ein neues Tabellenblatt verweist, erhält zusätzlich ein i-Attribut mit der ID des Tabellenblattes, die im workbook-Part angegeben wurde.

<c r="B2" i="1"/>
<c r="B3"/>
 [...]
<c r="A2" i="2"/>
<c r="C15"/>
 [...]

 

Styles

Mit dem styles-Part können die Zellen des Excel-Dokumentes unterschiedlich formatiert werden. Da es hierzu schier unermesslich viele Möglichkeiten zur Formatierung gibt, sollen hier lediglich folgende Layout-Konstruktionen beschrieben werden:

  • Schriftart und -schnitt

  • Schrift- und Hintergrundfarbe

  • Zellrahmen

  • Zahlenformate

  • Ausrichtung

Ein Style wird im Top-Level-Element <cellXfs> des styles-Parts mit einem <xf>-Element definiert. Für jede unterschiedlich formatierte Zelle muss hier ein Style hinterlegt werden. Soll einer Zelle ein Style zugewiesen werden, wird dem <c>-Element ein s-Attribut zugefügt:

<c r="B3" s="1">
  [...]
</c>

Der Wert des Attributs entspricht dem Index eines <xf>-Elements innerhalb des Elements <cellXfs>. Der Index der <xf>-Elemente beginnt bei 0, sodass in diesem Beispiel der zweite definierte Style zugewiesen wird.

<cellXfs> 
   <xf fontId="0" fillId="0" borderId="0"/>
   <xf fontId="1" fillId="2" borderId="0"/>
</cellXfs>

Das <xf>-Element wiederum verweist mit Attributen auf einzelne Komponenten einer Formatierung. So gibt es eine Referenz auf den verwendeten Font (fontId-Attribut), auf die Hintergrundfarbe (fillId) oder auf die Rahmen-Formatierung (borderId). Auch diese Referenzen verwenden den Index eines entsprechenden Container-Elements. Hier wird auf die Top-Level-Elemente <fonts>, <fills> bzw. <borders> verwiesen, die als Container-Elemente alle entsprechenden Formatangaben enthalten.

Schriftschnitt

Im Container <fonts> stellt ein <font>-Element einen Schnitt einer Schrift zur Verfügung. Eine Schriftart ist eine Sammlung verschiedener Schriftschnitte. Die Schriftschnitte unterscheiden sich anhand verschiedener Komponenten. Die am häufigsten berücksichtigten Komponenten sind dabei Schriftart, -stärke, -lage und -größe. Das bedeutet: Für jede Schriftart gibt es pro unterstützter Schriftstärke zwei Schriftschnitte: einen normalen und einen kursiven. Zudem enthalten Schriftschnitte häufig einen unterschiedlichen Schnitt für sehr kleine Schriftgrößen.

Das <font>-Element enthält so mit den Kindelementen folgender Liste die Angaben für den zu verwendenden Schriftschnitt:

<name>  Schriftart
<sz>  Schriftgröße
<i>  kursiv
<b>  Schriftstärke

Es handelt sich hierbei lediglich um eine Auswahl der möglichen Kindelemente des <font>-Elements.

Diese Elemente sind stets leer und erhalten jeweils ein val-Attribut, das die entsprechende Formatangabe als Wert erhält. Beim <name>-Element ist es der komplette Schriftname, bei <sz> eine Dezimalzahl, die die Schriftgröße in Punkt angibt, und bei <i> und <b> jeweils ein boolescher Wert, der angibt, ob der kursive bzw. fette Schriftschnitt verwendet werden soll.

Für die Schriftgröße ist zu beachten, dass Excel Schriftgrößen nur in halb-Punkt-Schritten unterstützt. Eine Angabe für die Schriftgröße mit der Dezimalzahl 11.7 wird folglich auf 11.5 abgerundet.

Die Elemente <i> und <b> benötigen dagegen nicht unbedingt ein val-Attribut, da der Wert true hier Default-Wert ist. Nur wenn eine kursive bzw. fette Formatierung aufgehoben werden soll, ist folglich das val-Attribut mit dem Wert false notwendig. Andere Schriftstärken als fett werden nicht unterstützt.

<fonts>
   <font>
      <b/>
      <sz val="11"/>
      <name val="Times New Roman"/>
   </font>
   <font>
      <i/>
      <sz val="10"/>
      <name val="Verdana"/>
   </font>
</fonts>
 [...]
<cellXfs> 
   <xf fontId="1" fillId="0" borderId="0"/>
   <xf fontId="0" fillId="2" borderId="0"/>
</cellXfs>

Hier werden zwei Schriftschnitte verwendet. Der erste ist von der Schriftart Times New Roman, mit einer Schriftgröße von 11 pt und fett ausgezeichnet. Der andere verwendet die Schriftart Verdana mit einer 10-Punkt-Schriftgröße und ist kursiv ausgezeichnet. Die zwei Styles im <cellXfs>-Element referenzieren mit dem Index (der sich aus der Reihenfolge der <font>-Elemente ergibt) im jeweiligen fontId-Attribut auf diese <font>-Elemente. Das erste <xf>-Element auf den Verdana-Schriftschnitt, der andere auf den mit der Schriftart Times New Roman.

Schriftfarbe

Im <font>-Element können auch weitere Formatierungseigenschaften angegeben werden, die eigentlich nicht zu einem Schriftschnitt gehören. Ein Beispiel ist die Schriftfarbe mit dem <color>-Element. Sollten zwei Styles den gleichen Schriftschnitt aber unterschiedliche Schriftfarben zugewiesen bekommen, ist zu beachten, dass auch auf unterschiedliche <font>-Elemente verwiesen werden muss.

Dem <color>-Element kann mit dem rgb-Attribut ein ARGB-Wert übergeben werden. Dieser besteht aus einer achtstelligen Hexadezimalzahl, die aber als vier aneinanderhängende zweistellige Hexadezimalzahlen gesehen werden muss. Diese Hexadezimalwerte haben also jeweils einen maximalen Wert von 255 (FF) und einen minimalen von 0 (00). Der erste Wert ist der sogenannte Alpha-Wert, der die Opazität der Farbe angibt. Dabei steht FF für eine Opazität von 100%, also vollständig deckend. Bei einem Wert 00 wäre eine Opazität von 0% erreicht. Die letzten drei Werte ergeben den RGB-Wert: Also der zweite Wert den Rot-, der dritte den Grün- und der vierte den Blau-Wert. In Excel hat der Alpha-Wert sowohl bei der Schrift- als auch bei der Hintergrundfarbe keinen weiteren Einfluss und wird von der Applikation ignoriert. Alle Farben werden vollständig deckend dargestellt.

Ein <font>-Element, das die Schriftart Verdana hat, in kursiv und mit einer Schriftgröße von 10 pt, und dem nun zusätzlich eine gelbe Schriftfarbe zugewiesen wird, zeigt folgendes Beispiel:

<font>
   <i/>
   <sz val="10"/>
   <name val="Verdana"/>
   <color rgb="FFFFFF00"/>
</font>

Hintergrundfarbe

Im Gegensatz zur Schriftfarbe ist die Hintergrundfarbe nicht an ein <font>-Element gebunden, sondern wird eigenständig im <fills>-Container hinterlegt. So können zwei verschiedene <xf>-Styles auf das gleiche <font>-Element verweisen, aber unterschiedliche Hintergrundfarben haben.

Wie bereits beim Font wird mit dem Index, der im fillId-Attribut des <xf>-Elements angegeben wird, auf ein <fill>-Element innerhalb dieses <fills>-Containers verwiesen.

Ein <fill>-Element enthält ein <patternFill>- oder ein <gradientFill>-Element. Für ein Muster, einen einfarbigen Hintergrund oder gar keinen Hintergrund wird Ersteres verwendet, für einen Verlauf Letzteres. Wir wollen uns hier allerdings nur auf die Beschreibung des <patternFill>-Elements beschränken, da Verläufe als stilistisches Mittel in Excel selten Einsatz finden.

Dem <patternFill>-Element wird über ein patternType-Attribut ein Typ mitgegeben, der angibt, ob es sich um einen einfarbigen oder einen transparenten Hintergrund handelt bzw. welches Muster verwendet werden soll. Für einen transparenten Hintergrund wird der Wert none angegeben, für einen einfarbigen der Wert solid. Für weitere Muster gibt der Standard eine Liste verschiedener Werte vor, die jeweils für ein bestimmtes Muster stehen.

Innerhalb des <patternFill>-Elements erfolgt nun die Farbangabe. Da bei Mustern zwei Farben verwendet werden, wird hier zwischen Hintergrund- und Vordergrundfarbe unterschieden. Das <bgColor>-Element gibt Erstere an, mit dem Element <fgColor> kann Letztere angegeben werden. Bei einfarbigen Mustern ist nur das <fgColor>-Element entscheidend. Abgesehen von der Unterscheidung zwischen Vorder- und Hintergrundfarbe gibt es keine Unterscheidung zu dem <color>-Element, das für die Schriftfarbe zuständig ist.

Folgendes <fill>-Element erzeugt einen einfarbigen gelben Hintergrund:

<fill>
   <patternFill patternType="solid">
      <fgColor rgb="FFFFFF00"/>
   </patternFill>
</fill>

Zellrahmen

Analog zu Schriftschnitt und Hintergrundfarbe, wird für die Rahmeneigenschaften im <xf>-Element mit dem borderId-Attribut auf ein <border>-Element im <borders>-Container verwiesen.

Das <border>-Element enthält für jede Seite der Zelle sowie für die Diagonale ein Element. Kindelemente können folglich sein: <left> (links), <right> (rechts), <top> (oben), <bottom> (unten) und <diagonal> (Diagonale).

Jedes dieser Elemente kann ein <color>-Element enthalten und ein style-Attribut haben. Ein Rahmen ist erst dann sichtbar, wenn dem jeweiligen Element mit dem <color>-Element wie bei der Schriftfarbe eine Farbe zugewiesen und mit dem style-Attribut eine Linienart bestimmt wurde. Dabei gibt es 14 vorgegebene Linienarten:

Abb. 8: Optionen in Excel für den Borderstyle (vgl. Tabelle 2)

Abb. 8: Optionen in Excel für den Borderstyle (vgl. Tabelle 2)

Tabelle 2: Attributwerte für unterschiedliche Borderstyles (vgl. Abb. 8)

Attributwerte für das style-Attribut

none

mediumDashDotDot

hair

slantDashDot

dotted

mediumDashDot

dashDotDot

mediumDashed

dashDot

medium

dashed

thick

thin

double

Soll eine Zelle einen gepunkteten blauen Rahmen an der Unterseite haben, muss ihr folgender Rahmen-Style zugewiesen werden:

<border>
   <bottom style="dotted">
      <color rgb="FF0000FF"/>
   </bottom>
</border>

Zahlenformate

Handelt es sich bei dem Inhalt einer Zelle um eine Zahl, gibt es verschiedene Möglichkeiten diese darzustellen. Beispielsweise kann sie als Währung mit dem entsprechenden Währungssymbol dargestellt werden, als ganze Zahl oder auch als Dezimalzahl mit mindestens drei Nachkommastellen. Wie die Zahl dargestellt wird, wird über ein Zahlenformat bestimmt, das dem Style einer Zelle also dem <xf>-Element zugewiesen wird.

Wieder wird beim <xf>-Element mit einem Attribut auf die genaue Spezifizierung in einem Container verwiesen. Bei dem Zahlenformat ist hierzu das Attribut numFmtId zuständig, das auf ein <numFmt>-Element im <numFmts>-Container verweist. In diesem Fall weicht SpreadsheetML ohne ersichtlichen Grund von der Referenz mittels Index ab und verwendet eine freiwählbare ID.

Da die <numFmt>-Elemente nicht mehr über den Index referenziert werden, muss jedes <numFmt>-Element eine ID erhalten. Hierzu erhält das Element ebenfalls ein Attribut numFmtId. Das Zahlenformat wird nun über einen String im Attribut formatCode angegeben.

Format-String

Für den String, der das Zahlenformat bestimmt, gelten Regeln, die eine Zeichenkette mittels Bestimmung von Schlüsselzeichen in ein Muster zur Darstellung von Zahlen umwandeln (Zahlenmuster). Die folgenden Beispiele sollen die wichtigsten Schlüsselzeichen erläutern.

Fixe Stellen

Die Tabelle 3 enthält Beispiele für die Darstellung von Werten anhand des Zahlenmusters 00.0:

Wert

Darstellung

0.10

00,1

1

01,0

5.555

05,6

=1/3 (Formel)

00,3

115

115,0

Wie zu erkennen ist, wird stets eine Zahl mit einer Stelle nach dem Komma dargestellt. Der Punkt steht im Zahlenmuster für das Dezimaltrennzeichen, das abhängig von der Applikation eingefügt wird (hier als Komma, was abhängig von den Einstellungen in Excel ist). Das Schlüsselzeichen 0 im Muster steht für eine zwingend erforderliche Ziffer. Ist der Wert zu klein für die Stelle des 0-Zeichens vor dem Komma oder zu ungenau für entsprechende Stellen nach dem Komma, wird eine auffüllende 0 an diesen Stellen eingefügt. Hat der Wert der Zelle mehr Stellen vor dem Dezimaltrennzeichen als das Zahlenmuster, werden diese trotzdem dargestellt. Hat der Zellwert mehr Stellen nach dem Komma als das Zahlenmuster, wird kaufmännisch auf die Stellenanzahl des Musterstrings gerundet.

Variable Stellen

Bisher ist hier nur das Schlüsselzeichen 0 als Zeichen für eine Stelle erläutert worden. Ein weiteres ist das Raute-Zeichen (#). Es steht für eine nicht zwingend erforderliche aber mögliche Zahl. Die Tabelle 4 zeigt anhand von Beispielen die Darstellung durch das Zahlenmuster #0.0#:

Wert

Darstellung

0.10

0,1

1

1,0

5.55

5,55

=1/3 (Formel)

0,33

115

115,0

5.555

5,56

Im Gegensatz zum 0-Zeichen, wird die #-Stelle nie durch eine auffüllende 0 dargestellt. Ist der Wert zu ungenau bzw. zu klein für diese Stelle, fällt diese bei der Darstellung weg. Die Stelle wird also abhängig vom Zellwert dargestellt und nicht jede Darstellung hat gleich viele Stellen.

Statische Zeichen

Anführungszeichen umschließen im Muster einen statisch einzufügenden String. Die Tabelle 6 enthält Beispiele für das Zahlenmuster "betrag:" 0.0 €:

Wert

Darstellung

1

betrag: 1,0 €

50

betrag: 50,0 €

Zu beachten ist hierbei, dass der Musterstring als Attributwert übergeben wird und hier die Anführungszeichen " nicht erlaubt sind. Üblich ist bei anderen XML-Sprachen, hier auf einfache Anführungszeichen (') auszuweichen. Dies ist jedoch im Musterstring nicht erlaubt. Daher müssen die Anführungszeichen hier durch die Entity &quot; ersetzt werden:

<numFmt numFmtId="0" formatCode="&amp;quot;betrag:&amp;quot; 0.0 "/>

Es gibt bestimmte Schlüsselzeichen, die unmaskiert statisch eingefügt werden. Hierzu gehören Währungszeichen wie € oder $, Leerzeichen sowie die Zeichen Plus (+), Minus (-) oder runde Klammern.

Sollen andere einzelne Zeichen statisch dargestellt werden, können diese mit einem vorstehenden Backslash (\) maskiert werden. Das Teil-Muster \e fügt ein statisches "e" ein.

Negative Werte

Das Zahlenmuster bietet auch die Möglichkeit, zwischen positiven und negativen Werten zu unterscheiden. Hierzu dienen zwei Teilmuster, die durch ein Semikolon (;) getrennt werden. Das Teilmuster vor dem Semikolon wird für positive Werte angewandt, das nach dem Semikolon für die negativen. Die Tabelle 6 zeigt die Darstellung des Zahlenmusters \P\: 0.00 €;\N\: 0.00 €:

Wert

Darstellung

10

P: 10,00 €

-10

N: 10,00 €

0

P: 0,00 €

Des Weiteren können noch zwei weitere Teilmuster ebenfalls durch Semikoli getrennt angehängt werden:

positiverWert;negativerWert;nullWert;stringMuster.

Das dritte Teilmuster wird für den Wert 0 verwendet (der ohne drittes Teilmuster als positiver Wert angesehen wird) und das vierte für die Darstellung eines Strings, der an Stelle eines Zahlenwertes in die Zelle eingegeben wurde.

Ausrichtung

Die Ausrichtung des Zelleninhalts zum Rahmen ist im Gegensatz zu den vorstehend beschriebenen Formatierungsmerkmalen direkt im <xf>-Element beschrieben. Dazu dient das Kindelement <alignment>, das sowohl die horizontale als auch die vertikale Ausrichtung angibt sowie weitere Besonderheiten, wie die Text-Rotation oder die Schreibrichtung. Für die Ausrichtung erhält das Element ein horizontal- bzw. ein vertical-Attribut. Für Ersteres kann die horizontale Ausrichtung mit den Werten center (für zentriert), general (abhängig vom Typ der Zelle), justify (Blocksatz), left (linksbündig) und right (rechtsbündig) angegeben werden. Hierbei handelt es sich lediglich um eine Auswahl der verbreitetsten horizontalen Ausrichtungen.

Für die vertikale Ausrichtung können u.a. die Werte center (mittig), top (nach oben ausgerichtet), bottom (nach unten ausgerichtet) und justify (Blocksatz) dem vertical-Attribut übergeben werden.

Zusammenfassung

Abb. 9: Vorgabe für Formatierung der Kopfzellen

Abb. 9: Vorgabe für Formatierung der Kopfzellen

Als Zusammenfassung der vorgestellten Formatierungseigenschaften soll für die Kopfzellen der Tabelle aus der Abbildung 9 ein Style dargestellt werden. Die Zellen benötigen also folgende Formatierungseigenschaften:

  • blauer Zellrahmen rechts und unten

  • gelber Hintergrund

  • Schriftschnitt:

    • Schriftart: Verdana

    • Schriftgröße: 10 pt

    • Auszeichnung: fett

    • Schriftfarbe: blau

  • Ausrichtung

    • Vertikal: oben

    • Horizontal: zentriert

<fonts>
   <font> [...] </font>
   <font>
      <b/>
      <sz val="10"/>
      <color rgb="FF0000FF"/>
      <name val="Verdana"/>
   </font>
</fonts>
<fills>
   <fill>
      <patternFill patternType="solid">
         <fgColor rgb="FFFFFF00"/>
      </patternFill>
   </fill>
</fills>
<borders>
   <border/>
   <border>
      <right style="medium">
         <color rgb="FF0000FF"/>
      </right>
      <bottom style="medium">
         <color rgb="FF0000FF"/>
      </bottom>
   </border>
</borders>
  [...]
<cellXfs>
   <xf fontId="0" fillId="0" borderId="0"/>
   <xf fontId="1" fillId="0" borderId="1">
      <alignment horizontal="center" vertical="top"/>
   </xf>
  [...]
</cellXfs>

Das zweite <xf>-Element ist für den Kopf der Tabelle zuständig. Es greift auf das zweite <font>-Element des <fonts>-Containers, auf das erste <fill>-Element des <fills>-Containers und auf das zweite <border>-Element des <borders>-Containers zurück. Zudem weist es dem Style mit dem <alignment>-Element eine zentrierte Ausrichtung in der Horizontalen und in der Vertikalen eine Ausrichtung zum oberen Zellrand zu.

Die Beschreibung in diesem Artikel ist natürlich nur eine Auswahl der am häufigsten verwendeten Formatierungseigenschaften, die der styles-Part den Zellen zuweist.

 

Formatierung ganzer Zeilen

Es gibt Formatierungsangaben für Tabellen, die eine gesamte Zeile betreffen. Dies ist beispielsweise die Zeilenhöhe, die eine Zelle nicht individuell haben kann.

Auch besteht bei den üblichen Tabellenmodellen die Möglichkeit, eine Formatierung für eine Zeile vorzugeben, die sämtliche Zellen einer Zeile erhalten, sofern der einzelnen Zelle nicht ein eigener Style zugewiesen wird. Werden alle Zellen einer Zeile gleich formatiert, muss dies in einem solchen Fall nur noch zentral für die ganze Zeile geschehen und nicht für jede Zeile einzeln.

Zeilenhöhe

Abb. 10: Höhe einer Tabellenzeile

Abb. 10: Höhe einer Tabellenzeile

Eine eigene Zeilenhöhe erhält die Zeile, indem dem <row>-Element ein customHeight-Attribut mit dem Wert 1 bzw. true mitgegeben wird. Nun kann der Zeile mit dem ht-Attribut eine Zeilenhöhe angegeben werden. Die Zeilenhöhe wird in Punkt angegeben.

<row r="1" customHeight="1" ht="21">
 [...]
</row>

Styles einer Zeile

Bei SpreadsheetML ist die Möglichkeit, allen Zellen einer Zeile zentral die gleiche Formatierungseigenschaft zuzuweisen, leider und unverständlicherweise nur eingeschränkt gegeben. Zwar kann eine Zeile einen eigenen Style erhalten, jedoch gilt dieser nur für Zellen, die nicht mit einem <c>-Element erzeugt wurden, also nur für leere Zellen. Sollen alle Zellen einer Zeile die gleichen Formatierungseigenschaften erhalten, muss folglich dem <row>-Element und allen <c>-Elementen der gleiche Style zugewiesen werden.

Abb. 11: Style einer Tabellenzeile

Abb. 11: Style einer Tabellenzeile

Ein Style wird einem <row>-Element, wie beim <c>-Element auch, mit dem s-Attribut zugewiesen. Das <row>-Element benötigt einen zusätzlichen Indikator, der angibt, dass eine manuelle Formatierung vorgenommen wird. Für die Formatierung ist dies das customFormat-Attribut, das mit dem Wert 1 oder true die manuelle Formatierung aktiviert:

<row r="1" s="2" customFormat="1">
   <c r="A1" s="2" t="inlineStr">
     [...]
   </c>
   <c r="B1" s="2" t="inlineStr">
     [...]
   </c>
</row>

Die s-Attribute der beiden <c>-Elemente sind notwendig, da ohne diese die entsprechenden Zellen keine Formatierung erhalten würden.

 

Formatierung ganzer Spalten

Äquivalent zu den Zeilen, muss es auch die Möglichkeit geben, ganzen Spalten Formatierungseigenschaften zuzuweisen. Hier entsteht die Problematik, dass es kein Element gibt, das alle Zell-Elemente einer Spalte enthält. SpreadsheetML hält sich hier an die Lösung vieler gängiger Tabellenmodelle: Für jede Spalte ist ein <col>-Element im <cols>-Container zuständig. Das <cols>-Element ist ein Top-Level-Element des sheet-Parts und steht direkt vor dem <sheetData>-Element:

<worksheet>
[...]
   <cols>
      [Enthält mit col-Elementen Angaben zu den Spalten]
   </cols>
   <sheetData>
      [...]
   </sheetData>
[...]
</worksheet>

Dabei muss nicht jede Spalte, die formatiert werden soll, ein eigenes <col>-Element erhalten. Ein <col>-Element kann auch für mehrere Spalten zuständig sein. Hierzu dienen dem <col>-Element die Attribute min und max, die mit Indizes einen Bereich von Spalten angeben, für die das <col>-Element zuständig sein kann.

<col min="2" max="4"/>

Dieses <col>-Element kann für die Spalten 2 (B), 3 (C) und 4 (D) zuständig sein. Enthalten die Bereiche verschiedener <col>-Elemente die gleiche Spalte, ist das <col>-Element zuständig, das als letztes im <cols>-Container steht.

<cols>
   <col min="2" max="4"/>
   <col min="3" max="5"/>
</cols>

Für die Spalte 2 ist das erste <col>-Element zuständig, für die Spalten 3, 4, und 5 ist es das zweite <col>-Element.

Spaltenbreite

Abb. 12: Style einer Tabellenspalte

Abb. 12: Style einer Tabellenspalte

Wie für eine Zeile die Höhe bestimmt wird, muss für eine Spalte zentral die Spaltenbreite angegeben werden. Hierzu dienen die Attribute customWidth und width. Das customWidth-Attribut ist der Indikator dafür, dass eine Breite manuell angegeben wird (mit 1 oder true). Die Angabe der Breite erfolgt im width-Attribut in einer Maßeinheit, die sich an der Anzahl der möglichen Ziffern orientieren soll, die die Zelle ohne Überlappung enthalten kann. Diese Berechnung scheint jedoch nur auf der Schriftart Calibri in 11 pt zu basieren.

Styles einer Spalte

Ebenso wie einer Zeile, kann auch einer Spalte ein Style für die leeren Zellen zugewiesen werden. Das Attribut, das beim <row>-Element das s-Attribut war, ist beim <col>-Element das style-Attribut. Auch hier wird wieder ein Style aus dem styles-Part durch einen Index referenziert. Im Gegensatz zum Style einer Zeile ist hier kein Indikator nötig, der angibt, dass dieser Spalte manuell eine Formatierung zugewiesen wurde.

<cols>
   <col min="1" max="1" style="1"/>
   <col min="2" max="2" style="5"/>
</cols>
<sheetData>
   <row r="1">
      <c r="A1" t="inlineStr" s="1"><is><t>x</t></is></c>
      <c r="B1" t="inlineStr" s="5"><is><t>y</t></is></c>
   </row>
   <row r="2">
      <c r="A2" s="1"><v>1</v></c>
      <c r="B2" s="5"><v>1</v></c>
   </row>
[...]
</sheetData>
 
Tipp der data2type-Redaktion:
Zum Thema SpreadsheetML bieten wir auch folgende Schulungen zur Vertiefung und professionellen Fortbildung an: