인쇄용 버전       전송     
평가 및 의견을 보내려면 클릭하십시오.
MSDN
MSDN Library
기술 문서(Technical Articles)
Others
 Open XML 개체 모델을 사용한  Word 2007 파일 조...
Open XML 개체 모델을 사용한  Word 2007 파일 조작 (파트 1/3)

소개 :Microsoft SDK for Open XML Formats 기술 프리뷰」는 Open XML 형식의 파일을 조작하기 위한 라이브러리입니다. 이 일련의 문서에서는 Microsoft Office Word 2007 파일의 액세스와 조작에 사용할 수 있는 Open XML 개체 모델의 코드를 설명합니다.

Frank Rice, Microsoft Corporation

2007 년 8 월

적용 대상 : Microsoft Office Word 2007

목차

배경

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 3.0 이상의 .NET Framework 기술의 일부로서 System.IO.Packaging 네임 스페이스로 이러한 파일에 액세스하기 위한 라이브러리를 「Microsoft SDK for Open XML Formats 기술 프리뷰」제공합니다. Open XML 개체 모델은 System.IO.Packaging 응용 프로그램 프로그래밍 인터페이스 (API)를 기반으로 생성되어, Open XML 문서를 조작하기 위한 강력한 형식 지정된 파트 클래스를 갖추고 있습니다. SDK 를 이용하여 Open XML 패키지 작업이 단순화됩니다. Open XML 개체 모델은 개발자가 Open XML 패키지에 대해서 실행하는 일반적인 작업의 대부분을 캡슐화하기 때문에 복잡한 조작을 몇 줄의 코드로 실행할 수 있습니다.

Note메모 :

Open XML 형식의 파일을 조작하는 그 외의 예제 및 Open XML 개체 모델에 포함된 각 구성원의 레퍼런스는 「2007 Office system: Microsoft SDK for Open XML Formats」을 참조해 주세요.

Office Open XML 패키지 사양에서는 XML 파일집합이 정의됩니다. 이 파일 집합에 의해,  하나의의 패키지에 보관된 모든 파트의 컨텐츠가 포함된 각 파트의 관계가 정의됩니다. 이 패키지에는 Open XML 형식을 지원하는 2007 Microsoft Office 프로그램 용무의 문서 파일을 구성하는 파트가 정리됩니다. 이 문서로 설명하는 Open XML 개체 모델을 사용하여, 패키지를 생성하여, 그 패키지를 구성하는 파일을 조작할 수 있습니다. 이 문서에서는 Word 2007에서 Open XML 패키지 액세스와 조작에 사용할 수 있는 코드를 설명합니다.


Office Open XML 패키지 생성

다음 코드에서는 Office Open XML 패키지를 Word 2007 문서로서 생성하여, 패키지의 주 문서 파트에 컨텐츠를 추가합니다.

Visual Basic
Public
Sub CreateNewWordDocument(ByVal document AsString)
   Dim wordDoc As WordprocessingDocument = WordprocessingDocument.Create(document,
   WordprocessingDocumentType.Document)
   Using (wordDoc)
      ' Set the content of the document so that Word can open it.
Dim mainPart As MainDocumentPart = wordDoc.AddMainDocumentPart
      SetMainDocumentContent(mainPart)
   End Using
End Sub
Public Sub SetMainDocumentContent(ByVal part As MainDocumentPart)
   Const docXml As
String = "<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes""?>" & _
   "<w:document xmlns:w=""http://schemas.openxmlformats.org/wordprocessingml/2006/main"">" & _
   "<w:body><w:p><w:r><w:t>Hello world!</w:t></w:r></w:p></w:body></w:document>"
Dim stream1 As Stream = part.GetStream
   Dim utf8encoder1 As UTF8Encoding = New UTF8Encoding()
   Dim buf() As Byte = utf8encoder1.GetBytes(docXml)
   stream1.Write(buf, 0, buf.Length)
End Sub

C#
// How to: Create a new package as a Word document.
public static void CreateNewWordDocument(string document)
{
   using (WordprocessingDocument wordDoc = WordprocessingDocument.Create(document, 
   WordprocessingDocumentType.Document))
   {
      // Set the content of the document so that Word can open it.
      MainDocumentPart mainPart = wordDoc.AddMainDocumentPart();

      SetMainDocumentContent(mainPart);
   }
}

// Set content of MainDocumentPart.
public static void SetMainDocumentContent(MainDocumentPart part)
{
   const string docXml = 
   @"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes""?>
<w:document xmlns:w=""http://schemas.openxmlformats.org/wordprocessingml/2006/main"">
    <w:body><w:p><w:r><w:t>Hello world!</w:t></w:r></w:p></w:body>
</w:document>";

    using (Stream stream = part.GetStream())
    {
       byte[] buf = (new UTF8Encoding()).GetBytes(docXml);
       stream.Write(buf, 0, buf.Length);
    }
}

첫번째 프로시저에서 Word 2007 문서 경로 및 문서 이름을 나타내는 매개 변수를 건네줍니다. 다음은 입력 문서의 이름에 근거한 패키지를 나타내는 WordprocessingDocument 개체를 생성합니다. 나머지의 코드는 생성 한 개체를 모두 적절히 폐기할 수 있도록 using 구문에 캡슐화됩니다.

다음에는 AddMainDocumentPart 메서드에 의해 주 문서 파트 (document.xml)를 생성하여, 패키지에 추가합니다. 주 문서 파트는 패키지내의/word 폴더에 추가됩니다. 다음은 이 주 문서 파트로 SetMainDocumentContent 프로시저가 호출됩니다. 이 프로시저는 Stream 개체를 사용하여 Word 2007 문서의 구조 및 컨텐츠를 포함한 XML 마크업을 파트에 추가합니다. 다음의 구조로 마크업 및 텍스트를 파트에 추가합니다.

Xml
@"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes""?>
<w:document xmlns:w=""http://schemas.openxmlformats.org/wordprocessingml/2006/main"">
	<w:body>
		<w:p>
			<w:r>
				<w:t>Hello world!</w:t>
			</w:r>
		</w:p>
	</w:body>
</w:document>

문서내의 수정을 모두 반영

다음 코드에서는 문서내의 보류된 수정이 모두 반영되도록 Word 2007 에게 알려주는 노드를 주 문서 파트에서 삭제합니다.

Visual Basic
Public Sub WDAcceptRevisions(ByVal docName As String, ByVal authorName As String)
   ' Given a document name and an author name (leave author name blank to accept revisions
' for all authors), accept revisions.
Const wordmlNamespace As String = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
Dim wdDoc As WordprocessingDocument = WordprocessingDocument.Open(docName, True)
   ' Manage namespaces to perform Xml XPath queries.
Dim nt As NameTable = New NameTable
   Dim nsManager As XmlNamespaceManager = New XmlNamespaceManager(nt)
   nsManager.AddNamespace("w", wordmlNamespace)
   ' Get the document part from the package.
Dim xdoc As XmlDocument = New XmlDocument(nt)
   ' Load the XML in the part into an XmlDocument instance.
   xdoc.Load(wdDoc.MainDocumentPart.GetStream)
   ' Handle formatting changes.
Dim nodes As XmlNodeList = Nothing
If String.IsNullOrEmpty(authorName) Then
      nodes = xdoc.SelectNodes("//w:pPrChange", nsManager)
   Else
      nodes = xdoc.SelectNodes(String.Format("//w:pPrChange[@w:author='{0}']", authorName), nsManager)
End If
For Each node As System.Xml.XmlNode In nodes
      node.ParentNode.RemoveChild(node)
   Next
' Handle deletions.
If String.IsNullOrEmpty(authorName) Then
      nodes = xdoc.SelectNodes("//w:del", nsManager)
   Else
      nodes = xdoc.SelectNodes(String.Format("//w:del[@w:author='{0}']", authorName), nsManager)
End If
For 
Each node As System.Xml.XmlNode In nodes
      node.ParentNode.RemoveChild(node)
   Next
' Handle insertions.
If String.IsNullOrEmpty(authorName) Then
      nodes = xdoc.SelectNodes("//w:ins", nsManager)
   Else
      nodes = xdoc.SelectNodes(String.Format("//w:ins[@w:author='{0}']", authorName), nsManager)
End If
For Each node As System.Xml.XmlNode In nodes
      ' You found one or more new content.
' Promote them to the same level as node, and then
' delete the node.
Dim childNodes As XmlNodeList
      childNodes = node.SelectNodes(".//w:r", nsManager)
      For Each childNode As System.Xml.XmlNode In childNodes
         If (childNode Is node.FirstChild) Then
            node.ParentNode.InsertAfter(childNode, node)
         Else
            node.ParentNode.InsertAfter(childNode, node.NextSibling)
         End If
Next
         node.ParentNode.RemoveChild(node)
         ' Remove the modification id from the node 
' so Word can merge it on the next save.
         node.Attributes.RemoveNamedItem("w:rsidR")
         node.Attributes.RemoveNamedItem("w:rsidRPr")
   Next
' Save the document XML back to its part.
   xdoc.Save(wdDoc.MainDocumentPart.GetStream(FileMode.Create))
End Sub

C#
public static void WDAcceptRevisions(string docName, string authorName)
{
   // Given a document name and an author name (leave author name blank to accept revisions
// for all authors), accept revisions.
const string wordmlNamespace = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";

   using (WordprocessingDocument wdDoc = WordprocessingDocument.Open(docName, true))
   {
       // Manage namespaces to perform Xml XPath queries.
       NameTable nt = new NameTable();
       XmlNamespaceManager nsManager = new XmlNamespaceManager(nt);
       nsManager.AddNamespace("w", wordmlNamespace);

       // Get the document part from the package.
       XmlDocument xdoc = new XmlDocument(nt);
       // Load the XML in the part into an XmlDocument instance.
       xdoc.Load(wdDoc.MainDocumentPart.GetStream());

       // Handle formatting changes.
       XmlNodeList nodes = null;
       if (string.IsNullOrEmpty(authorName))
       {
           nodes = xdoc.SelectNodes("//w:pPrChange", nsManager);
       }
       else
       {
          nodes = xdoc.SelectNodes(string.Format("//w:pPrChange[@w:author='{0}']", authorName), nsManager);
       }
       foreach (System.Xml.XmlNode node in nodes)
       {
          node.ParentNode.RemoveChild(node);
       }

       // Handle deletions.
	   if (string.IsNullOrEmpty(authorName))
       {
          nodes = xdoc.SelectNodes("//w:del", nsManager);
       }
       else
       {
          nodes = xdoc.SelectNodes(string.Format("//w:del[@w:author='{0}']", authorName), nsManager);
       }

       foreach (System.Xml.XmlNode node in nodes)
       {
           node.ParentNode.RemoveChild(node);
       }


       // Handle insertions.
     if (string.IsNullOrEmpty(authorName))
       {
          nodes = xdoc.SelectNodes("//w:ins", nsManager);
       }
       else
       {
          nodes = xdoc.SelectNodes(string.Format("//w:ins[@w:author='{0}']", authorName), nsManager);
       }

       foreach (System.Xml.XmlNode node in nodes)
       {
           // You found one or more new content.
		  // Promote them to the same level as node, and then
		  // delete the node.
          XmlNodeList childNodes;
          childNodes = node.SelectNodes(".//w:r", nsManager);
          foreach (System.Xml.XmlNode childNode in childNodes)
          {
             if (childNode == node.FirstChild)
             {
                 node.ParentNode.InsertAfter(childNode, node);
             }
             else
             {
                 node.ParentNode.InsertAfter(childNode, node.NextSibling);
              }
           }
           node.ParentNode.RemoveChild(node);

           // Remove the modification id from the node 
			// so Word can merge it on the next save.
           node.Attributes.RemoveNamedItem("w:rsidR");
           node.Attributes.RemoveNamedItem("w:rsidRPr");
       }

       // Save the document XML back to its part.
       xdoc.Save(wdDoc.MainDocumentPart.GetStream(FileMode.Create));
   }
}

이 프로시저에서는 먼저 소스 Word 2007 문서 경로와 문서 이름 ( 및 필요에 따라 문서 생성자의 이름)을 나타내는 매개 변수를 건네줍니다.

Note메모:

생성자명을 지정하지 않는 경우에서도 비어 있는 문자열을 건네줘야 합니다.

WordprocessingDocument 개체의 Open 메서드를 사용하여, 문서를 엽니다. 또한 XmlNamespaceManager 개체를 사용하여  네임 스페이스 관리자를 설정합니다. 수식자 (w)를 사용하여  기본값의 WordprocessingML 네임 스페이스 참조를 설정합니다. 주 문서 파트 (/word/document.xml)의 컨텐츠가 메모리 상주의 XML 문서에 읽힙니다. 다음은 XPath 식을 사용하고, 특정 생성자 (생성자명을 지정했을 경우)에 의해서 매핑 수정에 대해 w:pPrChange 노드를 테스트 합니다. 생성자명이 프로시저에게 건네지지 않은 경우, 모든 생성자에 의한 모든 수정이 대상이 됩니다. 다만, 다음의 구문에서는 모든 w:pPrChange 노드 (존재하는 경우)가 선택됩니다.


Visual Basic
nodes = xdoc.SelectNodes("//w:pPrChange", nsManager)

C#
nodes = xdoc.SelectNodes("//w:pPrChange", nsManager);

이러한 노드는 문서에 대한 보류중의 서식 변경을 보여줍니다. 삭제의 경우는 노드명 w:del 를 삽입의 경우는 w:ins 를 지정하고, 똑같이 모든 노드를 선택할 수 있습니다. 다음의 구문에서는 검색 된 노드의 자식 노드가 삭제됩니다.

Visual Basic
node.ParentNode.RemoveChild(node)

C#
node.ParentNode.RemoveChild(node);

이 구조를 이해하기 위해서 다음의 예를 살펴보겠습니다. 문서의 1 행의 텍스트를 선택하여 Title 스타일을 적용했습니다. 이 조작에 의해, 다음의 WordprocessingML 마크업이 주 문서 파트에 생성됩니다.

Xml
<w:pPr>
	<w:pStyle w:val="Title" />
		<w:pPrChange w:id="0" w:author="Nancy Davolio" w:date="2007-07-03T08:22:00Z">
			<w:pPr/>
		</w:pPrChange>
</w:pPr>
<w:r w:rsidRPr="00655EFA">
	<w:t>Gettysburg Address</w:t>
</w:r>

w:pStyle 요소는 이것이 스타일 변경인 것을 보여줍니다. 여기에서는 이 스타일 변경에 의해, 선택된 텍스트에 Title 스타일이 설정됩니다. w:pPrChange 요소는 수정의 생성자와 일자를 보여줍니다. 또, 변경이 보류중인 것을 Word 2007 에게 전하는 역할도 완수합니다. w:r <요소 및="">w:요소에 의해, 실행과 텍스트가 각각 지정됩니다. 이것에는 선택중의 텍스트 (이 경우는Gettysburg Address)가 포함됩니다. Word 2007에서 문서를 교열하는 경우, 텍스트를 선택해, [Review] 탭의 [Accept] 을 클릭하고, [Accept and Move Next] 을 클릭합니다. Word 2007 은 변경을 반영하고, w:pPrChange 요소를 삭제합니다. 코드를 사용하여  이 동작을 에뮬레이트 할 수 있습니다. w:pPrChange 요소를 삭제하는 코드를 사용하면, 수정의 반영과 같은 결과를 얻을 수 있습니다. 이 처리는 다음 구문으로 실행됩니다. </요소>

Visual Basic
node.ParentNode.RemoveChild(node)

Xml
node.ParentNode.RemoveChild(node);

여기서 현재 노드는 w:pPrChange 요소입니다. 현재 노드 ( w:pPrChange 요소)를 삭제하려면, 현재 노드의 부모 (w:pStyle 요소)를 지정하고, RemoveChild 메서드를 호출합니다. 이 방법으로 현재 노드를 삭제 변경을 반영하는 것과 같습니다. w:del 요소에 의한 삭제의 경우도 같은 프로세스가 실행됩니다.

삽입에서는w:ins 요소가 1 개 또는 복수의 삽입의 컨테이너인 경우가 있기 때문에 다른 서식 변경보다 복잡합니다. 예를 들어, 다음의 WordprocessingML 마크업과 같이, 하나의 조작으로 텍스트와 공간을 삽입하는 경우가 있습니다.

Xml
<w:ins w:id="12" w:author="Nancy Davolio" w:date="2007-07-03T08:23:00Z">
	<w:r w:rsidR="00655EFA">
		<w:t>word</w:t>
	</w:r>
	<w:proofErr w:type="spellEnd" />
	<w:r w:rsidR="00655EFA">
		<w:t xml:space="preserve"></w:t>
	</w:r>
</w:ins>

이 세그먼트에서는 문서에 word 라는 단어가 삽입되어 그 후에 공백 공간이 삽입됩니다. 이러한  w:t 텍스트 요소는 양쪽 모두 w:r run 요소에 포함됩니다. 이 요소는 w:ins 삽입 요소에 포함됩니다. 프로그래밍 코드 프로시저에서 이러한 노드 (w:ins 노드의 자식 노드)는 w:ins 노드와 같은 수준에 승격 됩니다. 계속 되어 w:ins 노드가 삭제되는 것으로, 수정의 반영과 같은 결과를 얻을 수 있습니다.

Visual Basic
nodes = xdoc.SelectNodes("//w:ins", nsManager)
...
For Each childNode As System.Xml.XmlNode In childNodes
   If (childNode Is node.FirstChild) Then
      node.ParentNode.InsertAfter(childNode, node)
   Else
      node.ParentNode.InsertAfter(childNode, node.NextSibling)
   End If
Next
node.ParentNode.RemoveChild(node)

C#
nodes = xdoc.SelectNodes("//w:ins", nsManager);
...
childNodes = node.SelectNodes(".//w:r", nsManager);
foreach (System.Xml.XmlNode childNode in childNodes)
{
   if (childNode == node.FirstChild)
   {
       node.ParentNode.InsertAfter(childNode, node);
   }
   else
   {
       node.ParentNode.InsertAfter(childNode, node.NextSibling);
   }
}
node.ParentNode.RemoveChild(node);

이 조작이 어려운 경우는  w:t 텍스트 요소가 처리되는 순서가 적절하지 않은 경우입니다. 앞에서 얘기의 예로,특정의 위치에 word 라는 단어를 삽입하여, 그 뒤로 공백 공간을 삽입합니다. 우선 ,word w:t 요소가 처리되어 부모 노드(w:r)의 후에 삽입됩니다. 다음은 공간의w:t 요소가 처리되어 똑같이 부모 노드 뒤에 삽입됩니다. 그 결과, w:r 친요소의 뒤에 공간이 표시되어 그 후에 텍스트의word 하지만 표시됩니다. 이것은 기대한 결과와는 역입니다. 이 문제를 피하다에는 텍스트 요소의 순서를 검색하는 방법이 필요합니다. 이 코드에서는 최초로w:t 요소를 부모 노드 뒤에 배포한 다음, 후속 요소를 최초의 자식 노드 뒤에 삽입합니다.

노드의 순서를 적절히 배포 한 다음은 해당하는 노드를 삭제하고, 업데이트 된 XML 를 문서 파트에 저장합니다. 업데이트 된 문서를 열었을 때에 XML 구문이 부족하기 때문에 Word 2007에서 수정이 반영되었던 것이 통지됩니다.


문서내의 머리글 바꾸기

다음 코드에서는 문서내의 기존의 머리글 파트를 삭제하고, WordprocessingML 마크업으로 바꾸고,문서의 머리글을 변경합니다.

Visual Basic
Public Sub WDAddHeader(ByVal docName As String, ByVal headerContent As Stream)
   ' Given a document name, and a stream containing valid header content,
' add the stream content as a header in the document and remove the original headers
Const wordmlNamespace As String = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
Const relationshipNamespace As String = "http://schemas.openxmlformats.org/officeDocument/2006/relationships"
Dim wdDoc As WordprocessingDocument = WordprocessingDocument.Open(docName, True)
   Using (wdDoc)
      ' Delete existing header part
      wdDoc.MainDocumentPart.DeleteParts(wdDoc.MainDocumentPart.HeaderParts)

      ' Create a new header part.
Dim headerPart As HeaderPart = wdDoc.MainDocumentPart.AddNewPart(Of HeaderPart)()
      Dim rId As String = wdDoc.MainDocumentPart.GetIdOfPart(headerPart)
      Dim headerDoc As XmlDocument = New XmlDocument
      headerContent.Position = 0
      headerDoc.Load(headerContent)

      ' Write the header out to its part.
      headerDoc.Save(headerPart.GetStream)

      ' Manage namespaces to perform Xml XPath queries.
Dim nt As NameTable = New NameTable
      Dim nsManager As XmlNamespaceManager = New XmlNamespaceManager(nt)
      nsManager.AddNamespace("w", wordmlNamespace)

      ' Get the document part from the package.
' Load the XML in the part into an XmlDocument instance.
Dim xdoc As XmlDocument = New XmlDocument(nt)
      xdoc.Load(wdDoc.MainDocumentPart.GetStream)

      ' Find the node containing the document layout.
Dim targetNodes As XmlNodeList = xdoc.SelectNodes("//w:sectPr", nsManager)
      For Each targetNode As XmlNode In targetNodes
         ' Delete any existing references to headers.
Dim headerNodes As XmlNodeList = targetNode.SelectNodes("./w:headerReference", nsManager)
         For Each headerNode As System.Xml.XmlNode In headerNodes
            targetNode.RemoveChild(headerNode)
         Next
' Create the new header reference node.
Dim node As XmlElement = xdoc.CreateElement("w:headerReference", wordmlNamespace)
         Dim attr As XmlAttribute = node.Attributes.Append(xdoc.CreateAttribute("r:id", relationshipNamespace))
         attr.Value = rId
         node.Attributes.Append(attr)
         targetNode.InsertBefore(node, targetNode.FirstChild)
      Next
' Save the document XML back to its part.
      xdoc.Save(wdDoc.MainDocumentPart.GetStream(FileMode.Create))
   End Using
End Sub

C#
public static void WDAddHeader(string docName, Stream headerContent)
{
   // Given a document name, and a stream containing valid header content,
// add the stream content as a header in the document and remove the original headers
const string wordmlNamespace = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
   const string relationshipNamespace = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";

   using (WordprocessingDocument wdDoc = WordprocessingDocument.Open(docName, true))
   {
      // Delete existing header part.
      wdDoc.MainDocumentPart.DeleteParts(wdDoc.MainDocumentPart.HeaderParts);

      // Create a new header part.
      HeaderPart headerPart = wdDoc.MainDocumentPart.AddNewPart<HeaderPart>();
      string rId = wdDoc.MainDocumentPart.GetIdOfPart(headerPart);
      XmlDocument headerDoc = new XmlDocument();
      headerContent.Position = 0;
      headerDoc.Load(headerContent);

      // Write the header out to its part.
      headerDoc.Save(headerPart.GetStream());

      // Manage namespaces to perform Xml XPath queries.
      NameTable nt = new NameTable();
      XmlNamespaceManager nsManager = new XmlNamespaceManager(nt);
      nsManager.AddNamespace("w", wordmlNamespace);

      // Get the document part from the package.
// Load the XML in the part into an XmlDocument instance.
      XmlDocument xdoc = new XmlDocument(nt);
      xdoc.Load(wdDoc.MainDocumentPart.GetStream());

      // Find the node containing the document layout.
      XmlNodeList targetNodes = xdoc.SelectNodes("//w:sectPr", nsManager);
      foreach (XmlNode targetNode in targetNodes)
      {
         // Delete any existing references to headers.
         XmlNodeList headerNodes = targetNode.SelectNodes("./w:headerReference", nsManager);
         foreach (System.Xml.XmlNode headerNode in headerNodes)
         {
            targetNode.RemoveChild(headerNode);
         }

         // Create the new header reference node.
         XmlElement node = xdoc.CreateElement("w:headerReference", wordmlNamespace);
         XmlAttribute attr = node.Attributes.Append(xdoc.CreateAttribute("r:id", relationshipNamespace));
         attr.Value = rId;
         node.Attributes.Append(attr);
         targetNode.InsertBefore(node, targetNode.FirstChild);
      }

      // Save the document XML back to its part.
      xdoc.Save(wdDoc.MainDocumentPart.GetStream(FileMode.Create));
   }
}

먼저 WDAddHeader 메서드가 호출되어, Word 2007 문서 참조 및 Stream 개체가 전달됩니다. 이 개체에는 바꾸기 머리글 마크업 및 데이터가 보관됩니다. 다음은 Open XML 파일 형식 패키지를 나타내는 WordprocessingDocument 개체 및 WordprocessingML 마크업의 네임 스페이스 관리자를 설정합니다. 다음 코드에서 문서내의 기존의 머리글 파트를 삭제하고, 공백의 머리글 파트를 생성합니다.

Visual Basic
wdDoc.MainDocumentPart.DeleteParts(wdDoc.MainDocumentPart.HeaderParts)

' Create a new header part.
Dim headerPart As HeaderPart = wdDoc.MainDocumentPart.AddNewPart(Of HeaderPart)()
Dim headerDoc As XmlDocument = New XmlDocument
headerContent.Position = 0
headerDoc.Load(headerContent)

' Write the header out to its part.
headerDoc.Save(headerPart.GetStream)

C#
wdDoc.MainDocumentPart.DeleteParts(wdDoc.MainDocumentPart.HeaderParts);

// Create a new header part.
HeaderPart headerPart = wdDoc.MainDocumentPart.AddNewPart<HeaderPart>();

XmlDocument headerDoc = new XmlDocument();
headerContent.Position = 0;
headerDoc.Load(headerContent);

// Write the header out to its part.
headerDoc.Save(headerPart.GetStream());

다음은 메모리 상주 XML 문서를 일시 홀더로서 생성하여, 그 문서에 바꾸기 머리글을 나타내는 마크업 및 데이터를 로드합니다. 그리고 코드에서 주 문서 파트로 방금 삭제한 머리글 파트 참조를 검색합니다. 이 검색에서는 XPath 쿼리를 사용하여 해당하는 네임 스페이스를 검색하여 삭제하고, 새로운 머리글 파트 참조를 삽입합니다. 마지막에 업데이트 된 WordprocessingML 마크업이 원본 주 문서 파트에 저장됩니다.


문서 주석 삭제

다음 코드에서는 Word 2007 문서의 주석 파트 및 그 파트 참조를 모두 삭제합니다.

Visual Basic
Public Sub WDDeleteComments(ByVal docName As String)
   ' Given a document name, remove all comments.
Const wordmlNamespace As String = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
Dim wdDoc As WordprocessingDocument = WordprocessingDocument.Open(docName, true)
   If (Not (wdDoc.MainDocumentPart.CommentsPart) Is Nothing) Then
      wdDoc.MainDocumentPart.DeletePart(wdDoc.MainDocumentPart.CommentsPart)

      ' Manage namespaces to perform Xml XPath queries.
		Dim nt As NameTable = New NameTable
		Dim nsManager As XmlNamespaceManager = New XmlNamespaceManager(nt)
      nsManager.AddNamespace("w", wordmlNamespace)

      ' Get the document part from the package.
' Load the XML in the part into an XmlDocument instance:
Dim xdoc As XmlDocument = New XmlDocument(nt)
      xdoc.Load(wdDoc.MainDocumentPart.GetStream)

      ' Retrieve a list of nodes representing the comment start elements, and delete them all.
Dim nodes As XmlNodeList = xdoc.SelectNodes("//w:commentRangeStart", nsManager)
      For Each node As System.Xml.XmlNode In nodes
         node.ParentNode.RemoveChild(node)
      Next
' Retrieve a list of nodes representing the comment end elements, and delete them all.
      nodes = xdoc.SelectNodes("//w:commentRangeEnd", nsManager)
      For Each node As System.Xml.XmlNode In nodes
         node.ParentNode.RemoveChild(node)
      Next
' Retrieve a list of nodes representing the comment reference elements, and delete them all.
      nodes = xdoc.SelectNodes("//w:r/w:commentReference", nsManager)
      For Each node As System.Xml.XmlNode In nodes
                node.ParentNode.RemoveChild(node)
      Next
' Save the document XML back to its part.
      xdoc.Save(wdDoc.MainDocumentPart.GetStream(FileMode.Create))
   End
If
End Sub

C#
public static void WDDeleteComments(string docName)
{
   // Given a document name, remove all comments.
const string wordmlNamespace = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";

   using (WordprocessingDocument wdDoc = WordprocessingDocument.Open(docName, true))
   {
      if (wdDoc.MainDocumentPart.CommentsPart != null)
      {
         wdDoc.MainDocumentPart.DeletePart(wdDoc.MainDocumentPart.CommentsPart);
         // Manage namespaces to perform Xml XPath queries.
         NameTable nt = new NameTable();
         XmlNamespaceManager nsManager = new XmlNamespaceManager(nt);
         nsManager.AddNamespace("w", wordmlNamespace);

         // Get the document part from the package.
// Load the XML in the part into an XmlDocument instance:
         XmlDocument xdoc = new XmlDocument(nt);
         xdoc.Load(wdDoc.MainDocumentPart.GetStream());

         // Retrieve a list of nodes representing the comment start elements, and delete them all.
         XmlNodeList nodes = xdoc.SelectNodes("//w:commentRangeStart", nsManager);
         foreach (System.Xml.XmlNode node in nodes)
         {
            node.ParentNode.RemoveChild(node);
         }

         // Retrieve a list of nodes representing the comment end elements, and delete them all.
         nodes = xdoc.SelectNodes("//w:commentRangeEnd", nsManager);
         foreach (System.Xml.XmlNode node in nodes)
         {
            node.ParentNode.RemoveChild(node);
         }

         // Retrieve a list of nodes representing the comment reference elements, and delete them all.
         nodes = xdoc.SelectNodes("//w:r/w:commentReference", nsManager);
         foreach (System.Xml.XmlNode node in nodes)
         {
            node.ParentNode.RemoveChild(node);
         }

         // Save the document XML back to its part.
         xdoc.Save(wdDoc.MainDocumentPart.GetStream(FileMode.Create));
      }
   }
}

먼저 WDDeleteComments 메서드가 호출되어, Word 2007 문서 참조가 전달됩니다. 다음은 Open XML 파일 형식 패키지를 나타내는 WordprocessingDocument 개체가 입력 문서에 근거해 생성됩니다. 다음은 패키지에 주석 파트가 존재하는지 확인되어 존재하는 경우는 삭제됩니다. XPath 쿼리를 설정하기 위해서 네임 스페이스 관리자가 생성됩니다. 이 쿼리는 //w:commentRangeStart //w:commentRangeEnd XPath 식을 사용하여 주 문서 파트로 시작 주석 노드 및 종료 주석 노드를 각각 검색합니다. 목록이 완료되면, 각 노드가 삭제됩니다.


Visual Basic
Dim nodes As XmlNodeList = xdoc.SelectNodes("//w:commentRangeStart", nsManager)
For Each node As System.Xml.XmlNode In nodes
   node.ParentNode.RemoveChild(node)
Next
' Retrieve a list of nodes representing the comment end elements, and delete them all.
nodes = xdoc.SelectNodes("//w:commentRangeEnd", nsManager)
For Each node As System.Xml.XmlNode In nodes
   node.ParentNode.RemoveChild(node)
Next

C#
XmlNodeList nodes = xdoc.SelectNodes("//w:commentRangeStart", nsManager);
foreach (System.Xml.XmlNode node in nodes)
{
   node.ParentNode.RemoveChild(node);
}

// Retrieve a list of nodes representing the comment end elements, and delete them all.
nodes = xdoc.SelectNodes("//w:commentRangeEnd", nsManager);
foreach (System.Xml.XmlNode node in nodes)
{
   node.ParentNode.RemoveChild(node);
}

//w:r/w:commentReference XPath 식을 사용하여  주석을 참조하는 노드를 삭제하는 경우도 같은 프로세스가 사용됩니다. 마지막에 업데이트 된 WordprocessingML 마크업이 원본 주 문서 파트에 저장 됩니다.


문서내의 머리글 및 바닥글 삭제

다음 코드에서는 Word 2007 문서의 머리글과 바닥글을 삭제합니다.

Visual Basic
Public Sub WDRemoveHeadersFooters(ByVal docName As String)
   ' Given a document name, remove all headers and footers.
	Const wordmlNamespace As String = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
	Dim wdDoc As WordprocessingDocument = WordprocessingDocument.Open(docName, true)
   Using (wdDoc)
      If ((wdDoc.MainDocumentPart.GetPartsCountOfType(Of HeaderPart)() > 0) OR (wdDoc.MainDocumentPart.GetPartsCountOfType(Of FooterPart)() > 0))
         wdDoc.MainDocumentPart.DeleteParts(wdDoc.MainDocumentPart.HeaderParts)
         wdDoc.MainDocumentPart.DeleteParts(wdDoc.MainDocumentPart.FooterParts)

         ' Manage namespaces to perform XPath queries.
		 Dim nt As NameTable = New NameTable
         Dim nsManager As XmlNamespaceManager = New XmlNamespaceManager(nt)
         nsManager.AddNamespace("w", wordmlNamespace)

         ' Get the document part from the package.
		' Load the XML in the part into an XmlDocument instance.
		Dim xdoc As XmlDocument = New XmlDocument(nt)
        xdoc.Load(wdDoc.MainDocumentPart.GetStream)

         ' Find the node containing the document layout.
		Dim layoutNodes As XmlNodeList = xdoc.SelectNodes("//w:sectPr", nsManager)
         For Each layoutNode As System.Xml.XmlNode In layoutNodes
            ' Delete any existing references to headers.
			Dim headerNodes As XmlNodeList = layoutNode.SelectNodes("./w:headerReference", nsManager)
            For Each headerNode As System.Xml.XmlNode In headerNodes
               layoutNode.RemoveChild(headerNode)
            Next
		' Delete any existing references to footers.
		Dim footerNodes As XmlNodeList = layoutNode.SelectNodes("./w:footerReference", nsManager)
        For Each footerNode As System.Xml.XmlNode In footerNodes
               layoutNode.RemoveChild(footerNode)
            Next
		Next
		' Save the document XML back to its part.
         xdoc.Save(wdDoc.MainDocumentPart.GetStream(FileMode.Create))
      End If
	End Using
End Sub

C#
public static void WDRemoveHeadersFooters(string docName)
{
   // Given a document name, remove all headers and footers.
const string wordmlNamespace = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";

   using (WordprocessingDocument wdDoc = WordprocessingDocument.Open(docName, true))
   {
      if (wdDoc.MainDocumentPart.GetPartsCountOfType<HeaderPart>() > 0 ||
        wdDoc.MainDocumentPart.GetPartsCountOfType<FooterPart>() > 0)
      {
         wdDoc.MainDocumentPart.DeleteParts(wdDoc.MainDocumentPart.HeaderParts);
         wdDoc.MainDocumentPart.DeleteParts(wdDoc.MainDocumentPart.FooterParts);

         // Manage namespaces to perform XPath queries.
         NameTable nt = new NameTable();
         XmlNamespaceManager nsManager = new XmlNamespaceManager(nt);
         nsManager.AddNamespace("w", wordmlNamespace);

         // Get the document part from the package.
		// Load the XML in the part into an XmlDocument instance.
         XmlDocument xdoc = new XmlDocument(nt);
         xdoc.Load(wdDoc.MainDocumentPart.GetStream());

         // Find the node containing the document layout.
         XmlNodeList layoutNodes = xdoc.SelectNodes("//w:sectPr", nsManager);
         foreach (System.Xml.XmlNode layoutNode in layoutNodes)
         {
            // Delete any existing references to headers.
            XmlNodeList headerNodes = layoutNode.SelectNodes("./w:headerReference", nsManager);
            foreach (System.Xml.XmlNode headerNode in headerNodes)
            {
               layoutNode.RemoveChild(headerNode);
            }

            // Delete any existing references to footers.
            XmlNodeList footerNodes = layoutNode.SelectNodes("./w:footerReference", nsManager);
            foreach (System.Xml.XmlNode footerNode in footerNodes)
            {
               layoutNode.RemoveChild(footerNode);
            }
         }

         // Save the document XML back to its part.
         xdoc.Save(wdDoc.MainDocumentPart.GetStream(FileMode.Create));
      }
   }
}

최초로,WDRemoveHeadersFooters 메서드가 호출되어, Word 2007 문서 참조가 전달됩니다. 다음은 Open XML 파일 형식 패키지를 나타내는 WordprocessingDocument 개체가 입력 문서에 근거해 생성됩니다. 다음은 패키지에 머리글 파트 및 바닥글 파트가 존재하는지 확인되어 존재하는 경우는 삭제됩니다. XPath 쿼리를 설정하기 위해서 네임 스페이스 관리자가 생성됩니다.

다음은 메모리 상주 XML 문서를 일시 홀더로서 생성하여, 그 문서에 주 문서 파트에서 마크업 및 데이터를 로드합니다. 이 후의 코드에서 방금전 삭제한 머리글 및 바닥글 파트를 참조하는 노드를 검색하여 그것들을 삭제합니다.

Visual Basic
Dim layoutNodes As XmlNodeList = xdoc.SelectNodes("//w:sectPr", nsManager)
For Each layoutNode As System.Xml.XmlNode In layoutNodes
   ' Delete any existing references to headers.
	Dim headerNodes As XmlNodeList = layoutNode.SelectNodes("./w:headerReference", nsManager)
   For Each headerNode As System.Xml.XmlNode In headerNodes
      layoutNode.RemoveChild(headerNode)
   Next
	' Delete any existing references to footers.
	Dim footerNodes As XmlNodeList = layoutNode.SelectNodes("./w:footerReference", nsManager)
   For Each footerNode As System.Xml.XmlNode In footerNodes
      layoutNode.RemoveChild(footerNode)
   Next
Next

C#
XmlNodeList layoutNodes = xdoc.SelectNodes("//w:sectPr", nsManager);
foreach (System.Xml.XmlNode layoutNode in layoutNodes)
{
   // Delete any existing references to headers.
   XmlNodeList headerNodes = layoutNode.SelectNodes("./w:headerReference", nsManager);
   foreach (System.Xml.XmlNode headerNode in headerNodes)
   {
      layoutNode.RemoveChild(headerNode);
   }

   // Delete any existing references to footers.
   XmlNodeList footerNodes = layoutNode.SelectNodes("./w:footerReference", nsManager);
   foreach (System.Xml.XmlNode footerNode in footerNodes)
   {
      layoutNode.RemoveChild(footerNode);
   }
}

마지막에 업데이트 된 WordprocessingML 마크업이 원본 주 문서 파트에 저장 됩니다.


요약

이 문서로 설명한 것처럼, 「Microsoft SDK for Open XML Formats 기술 프리뷰」를 참조하면 Word 2007 파일 조작이 매우 간단해집니다. 이 시리즈의 파트 2 의 문서에서는 Open XML Formats SDK에서 실행할 수 있는 다른 일반적인 작업에 대해 설명합니다.


© 2009 Microsoft Corporation. All rights reserved. 사용약관 | 상표 | 개인정보취급방침 및 청소년보호정책
Page view tracker