using DocumentFormat.OpenXml; using DocumentFormat.OpenXml.Packaging; using DocumentFormat.OpenXml.Wordprocessing; using System.Text.RegularExpressions; namespace WorkFlowCheck.BL.DocumentGenerator { public class SablonGenerator : IDisposable { private readonly List _currentRoot; private MemoryStream Mem { get; } private WordprocessingDocument Doc { get; set; } private List CurrentRoot => Repeater?.SablonRoot ?? _currentRoot; private SubSablon Repeater { get; set; } protected class SubSablon : IDisposable { private List SablonRootBase { get; set; } protected internal List SablonRoot { get; private set; } public BookmarkStart BookmarkStart { get; } public BookmarkEnd BookmarkEnd { get; } protected internal SubSablon(WordprocessingDocument doc, string key) { var bookmark = doc.MainDocumentPart.RootElement.Descendants() .FirstOrDefault(x => x.Name == key); //var parentBookmark = false; if (bookmark != null) { SablonRoot = new List(); var nextSibling = bookmark.NextSibling(); if (nextSibling == null) nextSibling = bookmark.Parent; while (nextSibling != null) { var endBookmark = (nextSibling is BookmarkEnd end && end.Id == bookmark.Id.Value) ? end : null; if (endBookmark == null) { endBookmark = nextSibling.Descendants().FirstOrDefault(x => x.Id == bookmark.Id.Value); if (endBookmark != null) SablonRoot.Add(nextSibling); } if (endBookmark != null) { bookmark.Remove(); endBookmark.Remove(); break; } SablonRoot.Add(nextSibling); var tmpNextSibling = nextSibling.NextSibling(); if (tmpNextSibling == null) { tmpNextSibling = nextSibling.Parent; if (tmpNextSibling != null && !(tmpNextSibling is Body) && !(tmpNextSibling is Document)) SablonRoot.Clear(); else break; } nextSibling = tmpNextSibling; } } if (SablonRoot != null && SablonRoot.Count > 0) { SablonRootBase = new List(); foreach (var item in SablonRoot) { SablonRootBase.Add(item.CloneNode(true)); } BookmarkStart = new BookmarkStart() { Name = "repeater", Id = "1000" }; BookmarkEnd = new BookmarkEnd() { Id = "1000" }; if (SablonRoot.First().Parent != null) { SablonRoot.First().InsertBeforeSelf(BookmarkStart); SablonRoot.First().InsertBeforeSelf(BookmarkEnd); foreach (var rootItem in SablonRoot) rootItem.Remove(); } else { foreach (var rootItem in SablonRoot) foreach (var rootItemChildElement in rootItem.ChildElements) rootItemChildElement.Remove(); SablonRoot.First().AppendChild(BookmarkStart); SablonRoot.First().AppendChild(BookmarkEnd); } Reset(); } } private void Insert() { var root = SablonRoot; if (root.Count == 1 && root.First() is Document) { root = root.First().ChildElements.ToList(); } for (var i = 0; i < root.Count; i++) { if (i == 0) BookmarkStart.InsertBeforeSelf(root[i]); else root[i - 1].InsertAfterSelf(root[i]); } } private void Reset() { SablonRoot.Clear(); foreach (var item in SablonRootBase) { SablonRoot.Add(item.CloneNode(true)); } } protected internal void InsertAndReset() { Insert(); Reset(); } public void Dispose() { BookmarkStart?.Remove(); BookmarkEnd?.Remove(); SablonRootBase = null; SablonRoot = null; } } public IDisposable Repeat(string key) { Repeater = new SubSablon(Doc, key); return Repeater; } public SablonGenerator(byte[] content) { Mem = new MemoryStream(); Mem.Write(content, 0, content.Length); try { Doc = WordprocessingDocument.Open(Mem, true, new OpenSettings() { MarkupCompatibilityProcessSettings = new MarkupCompatibilityProcessSettings(MarkupCompatibilityProcessMode.ProcessAllParts, FileFormatVersions.Office2010) }); } catch (Exception) { //if (!string.IsNullOrEmpty(Config.TryGetStringValue("SablonGeneratorErrorPath"))) //{ // File.WriteAllBytes(Path.Combine(Config.GetStringValue("SablonGeneratorErrorPath"), DateTime.Now.ToString("yyyyMMddHHHmmss.content")), content); //} throw; } _currentRoot = new List(); CurrentRoot.AddRange(Doc.MainDocumentPart.HeaderParts.Select(x => x.RootElement)); CurrentRoot.Add(Doc.MainDocumentPart.RootElement); CurrentRoot.AddRange(Doc.MainDocumentPart.FooterParts.Select(x => x.RootElement)); } public static void CheckOpenXmlDocument(byte[] content) { WordprocessingDocument doc = null; var mem = new MemoryStream(); mem.Write(content, 0, content.Length); try { doc = WordprocessingDocument.Open(mem, true, new OpenSettings() { MarkupCompatibilityProcessSettings = new MarkupCompatibilityProcessSettings(MarkupCompatibilityProcessMode.ProcessAllParts, FileFormatVersions.Office2010) }); } catch (Exception ex) { #if DEBUG //LoggerHelper.DiagnosticAudit.Information(DateTime.Now, //Common.Enums.Area.BaseSystem, //0, //string.Format(ex.ToString()), //new Guid().ToString()); //LoggerHelper.DiagnosticAudit.Log.Information(ex.ToString()); #else //LoggerHelper.DiagnosticAudit.Information(DateTime.Now, //Common.Enums.Area.BaseSystem, //0, //string.Format(ex.Message), //Guid.Empty.ToString()); #endif //throw new BusinessException("Hibás vagy nem megfelelő OpenXML állomány."); } finally { mem?.Dispose(); doc?.Dispose(); } } public void Generate(Dictionary propertyDictionary) { ReplaceBookmarks(propertyDictionary); if (Repeater?.SablonRoot != null) Repeater.InsertAndReset(); } public void SimpleReplace(string key, string value) { value = value == null ? "" : value; foreach (var headerPart in Doc.MainDocumentPart.HeaderParts) SimpleReplace2(headerPart.Header, key, value); SimpleReplace2(Doc.MainDocumentPart.Document.Body, key, value); foreach (var footerPart in Doc.MainDocumentPart.FooterParts) SimpleReplace2(footerPart.Footer, key, value); } protected void SimpleReplace(OpenXmlCompositeElement target, string key, string value) { var keyValue = key.Replace("#", ""); var texts = target.Descendants(); Text start = null; Text keyValueText = null; foreach (var text in texts) if (text.Text == "#" && start == null) start = text; else if (text.Text == "#" && start != null && keyValueText != null) { var end = text; keyValueText.Text = value; start.Remove(); end.Remove(); start = null; keyValueText = null; } else if (start != null && text.Text.ToUpper().Contains(keyValue.ToUpper())) keyValueText = text; else if (text.Text.ToUpper().Contains(key.ToUpper())) { start = null; keyValueText = null; text.Text = Regex.Replace(text.Text, key, value, RegexOptions.IgnoreCase); } else { start = null; keyValueText = null; } } protected void SimpleReplace2(OpenXmlCompositeElement target, string key, string value) { var texts = target.Descendants(); Text start = null; var tokens = new List(); string tokenText = ""; foreach (var text in texts) { if (text.Text == "#" && start == null) { start = text; tokenText += text.Text; } else if (text.Text == "#" && start != null) { var end = text; tokenText += text.Text; if (tokenText.ToUpper() == key.ToUpper()) { start.Text = value; foreach (var token in tokens) { token.Remove(); } tokens.Clear(); end.Remove(); start = null; tokenText = ""; } else { start = null; tokens.Clear(); tokenText = ""; end = null; } } else if (text.Text.Contains('#') && text.Text.ToUpper() == key.ToUpper()) { text.Text = value; } else if (text.Text.Contains('#')) { } else if (start != null) { tokens.Add(text); tokenText += text.Text; } } } public void SimpleReplaceForCV(string key, string value) { value = value == null ? "" : value; SimpleReplaceForCV(Doc.MainDocumentPart.Document.Body, key, value); } protected void SimpleReplaceForCV(OpenXmlCompositeElement target, string key, string value) { var keyValue = key.Replace("#", ""); var texts = target.Descendants(); Text start = null; Text keyValueText = null; var keyindox = ""; foreach (var text in texts) { if (text.Text.Contains(key)) { text.Text = text.Text.Replace(key, value); break; } if (text.Text.Contains(keyValue + "#") && start != null) { start.Text = ""; text.Text = text.Text.Replace(keyValue + "#", value); break; } if ((text.Text == "#" || (text.Text.Contains("#") && text.Text.Count(x => x == '#') == 1)) && start == null) { start = text; keyindox = start.Text; } else if (start != null && (text.Text == "#" || text.Text.Contains("#"))) { for (int i = texts.ToList().IndexOf(start) + 1; i < texts.ToList().IndexOf(text) + 1; i++) { if (texts.ToList()[i].Text.Contains(key)) { texts.ToList()[i].Text = texts.ToList()[i].Text.Replace(key, value); break; } keyindox = keyindox + texts.ToList()[i].Text; } keyindox = keyindox.Replace("#", ""); if (keyindox == keyValue || keyindox.Replace(" ", "") == keyValue) { for (int i = texts.ToList().IndexOf(start) + 1; i < texts.ToList().IndexOf(text); i++) { texts.ToList()[i].Text = ""; } start.Text = ""; text.Text = value; } if (keyindox.Contains(keyValue)) { for (int i = texts.ToList().IndexOf(start) + 1; i < texts.ToList().IndexOf(text); i++) { texts.ToList()[i].Text = ""; } start.Text = ""; text.Text = keyindox.Replace(keyValue, value); } start = null; keyindox = ""; } } } private void ReplaceBookmarks(Dictionary propertyDictionary) { var bookmarkEndList = new List(); foreach (var item in CurrentRoot) { var bookmarkEnds = item.Descendants(); bookmarkEndList.AddRange(bookmarkEnds.ToList()); } foreach (var docContent in CurrentRoot) { var bookmarkStarts = docContent.Descendants(); var bookmarkStartList = bookmarkStarts.ToList(); if (docContent is BookmarkStart) bookmarkStartList.Add(docContent as BookmarkStart); for (int k = 0; k < bookmarkStartList.Count; k++) { Run bookmarkRun = bookmarkStartList[k].NextSibling(); if (bookmarkRun != null) { var bookmarkText = bookmarkRun.GetFirstChild().InnerText; if (propertyDictionary.ContainsKey(bookmarkText)) { var itemValue = propertyDictionary[bookmarkText]; bookmarkRun.GetFirstChild().Text = itemValue ?? string.Empty; var id = bookmarkStartList[k].Id.Value; bookmarkStartList[k].Remove(); var end = bookmarkEndList.Find(x => x.Id == id); end.Remove(); } } } } } /// /// Táblázat generálás (a keyinrow paramétert keresi a táblázat első sorában (nem fejléc), ezt a sort kitörli, és helyére szúrja be az új sorokat /// amit az első paraméterben kap meg /// /// sorok és benne az egyes cellák tartalma /// első (nem fejléc) sorában lévő kulcs, ez alapján azonosítjuk be a táblázatot /// ha igaz, a táblázat összes meglévő sorát törli public void SetTable_Old(List> rowsAndCells, string keyInRow, bool deleteEmptyRow = false) { Body bod = Doc.MainDocumentPart.Document.Body; var table = bod.Descendants().Where(tbl => tbl.InnerText.Contains(keyInRow)).FirstOrDefault(); if (table != null) { if (deleteEmptyRow) { var firstRow = table.ChildElements.Where(x => x is TableRow).FirstOrDefault(); var deletedRows = table.ChildElements.Where(x => x is TableRow).ToList(); deletedRows.Remove(firstRow); foreach (var item in deletedRows) table.RemoveChild(item); } else { var deletedRow = table.ChildElements.Where(x => x is TableRow).LastOrDefault(); table.RemoveChild(deletedRow as TableRow); } foreach (var row in rowsAndCells) { List cells = new List(); foreach (var cell in row) { var tableCell = new TableCell(new Paragraph(new Run(new Text(cell)))); cells.Add(tableCell); } table.Append(new TableRow(cells)); } } } public void SetTable(List> rowsAndCells, string keyInRow, bool deleteEmptyRow = false) { Body bod = Doc.MainDocumentPart.Document.Body; var table = bod.Descendants
().Where(tbl => tbl.InnerText.Contains(keyInRow)).FirstOrDefault(); if (table != null) { TableRow formatRow = null; // Megkeressük az első sort és elmentjük a formázást if (deleteEmptyRow) { var firstRow = table.ChildElements.OfType().FirstOrDefault(); if (firstRow != null) { formatRow = (TableRow)firstRow.CloneNode(true); // Az első sor másolása formázással var deletedRows = table.ChildElements.OfType().ToList(); foreach (var item in deletedRows) table.RemoveChild(item); } } else { var deletedRow = table.ChildElements.OfType().LastOrDefault(); if (deletedRow != null) { formatRow = (TableRow)deletedRow.CloneNode(true); // Az utolsó sor másolása formázással table.RemoveChild(deletedRow); } } // Új sorok beszúrása a mentett formázással foreach (var row in rowsAndCells) { List cells = new List(); for (int i = 0; i < row.Count; i++) { var cellText = row[i].Replace("#", ""); // Ha van formázási minta, alkalmazzuk TableCell newCell; if (formatRow != null && i < formatRow.Elements().Count()) { var formatCell = formatRow.Elements().ElementAt(i); var clonedCell = (TableCell)formatCell.CloneNode(true); var para = clonedCell.Descendants().FirstOrDefault(); // Ha van beágyazott szöveg, frissítjük a tartalmát if (para != null) { var run = para.Descendants().FirstOrDefault(); if (run != null) { run.RemoveAllChildren(); run.AppendChild(new Text(cellText)); } } newCell = clonedCell; } else { // Alapértelmezett cella, ha nincs formázási minta newCell = new TableCell(new Paragraph(new Run(new Text(cellText)))); } cells.Add(newCell); } table.Append(new TableRow(cells)); } } } public byte[] CloseAndGetDocument() { Doc.Dispose(); Doc = null; return Mem.ToArray(); } public void Dispose() { Doc?.Dispose(); Mem.Dispose(); } /// /// Hozzáfűzi a már megnyitott fájlhoz a paraméterként kapott dokumentum tartalmát. /// /// /// public void AppendDocument(byte[] document, bool addPageBreak = true) { var mainPart = Doc.MainDocumentPart; string altChunkId = "AltChunk_" + Guid.NewGuid().ToString().Replace("-", ""); var chunk = mainPart.AddAlternativeFormatImportPart(AlternativeFormatImportPartType.WordprocessingML, altChunkId); chunk.FeedData(new MemoryStream(document)); // oldaltörés, ha kell if (addPageBreak) { mainPart.Document.Body.AppendChild(new Paragraph(new Run(new Break() { Type = BreakValues.Page }))); } mainPart.Document.Body.AppendChild(new AltChunk() { Id = altChunkId }); mainPart.Document.Save(); } } }