Open XML オブジェクト モデルを使用して Excel 2007 ファイルおよび PowerPoint 2007 ファイルを操作する (パート 1/2)

概要 :Microsoft SDK for Open XML Formats テクノロジ プレビュー」は、Open XML 形式のファイルにアクセスするためのライブラリです。この記事 (全 2 記事の 1 つ目) では、Microsoft Office Excel 2007 ファイルと Microsoft Office PowerPoint 2007 ファイルへのアクセスと操作に使用できる Open XML オブジェクト モデル コードについて説明します。(12 印刷ページ)

Frank Rice、Microsoft Corporation

2007 年 8 月

適用対象 : Microsoft Office Excel 2007、Microsoft Office PowerPoint 2007

目次

  • 概要

  • ブック内のコメントをユーザー名ごとに削除する

  • ワークシートを削除する

  • ワークシート内の非表示の行と列を削除する

  • ワークシートのグラフをエクスポートする

  • 非表示のワークシートの一覧を取得する

  • ワークシート内のセルの値を取得する

  • まとめ

  • 追加情報

パート 2 の「Open XML オブジェクト モデルを使用して Excel 2007 ファイルおよび PowerPoint 2007 ファイルを操作する (パート 2/2)」を参照してください。

概要

2007 Microsoft Office system では、Open XML 形式と呼ばれる、XML に基づく新しいファイル形式が導入されています。Microsoft Office Word 2007、Microsoft Office Excel 2007、および Microsoft Office PowerPoint 2007 では、このファイル形式が既定のファイル形式として使用されます。Open XML 形式は、ZIP と XML という一般的なテクノロジに基づくオープン スタンダードであるため、使いやすいことが特徴です。Microsoft では, .NET Framework 3.0 テクノロジの一部として、System.IO.Packaging 名前空間でこれらのファイルにアクセスするためのライブラリを「Microsoft SDK for Open XML Formats テクノロジ プレビュー」に用意しています。Open XML オブジェクト モデルは System.IO.Packaging API を基盤として作成されており、Open XML ドキュメントを操作するための厳密に型指定されたパーツ クラスを備えています。この SDK を利用することで、Open XML パッケージの操作が容易になります。Open XML オブジェクト モデルは、開発者が Open XML パッケージに対して実行する一般的なタスクの多くをカプセル化しているため、複雑な操作を数行のコードで実行できます。

注意

Open XML 形式のファイルを操作するその他のサンプルおよび Open XML オブジェクト モデルに含まれている各メンバのリファレンスについては、「2007 Office system: Microsoft SDK for Open XML Formats」を参照してください。

Open Package Convention specification (英語)」では、XML ファイルのセットが定義されます。このファイル セットにより、1 つのパッケージに格納されるすべてのパーツのコンテンツが含まれ、各パーツのリレーションシップが定義されます。このパッケージには、Open XML 形式をサポートする 2007 Microsoft Office プログラム用のドキュメント ファイルを構成するパーツがまとめられます。この記事で説明する Open XML オブジェクト モデルを使用して、パッケージを作成し、そのパッケージを構成するファイルを操作することができます。この一連の記事では、Excel 2007 と PowerPoint 2007 の Open XML パッケージにアクセスして操作するためのコードについて説明します。

ブック内のコメントをユーザー名ごとに削除する

次に示すコードでは、特定のユーザー名に対応するドキュメント コンテンツを削除します。

Public Sub XLDeleteCommentsByUser(ByVal fileName As String, ByVal userName As String)
   Const commentsSchema As String = "http://schemas.liquid-technologies.com/OfficeOpenXML/2006/default.html"
   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
public static void XLDeleteCommentsByUser(string fileName, string userName)
{
   const string commentsSchema = "http://schemas.liquid-technologies.com/OfficeOpenXML/2006/default.html";

   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));
         }
      }
   }
}

このプロシージャでは、ファイルへの完全なパスと、削除するコメントに関連付けられているユーザー名という 2 つのパラメータを渡します。次に、SpreadsheetDocument オブジェクトの Open メソッドを使用して、入力ファイルを Open XML パッケージとして開きます。さらに、XmlNamespaceManager オブジェクトを使用して名前空間マネージャを設定します。sh 修飾子を使用して、既定の SpreadsheetML 名前空間への参照を設定します。

次に、パッケージにコメント パーツが存在するかどうかをチェックします。コメント パーツの内容が、メモリ常駐の XML ドキュメントにロードされます。次に、XPath 式 sh:authors/sh:author を使用して、特定のユーザー名に対応するノードをブック内で検索します。そのユーザー名が見つかった場合、そのユーザー名の序数値を検索します。その後、選択されたノードのインデックスを取得します。そのために、そのノードへの参照を取得して、前に存在するノードの数を調べます。

最後に、更新されたコメント マークアップ ストリームを元のコメント パーツに保存します。

ワークシートを削除する

次のコードでは、スプレッドシート ドキュメントからワークシートを削除します。

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
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;
}

このプロシージャでは、ブックへの完全なパスと、削除するワークシートの名前という 2 つのパラメータを渡します。次に、SpreadsheetDocument オブジェクトの Open メソッドを使用して、入力ファイルを Open XML パッケージとして開きます。XML DOM ドキュメントに、ブックの内容をロードします。さらに、XmlNamespaceManager オブジェクトを使用して名前空間マネージャを設定します。d 修飾子を使用して既定の SpreadsheetML 名前空間への参照を設定します。このドキュメント内で、//d:sheet ノードの name 属性を使用して、指定されたワークシートを検索します。

見つかったすべてのノード (存在する場合) について、リレーションシップ Id が取得され、Id に対応するワークシートが削除されます。

最後に、更新された SpreadsheetML マークアップが元のメインのブック パーツに保存されます。

ワークシート内の非表示の行と列を削除する

次に示すコードにブックとワークシート名を指定すると、非表示の行の番号の一覧、または非表示の列の番号の一覧が返されます。

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.liquid-technologies.com/OfficeOpenXML/2006/default.html"
   '  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
public static List<int> XLDetectHiddenRowsOrCols(string fileName, string sheetName, bool detectRows)
{
   const string worksheetSchema = "http://schemas.liquid-technologies.com/OfficeOpenXML/2006/default.html";

   //  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;
}

このプロシージャでは、Excel 2007 ブックへの完全なパス、ワークシートの名前、さらに非表示の行を検索するかどうかを指定する Boolean 値という 3 つのパラメータを渡します。detectRows が true の場合、非表示の行の一覧が返されます。detectRows が false の場合、非表示の列の一覧が返されます。次に、SpreadsheetDocument オブジェクトの Open メソッドを使用して、入力ファイルを Open XML パッケージとして開きます。XML DOM ドキュメントに、ブックの内容をロードします。さらに、XmlNamespaceManager オブジェクトを使用して名前空間マネージャを設定します。d 修飾子を使用して既定の SpreadsheetML 名前空間への参照を設定します。このドキュメント内で、//d:sheet ノードの name 属性を使用して、指定されたワークシートを表すノードを検索します。

該当するノードが見つかった場合、ブックとワークシートのリレーションシップが取得されます。まず、ワークシートの内容をロードします。detectRows が true の場合、//d:row ノードの hidden 属性を使用して、非表示の行の一覧を取得します。

注意

行の番号は 1 から開始されます。列の番号は 0 から開始されます。

detectRows が false の場合、非表示の列を検索するものとして処理します。これには //d:cols/d:col ノードの hidden 属性が使用されます。

最後に、項目の一覧が呼び出し元プロシージャに返されます。

ワークシートのグラフをエクスポートする

Excel 2007 ブックとグラフのタイトルを指定して、Word 2007 ファイルを作成し、グラフをエクスポートします。

Public Sub XLExportChart(ByVal inputFileName As String, ByVal outputFileName As String, ByVal chartTitle As String)
   Const drawingMLSchema As String = "http://schemas.liquid-technologies.com/OfficeOpenXML/2006/default.html"
   Const chartMLSchema As String = "http://schemas.liquid-technologies.com/OfficeOpenXML/2006/default.html"
   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
public static void XLExportChart(string inputFileName, string outputFileName, string chartTitle)
{
   const string drawingMLSchema = "http://schemas.liquid-technologies.com/OfficeOpenXML/2006/default.html";
   const string chartMLSchema = "http://schemas.liquid-technologies.com/OfficeOpenXML/2006/default.html";

   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;
          }
      }
   }
}

このプロシージャでは、ブックへの完全なパスと、出力ファイルの完全なパス、およびグラフの名前という 3 つのパラメータを渡します。

注意

このプロシージャでは、グラフ パーツの一時的な保存先として Word 2007 ドキュメントを使用します。そのため、リレーションシップは定義されません。したがって、このドキュメントを Word で開くことはできません。このプロシージャのコードは、ドキュメント パッケージにパーツを適切に追加するコードに置き換えることができます。このようなコードの例については、「2007 Office system: Microsoft SDK for Open XML Formats」を参照してください。

まず、SpreadsheetDocument オブジェクトの Open メソッドを使用して、入力ファイルを Open XML パッケージとして開きます。次に、XmlNamespaceManager オブジェクトを使用して名前空間マネージャを設定します。sh 修飾子を使用して既定の chartML 名前空間への参照を、a 修飾子を使用して drawingML 名前空間への参照を設定します。

各 chartPart パーツをループ処理し、//c:chart//c:title//a:t XPath 式を使用して、グラフのタイトルを検索します。グラフが見つかった場合、Word 2007 ドキュメントが作成され、パッケージに chartPart パーツがエクスポートされます。

非表示のワークシートの一覧を取得する

次のコード例では、ブック内のすべての非表示ワークシートの一覧を作成します。

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
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;
}

このプロシージャでは、1 つのパラメータ (ブックの完全なパス) を渡します。次に、SpreadsheetDocument オブジェクトの Open メソッドを使用して、入力ファイルを Open XML パッケージとして開き、データを XML ドキュメントにロードします。さらに、XmlNamespaceManager オブジェクトを使用して名前空間マネージャを設定します。既定の SpreadsheetML 名前空間への参照を設定して、非表示のワークシートを検索します。

このドキュメント内で、//default:sheets//default:sheet ノードの state 属性を使用して、非表示のワークシートを検索します。非表示のワークシートの名前が sheets リストに追加されます。すべてのワークシートが検索されると、呼び出し元のプロシージャに sheets リストが返されます。

ワークシート内のセルの値を取得する

次のコードでは、ワークシート内のセルの値を取得します。

Public Function XLGetCellValue(ByVal fileName As String, ByVal sheetName As String, ByVal addressName As String) As String
   Const worksheetSchema As String = "http://schemas.liquid-technologies.com/OfficeOpenXML/2006/default.html"
   Const sharedStringSchema As String = "http://schemas.liquid-technologies.com/OfficeOpenXML/2006/default.html"
   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
public static string XLGetCellValue(string fileName, string sheetName, string addressName)
{
   const string worksheetSchema = "http://schemas.liquid-technologies.com/OfficeOpenXML/2006/default.html";
   const string sharedStringSchema = "http://schemas.liquid-technologies.com/OfficeOpenXML/2006/default.html";

   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;
}

このプロシージャでは、ブックへの完全なパス、ワークシートの名前、および取得する値が含まれるセルのアドレスという 3 つのパラメータを渡します。次に、SpreadsheetDocument オブジェクトの Open メソッドを使用して、入力ファイルを Open XML パッケージとして開き、データを XML ドキュメントにロードします。次に、XmlNamespaceManager オブジェクトを使用して名前空間マネージャを設定します。d 修飾子を使用して既定の worksheetSchema 名前空間への参照を、s 修飾子を使用して sharedStringSchema 名前空間への参照を設定します。sharedStringSchema 名前空間は SharedStringTablePart パーツを参照しています。このパーツには複数のセルで共有される文字列が格納されています。

//d:sheet ノードの name 属性を選択して、メインのブック パーツ内の指定ワークシートを表すノードを取得します。ノードが見つかった場合、そのワークシートのリレーションシップ ID を取得し、その ID を使用してワークシートを XML ドキュメントにロードします。次に、その値を取得します。そのノードの t 属性に s が格納されている場合、これは共有文字列であるため、SharedStringTablePart パーツ内で参照する必要があります。それ以外の場合、値はノードから直接取得できます。

注意

このコードでは、Boolean 値と String 値のみを個別にチェックします。

最後に、セルの値、または検索が正常に実行されたかどうかを表す Boolean 値を返します。

まとめ

この記事で説明したように、「Microsoft SDK for Open XML Formats テクノロジ プレビュー」を参照することで、Excel 2007 および PowerPoint 2007 ファイルの操作が非常に簡単になります。このシリーズのパート 2 では、Excel 2007 ファイルおよび PowerPoint 2007 ファイルを使用して実行できるその他の一般的なタスクについて説明します。

追加情報

詳細については、以下のリソースを参照してください。

準備中 :