private Dictionary <string, string> ParseDocument(string fileName) { Dictionary <string, string> contentControllerData = new Dictionary <string, string>(); using (WordprocessingDocument doc = WordprocessingDocument.Open(fileName, false)) { foreach (var cc in doc.ContentControls()) { SdtProperties props = cc.Elements <SdtProperties>().FirstOrDefault(); Tag tag = props.Elements <Tag>().FirstOrDefault(); contentControllerData.Add(tag.Val, cc.InnerText); } } return(contentControllerData); }
public void BindSdtToXml(Guid guid, string prefixMapping, string xPath, string sdtTag) { var sdtList = document.ContentControls(); foreach (var sdt in sdtList) { SdtProperties property = sdt.Elements <SdtProperties>().FirstOrDefault(); var tag = property.Elements <Tag>().FirstOrDefault(); if (tag.Val == sdtTag) { var binding = new DataBinding(); binding.StoreItemId = "{" + guid.ToString().ToUpper() + "}"; binding.PrefixMappings = prefixMapping; binding.XPath = xPath; property.AppendChild <DataBinding>(binding); } } }
public TemplateDocument(WordprocessingDocument wpd) { WordprocessingDocument = wpd; var sdtElements = WordprocessingDocument.ContentControls(); firstOrderContentControls = new List <ContentControl>(); innerContentControls = new List <ContentControl>(); allContentControls = new List <ContentControl>(); foreach (var sdtElement in sdtElements) { if (sdtElement.IsDescendantOfAContentControl(out var parentSdtElement)) { //Find the parent content control for that element var contentControlParent = allContentControls.FirstOrDefault(c => c.SdtElement == parentSdtElement); var cc = new ContentControl(sdtElement, true, this); allContentControls.Add(cc); innerContentControls.Add(cc); if (contentControlParent == null) { Console.WriteLine("Warning. Content control parent not found for element that should have one"); } else { cc.Parent = contentControlParent; cc.Parent.AddDescendingControl(cc); } } else { var cc = new ContentControl(sdtElement, false, this); firstOrderContentControls.Add(cc); allContentControls.Add(cc); } } }
public void Create(Stream output, GroupReport report) { #if f if (output == null) { throw new ArgumentNullException("output", Message.Get("Common.NullArgument", "output")); } if (report == null) { throw new ArgumentNullException("report", Message.Get("Common.NullArgument", "report")); } #endif // Открываем содержимое в памяти. var content = report.Template.Content; using (var memory = new MemoryStream()) { memory.Write(content, 0, (int)content.Length); try { Document = WordprocessingDocument.Open(memory, true); Document.ChangeDocumentType(DocumentFormat.OpenXml.WordprocessingDocumentType.Document); } #warning TODO Посмотреть актуальные исключения на операции. catch (Exception ex) { throw new InvalidOperationException("Возникла ошибка при чтении тела шаблона.\n", ex.InnerException); } var properties = report.Instances.First().TelefReprotProperties; var baseProperties = report.Instances.First().OwnProperties; bool useBaseProperties = baseProperties != null; // Получаем список закладок... var placeholders = Document.ContentControls(); if (placeholders.Count() == 0) { Document.Close(); throw new InvalidOperationException("В теле шаблона не найдено Structured Document Tag элементов."); } foreach (var placeholder in placeholders) { var placeholderId = placeholder.GetSdtTagText(); object entityId, hashedAttributeId, formatId; var uid = new UniqueIDCreator(); uid.Split(placeholderId, out entityId, out hashedAttributeId, out formatId); // В случае отсутствия value - оставлять элемент с оригинальным текстом, но выделять красным шрифтом. if (!useBaseProperties) { if (properties.First(x => x.Field.Attribute.ID.ToString() == hashedAttributeId.ToString()).Value == null) { (placeholder as SdtElement).SetSdtTextColor("FF0000"); } else { // Заполняем try { var value = properties .Where( x => (x.Field.Attribute.ID.ToString() == hashedAttributeId.ToString()) && (x.Field.Format.ID.ToString() == formatId.ToString()) ) .First().Value; var element = placeholder as SdtElement; element.SetSdtText(value.ToString()); element.SetSdtTextColor("000000"); } catch (InvalidOperationException ex) { Document.Close(); throw new InvalidOperationException(String.Format("Не удалось найти атрибут.\n{0}.", ex.Message)); } } } else { var property = baseProperties.SingleOrDefault(x => x.Attribute.ID.ToString() == hashedAttributeId.ToString()); if (property == null || property.Value == null || property.Value is DBNull) { (placeholder as SdtElement).SetSdtTextColor("FF0000"); } else { try { var element = placeholder as SdtElement; var format = property.Attribute.Type.GetAdmissableFormats(). First(o => o.ID.ToString() == formatId.ToString()); element.SetSdtText(string.Format(format.Provider, format.FormatString, property.Value)); element.SetSdtTextColor("000000"); } catch (InvalidOperationException ex) { Document.Close(); throw new InvalidOperationException(String.Format("Не удалось найти атрибут.\n{0}.", ex.Message)); } } } #warning Неплохо бы выводить сведения о хеше. } Document.Close(); // Результат - пишем в поток. try { memory.Seek(0, SeekOrigin.Begin); memory.CopyTo(output); } catch (NotSupportedException ex) { throw new InvalidOperationException(String.Format("Поток назначения не поддерживает запись:\n{0}.", ex.Message)); } catch (ObjectDisposedException ex) { throw new InvalidOperationException(String.Format("Поток назначения был преждевременно закрыт:\n{0}.", ex.Message)); } catch (IOException ex) { throw new InvalidOperationException(String.Format("Возникла общая ошибка ввода-вывода:\n{0}.", ex.Message)); } } }
/// <summary> /// Finds a content control within this document by its tag name /// </summary> public static SdtElement FindContentControl(this WordprocessingDocument doc, string tagName) { return(doc.ContentControls() .FirstOrDefault(e => e.GetContentControlTag() == tagName)); }
/// <summary> /// Findss all content controls within this document by their tag name /// </summary> public static IEnumerable <SdtElement> FindContentControls(this WordprocessingDocument doc, string tagName) { return(doc.ContentControls() .Where(e => e.GetContentControlTag() == tagName)); }
public static MemoryStream BuildReport(IConfigurationRoot config) { //Read the template from disk byte[] byteArray = File.ReadAllBytes(config["ReportConfiguration:TemplateFile"]); //Load it into memory MemoryStream mem = new MemoryStream(); mem.Write(byteArray, 0, byteArray.Length); //Open the word document from memory using (WordprocessingDocument output = WordprocessingDocument.Open(mem, true)) { var doc = output.MainDocumentPart.Document; var contentControls = output.ContentControls().ToList(); foreach (var cc in contentControls) { wp.SdtProperties props = cc.Elements <wp.SdtProperties>().FirstOrDefault(); string controlTitle = props.Elements <wp.SdtAlias>().FirstOrDefault().Val; string controlTag = props.Elements <wp.Tag>().FirstOrDefault().Val; string configKeyResult = String.Format("{0}:Result", controlTitle); string queryResult = config[configKeyResult]; Type sdtType = ((wp.SdtElement)cc).GetType(); OpenXmlElement targetContent = null; //Determine if the content control is actually a docpart (Table of Contents, etc.), so we can ignore it. bool isDocPart = false; //If the content control document tag is a block tag and has docpart object children, it's a docpart. if (sdtType == typeof(wp.SdtBlock) && (((wp.SdtBlock)cc).Descendants <wp.SdtContentDocPartObject>().Count() > 0)) { isDocPart = true; } if (!isDocPart) { //Replace our ReportParameter placeholders. if (controlTag.Equals("ReportParameter")) { if (config[controlTitle] != null) { targetContent = new wp.Text(config[controlTitle]); } else { targetContent = new wp.Text("No Result"); } } //Replace our SingleValue placeholders with tables containing the query results. if (controlTag.Equals("SingleValue")) { if (queryResult != null) { dynamic svData = JsonConvert.DeserializeObject <dynamic>(queryResult); if (svData.rows.Count == 1) { targetContent = new wp.Text(svData.rows[0][0].ToString()); } else { throw new IndexOutOfRangeException(String.Format("The QueryResult for {0} contained {1} row/s but a single row was expected.", controlTitle, svData.rows.Count)); } } else { targetContent = new wp.Text("No Result"); } } //Special handling is needed if a SingleValue or ReportParameter content control is actually configured as a SdtBlock instead of SdtRun. if (controlTag.Equals("ReportParameter") || controlTag.Equals("SingleValue")) { if (sdtType == typeof(wp.SdtBlock)) { var targetContentParent = cc.GetFirstChild <wp.SdtContentBlock>().GetFirstChild <wp.Paragraph>().CloneNode(true); targetContentParent.GetFirstChild <wp.Run>().InsertAfterSelf(new wp.Run(targetContent)); targetContentParent.GetFirstChild <wp.Run>().Remove(); targetContent = targetContentParent; } } //Replace our Table placeholders with tables containing the query results. if (controlTag.Equals("Table")) { targetContent = BuildTable(queryResult, config["ReportConfiguration:TableStyle"]); } //Update the charts in our Chart placeholders with the data from the query results. if (controlTag.Equals("Chart")) { UpdateChart( cc.Descendants <drc.ChartReference>().FirstOrDefault(), output, controlTitle.Split(':').Last(), queryResult); targetContent = cc.GetFirstChild <wp.SdtContentBlock>().GetFirstChild <wp.Paragraph>().CloneNode(true); } //Remove PlaceholderText styles from all Run elements foreach (var item in cc.Descendants <wp.Run>()) { var rPr = item.GetFirstChild <wp.RunProperties>(); if (rPr != null && rPr.RunStyle != null) { if (rPr.RunStyle.Val == "PlaceholderText") { rPr.RunStyle.Remove(); } } } if (targetContent != null) { //The content control is inline if (sdtType == typeof(wp.SdtRun)) { cc.InsertAfterSelf(new wp.Run(targetContent)); cc.Remove(); } //The content control is a table cell else if (sdtType == typeof(wp.SdtCell)) { wp.TableCell tc = (wp.TableCell)((cc.Descendants <wp.TableCell>().FirstOrDefault()).CloneNode(true)); if (targetContent.GetType() == typeof(wp.Text)) { wp.Run targetRun = tc.Descendants <wp.Run>().FirstOrDefault(); targetRun.RemoveAllChildren(); targetRun.Append(targetContent); } else { tc.Append(targetContent); } cc.InsertAfterSelf(tc); cc.Remove(); } //The content control is multi-line else if (sdtType == typeof(wp.SdtBlock)) { cc.InsertAfterSelf(targetContent); cc.Remove(); } } } } foreach (var footer in output.MainDocumentPart.FooterParts) { footer.Footer.Save(); } doc.Save(); output.Close(); return(mem); } }