Thắng PQ Thắng PQ - 2 months ago 39
Java Question

Change document's font using Open XML

I'm having trouble to change fonts of a document by using Open XML. I tried to use PrependChild to apply the new font to paragraph. However, it threw the exception "Cannot insert the OpenXmlElement "newChild" because it is part of a tree.". After some research, I found out that I need to clone that element into a seperate object and make changes there, so I made this approach

clonedRun = (Run)runList[j].CloneNode(true);
clonedRun.PrependChild(runProp);
runList[j] = clonedRun;


but that exception message still comes out. I tried to remove that run's parent element to make it not part of a tree anymore, however, its parent is null (of course).

static void Main(string[] args)
{
using (var doc = WordprocessingDocument.Open(@"mydoc.docx", true))
{
RunProperties runProp = new RunProperties(); // Create run properties.
RunFonts runFont = new RunFonts(); // Create font
runFont.Ascii = "Arial"; // Specify font family
FontSize size = new FontSize();
size.Val = new StringValue("48"); // 48 half-point font size
runProp.Append(runFont);
runProp.Append(size);

var clonedParagraph = new Paragraph();
var clonedRun = new Run();

var paragraphList = doc.MainDocumentPart.RootElement.Descendants<Paragraph>()
.ToList<Paragraph>();
for (int i = 0; i < paragraphList.Count; i++)
{
clonedParagraph = (Paragraph)paragraphList[i].CloneNode(true);
var runList = clonedParagraph.Elements<Run>().ToList();

for (int j = 0; j < runList.ToList().Count; j++)
{
clonedRun = (Run)runList[j].CloneNode(true);
clonedRun.PrependChild(runProp);
runList[j] = clonedRun;
}
paragraphList[i] = clonedParagraph;
}
doc.MainDocumentPart.Document.Save();
}
}


Here's the inner XML of clonedNode

<w:r w:rsidRPr="00E474DB" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:rPr>
<w:rFonts w:ascii="Calibri" w:hAnsi="Calibri" w:eastAsia="MS Pゴシック" w:cs="Calibri" />
<w:sz w:val="48" />
<w:szCs w:val="48" />
<w:lang w:eastAsia="ja-JP" />
</w:rPr>
<w:t>Curriculum Vitae</w:t>
</w:r>

Answer

I found the issue of my code. What I need to do is make changes down to the RunPropeties element, instead of Run. Below is my new working code

using (var doc = WordprocessingDocument.Open(@"D:\FSoft_CV - ThangPQ.docx", true))
        {               
            Body body = doc.MainDocumentPart.Document.Body;
            //Get all paragraphs
            var lstParagrahps = body.Descendants<Paragraph>().ToList();
            foreach (var para in lstParagrahps)
            {
                var subRuns = para.Descendants<Run>().ToList();
                foreach (var run in subRuns)
                {
                    var subRunProp = run.Descendants<RunProperties>().ToList().FirstOrDefault();

                    var newFont = new RunFonts();
                    newFont.Ascii = "Algerian";
                    newFont.EastAsia = "Algerian";

                    if (subRunProp != null)
                    {
                        var font = subRunProp.Descendants<RunFonts>().FirstOrDefault();
                        subRunProp.ReplaceChild<RunFonts>(newFont, font);
                    }
                    else
                    {
                        var tmpSubRunProp = new RunProperties();
                        tmpSubRunProp.AppendChild<RunFonts>(newFont);
                        run.AppendChild<RunProperties>(tmpSubRunProp);
                    }

                }        
            }
            doc.MainDocumentPart.Document.Save();
            doc.Close();
        }
Comments