LibreOffice-val dokumentum konvertálása PDF-re most jó

This commit is contained in:
2025-04-02 16:51:11 +02:00
parent 90637b3848
commit 001c59a669
8 changed files with 170 additions and 27 deletions
@@ -47,7 +47,7 @@ namespace WorkFlowCheck.API.Controllers
IsSuccess = true, IsSuccess = true,
}; };
var checkListHeader = await _checkListService.GetCheckListHeaderAsync(id); var checkListHeader = await _checkListService.GetCheckListHeaderAsync(id);
var response = _checkListService.CreatePDF(id); var response = await _checkListService.CreatePDF(id);
if (response != null) if (response != null)
{ {
Binary file not shown.
@@ -1,35 +1,59 @@
using DevExpress.XtraRichEdit; using System.Diagnostics;
namespace WorkFlowCheck.BL.DocumentGenerator namespace WorkFlowCheck.BL.DocumentGenerator
{ {
public class DokumentumGenerator public class DokumentumGenerator
{ {
public static byte[] DocxToPdf(byte[] wordBytes) public static byte[] DocxToPdfL(byte[] wordBytes)
{
using (MemoryStream inputStream = new MemoryStream(wordBytes))
using (MemoryStream outputStream = new MemoryStream())
{ {
string pdfDirectory = Path.Combine(Directory.GetCurrentDirectory(), "Pdf");
string fileName = Guid.NewGuid().ToString();
string tempWordPath = Path.Combine(pdfDirectory, fileName + ".docx");
string tempPdfPath = Path.Combine(pdfDirectory, fileName + ".pdf");
try try
{ {
// RichEditDocumentServer használata a konverzióhoz // Word fájl mentése ideiglenes fájlba
using (RichEditDocumentServer wordProcessor = new RichEditDocumentServer()) File.WriteAllBytes(tempWordPath, wordBytes);
// LibreOffice parancssori konverzió
ProcessStartInfo startInfo = new ProcessStartInfo
{ {
// Dokumentum betöltése a byte tömbből FileName = "e:\\LibreOffice\\program\\soffice", // LibreOffice parancs
wordProcessor.LoadDocument(inputStream, DevExpress.XtraRichEdit.DocumentFormat.OpenXml); Arguments = $"--headless --convert-to pdf \"{tempWordPath}\" --outdir \"{pdfDirectory}",
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true
};
// PDF formátumba mentés a memóriafolyamba using (Process process = Process.Start(startInfo))
wordProcessor.ExportToPdf(outputStream); {
process.WaitForExit();
}
// PDF byte tömb visszaadása // Ellenőrzés, hogy létrejött-e a PDF
return outputStream.ToArray(); if (File.Exists(tempPdfPath))
{
byte[] pdfBytes = File.ReadAllBytes(tempPdfPath);
// Ideiglenes fájlok törlése
File.Delete(tempWordPath);
File.Delete(tempPdfPath);
return pdfBytes;
}
else
{
throw new Exception("PDF konverzió sikertelen.");
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Console.WriteLine("Hiba a konverzió során: " + ex.Message); Console.WriteLine("Hiba a PDF konverzió során: " + ex.Message);
return new byte[0]; return null;
}
} }
} }
} }
} }
@@ -424,7 +424,7 @@ namespace WorkFlowCheck.BL.DocumentGenerator
/// <param name="rowsAndCells">sorok és benne az egyes cellák tartalma</param> /// <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="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> /// <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) public void SetTable_Old(List<List<string>> rowsAndCells, string keyInRow, bool deleteEmptyRow = false)
{ {
Body bod = Doc.MainDocumentPart.Document.Body; Body bod = Doc.MainDocumentPart.Document.Body;
var table = bod.Descendants<Table>().Where(tbl => tbl.InnerText.Contains(keyInRow)).FirstOrDefault(); var table = bod.Descendants<Table>().Where(tbl => tbl.InnerText.Contains(keyInRow)).FirstOrDefault();
@@ -458,6 +458,79 @@ namespace WorkFlowCheck.BL.DocumentGenerator
} }
} }
} }
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)
{
TableRow formatRow = null;
// Megkeressük az első sort és elmentjük a formázást
if (deleteEmptyRow)
{
var firstRow = table.ChildElements.OfType<TableRow>().FirstOrDefault();
if (firstRow != null)
{
formatRow = (TableRow)firstRow.CloneNode(true); // Az első sor másolása formázással
var deletedRows = table.ChildElements.OfType<TableRow>().ToList();
foreach (var item in deletedRows)
table.RemoveChild(item);
}
}
else
{
var deletedRow = table.ChildElements.OfType<TableRow>().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<OpenXmlElement> cells = new List<OpenXmlElement>();
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<TableCell>().Count())
{
var formatCell = formatRow.Elements<TableCell>().ElementAt(i);
var clonedCell = (TableCell)formatCell.CloneNode(true);
var para = clonedCell.Descendants<Paragraph>().FirstOrDefault();
// Ha van beágyazott szöveg, frissítjük a tartalmát
if (para != null)
{
var run = para.Descendants<Run>().FirstOrDefault();
if (run != null)
{
run.RemoveAllChildren<Text>();
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() public byte[] CloseAndGetDocument()
{ {
@@ -1,4 +1,5 @@
using AutoMapper; using AutoMapper;
using DocumentFormat.OpenXml.Office.CustomUI;
using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Serilog; using Serilog;
@@ -424,18 +425,40 @@ namespace WorkFlowCheck.BL.Services
return retVal; return retVal;
} }
public byte[] CreatePDF(int checkListHeaderId) public async Task<byte[]> CreatePDF(int checkListHeaderId)
{ {
try try
{ {
var checkListHeader = await this.GetCheckListHeaderAsync(checkListHeaderId);
string pdfDirectory = Path.Combine(Directory.GetCurrentDirectory(), "Pdf"); string pdfDirectory = Path.Combine(Directory.GetCurrentDirectory(), "Pdf");
byte[] byteArray = File.ReadAllBytes(Path.Combine(pdfDirectory, "CheckList_Template_V1.docx")); byte[] byteArray = File.ReadAllBytes(Path.Combine(pdfDirectory, "CheckList_Template_V1.docx"));
SablonGenerator gen = new SablonGenerator(byteArray); SablonGenerator gen = new SablonGenerator(byteArray);
if (checkListHeader.CheckListRowDTO != null && checkListHeader.CheckListRowDTO.Count > 0)
{
var elements = new List<List<string>>();
foreach (var item in checkListHeader.CheckListRowDTO)
{
if (item.CheckListTemplateRowDTO != null)
{
var cells = new List<string>
{
$"{item.CheckListTemplateRowDTO.RowIndex.ToString()}.",
item.CheckListTemplateRowDTO.OperationDescription,
item.Answer
};
elements.Add(cells);
}
}
gen.SetTable(elements, "#rowindex");
}
byte[] content = gen.CloseAndGetDocument(); byte[] content = gen.CloseAndGetDocument();
return DokumentumGenerator.DocxToPdf(content); return DokumentumGenerator.DocxToPdfL(content);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -23,6 +23,6 @@ namespace WorkFlowCheck.BL.Services.Interfaces
Task<CheckListRowDTO> UpdateCheckListRowAsync(CheckListRowDTO checkListRowDTO); Task<CheckListRowDTO> UpdateCheckListRowAsync(CheckListRowDTO checkListRowDTO);
byte[] CreatePDF(int checkListHeaderId); Task<byte[]> CreatePDF(int checkListHeaderId);
} }
} }
@@ -8,7 +8,6 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="AutoMapper" Version="13.0.1" /> <PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="DevExpress.Document.Processor" Version="24.2.6" />
<PackageReference Include="DocumentFormat.OpenXml" Version="3.3.0" /> <PackageReference Include="DocumentFormat.OpenXml" Version="3.3.0" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.3" /> <PackageReference Include="Serilog.AspNetCore" Version="8.0.3" />
</ItemGroup> </ItemGroup>
+26 -2
View File
@@ -194,7 +194,31 @@ function renderAnswerType(data) {
} }
function renderAnswerPhoto(data, row) { function renderAnswerPhoto(data, row) {
if (row.checkListTemplateRowDTO.answerType === 'P') { if (row.checkListTemplateRowDTO.answerType === 'P') {
return `<img src="${data}" alt="Image" style="height: 100px; width: auto;" />` return `<div class="text-center"><img src="${data}" alt="Image" style="height: 100px; width: auto;" /></div>`;
} }
return data; if (row.checkListTemplateRowDTO.answerType === 'SI-N' && data === 'Igen') {
return '<div class="text-center"><div class="box yellow-box">I</div></div>';
}
if (row.checkListTemplateRowDTO.answerType === 'SI-N' && data === 'Nem') {
return '<div class="text-center"><div class="box">N</div></div>';
}
if (row.checkListTemplateRowDTO.answerType === 'I-SN' && data === 'Igen') {
return '<div class="text-center"><div class="box">I</div></div>';
}
if (row.checkListTemplateRowDTO.answerType === 'I-SN' && data === 'Nem') {
return '<div class="text-center"><div class="box yellow-box">N</div></div>';
}
if (row.checkListTemplateRowDTO.answerType === 'PI-N' && data === 'Igen') {
return '<div class="text-center"><div class="box red-box">I</div></div>';
}
if (row.checkListTemplateRowDTO.answerType === 'PI-N' && data === 'Nem') {
return '<div class="text-center"><div class="box">N</div></div>';
}
if (row.checkListTemplateRowDTO.answerType === 'I-PN' && data === 'Igen') {
return '<div class="text-center"><div class="box">I</div></div>';
}
if (row.checkListTemplateRowDTO.answerType === 'I-PN' && data === 'Nem') {
return '<div class="text-center"><div class="box red-box">N</div></div>';
}
return `<div class="text-center">${data}</div></div>`;
} }