I have 2 docx files, one contains the styles I want to use.
The other one needs to get these styles. (I believe this is working)
But in the second file I also need to find paragraphs that contain <H1> or <H2> etc.
I can find the paragraphs , but when I then apply a style to it (Heading 1, Heading 2 etc) I don't see anything happening in
the final document. I believe the styles are in the document, just the 'apply' does not seem to do anything.I also look for <TOC> and insert a TOC at that location, that works fine, but the styling...is a problem.
The full example (C#) can be downloaded from
http://www.geerdes.nl/openxml.zip
In the debug directory you will find the FileC.docx, styles.docx that I use.
I really could use some help here.
Thanks in advance
Ben
private void button1_Click(object sender, EventArgs e)
{ WordprocessingDocument styleDocument = WordprocessingDocument.Open(@"styles.docx", true); byte[] byteArray = File.ReadAllBytes(@"FileC.docx"); MemoryStream stream = new MemoryStream(); stream.Write(byteArray, 0, (int)byteArray.Length); WordprocessingDocument wordDocument = WordprocessingDocument.Open(stream, true); Dictionary<String, Style> dictstylesin = new Dictionary<string, Style>(); Dictionary<String, Style> dictstylesout = new Dictionary<string, Style>(); var node = WDExtractStyles(styleDocument, false); if (node != null) WDReplaceStyles(wordDocument, node, false); StyleDefinitionsPart styleDefinitionsPartIn = styleDocument.MainDocumentPart.StyleDefinitionsPart; Styles stylesin = styleDefinitionsPartIn.Styles; String headername = "Heading"; StyleDefinitionsPart styleDefinitionsPartOut = wordDocument.MainDocumentPart.StyleDefinitionsPart; // If the Styles part does not exist, add it and then add the style. if (styleDefinitionsPartOut == null) { styleDefinitionsPartOut = wordDocument.MainDocumentPart.AddNewPart<StyleDefinitionsPart>(); Styles root = new Styles(); root.Save(styleDefinitionsPartOut); } Styles stylesout = styleDefinitionsPartOut.Styles; foreach (var st in stylesout) { if (st is DocumentFormat.OpenXml.Wordprocessing.Style) { dictstylesout.Add(((DocumentFormat.OpenXml.Wordprocessing.Style)st).StyleName.Val.ToString(), ((DocumentFormat.OpenXml.Wordprocessing.Style)st)); if (((DocumentFormat.OpenXml.Wordprocessing.Style)st).StyleId.ToString().ToLower().Contains("kop")) { headername = "Kop"; } } } foreach (OpenXmlElement ox in wordDocument.MainDocumentPart.Document.Body.Descendants().Where(x => x is Text && x.InnerText.Contains("<H1>"))) { Run run = (Run)ox.Parent; Paragraph p = (Paragraph)run.Parent; ApplyStyleToParagraph(wordDocument, headername + "1", "heading 1", p); } foreach (OpenXmlElement ox in wordDocument.MainDocumentPart.Document.Body.Descendants().Where(x => x is Text && x.InnerText.Contains("<H2>"))) { Run run = (Run)ox.Parent; Paragraph p = (Paragraph)run.Parent; ApplyStyleToParagraph(wordDocument, headername + "2", "heading 2", p); } foreach (OpenXmlElement ox in wordDocument.MainDocumentPart.Document.Body.Descendants().Where(x => x is Text && x.InnerText.Contains("<H3>"))) { Run run = (Run)ox.Parent; Paragraph p = (Paragraph)run.Parent; ApplyStyleToParagraph(wordDocument, headername + "3", "heading 3", p); } // Inserts a TOC with a different title XElement firstPara = wordDocument .MainDocumentPart .GetXDocument() .Descendants(W.p) .Where( y => y.Value.ToLower().Contains("<toc>")).FirstOrDefault(); if (firstPara != null) { TocAdder.AddToc(wordDocument, firstPara, @"TOC \o '1-3' \h \z \u", firstPara.Value.Replace("<TOC>","").Replace("<toc>",""), null); firstPara.RemoveAll(); } OpenXmlElement para = wordDocument.MainDocumentPart.Document.Body.Descendants().Where(x => x is Text && x.InnerText.Contains("<TOC>")).FirstOrDefault(); if (para != null) { Run run = (Run)para.Parent; Paragraph p = (Paragraph)run.Parent; p.InnerXml = ""; p.RemoveAllChildren(); p.Remove(); } wordDocument.MainDocumentPart.PutXDocument(); wordDocument.MainDocumentPart.StyleDefinitionsPart.PutXDocument(); wordDocument.MainDocumentPart.DocumentSettingsPart.PutXDocument(); File.WriteAllBytes("newFile.docx", stream.ToArray()); styleDocument.Dispose(); wordDocument.Dispose();
}// Add a StylesDefinitionsPart to the document. Returns a reference to it.public static StyleDefinitionsPart AddStylesPartToPackage(WordprocessingDocument doc)
{ StyleDefinitionsPart part; part = doc.MainDocumentPart.AddNewPart<StyleDefinitionsPart>(); Styles root = new Styles(); root.Save(part); return part;
}// Return true if the style id is in the document, false otherwise.public static bool IsStyleIdInDocument(WordprocessingDocument doc, string styleid)
{ // Get access to the Styles element for this document. Styles s = doc.MainDocumentPart.StyleDefinitionsPart.Styles; // Check that there are styles and how many. int n = s.Elements<Style>().Count(); if (n == 0) return false; // Look for a match on styleid. Style style = s.Elements<Style>() .Where(st => (st.StyleId == styleid) && (st.Type == StyleValues.Paragraph)) .FirstOrDefault(); if (style == null) return false; return true;
}// Apply a style to a paragraph.public static void ApplyStyleToParagraph(WordprocessingDocument doc, string styleid, string stylename, Paragraph p)
{ // If the paragraph has no ParagraphProperties object, create one. if (p.Elements<ParagraphProperties>().Count() == 0) { p.PrependChild<ParagraphProperties>(new ParagraphProperties()); } // Get the paragraph properties element of the paragraph. ParagraphProperties pPr = p.Elements<ParagraphProperties>().First(); // Get the Styles part for this document. StyleDefinitionsPart part = doc.MainDocumentPart.StyleDefinitionsPart; // If the style is not in the document, add it. if (IsTheStyleIdInDocument(doc, styleid) != true) { // No match on styleid, so let's try style name. string styleidFromName = GetStyleIdFromStyleName(doc, stylename); styleid = styleidFromName; } // Set the style of the paragraph. pPr.ParagraphStyleId = new ParagraphStyleId() { Val = styleid };
}// Return true if the style id is in the document, false otherwise.public static bool IsTheStyleIdInDocument(WordprocessingDocument doc, string styleid)
{ // Get access to the Styles element for this document. Styles s = doc.MainDocumentPart.StyleDefinitionsPart.Styles; // Check that there are styles and how many. int n = s.Elements<Style>().Count(); if (n == 0) return false; // Look for a match on styleid. Style style = s.Elements<Style>() .Where(st => (st.StyleId == styleid) && (st.Type == StyleValues.Paragraph)) .FirstOrDefault(); if (style == null) return false; return true;
}// Return styleid that matches the styleName, or null when there's no match.public static string GetStyleIdFromStyleName(WordprocessingDocument doc, string styleName)
{ StyleDefinitionsPart stylePart = doc.MainDocumentPart.StyleDefinitionsPart; string styleId = stylePart.Styles.Descendants<StyleName>() .Where(s => s.Val.Value.Equals(styleName) && (((Style)s.Parent).Type == StyleValues.Paragraph)) .Select(n => ((Style)n.Parent).StyleId).FirstOrDefault(); return styleId;
}public static void WDReplaceStyles(WordprocessingDocument document, XDocument newStyles, bool setStylesWithEffectsPart = true)
{ var docPart = document.MainDocumentPart; StylesPart stylesPart = null; if (setStylesWithEffectsPart) stylesPart = docPart.StylesWithEffectsPart; else stylesPart = docPart.StyleDefinitionsPart; if (stylesPart != null) { newStyles.Save(new StreamWriter(stylesPart.GetStream( FileMode.Create, FileAccess.Write))); }
}public static XDocument WDExtractStyles( WordprocessingDocument document, bool getStylesWithEffectsPart = true)
{ XDocument styles = null; var docPart = document.MainDocumentPart; StylesPart stylesPart = null; if (getStylesWithEffectsPart) stylesPart = docPart.StylesWithEffectsPart; else stylesPart = docPart.StyleDefinitionsPart; if (stylesPart != null) { using (var reader = XmlNodeReader.Create( stylesPart.GetStream(FileMode.Open, FileAccess.Read))) { // Create the XDocument: styles = XDocument.Load(reader); } } return styles;
}