Welcome to OpenXML Developer Sign in | Join | Help

Create an Open XML document in .NET (web version)

Author: Sanjay Kumar Madhva of Sonata Software Limited

Introduction

We may have scenario where we may have to create a word document at places where we have no word installed or running. We can programmatically create a word document using the OpenXML format.

The idea of this article is to show how easy it is to create an OpenXML WordprocessingML using ASP.NET and using System.IO.Packaging provided by WinFx.

What we need, is to create an ASP.NET application that lets user enter multi line of text. The user is provided a button that on click creates a WordprocessingML. When the user clicks on the button all we need to code for, breaking the user entered text into paragraphs and creating an document.xml as shown below. Package it into an OpenXML document.

Content of document.xml

<?xml version="1.0" encoding="utf-8" ?>
<?xml:namespace prefix = w /><w:wordDocument
 xmlns:w="http://schemas.microsoft.com/office/word/2005/10/wordml">
    <w:body>
        <w:p>
            <w:r>
                <w:t>Text which as paragraph 1 </w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:r>
                <w:t>Text which as paragraph 2 </w:t>
            </w:r>
        </w:p>
        .
        .
        .
        .
        .
        .
        <w:p>
            <w:r>
                <w:t>Text which as paragraph n </w:t>
            </w:r>
        </w:p>
    </w:body>
</w:wordDocument>

Here are the steps to follow for this project ...

Create a new Web Site

To create an ASP.NET Web site, open visual studio, from the file menu select new web site sub menu.

From the template selection select ASP.NET Web site. and language as Visual Basic.

Add reference to WindowsBase provided WinFx

Right click on the reference and from the pop up menu select “Add Reference” ...

Add reference windows pops up. Select “Windows Base” from the .NET tab as shown in the fig below.

Add a Text box to the web page

Drag and drop TextBox from the ToolBox on to the web page.

Resize the textbox

Resize the textbox to fit to the screen.

Change the property to accept Multi-Line

Change the textbox property to accept multi-line data entry.

... and rename it to mleTextBox1 ...

Add a Button

Rename the Button

Rename the button to GenerateDocument and change the text to “&Generate Document” ...

Add Imports directive

Double-click on the Generate button to go the code behind, then add this code:

Imports System.Xml;
Imports System.IO;
Imports System.IO.Packaging;

Create a private method “CreateFile”

Create a method CreateFile which will accept a filepath with file name and content to be written into the document.

The document creation can be achieved by following 5 easy steps:

1. Take the text entered by the user in the multilane edit has to be split into paragraph and creating a “document.xml” as shown under “Content of document.xml”.
2. Creating an instance of Package class.
3. Create the main document part (document.xml) using the package class.
4. Create the relationship file.
5. Close the document.

Private Sub CreateFile(ByVal filepath As String, ByVal content As String)
  Dim doc As XmlDocument
  doc = New XmlDocument()
  Dim _wWordDocument As XmlElement
  _wWordDocument = doc.CreateElement("w:wordDocument", _
      "http://schemas.microsoft.com/office/word/2005/10/wordml")
  doc.AppendChild(_wWordDocument)

  Dim _wbody As XmlElement
  _wbody = doc.CreateElement("w:body", _
      "http://schemas.microsoft.com/office/word/2005/10/wordml")
  _wWordDocument.AppendChild(_wbody)

  ' Check if the string contains a line feed
  Dim _SplitStr() As String
  _SplitStr = content.Split(vbLf)

  ' if it contains line feed then each entry with a
  ' line feed goes to a new paragraph.
  Dim row As Integer
  For row = 0 To _SplitStr.Length - 1
    Dim _wp1 As XmlElement
    _wp1 = doc.CreateElement("w:p", _
        "http://schemas.microsoft.com/office/word/2005/10/wordml")
    _wbody.AppendChild(_wp1)

    Dim _wr1 As XmlElement
    _wr1 = doc.CreateElement("w:r", _
        "http://schemas.microsoft.com/office/word/2005/10/wordml")
    _wp1.AppendChild(_wr1)

    Dim _wt11 As XmlElement
    _wt11 = doc.CreateElement("w:t", _
        "http://schemas.microsoft.com/office/word/2005/10/wordml")
    _wr1.AppendChild(_wt11)

    Dim _wt1 As XmlNode
    _wt1 = doc.CreateNode(XmlNodeType.Text, "w:t", _
        "http://schemas.microsoft.com/office/word/2005/10/wordml")
    _wt1.Value = _SplitStr(row)
    _wt11.AppendChild(_wt1)

  Next

  '-- Step 1 - Creating the Package
  Dim _package As Package
  _package = Package.Open(filepath, FileMode.Create, FileAccess.ReadWrite)

  '-- Step 2 - Create the main document part (document.xml)
  Dim _uri As Uri

  _uri = New Uri("/word/document.xml", UriKind.Relative)

  Dim part As PackagePart
  part = _package.CreatePart(_uri, "application/vnd.ms-word.main+xml")

  Dim partWrt As StreamWriter
  partWrt = New StreamWriter(part.GetStream(FileMode.Create, FileAccess.Write))

   doc.Save(partWrt)
  partWrt.Close()

  _package.Flush()

  '-- Step 3 - Create the relationship file

  _uri = New Uri("/word/document.xml", UriKind.Relative)
  Dim rel As PackageRelationship

  rel = _package.CreateRelationship(_uri, TargetMode.Internal, _
      "http://schemas.microsoft.com/office/2006/relationships/officeDocument", _
      "rId1")

  _package.Flush()

  '-- Step 4- Close the document.
  _package.Close()
End Sub

Create a private method “ReturnStream”

This method will take the document and return the file back.

Private Sub ReturnStream(ByVal filepath As String)
  Dim iStream As System.IO.Stream

  ' Buffer to read 10K bytes in chunk:
  Dim buffer(10000) As Byte

  ' Length of the file:
  Dim length As Integer

  ' Total bytes to read:
  Dim dataToRead As Long

  ' Identify the file to download including its path.
  'filepath = "C:\OpenXML1\sanjay.docx"

  ' Identify the file name.
  Dim filename As String = System.IO.Path.GetFileName(filepath)

  Try
    ' Open the file.
    iStream = New System.IO.FileStream(filepath, _
              System.IO.FileMode.Open, IO.FileAccess.Read, _
              IO.FileShare.Read)

    ' Total bytes to read:
    dataToRead = iStream.Length

    Response.ContentType = "application/vnd.ms-word.document.12"
    'Response.ContentType = "application/octet-stream"
    Response.AddHeader("Content-Disposition", _
        "attachment; filename=" & filename)

    ' Read the bytes.
    While dataToRead > 0
      ' Verify that the client is connected.
      If Response.IsClientConnected Then
        ' Read the data in buffer
        length = iStream.Read(buffer, 0, 10000)

        ' Write the data to the current output stream.
        Response.OutputStream.Write(buffer, 0, length)

        ' Flush the data to the HTML output.
        Response.Flush()

        ReDim buffer(10000) ' Clear the buffer
        dataToRead = dataToRead - length
      Else
        'prevent infinite loop if user disconnects
        dataToRead = -1
      End If
    End While

  Catch ex As Exception
    ' Trap the error, if any.
    Response.Write("Error : " & ex.Message)
  Finally
    If IsNothing(iStream) = False Then
      ' Close the file.
      iStream.Close()
    End If
  End Try
End Sub

Code for the event “GenerateDocument“

This will create a temp file and write the call the above two method to generate and return the file.

Protected Sub GenerateDocument_Click(ByVal sender As Object, _
      ByVal e As System.EventArgs)
      Handles GenerateDocument.Click

  Dim filepath As String
  Dim content As String

  content = mleTextBox1.Text
  filepath = Guid.NewGuid.ToString() + ".docx"

  CreateFile(filepath, content)
  ReturnStream(filepath)

End Sub

Build and Run

From the Build menu select “Build Web Site”

To run with out debug, select “Start Without Debugging” under “Debug” menu or press Ctrl+F5.

Web page you just created appears in the browser as shown below.

Key in some text and click on “Generate Document” button, a file download dialog appears. Use the Save option. Note: I had some issue in using the Open Option.

Note: remember the save in directory.

After the saving the Download Complete dialog will appear with an button to open the document. Use the option to view the document.

See the content you typed being displayed as a document.

Published Tuesday, April 25, 2006 6:23 PM by dmahugh
Filed Under: , ,

Comments

 

SanjayKumarM said:

If you are using Office 2007 Beta2 then you may have to make the following changes to make tha application work
1.
Seach for->
http://schemas.microsoft.com/office/word/2005/10/wordml
replace with->
http://schemas.openxmlformats.org/wordprocessingml/2006/3/main

2.
Seach for-> application/vnd.ms-word.main+xml
replace with->
application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml

3.
Seach for->
http://schemas.microsoft.com/office/2006/relationships/officeDocument
replace with->
http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument

May 24, 2006 4:43 AM
 

miss_xml said:

hi,
i have tried this article,i was really helpful,but i had some problems while following the steps you mentionned.
i remind you that i'm using microsoft office 2003 and visual basic 2005.

*first,i have downloaded the winfx run time(which generates WindowsBase.dll) and installed it in my computer,but when i wanted to add it in references i didn't find it in the .net references;so i have used the browse option to bring it.is it right?

*my second problem is that the ".docx" file is not known in my computer: the compilation result provides a file having the extension "docx" which is not open automatically with word, and when i choose the word office to open the file ,different characters appear in the document which are totally different from what i have written in the textbox.

how can i resolve these problems??
you will find an attached word document which shows the 2 problems.

pleaaaase i need your help
thank you
September 13, 2006 9:21 AM
 

miss_xml said:

i don't know how to attach a file here ! :-s
September 13, 2006 9:23 AM
Anonymous comments are disabled