Bearbeiten von Excel 2007- und PowerPoint 2007-Dateien mit dem Open XML-Objektmodell (Teil 1 von 2)

Zusammenfassung: Die Technologievorschau des Microsoft-SDK für Open XML-Formate ist eine Bibliothek für den Zugriff auf Dateien im Open XML-Format. In diesem ersten von zwei Artikeln wird der Open XML-Objektmodellcode beschrieben, den Sie verwenden können, um auf Microsoft Excel 2007- und Microsoft PowerPoint 2007-Dateien zuzugreifen und sie zu bearbeiten. (12 gedruckte Seiten)

Frank Rice, Microsoft Corporation

August 2007

Gilt für: Microsoft Office Excel 2007 und Microsoft Office PowerPoint 2007

Inhalt

Lesen Sie Teil 2: Bearbeiten von Excel 2007- und PowerPoint 2007-Dateien mit dem Open XML-Objektmodell (Teil 2 von 2).

Übersicht

Mit 2007 Microsoft Office System werden neue XML-basierte Dateiformate mit der Bezeichnung „Open XML-Formate“ eingeführt. Microsoft Office Word 2007, Microsoft Office Excel 2007 und Microsoft Office PowerPoint 2007 verwenden diese Formate als Standarddateiformat. Open XML-Formate sind nützlich, weil sie einen offenen Standard darstellen und auf bekannten Technologien basieren: ZIP und XML. Microsoft stellt als Bestandteil der .NET Framework 3.0-Technologien im Namespace System.IO.Packaging in der Technologievorschau des Microsoft-SDK für Open XML-Formate eine Bibliothek für den Zugriff auf diese Dateien bereit. Das Open XML-Objektmodell basiert auf der System.IO.Packaging-API und stellt stark typisierte Teilklassen zum Bearbeiten von Open XML-Dokumenten zur Verfügung. Das SDK vereinfacht das Bearbeiten von Open XML-Paketen. Da das Open XML-Objektmodell viele der Aufgaben umfasst, die von Entwicklern häufig an Open XML-Paketen durchgeführt werden, können Sie komplizierte Vorgänge mit nur wenigen Codezeilen durchführen.

HinweisHinweis:

Weitere Beispiele für die Bearbeitung von Dateien, die im Open XML-Format vorliegen, sowie Verweise auf jeden im Open XML-Objektmodell enthaltenen Member finden Sie im 2007 Office System: Microsoft-SDK für Open XML-Formate.

Die Open Package Convention-Spezifikation definiert einen Satz von XML-Dateien, die den Inhalt aller in einem einzigen Paket gespeicherten Dokumentteile umfassen und deren Beziehungen definieren. In diesen Paketen werden die Teile kombiniert, aus denen die Dokumentdateien für die 2007 Microsoft Office-Programme bestehen, die das Open XML-Format unterstützen. Das Open XML-Objektmodell, das in diesem Artikel behandelt wird, ermöglicht Ihnen, Pakete zu erstellen und die Dateien zu bearbeiten, aus denen diese Pakete bestehen. In dieser Artikelreihe beschreibe ich den Code, mit dem Sie auf Open XML-Pakete in Excel 2007 und PowerPoint 2007 zugreifen und diese bearbeiten können.

Löschen von Kommentaren in Arbeitsmappen nach Benutzername

Im folgenden Code entfernen Sie Dokumentkommentare für einen bestimmten Benutzernamen.

Visual Basic
Public Sub XLDeleteCommentsByUser(ByVal fileName As String, ByVal userName As String)
   Const commentsSchema As String = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
   Dim doc As SpreadsheetDocument = SpreadsheetDocument.Open(fileName, True)
   '  Manage namespaces to perform XML XPath queries.
   Dim nt As NameTable = New NameTable
   Dim nsManager As XmlNamespaceManager = New XmlNamespaceManager(nt)
   nsManager.AddNamespace("sh", commentsSchema)
   For Each part As WorksheetPart In doc.WorkbookPart.WorksheetParts
      If (Not (part.WorksheetCommentsPart) Is Nothing) Then
         Dim commentDoc As XmlDocument = New XmlDocument
         commentDoc.Load(part.WorksheetCommentsPart.GetStream)
         Dim searchString As String = String.Format("//sh:authors/sh:author[text()='{0}']", userName)
         Dim node As XmlNode = commentDoc.SelectSingleNode(searchString, nsManager)
         If (Not (node) Is Nothing) Then
            Dim nodes As XmlNodeList = node.SelectNodes("preceding-sibling::sh:author", nsManager)
            Dim authorID As Integer = nodes.Count

            Dim commentListNode As XmlNode = commentDoc.SelectSingleNode("sh:comments/sh:commentList", nsManager)
            If (Not (commentListNode) Is Nothing) Then
               searchString = String.Format("./sh:comment[@authorId='{0}']", authorID)
               Dim comments As XmlNodeList = commentListNode.SelectNodes(searchString, nsManager)
               For Each commentNode As System.Xml.XmlNode In comments
                  commentListNode.RemoveChild(commentNode)
               Next
            End If
         End If
         '  Save the comment XML back to its part.
         commentDoc.Save(part.WorksheetCommentsPart.GetStream(FileMode.Create))
      End If
   Next
End Sub
C#
public static void XLDeleteCommentsByUser(string fileName, string userName)
{
   const string commentsSchema = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";

   using (SpreadsheetDocument doc = SpreadsheetDocument.Open(fileName, true))
   {
      //  Manage namespaces to perform XML XPath queries.
      NameTable nt = new NameTable();
      XmlNamespaceManager nsManager = new XmlNamespaceManager(nt);
      nsManager.AddNamespace("sh", commentsSchema);

      foreach (WorksheetPart part in doc.WorkbookPart.WorksheetParts)
      {
         if (part.WorksheetCommentsPart != null)
         {
            XmlDocument commentDoc = new XmlDocument();
            commentDoc.Load(part.WorksheetCommentsPart.GetStream());
            string searchString = string.Format("//sh:authors/sh:author[text()='{0}']", userName);
            XmlNode node = commentDoc.SelectSingleNode(searchString, nsManager);
            if (node != null)
            {
                XmlNodeList nodes = node.SelectNodes("preceding-sibling::sh:author", nsManager);
                int authorID = nodes.Count;

                XmlNode commentListNode = commentDoc.SelectSingleNode("sh:comments/sh:commentList", nsManager);
                if (commentListNode != null)
                {
                   searchString = string.Format("./sh:comment[@authorId='{0}']", authorID);
                   XmlNodeList comments = commentListNode.SelectNodes(searchString, nsManager);
                   foreach (System.Xml.XmlNode commentNode in comments)
                   {
                      commentListNode.RemoveChild(commentNode);
                   }
                }
            }
            //  Save the comment XML back to its part.
       commentDoc.Save(part.WorksheetCommentsPart.GetStream(FileMode.Create));
         }
      }
   }
}

In dieser Prozedur übergeben Sie zwei Parameter: den vollständigen Pfad zur Datei und den Benutzernamen der Person, deren Kommentare Sie löschen möchten. Danach öffnen Sie mithilfe der Methode Open des Objekts SpreadsheetDocument die Eingabedatei als ein Open XML-Paket. Anschließend richten Sie mithilfe des Objekts XmlNamespaceManager und durch Festlegen eines Verweises zum Standard-Namespace SpreadsheetML mit dem Qualifizierer sh einen Namespacemanager ein.

Danach überprüft die Prozedur, ob der Kommentarbestandteil im Paket enthalten ist. Die Inhalte des Kommentarbestandteils werden in ein speicherresidentes XML-Dokument geladen. Anschließend durchsuchen Sie mithilfe des XPath-Ausdrucks „sh:authors/sh:author“ die Arbeitsmappe über einem bestimmten Benutzernamen nach Knoten. Wenn der Benutzername gefunden wird, finden Sie auch den Ordinalwert dieses Benutzernamens. Anschließend rufen Sie den Index des ausgewählten Knotens ab. Um dies zu tun, zählen Sie die Anzahl der vorhergehenden Knoten, indem Sie einen Verweis zu diesen Knoten abrufen.

Zum Schluss wird der aktualisierte Kommentarmarkupstream wieder im Kommentarbestandteil gespeichert.

Löschen von Arbeitsblättern

Im folgenden Code löschen Sie ein Arbeitsblatt aus einem Tabellendokument.

Visual Basic
Public Function XLDeleteSheet(ByVal fileName As String, ByVal sheetToDelete As String) As Boolean
   Dim returnValue As Boolean = False
   '  Open the package with read/write access.
   Dim xlDoc As SpreadsheetDocument = SpreadsheetDocument.Open(fileName, True)
   Dim doc As XmlDocument = New XmlDocument
   doc.Load(xlDoc.WorkbookPart.GetStream)
   Dim nsManager As XmlNamespaceManager = New XmlNamespaceManager(doc.NameTable)
   nsManager.AddNamespace("d", doc.DocumentElement.NamespaceURI)
   Dim searchString As String = String.Format("//d:sheet[@name='{0}']", sheetToDelete)
   Dim node As XmlNode = doc.SelectSingleNode(searchString, nsManager)
   If (Not (node) Is Nothing) Then
      Dim relationAttribute As XmlAttribute = node.Attributes("r:id")
      If (Not (relationAttribute) Is Nothing) Then
         Dim relId As String = relationAttribute.Value
         xlDoc.WorkbookPart.DeletePart(relId)
         node.ParentNode.RemoveChild(node)
         doc.Save(xlDoc.WorkbookPart.GetStream(FileMode.Create))
         returnValue = True
      End If
   End If
   Return returnValue
End Function
C#
public static bool XLDeleteSheet(string fileName, string sheetToDelete)
{
   bool returnValue = false;
   using (SpreadsheetDocument xlDoc = SpreadsheetDocument.Open(fileName, true))
   {
      XmlDocument doc = new XmlDocument();
      doc.Load(xlDoc.WorkbookPart.GetStream());

      XmlNamespaceManager nsManager = new XmlNamespaceManager(doc.NameTable);
      nsManager.AddNamespace("d", doc.DocumentElement.NamespaceURI);

      string searchString = string.Format("//d:sheet[@name='{0}']", sheetToDelete);
      XmlNode node = doc.SelectSingleNode(searchString, nsManager);
      if (node != null)
      {
         XmlAttribute relationAttribute = node.Attributes["r:id"];
         if (relationAttribute != null)
         {
            string relId = relationAttribute.Value;
            xlDoc.WorkbookPart.DeletePart(relId);
            node.ParentNode.RemoveChild(node);
            doc.Save(xlDoc.WorkbookPart.GetStream(FileMode.Create));
            returnValue = true;
          }
      }
   }
   return returnValue;
}

In dieser Prozedur übergeben Sie zwei Parameter: Den vollständigen Pfad zur Arbeitsmappe und den Namen des Arbeitsblatts, das gelöscht werden soll. Danach öffnen Sie mithilfe der Methode Open des Objekts SpreadsheetDocument die Eingabedatei als ein Open XML-Paket. Anschließend laden Sie den Inhalt der Arbeitsmappe in ein XML-DOM-Dokument. Danach richten Sie mithilfe des Objekts XmlNamespaceManager und durch Festlegen eines Verweises zum Standard-Namespace SpreadsheetML mit dem Qualifizierer d einen Namespace-Manager ein. Anschließend durchsuchen Sie das Dokument mithilfe des name-Attributs des Knotens „//d:sheet“ nach dem angegebenen Arbeitsblatt.

Bei allen übereinstimmenden Knoten (sofern vorhanden) wird die Beziehungs-ID abgerufen und das Arbeitsblatt, das dieser ID entspricht, gelöscht.

Zum Schluss wird das aktualisierte SpreadsheetML-Markup im Hauptarbeitsmappenbestandteil zurückgespeichert.

Erkennen ausgeblendeter Zeilen und Spalten in Arbeitsblättern

Bei Vorgabe einer Arbeitsmappe und eines Arbeitsblattnamens gibt der folgende Code entweder eine Liste der Nummern ausgeblendeter Zeilen oder eine Liste der Nummern ausgeblendeter Spalten zurück.

Visual Basic
Public Function XLDetectHiddenRowsOrCols(ByVal fileName As String, ByVal sheetName As String, ByVal detectRows As Boolean) As List(Of Integer)
   Const worksheetSchema As String = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
   '  Set up the return value list.
   Dim itemList As List(Of Integer) = New System.Collections.Generic.List(Of Integer)
   Dim xlDoc As SpreadsheetDocument = SpreadsheetDocument.Open(fileName, False)
   '  Load the contents of the workbook.
   Dim doc As XmlDocument = New XmlDocument
   doc.Load(xlDoc.WorkbookPart.GetStream)
   '  Create a namespace manager, so you can search.
   '  Add a prefix for the default namespace.
   Dim nsManager As XmlNamespaceManager = New XmlNamespaceManager(doc.NameTable)
   nsManager.AddNamespace("d", worksheetSchema)
   Dim searchString As String = String.Format("//d:sheet[@name='{0}']", sheetName)
   Dim sheetNode As XmlNode = doc.SelectSingleNode(searchString, nsManager)
   If (Not (sheetNode) Is Nothing) Then
      '  Get the relId attribute.
      Dim relationAttribute As XmlAttribute = sheetNode.Attributes("r:id")
      If (Not (relationAttribute) Is Nothing) Then
         Dim relId As String = relationAttribute.Value
         Dim sheetPart As WorksheetPart = CType(xlDoc.WorkbookPart.GetPartById(relId), WorksheetPart)
         '  First, get the relationship between the document and the sheet.
         '  Load the contents of the workbook.
         Dim sheetDoc As XmlDocument = New XmlDocument
         sheetDoc.Load(sheetPart.GetStream(FileMode.Open))
         If detectRows Then
             '  Retrieve the list of hidden rows.
             For Each node As System.Xml.XmlNode In sheetDoc.SelectNodes("//d:row[@hidden='1']", nsManager)
                  '  For each hidden row, add information to the output list.
                  Dim rowAttr As XmlAttribute = node.Attributes("r")
                  If (Not (rowAttr) Is Nothing) Then
                      itemList.Add(Convert.ToInt32(rowAttr.Value))
                  End If
          Next
      Else
          '  Retrieve the list of hidden columns
          For Each node As System.Xml.XmlNode In sheetDoc.SelectNodes("//d:cols/d:col", nsManager)
            Dim hiddenAttr As XmlAttribute = node.Attributes("hidden")
            If (Not (hiddenAttr) Is Nothing) Then
                If (hiddenAttr.Value = "1") Then
                   '  Get the range of columns that are hidden.
                   Dim minAttr As XmlAttribute = node.Attributes("min")
                   Dim maxAttr As XmlAttribute = node.Attributes("max")
                   If ((Not (minAttr) Is Nothing) AndAlso (Not (maxAttr) Is Nothing)) Then
                      '  Finally, add the range of values to the list.
                      Dim minValue As Integer = Convert.ToInt32(minAttr.Value)
                      Dim maxValue As Integer = Convert.ToInt32(maxAttr.Value)
                      Dim i As Integer = minValue
                      Do While (i <= maxValue)
                         itemList.Add(i)
                         i = (i + 1)
                      Loop
                   End If
                 End If
              End If
            Next
         End If
      End If
   End If
   Return itemList
End Function
C#
public static List<int> XLDetectHiddenRowsOrCols(string fileName, string sheetName, bool detectRows)
{
   const string worksheetSchema = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";

   //  Set up the return value list.
   List<int> itemList = new System.Collections.Generic.List<int>();

   using (SpreadsheetDocument xlDoc = SpreadsheetDocument.Open(fileName, false))
   {
      //  Load the contents of the workbook.
      XmlDocument doc = new XmlDocument();
      doc.Load(xlDoc.WorkbookPart.GetStream());

      //  Create a namespace manager, so you can search.
      //  Add a prefix for the default namespace.
      XmlNamespaceManager nsManager = new XmlNamespaceManager(doc.NameTable);
      nsManager.AddNamespace("d", worksheetSchema);

      string searchString = string.Format("//d:sheet[@name='{0}']", sheetName);
      XmlNode sheetNode = doc.SelectSingleNode(searchString, nsManager);
      if (sheetNode != null)
      {
          //  Get the relId attribute.
          XmlAttribute relationAttribute = sheetNode.Attributes["r:id"];
          if (relationAttribute != null)
          {
            string relId = relationAttribute.Value;

            WorksheetPart sheetPart = (WorksheetPart)xlDoc.WorkbookPart.GetPartById(relId);
            //  First, get the relationship between the document and the sheet.

            //  Load the contents of the workbook.
            XmlDocument sheetDoc = new XmlDocument();
            sheetDoc.Load(sheetPart.GetStream(FileMode.Open));

            if (detectRows)
            {
                //  Retrieve the list of hidden rows.
                foreach (System.Xml.XmlNode node in sheetDoc.SelectNodes("//d:row[@hidden='1']", nsManager))
                {
                  //  For each hidden row, add information to the output list.
                  XmlAttribute rowAttr = node.Attributes["r"];
                  if (rowAttr != null)
                  {
                      itemList.Add(Convert.ToInt32(rowAttr.Value));
                  }
                }
            }
            else
            {
               //  Retrieve the list of hidden columns.
               foreach (System.Xml.XmlNode node in sheetDoc.SelectNodes("//d:cols/d:col", nsManager))
               {
                  XmlAttribute hiddenAttr = node.Attributes["hidden"];
                  if (hiddenAttr != null)
                  {
                      if (hiddenAttr.Value == "1")
                      {
                          //  Get the range of columns that are hidden.
                          XmlAttribute minAttr = node.Attributes["min"];
                          XmlAttribute maxAttr = node.Attributes["max"];
                          if (minAttr != null && maxAttr != null)
                          {
                             //  Finally, add the range of values to the list.
                             int minValue = Convert.ToInt32(minAttr.Value);
                             int maxValue = Convert.ToInt32(maxAttr.Value);
                             for (int i = minValue; i <= maxValue; i++)
                             {
                                itemList.Add(i);
                             }
                          }
                      }
                   }
                }
             }
          }
       }
   }
   return itemList;
}

In dieser Prozedur übergeben Sie drei Parameter: Den vollständigen Pfad zur Excel 2007-Arbeitsmappe, den Namen des Arbeitsblatts und einen booleschen Wert, der angibt, ob nach ausgeblendeten Zeilen gesucht werden soll. Wenn detectRows den booleschen Wert true hat, gibt die Prozedur eine Liste ausgeblendeter Zeilen zurück. Wenn detectRows den booleschen Wert false hat, wird die Liste ausgeblendeter Spalten zurückgegeben. Danach öffnen Sie mithilfe der Methode Open des Objekts SpreadsheetDocument die Eingabedatei als ein Open XML-Paket. Anschließend laden Sie den Inhalt der Arbeitsmappe in ein XML-DOM-Dokument. Danach richten Sie mithilfe des Objekts XmlNamespaceManager und durch Festlegen eines Verweises zum Standard-Namespace „SpreadsheetML“ mit dem Qualifizierer d einen Namespacemanager ein. Anschließend durchsuchen Sie das Dokument mithilfe des name-Attributs des Knotens „//d:sheet“ nach dem Knoten, der das angegebene Arbeitsblatt repräsentiert.

Wenn der übereinstimmende Knoten gefunden wird, rufen Sie die Beziehung zwischen der Arbeitsmappe und dem Arbeitsblatt ab. Laden Sie zunächst die Inhalte des Arbeitsblatts. Wenn detectRows den booleschen Wert truehat, rufen Sie mithilfe des hidden-Attributs des Knotens „//d:row“ die Liste der ausgeblendeten Zeilen ab.

HinweisHinweis:

Die Nummerierung der Zeilen beginnt bei 1, die Nummerierung der Spalten dagegen bei null (0).

Wenn detectRows den booleschen Wert false hat, wird angenommen, dass Sie nach ausgeblendeten Spalten suchen möchten, wozu Sie dann das hidden-Attribut des Knotens „//d:cols/d:col“ verwenden.

Zum Schluss wird die Liste der Elemente an die aufrufende Prozedur zurückgegeben.

Exportieren von Diagrammen aus Arbeitsblättern

Wenn eine Excel 2007-Arbeitsmappe und der Titels eines Diagramms vorhanden sind, erstellen Sie eine Word 2007-Datei, und exportieren Sie das Diagramm.

Visual Basic
Public Sub XLExportChart(ByVal inputFileName As String, ByVal outputFileName As String, ByVal chartTitle As String)
   Const drawingMLSchema As String = "http://schemas.openxmlformats.org/drawingml/2006/main"
   Const chartMLSchema As String = "http://schemas.openxmlformats.org/drawingml/2006/chart"
   Dim chartFound As Boolean = False
   Dim xlDoc As SpreadsheetDocument = SpreadsheetDocument.Open(inputFileName, False)
   For Each sheetPart As WorksheetPart In xlDoc.WorkbookPart.WorksheetParts
      If (sheetPart.DrawingsPart Is Nothing) Then
         Continue For
      End If
      '  Loop through all the parts related to the worksheet.
      For Each chartPart As ChartPart In sheetPart.DrawingsPart.ChartParts
         '  A chart is found. Does it have the correct title?
         '  Create a namespace manager, so you can search.
         Dim nt As NameTable = New NameTable
         Dim nsManager As XmlNamespaceManager = New XmlNamespaceManager(nt)
         nsManager.AddNamespace("c", chartMLSchema)
         nsManager.AddNamespace("a", drawingMLSchema)
         '  Load the chart document from the part's stream, and 
         '  search for the requested title.
         Dim chartDoc As XmlDocument = New XmlDocument(nt)
         chartDoc.Load(chartPart.GetStream)
         Dim titleNode As XmlNode = chartDoc.SelectSingleNode("//c:chart//c:title//a:t", nsManager)
         If (Not (titleNode) Is Nothing) Then
            If (String.Compare(titleNode.InnerText, chartTitle, True) = 0) Then
               Dim newDoc As WordprocessingDocument = WordprocessingDocument.Create(outputFileName, WordprocessingDocumentType.Document)
               newDoc.AddMainDocumentPart()
            newDoc.MainDocumentPart.AddPart(Of ChartPart)(chartPart)
               '  Tell the outer loops that you are finished.
               chartFound = True
             End If
         End If
      Next
      '  Because you need to export only a single chart, exit.
      If chartFound Then
         Exit Sub
      End If
   Next
End Sub
C#
public static void XLExportChart(string inputFileName, string outputFileName, string chartTitle)
{
   const string drawingMLSchema = "http://schemas.openxmlformats.org/drawingml/2006/main";
   const string chartMLSchema = "http://schemas.openxmlformats.org/drawingml/2006/chart";

   bool chartFound = false;

   using (SpreadsheetDocument xlDoc = SpreadsheetDocument.Open(inputFileName, false))
   {
      foreach (WorksheetPart sheetPart in xlDoc.WorkbookPart.WorksheetParts)
      {
          if (sheetPart.DrawingsPart == null)
            continue;
          //  Loop through all the parts related to the worksheet.
          foreach (ChartPart chartPart in sheetPart.DrawingsPart.ChartParts)
          {
              //  A chart is found. Does it have the correct title?      

              //  Create a namespace manager, so you can search.
              NameTable nt = new NameTable();
              XmlNamespaceManager nsManager = new XmlNamespaceManager(nt);
              nsManager.AddNamespace("c", chartMLSchema);
              nsManager.AddNamespace("a", drawingMLSchema);

              //  Load the chart document from the part's stream, and 
              //  search for the requested title.
              XmlDocument chartDoc = new XmlDocument(nt);
              chartDoc.Load(chartPart.GetStream());

              XmlNode titleNode = chartDoc.SelectSingleNode("//c:chart//c:title//a:t", nsManager);
              if (titleNode != null)
              {
                 if (string.Compare(titleNode.InnerText, chartTitle, true) == 0)
                 {
                    using (WordprocessingDocument newDoc = WordprocessingDocument.Create(outputFileName, WordprocessingDocumentType.Document))
                    {
                        newDoc.AddMainDocumentPart();
                        newDoc.MainDocumentPart.AddPart<ChartPart>(chartPart);
                    }

                    //  Tell the outer loops that you are finished.
                    chartFound = true;
                 }
            }
          }
          //  You need to export only a single chart, so get out now.
          if (chartFound)
          {
            break;
          }
      }
   }
}

In dieser Prozedur übergeben Sie drei Parameter: den vollständigen Pfad zur Arbeitsmappe, den vollständigen Pfad zur Ausgabedatei und den Namen des Diagramms.

HinweisHinweis:

In dieser Prozedur wird das Word 2007-Dokument als temporärer Speicher für den Diagrammbestandteil verwendet, weshalb keine Beziehungen definiert werden. Aus diesem Grund kann das Dokument nicht in Word geöffnet werden. Sie können den Code dieser Prozedur durch Code ersetzen, der dem Dokumentpaket ordnungsgemäß einen Bestandteil hinzufügt. Ein Beispiel für diese Art von Code finden Sie im 2007 Office System: Microsoft-SDK für Open XML-Formate.

Zunächst öffnen Sie mithilfe der Methode Open des Objekts SpreadsheetDocument die Eingabedatei als Open XML-Paket. Danach richten Sie mithilfe des Objekts XmlNamespaceManager und durch Festlegen eines Verweises zum Standardnamespace chartML mit dem Qualifizierer c und zum Namespace drawingML mit dem Qualifizierer a einen Namespacemanager ein.

Anschließend arbeitet die Prozedur in einer Schleife jeden chartPart-Bestandteil ab und sucht mithilfe des XPath-Ausdrucks „//c:chart//c:title//a:t“ nach dem Diagrammtitel. Wenn er gefunden wird, wird ein Wort 2007-Dokument erstellt und der chartPart-Bestandteil ins Paket exportiert.

Abrufen von Listen ausgeblendeter Arbeitsblätter

Im folgenden Codebeispiel erstellen Sie eine Liste aller ausgeblendeten Arbeitsblätter einer Arbeitsmappe.

Visual Basic
Public Function XLGetHiddenSheets(ByVal fileName As String) As List(Of String)
   Dim sheets As List(Of String) = New List(Of String)()
   Dim xlDoc As SpreadsheetDocument = SpreadsheetDocument.Open(fileName, False)
   '  Get the main document part (workbook.xml).
   Dim doc As XmlDocument = New XmlDocument
   doc.Load(xlDoc.WorkbookPart.GetStream)
   '  Create a NamespaceManager to handle the default namespace, 
   '  and create a prefix for the default namespace.
   Dim nsManager As XmlNamespaceManager = New XmlNamespaceManager(doc.NameTable)
   nsManager.AddNamespace("default", doc.DocumentElement.NamespaceURI)
   For Each node As System.Xml.XmlNode In doc.SelectNodes("//default:sheets//default:sheet[@state='hidden']", nsManager)
      Dim sheetName As String = node.Attributes("name").Value
      sheets.Add(sheetName)
   Next
   Return sheets
End Function
C#
public static List<string> XLGetHiddenSheets(string fileName)
{
   List<string> sheets = new List<string>();

   using (SpreadsheetDocument xlDoc = SpreadsheetDocument.Open(fileName, false))
   {
      //  Get the main document part (workbook.xml).
      XmlDocument doc = new XmlDocument();
      doc.Load(xlDoc.WorkbookPart.GetStream());

      //  Create a NamespaceManager to handle the default namespace, 
      //  and create a prefix for the default namespace.
      XmlNamespaceManager nsManager = new XmlNamespaceManager(doc.NameTable);
      nsManager.AddNamespace("default", doc.DocumentElement.NamespaceURI);

      foreach (System.Xml.XmlNode node in doc.SelectNodes("//default:sheets//default:sheet[@state='hidden']", nsManager))
      {
         string sheetName = node.Attributes["name"].Value;
         sheets.Add(sheetName);
      }
   }
   return sheets;
}

In dieser Prozedur übergeben Sie einen einzigen Parameter: den vollständigen Pfad zur Arbeitsmappe. Danach öffnen Sie mithilfe der Methode Open des Objekts SpreadsheetDocument die Eingabedatei als Open XML-Paket und laden die Daten in ein XML-Dokument. Anschließend richten Sie mithilfe des Objekts XmlNamespaceManager und durch Festlegen eines Verweises zum Standardnamespace SpreadsheetML einen Namespacemanager ein, um nach den ausgeblendeten Arbeitsblättern zu suchen.

Danach durchsuchen Sie mithilfe des state-Attributs des Knotens „//default:sheets//default:sheet“ das Dokument nach ausgeblendeten Arbeitsblättern. Der Name jedes ausgeblendeten Arbeitsblatts wird der Liste der Blätter hinzugefügt. Sobald alle Arbeitsblätter abgesucht wurden, wird die Liste der Blätter an die aufrufende Prozedur zurückgegeben.

Abrufen der Werte von Zellen in Arbeitsblättern

Im folgenden Code rufen Sie den Wert einer Zelle in einem Arbeitsblatt ab.

Visual Basic
Public Function XLGetCellValue(ByVal fileName As String, ByVal sheetName As String, ByVal addressName As String) As String
   Const worksheetSchema As String = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
   Const sharedStringSchema As String = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
   Dim cellValue As String = Nothing
   '  Retrieve the stream containing the requested
   '  worksheet's information.
   Dim xlDoc As SpreadsheetDocument = SpreadsheetDocument.Open(fileName, False)
   '  Get the main document part (workbook.xml).
   Dim doc As XmlDocument = New XmlDocument
   doc.Load(xlDoc.WorkbookPart.GetStream)
   '  Create a namespace manager, so you can search.
   '  Add a prefix (d) for the default namespace.
   Dim nt As NameTable = New NameTable
   Dim nsManager As XmlNamespaceManager = New XmlNamespaceManager(nt)
   nsManager.AddNamespace("d", worksheetSchema)
   nsManager.AddNamespace("s", sharedStringSchema)
   Dim searchString As String = String.Format("//d:sheet[@name='{0}']", sheetName)
   Dim sheetNode As XmlNode = doc.SelectSingleNode(searchString, nsManager)
   If (Not (sheetNode) Is Nothing) Then
      '  Get the relId attribute.
      Dim relationAttribute As XmlAttribute = sheetNode.Attributes("r:id")
      If (Not (relationAttribute) Is Nothing) Then
         Dim relId As String = relationAttribute.Value
         '  Load the contents of the workbook.
         Dim sheetDoc As XmlDocument = New XmlDocument(nt)
         sheetDoc.Load(xlDoc.WorkbookPart.GetPartById(relId).GetStream)
         Dim cellNode As XmlNode = sheetDoc.SelectSingleNode(String.Format("//d:sheetData/d:row/d:c[@r='{0}']", addressName), nsManager)
         If (Not (cellNode) Is Nothing) Then
            Dim typeAttr As XmlAttribute = cellNode.Attributes("t")
            Dim cellType As String = String.Empty
            If (Not (typeAttr) Is Nothing) Then
               cellType = typeAttr.Value
            End If
            Dim valueNode As XmlNode = cellNode.SelectSingleNode("d:v", nsManager)
            If (Not (valueNode) Is Nothing) Then
               cellValue = valueNode.InnerText
            End If
            If (cellType = "b") Then
               If (cellValue = "1") Then
                  cellValue = "TRUE"
               Else
                  cellValue = "FALSE"
               End If
            ElseIf (cellType = "s") Then
               If (Not (xlDoc.WorkbookPart.SharedStringTablePart) Is Nothing) Then
                   Dim stringDoc As XmlDocument = New XmlDocument(nt)
                   stringDoc.Load(xlDoc.WorkbookPart.SharedStringTablePart.GetStream)
                   '  Add the string schema to the namespace manager.
                   nsManager.AddNamespace("s", sharedStringSchema)
                   Dim requestedString As Integer = Convert.ToInt32(cellValue)
                   Dim strSearch As String = String.Format("//s:sst/s:si[{0}]", (requestedString + 1))
                   Dim stringNode As XmlNode = stringDoc.SelectSingleNode(strSearch, nsManager)
                   If (Not (stringNode) Is Nothing) Then
                      cellValue = stringNode.InnerText
                   End If
                End If
            End If
         End If
      End If
   End If
   Return cellValue
End Function
C#
public static string XLGetCellValue(string fileName, string sheetName, string addressName)
{
   const string worksheetSchema = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
   const string sharedStringSchema = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";

   string cellValue = null;

   //  Retrieve the stream containing the requested
   //  worksheet's info.
   using (SpreadsheetDocument xlDoc = SpreadsheetDocument.Open(fileName, false))
   {
      //  Get the main document part (workbook.xml).
      XmlDocument doc = new XmlDocument();
      doc.Load(xlDoc.WorkbookPart.GetStream());

      //  Create a namespace manager, so you can search.
      //  Add a prefix (d) for the default namespace.
      NameTable nt = new NameTable();
      XmlNamespaceManager nsManager = new XmlNamespaceManager(nt);
      nsManager.AddNamespace("d", worksheetSchema);
      nsManager.AddNamespace("s", sharedStringSchema);

      string searchString = string.Format("//d:sheet[@name='{0}']", sheetName);
      XmlNode sheetNode = doc.SelectSingleNode(searchString, nsManager);
      if (sheetNode != null)
      {
         //  Get the relId attribute.
          XmlAttribute relationAttribute = sheetNode.Attributes["r:id"];
         if (relationAttribute != null)
         {
            string relId = relationAttribute.Value;
            //  Load the contents of the workbook.
            XmlDocument sheetDoc = new XmlDocument(nt);
            sheetDoc.Load(xlDoc.WorkbookPart.GetPartById(relId).GetStream());

            XmlNode cellNode = sheetDoc.SelectSingleNode(string.Format("//d:sheetData/d:row/d:c[@r='{0}']", addressName), nsManager);
            if (cellNode != null)
            {
               XmlAttribute typeAttr = cellNode.Attributes["t"];
               string cellType = string.Empty;
               if (typeAttr != null)
               {
                  cellType = typeAttr.Value;
               }

               XmlNode valueNode = cellNode.SelectSingleNode("d:v", nsManager);
               if (valueNode != null)
               {
                  cellValue = valueNode.InnerText;
               }
               if (cellType == "b")
               {
                  if (cellValue == "1")
                  {
                     cellValue = "TRUE";
                  }
                  else
                  {
                     cellValue = "FALSE";
                  }
               }
               else if (cellType == "s")
               {
                   if (xlDoc.WorkbookPart.SharedStringTablePart != null)
                   {
                      XmlDocument stringDoc = new XmlDocument(nt);
                      stringDoc.Load(xlDoc.WorkbookPart.SharedStringTablePart.GetStream());
                      //  Add the string schema to the namespace manager.
                      nsManager.AddNamespace("s", sharedStringSchema);

                      int requestedString = Convert.ToInt32(cellValue);
                      string strSearch = string.Format("//s:sst/s:si[{0}]", requestedString + 1);
                      XmlNode stringNode = stringDoc.SelectSingleNode(strSearch, nsManager);
                      if (stringNode != null)
                      {
                          cellValue = stringNode.InnerText;
                      }
                   }
                }
            }
         }
       }
   }
   return cellValue;
}

In dieser Prozedur übergeben Sie drei Parameter: Den vollständigen Pfad zur Arbeitsmappe, den Namen des Arbeitsblatts und die Adresse der Zelle, die den Wert enthält, den Sie abrufen möchten. Danach öffnen Sie mithilfe der Methode Open des Objekts SpreadsheetDocument die Eingabedatei als Open XML-Paket und laden die Daten in ein XML-Dokument. Anschließend richten Sie mithilfe des Objekts XmlNamespaceManager und durch Festlegen eines Verweises zum Standardnamespace worksheetSchema mit dem Qualifizierer d und zum Namespace sharedStringSchema mit dem Qualifizierer s einen Namespacemanager ein. Der Namespace sharedStringSchema verweist auf den Bestandteil „SharedStringTablePart“, der freigegebene Zeichenfolgen enthält, die von mehreren Zellen gemeinsam genutzt werden.

Danach rufen Sie den Knoten ab, der das angegebene Arbeitsblatt im Hauptarbeitsmappenbestandteil repräsentiert, indem Sie das name-Attribut des Knotens „//d:sheet“ auswählen. Wenn der Knoten gefunden wird, wird die Beziehungs-ID des Arbeitsblatts abgerufen und dazu verwendet, das Arbeitsblatt in ein XML-Dokument zu laden. Anschließend rufen Sie den Wert ab. Wenn das Attribut t im Knoten ein s enthält, zeigt dies an, dass dies eine freigegebene Zeichenfolge ist, die im Bestandteil „SharedStringTablePart“ nachgesehen werden muss. Ist dies nicht der Fall, kann der Wert direkt vom Knoten abgerufen werden.

HinweisHinweis:

Dieser Code überprüft nur einzeln nach booleschen Werten und nach Zeichenfolgenwerten.

Zum Schluss gibt die Prozedur entweder den Zellenwert oder einen booleschen Wert zurück, der angibt, ob die Suche erfolgreich verlaufen ist.

Schlussbemerkung

Wie dieser Artikel zeigt, ist das Arbeiten mit Excel 2007- und PowerPoint 2007-Dateien mittels der Technologievorschau des Microsoft-SDK für Open XML-Formate viel einfacher. Im 2. Teil dieser Artikelreihe, der in Kürze veröffentlich wird, beschreibe ich andere häufige Aufgaben, die Sie mit Excel 2007- und PowerPoint 2007-Dateien durchführen können.

Weitere Ressourcen

Anzeigen: