Introduction
Hi, thanks for your interest in this tip. I am writing this tip because I faced a problem in achieving a simple goal.
The goal was to use a Word document as a template and create a new one, some contents from the template should get replaced by user provided values.
There are plenty of ways provided for this task but it needed more understanding of XML templates. May be some of us expect rapid task completion without spending more
time on understandings. Hence this tip is useful.
A detailed problem and its solution are provided below.
Background
OpenXML is widely used for creating/updating Office documents. It has a predefined structure of XML for document. One can refer to this
link for details.
My Task: Use Open XML and create a new Word document. Template is predefined with extension as "*.docx".
This template contains some words which need to be replaced by user provided values.
Let's Do It
Before you start using Visual Studio, check whether you have installed Open XML 2.0
on machine. If yes, we are good to go forward.
Follows the steps:
- Open Visual Studio and select the blank ASP.NET project, add references
of two DLLs to the project: "
WindowsBase
" and "DocumentFormat.OpenXml
". - Then create two folders "Templates" and "New Documents".
- Add a Word document "mytemplate.docx" in the template
folder to use it as template for new documents.
- Add your text in document. E.g., Hi folks, My name is “Replaceable Text”.
- Now on default.aspx, add the following code:
Please enter your name <asp:TextBox ID="txtName" runat="server" />
:
<asp:Button ID="btnSubmit" runat="server" Text="Create" />
- Now click onto button to generate click event and add the below code in it.
protected void btnSubmit_Click(object sender, EventArgs e){
#region
try
{
string sourceFile = Server.MapPath(Path.Combine("/", "Templates/mytemplate.docx"));
string destinationFile = Server.MapPath
(Path.Combine("/", "New Documents/FirstDocument.docx"));
File.Copy(sourceFile, destinationFile, true);
Dictionary<string, string> keyValues = new Dictionary<string, string>();
keyValues.Add(""Replaceable Text"", txtName.Text);
SearchAndReplace(destinationFile, keyValues);
Process.Start(destinationFile);
}
catch (Exception ex)
{
throw ex;
}
#endregion
}
Note: "Replaceable Text" can be any text like 'My text' or ::#My Text::#
- Add one more function below above event.
public static void SearchAndReplace(string document, Dictionary<string, string> dict)
{
using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(document, true))
{
string docText = null;
using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
{
docText = sr.ReadToEnd();
}
foreach (KeyValuePair<string, string> item in dict)
{
Regex regexText = new Regex(item.Key);
docText = regexText.Replace(docText, item.Value);
}
using (StreamWriter sw = new StreamWriter(
wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
{
sw.Write(docText);
}
}
}
- Compile code and execute it and we are done with code.
- Enter name in text box and file will open automatically.
Expected Problems and Limitations
This article has been developed by considering that the template you are using is correctly formatted.
- Let me explain in detail as:
Consider you are trying to replace word from document is "Employee
" it will not work with above code replacement.
Because docx file is formatted in XML format internally. XML format for this word can be as follows:
<w:r>
<w:rPr>
<w:b />
<w:color w:val="333333" />
<w:sz w:val="32" />
<w:szCs w:val="32" />
</w:rPr>
<w:t>E</w:t>
</w:r>
<w:r w:rsidRPr="00DA41AA">
<w:rPr>
<w:color w:val="333333" />
<w:sz w:val="32" />
<w:szCs w:val="32" />
</w:rPr>
<w:t>mployee</w:t>
</w:r>
As you can see, it has <w:t>E</w:t>
formatting for E and rest of the characters are in <w:t>mployee</w:t>
XML element, hence our code won't find Employee
word.
So it cannot be replaced.
- We have used
Regx
class so take care of those charters used in regular expression formatting.