WORD -> PDF

This commit is contained in:
2025-03-27 11:13:42 +01:00
parent cb38e869a1
commit 04cca012f4
16 changed files with 808 additions and 7 deletions
@@ -0,0 +1,108 @@
using Aspose.Words;
using Aspose.Words.Tables;
using Serilog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WorkFlowCheck.BL.DocumentGenerator
{
public class DokumentumGenerator
{
static DokumentumGenerator()
{
Aspose.Words.License license = new Aspose.Words.License();
try
{
license.SetLicense("Aspose.Words.lic");
Log.Information("License set successfully.");
}
catch (Exception e)
{
Log.Error(e, "\nThere was an error setting the license: " + e.Message);
}
}
public static byte[] HtmlToDocx(string html)
{
byte[] generated = Encoding.UTF8.GetBytes(html);
var docHTML = new Aspose.Words.Document();
Aspose.Words.DocumentBuilder builder = new Aspose.Words.DocumentBuilder(docHTML);
builder.InsertHtml(html);
docHTML.CompatibilityOptions.OptimizeFor(Aspose.Words.Settings.MsWordVersion.Word2016);
MemoryStream outStream = new MemoryStream();
docHTML.Save(outStream, Aspose.Words.SaveFormat.Docx);
generated = outStream.ToArray();
outStream.Dispose();
return generated;
}
public static byte[] HtmlToPdf(string html)
{
byte[] generated = Encoding.UTF8.GetBytes(html);
Stream inStream = new MemoryStream(generated);
var docHTML = new Aspose.Words.Document(inStream);
MemoryStream outStream = new MemoryStream();
docHTML.Save(outStream, Aspose.Words.SaveFormat.Pdf);
generated = outStream.ToArray();
inStream.Dispose();
outStream.Dispose();
return generated;
}
public static byte[] DocxToPdf(byte[] generated)
{
Stream inStream = new MemoryStream(generated);
var doc = new Aspose.Words.Document(inStream);
MemoryStream outStream = new MemoryStream();
doc.Save(outStream, Aspose.Words.SaveFormat.Pdf);
generated = outStream.ToArray();
inStream.Dispose();
outStream.Dispose();
return generated;
}
public static byte[] DocxToPdfForTopic(byte[] generated)
{
Stream inStream = new MemoryStream(generated);
var doc = new Aspose.Words.Document(inStream);
doc.Styles.DefaultFont.Name = "Times New Roman";
doc.Styles.DefaultFont.Size = 12;
var collection = doc.GetChildNodes(NodeType.Row, true);
foreach (Row row in collection)
{
row.RowFormat.Height = 40;
row.RowFormat.HeightRule = HeightRule.AtLeast;
}
MemoryStream outStream = new MemoryStream();
doc.Save(outStream, Aspose.Words.SaveFormat.Pdf);
generated = outStream.ToArray();
inStream.Dispose();
outStream.Dispose();
return generated;
}
}
}
@@ -0,0 +1,499 @@
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<OpenXmlElement> _currentRoot;
private MemoryStream Mem { get; }
private WordprocessingDocument Doc { get; set; }
private List<OpenXmlElement> CurrentRoot => Repeater?.SablonRoot ?? _currentRoot;
private SubSablon Repeater { get; set; }
protected class SubSablon : IDisposable
{
private List<OpenXmlElement> SablonRootBase { get; set; }
protected internal List<OpenXmlElement> 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<BookmarkStart>()
.FirstOrDefault(x => x.Name == key);
//var parentBookmark = false;
if (bookmark != null)
{
SablonRoot = new List<OpenXmlElement>();
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<BookmarkEnd>().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<OpenXmlElement>();
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<OpenXmlElement>();
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<string, string> 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);
}
protected void SimpleReplace(OpenXmlCompositeElement target, string key, string value)
{
var keyValue = key.Replace("#", "");
var texts = target.Descendants<Text>();
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>();
Text start = null;
var tokens = new List<Text>();
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>();
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<string, string> propertyDictionary)
{
var bookmarkEndList = new List<BookmarkEnd>();
foreach (var item in CurrentRoot)
{
var bookmarkEnds = item.Descendants<BookmarkEnd>();
bookmarkEndList.AddRange(bookmarkEnds.ToList());
}
foreach (var docContent in CurrentRoot)
{
var bookmarkStarts = docContent.Descendants<BookmarkStart>();
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<Run>();
if (bookmarkRun != null)
{
var bookmarkText = bookmarkRun.GetFirstChild<Text>().InnerText;
if (propertyDictionary.ContainsKey(bookmarkText))
{
var itemValue = propertyDictionary[bookmarkText];
bookmarkRun.GetFirstChild<Text>().Text = itemValue ?? string.Empty;
var id = bookmarkStartList[k].Id.Value;
bookmarkStartList[k].Remove();
var end = bookmarkEndList.Find(x => x.Id == id);
end.Remove();
}
}
}
}
}
/// <summary>
/// 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
/// </summary>
/// <param name="rowsAndCells">sorok és benne az egyes cellák tartalma</param>
/// <param name="keyInRow">első (nem fejléc) sorában lévő kulcs, ez alapján azonosítjuk be a táblázatot</param>
/// <param name="deleteEmptyRow">ha igaz, a táblázat összes meglévő sorát törli</param>
public void SetTable(List<List<string>> rowsAndCells, string keyInRow, bool deleteEmptyRow = false)
{
Body bod = Doc.MainDocumentPart.Document.Body;
var table = bod.Descendants<Table>().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<TableRow>(deletedRow as TableRow);
}
foreach (var row in rowsAndCells)
{
List<OpenXmlElement> cells = new List<OpenXmlElement>();
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 byte[] CloseAndGetDocument()
{
Doc.Dispose();
Doc = null;
return Mem.ToArray();
}
public void Dispose()
{
Doc?.Dispose();
Mem.Dispose();
}
/// <summary>
/// Hozzáfűzi a már megnyitott fájlhoz a paraméterként kapott dokumentum tartalmát.
/// </summary>
/// <param name="document"></param>
/// <param name="addPageBreak"></param>
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();
}
}
}
@@ -49,6 +49,11 @@ namespace WorkFlowCheck.BL.Mappings
CreateMap<CheckListRow, CheckListRowDTO>()
.ForMember(dest => dest.CheckListTemplateRowDTO, opt => opt.MapFrom(src => src.CheckListTemplateRow));
CreateMap<RoleCheckListTemplateHeader, RoleCheckListTemplateHeaderDTO>()
.ForMember(dest => dest.RoleDTO, opt => opt.MapFrom(src => src.Role))
.ForMember(dest => dest.CheckListTemplateHeaderDTO, opt => opt.MapFrom(src => src.CheckListTemplateHeader));
}
}
}
@@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WorkFlowCheck.BL.DocumentGenerator;
using WorkFlowCheck.BL.Services.Interfaces;
using WorkFlowCheck.Common.DTO;
using WorkFlowCheck.DL;
@@ -51,7 +52,7 @@ namespace WorkFlowCheck.BL.Services
.OrderBy(r => r.CheckListTemplateRow.CheckPoint?.ShortName ?? string.Empty)
.ThenBy(r => r.CheckListTemplateRow.RowIndex)
.ToList();
}
if (res != null)
@@ -361,5 +362,17 @@ namespace WorkFlowCheck.BL.Services
return retVal;
}
public byte[] CreatePDF(int checkListHeaderId)
{
var location = System.Reflection.Assembly.GetEntryAssembly().Location;
var directory = System.IO.Path.GetDirectoryName(location);
byte[] byteArray = System.IO.File.ReadAllBytes(Path.Combine(directory, "DocumentGenerator", "CheckList_Template_V1.docx"));
SablonGenerator gen = new SablonGenerator(byteArray);
byte[] content = gen.CloseAndGetDocument();
return DokumentumGenerator.DocxToPdf(content);
}
}
}
@@ -23,5 +23,6 @@ namespace WorkFlowCheck.BL.Services.Interfaces
Task<CheckListTemplateRowDTO> GetCheckListTemplateRowAsync(int id);
Task<CheckListTemplateRowDTO> UpdateCheckListTemplateRowAsync(CheckListTemplateRowDTO checkListTemplateRowDTO);
byte[] CreatePDF(int checkListHeaderId);
}
}
@@ -22,7 +22,7 @@ namespace WorkFlowCheck.BL.Services.Interfaces
Task<List<UserRoleDTO>> GetAllUserRoleAsync();
Task<UserRoleDTO> UpdateUserRoleAsync(UserRoleDTO userRoleDTO);
Task<List<RoleCheckListTemplateHeaderDTO>> GetAllRoleCheckListTemplateHeadersAsync();
string GenerateJwtToken(UserDTO userDTO);
}
@@ -340,5 +340,6 @@ namespace WorkFlowCheck.BL.Services
return retVal;
}
public Task<List<RoleCheckListTemplateHeaderDTO>> GetAllRoleCheckListTemplateHeadersAsync() => throw new NotImplementedException();
}
}
@@ -7,7 +7,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Aspose.Words" Version="25.3.0" />
<PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="DocumentFormat.OpenXml" Version="3.3.0" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.3" />
</ItemGroup>