May 27

Here is a quick tip to convert a template to a document (dotx -> docx). Renaming the extension of the filename is not the solution ;-)

 

using (WordprocessingDocument template = WordprocessingDocument.Open(documentStream, true))
{
   template.ChangeDocumentType(DocumentFormat.OpenXml.WordprocessingDocumentType.Document);

   MainDocumentPart mainPart = template.MainDocumentPart;
   mainPart.DocumentSettingsPart.AddExternalRelationship(
     "http://schemas.openxmlformats.org/officeDocument/2006/relationships/attachedTemplate",
     new Uri(@"C:\temp.dotx", UriKind.Absolute));

   ...
}

 

The short lines of code above do the tricks. I found that the attachedTemplate link should be added, when using a WinMerge to see the difference between a dotx and a docx saved by Word. There is a lot of garbage but only that link is mandatory.

You can put whatever you want in the Uri of the attached template, it's purely informative and may not exists. In theory, it should refer to the location of the template used to build the document.

 

Note: ChangeDocumentType requires a writable WordProcessingDocument. In the complete source code, I don't want to overwrite my template so I copy the initial template to a writable temporary stream.

 

Complete source code

using System;
using System.IO;
using DocumentFormat.OpenXml.Packaging;

namespace TemplateConverter
{
   class Program
  
{
      static void Main(string[] args)
      {
         MemoryStream documentStream;
         String templatePath = Path.Combine(Environment.CurrentDirectory, "template.dotx");
         using (Stream tplStream = File.OpenRead(templatePath))
         {
            documentStream = new MemoryStream((int)tplStream.Length);
            CopyStream(tplStream, documentStream);
            documentStream.Position = 0L;
         }

         using (WordprocessingDocument template = WordprocessingDocument.Open(documentStream, true))
         {
            template.ChangeDocumentType(DocumentFormat.OpenXml.WordprocessingDocumentType.Document);
            MainDocumentPart mainPart = template.MainDocumentPart;
            mainPart.DocumentSettingsPart.AddExternalRelationship(
               http://schemas.openxmlformats.org/officeDocument/2006/relationships/attachedTemplate",
               new Uri(templatePath, UriKind.Absolute));

            mainPart.Document.Save();
         }

         string path = "test.doc";
         File.WriteAllBytes(path, documentStream.ToArray());

         // Run Word to open the document:
        
System.Diagnostics.Process.Start(path);
      }

      ///
<summary>
      ///
Write the content of a stream into another.
     
/// </summary>
     
public static void CopyStream(Stream source, Stream target)
      {
          if (source != null)
          {
             MemoryStream mstream = source as MemoryStream;
             if (mstream != null) mstream.WriteTo(target);
             else
            
{
               byte[] buffer = new byte[2048];
               int length = buffer.Length, size;
              
while ((size = source.Read(buffer, 0, length)) != 0)
                  target.Write(buffer, 0, size);
             }
          }
      }
   }
}

Tags:

Comments

Jessica

Posted on Wednesday, 27 May 2009 06:08

  
Thanks for the code and it seems to me that it took you quite a long time!

Henderson Nevada real estate

Posted on Sunday, 12 July 2009 10:59

Thanks a ton for sharing your knowledge with everyone here. I appreciate your efforts. Thank you buddy Smile

free online gambling bonus

Posted on Tuesday, 21 July 2009 08:28

It worked great!! The only difficulty right now is using different content types. I created three document content types, but it always creates de DOCX using the one I added first as the template.

hunting

Posted on Friday, 31 July 2009 09:52

Thank you so much for the overwhelming information. I admire you for sharing your knowlege and dedication to help others. Keep up the good work!

Janez

Posted on Thursday, 17 September 2009 07:16

It works perfectly, thanks so much!

geteducated

Posted on Friday, 30 October 2009 06:05

I created three document content types, but it always creates de DOCX using the one I added first as the template.

Sandy

Posted on Monday, 2 November 2009 15:30

Hi,
thanks a really interesting topic you are tackling. I wasn't aware that it is possible to convert dotx to docx with openXML.

Michael

Posted on Friday, 15 January 2010 22:36

Another possible bit of code is:

File.Copy(source, dest)
Dim newFile As WordprocessingDocument = WordprocessingDocument.Open(dest, True)
newFile.ChangeDocumentType(WordprocessingDocumentType.Document)
newFile.Close()

Lukasz

Posted on Monday, 18 January 2010 07:39

When I am using Mail Merge in template (.dotx) I have problem with open document(.docx). How it can solve?

Thanks.

moving to raleigh

Posted on Monday, 25 January 2010 06:43

Hi nice site design


Regards

Mainn

niama

Posted on Monday, 1 February 2010 03:49

Thanks.... works great.

I've subscribe to the feed. if there is any update, do let us know.

Add comment




  Country flag

biuquote
Loading