Thursday, August 2, 2012

Applying superscript and subscript to WordXML


I wrote an entry sometime back in Jan 2011 to show how you can easily generate a Word document using the OpenXML SDK with font size, font color and bold formatting.
Yesterday, I received a comment from Hema, who asked me how to add subscript and superscript formatting.
To tell the truth, I had not dabbled in those before.  But I decided since I have already come so far, I can just spend a little time to see if I can apply subscript and superscript effects to my previous code too.
I am glad I tried, because I realised its not too difficult.  The only problem is that there’s little documentation out there, so I managed to arrive at the solution purely through my own ‘experiment’ and I am not sure if my method is the most efficient!
I am assuming that you are familiar with the OpenXML SDK and procedures such as how to create Run and RunProperties based on my previous post.  What you need to add superscript or subscript is to use the “VerticalTextAlignment” class to specify if you wish to have a “Superscript” or “Subscript” or the default “Baseline” alignment.
Scroll below for the full code to generate a Word document with one single sentence with output like this:
2012-08-02_112934
 public void GenerateSentence(string filename)
        {
            WordprocessingDocument doc = WordprocessingDocument.Create(filename, 
               WordprocessingDocumentType.Document);
            MainDocumentPart mainPart = doc.AddMainDocumentPart();
            mainPart.Document = new Document();
            Body body = new Body();

            /**** Create the contents ****/
            DocumentFormat.OpenXml.Wordprocessing.Run run1;
            Paragraph para;

            string text1 = "The answer for ";
            string text2 = "10";            
            string text3 = "2";
            string text4 = " is 100";


            DocumentFormat.OpenXml.Wordprocessing.RunProperties runProperties1 = 
               new DocumentFormat.OpenXml.Wordprocessing.RunProperties
               (new RunFonts() { Ascii = "Script" });
            DocumentFormat.OpenXml.Wordprocessing.RunProperties runProperties2 = 
               new DocumentFormat.OpenXml.Wordprocessing.RunProperties
               (new RunFonts() { Ascii = "Courier New" });
            DocumentFormat.OpenXml.Wordprocessing.RunProperties runProperties3 = 
               new DocumentFormat.OpenXml.Wordprocessing.RunProperties
               (new RunFonts() { Ascii = "Arial" });
            DocumentFormat.OpenXml.Wordprocessing.RunProperties runProperties4 = 
               new DocumentFormat.OpenXml.Wordprocessing.RunProperties
               (new RunFonts() { Ascii = "Times New Roman" });            

            DocumentFormat.OpenXml.Wordprocessing.FontSize fs1 = 
               new DocumentFormat.OpenXml.Wordprocessing.FontSize();
            DocumentFormat.OpenXml.Wordprocessing.Color c1 = 
               new DocumentFormat.OpenXml.Wordprocessing.Color();
            DocumentFormat.OpenXml.Wordprocessing.Bold b1 = 
               new DocumentFormat.OpenXml.Wordprocessing.Bold();
            DocumentFormat.OpenXml.Wordprocessing.VerticalTextAlignment vta1 = 
               new DocumentFormat.OpenXml.Wordprocessing.VerticalTextAlignment();

            DocumentFormat.OpenXml.Wordprocessing.FontSize fs2 = 
               new DocumentFormat.OpenXml.Wordprocessing.FontSize();
            DocumentFormat.OpenXml.Wordprocessing.Color c2 = 
               new DocumentFormat.OpenXml.Wordprocessing.Color();
            DocumentFormat.OpenXml.Wordprocessing.Bold b2 = 
               new DocumentFormat.OpenXml.Wordprocessing.Bold();
            DocumentFormat.OpenXml.Wordprocessing.VerticalTextAlignment vta2 = 
               new DocumentFormat.OpenXml.Wordprocessing.VerticalTextAlignment();

            DocumentFormat.OpenXml.Wordprocessing.FontSize fs3 = 
               new DocumentFormat.OpenXml.Wordprocessing.FontSize();
            DocumentFormat.OpenXml.Wordprocessing.Color c3 = 
               new DocumentFormat.OpenXml.Wordprocessing.Color();
            DocumentFormat.OpenXml.Wordprocessing.Bold b3 = 
               new DocumentFormat.OpenXml.Wordprocessing.Bold();
            DocumentFormat.OpenXml.Wordprocessing.VerticalTextAlignment vta3 = 
               new DocumentFormat.OpenXml.Wordprocessing.VerticalTextAlignment();


            DocumentFormat.OpenXml.Wordprocessing.FontSize fs4 = 
               new DocumentFormat.OpenXml.Wordprocessing.FontSize();
            DocumentFormat.OpenXml.Wordprocessing.Color c4 = 
               new DocumentFormat.OpenXml.Wordprocessing.Color();
            DocumentFormat.OpenXml.Wordprocessing.Bold b4 = 
               new DocumentFormat.OpenXml.Wordprocessing.Bold();
            DocumentFormat.OpenXml.Wordprocessing.VerticalTextAlignment vta4 = 
               new DocumentFormat.OpenXml.Wordprocessing.VerticalTextAlignment();
            
        


            /*** Format text1, text2, text3 and text4  as one paragraph ***/
            run1 = new DocumentFormat.OpenXml.Wordprocessing.Run();

            fs1.Val = "40";
            c1.Val = "black";
            b1.Val = false;
            vta1.Val = VerticalPositionValues.Baseline;
            runProperties1.Append(fs1);
            runProperties1.Append(c1);
            runProperties1.Append(b1);
            runProperties1.Append(vta1);
            run1.Append(runProperties1);
            run1.Append(new DocumentFormat.OpenXml.Wordprocessing.Text(text1));

            fs2.Val = "40";
            c2.Val = "black";
            b2.Val = false;
            vta2.Val = VerticalPositionValues.Baseline;
            runProperties2.Append(fs2);
            runProperties2.Append(c2);
            runProperties2.Append(b2);
            runProperties2.Append(vta2);
            run1.Append(runProperties2);
            run1.Append(new DocumentFormat.OpenXml.Wordprocessing.Text(text2));

            fs3.Val = "40";
            c3.Val = "black";
            b3.Val = false;
            vta3.Val = VerticalPositionValues.Superscript;
            runProperties3.Append(fs3);
            runProperties3.Append(c3);
            runProperties3.Append(b3);
            runProperties3.Append(vta3);
            run1.Append(runProperties3);
            run1.Append(new DocumentFormat.OpenXml.Wordprocessing.Text(text3));


            fs4.Val = "40";
            c4.Val = "green";
            b4.Val = false;
            vta4.Val = VerticalPositionValues.Baseline;
            runProperties4.Append(fs4);
            runProperties4.Append(c4);
            runProperties4.Append(b4);
            runProperties4.Append(vta4);
            run1.Append(runProperties4);
            run1.Append(new DocumentFormat.OpenXml.Wordprocessing.Text(text4));

            para = new Paragraph(run1);
            body.AppendChild(para);

            /*** Append the entire body ****/
            mainPart.Document.Append(body);

            /* Save the results and close */
            mainPart.Document.Save();
            doc.Close();
        }//end GenerateSentence

NOTE: You might notice that when you open up the Word document, the spaces go missing.  I had this problem too, and upon Googling, found out that this is due to a  bug in Microsoft’s OpenXML Office 2010/2007 implementation.  Oh well….

No comments: