Add project files.
This commit is contained in:
401
PDF.cs
Normal file
401
PDF.cs
Normal file
@@ -0,0 +1,401 @@
|
||||
using MigraDoc.DocumentObjectModel;
|
||||
using MigraDoc.DocumentObjectModel.Tables;
|
||||
using MigraDoc.Rendering;
|
||||
using PdfSharp.Pdf;
|
||||
using PdfSharp.Pdf.IO;
|
||||
using Image = MigraDoc.DocumentObjectModel.Shapes.Image;
|
||||
|
||||
namespace AiQ_GUI
|
||||
{
|
||||
internal class PDF
|
||||
{
|
||||
public const string TestRecordDir = "G:\\Shared drives\\MAV Production Test Records\\AiQ\\";
|
||||
public const string ImageDir = $"{GoogleAPI.DrivePath}AiQ\\GUI's\\";
|
||||
public static void CreateFinalTestReport(Camera CamOnTest, string UserName, string fulltestvalues, DateTime PCTime)
|
||||
{
|
||||
// Create a new PDF document
|
||||
Document document = new();
|
||||
Section section = document.AddSection();
|
||||
|
||||
// Create a table with two columns
|
||||
Table latable = section.AddTable();
|
||||
latable.Borders.Visible = false; // No visible borders
|
||||
latable.AddColumn(Unit.FromCentimeter(13)); // Left column for MAV logo
|
||||
latable.AddColumn(Unit.FromCentimeter(3)); // Right column for AiQ logo
|
||||
|
||||
// Add a row for the logos
|
||||
Row larow = latable.AddRow();
|
||||
Cell cellMAV = larow.Cells[0];
|
||||
Cell cellAiQ = larow.Cells[1];
|
||||
|
||||
// Add MAV logo to the left cell
|
||||
Image imageMAV = cellMAV.AddImage($"{ImageDir}MAV-Logo.png");
|
||||
imageMAV.LockAspectRatio = true;
|
||||
imageMAV.Height = Unit.FromCentimeter(1); // Set height to 1 cm
|
||||
|
||||
// Add AiQ logo to the right cell
|
||||
Image imageAiQ = cellAiQ.AddImage($"{ImageDir}AiQ-Logo.png");
|
||||
imageAiQ.LockAspectRatio = true;
|
||||
imageAiQ.Height = Unit.FromCentimeter(1.25); // Set height to 1 cm
|
||||
|
||||
// Add spacing below the table
|
||||
Paragraph tableParagraph = section.AddParagraph();
|
||||
tableParagraph.Format.SpaceAfter = "0.5cm";
|
||||
|
||||
// Add Title
|
||||
Paragraph title = section.AddParagraph("Certificate of Conformity");
|
||||
title.Format.Font.Size = 20;
|
||||
title.Format.Font.Bold = true;
|
||||
title.Format.Alignment = ParagraphAlignment.Center;
|
||||
title.Format.SpaceAfter = "0.15cm";
|
||||
|
||||
// Add SubTitle
|
||||
string Subtitle = $"AiQ {CamOnTest.Model} {CamOnTest.Serial}" + (CamOnTest.RMANum != 0 ? $" (RMA {CamOnTest.RMANum})" : "");
|
||||
Paragraph subtitle = section.AddParagraph(Subtitle);
|
||||
subtitle.Format.Font.Size = 14;
|
||||
subtitle.Format.Alignment = ParagraphAlignment.Center;
|
||||
subtitle.Format.SpaceAfter = "0.5cm";
|
||||
|
||||
// Add Date
|
||||
Paragraph date = section.AddParagraph($"Date: {PCTime}{Environment.NewLine}Engineer: {UserName}{Environment.NewLine}Tested in accordance with MAV.146.060.010.01");
|
||||
date.Format.Font.Size = 10;
|
||||
date.Format.SpaceAfter = "0.5cm";
|
||||
|
||||
// Add Test Values header
|
||||
Paragraph valuesHeader = section.AddParagraph("Test Values:");
|
||||
valuesHeader.Format.Font.Size = 14;
|
||||
valuesHeader.Format.Font.Bold = true;
|
||||
valuesHeader.Format.SpaceAfter = "0.25cm";
|
||||
|
||||
// Add Test Values
|
||||
Paragraph FTV = section.AddParagraph(fulltestvalues);
|
||||
FTV.Format.Font.Size = 10;
|
||||
FTV.Format.SpaceAfter = "0.5cm";
|
||||
|
||||
// Add Images
|
||||
Paragraph imagesHeader = section.AddParagraph("Images:");
|
||||
imagesHeader.Format.Font.Size = 14;
|
||||
imagesHeader.Format.Font.Bold = true;
|
||||
imagesHeader.Format.SpaceAfter = "0.25cm";
|
||||
|
||||
// Create a table with two columns
|
||||
Table table = section.AddTable();
|
||||
table.Borders.Width = 0; // No border
|
||||
table.AddColumn(Unit.FromCentimeter(6)); // Column 1 width
|
||||
table.AddColumn(Unit.FromCentimeter(6)); // Column 2 width
|
||||
table.AddColumn(Unit.FromCentimeter(6)); // Column 3 width
|
||||
table.Rows.Alignment = RowAlignment.Center;
|
||||
|
||||
Row row = table.AddRow();
|
||||
|
||||
// Add IR F16 to the first column
|
||||
Cell cell1 = row.Cells[0];
|
||||
cell1.Format.Alignment = ParagraphAlignment.Center; // Center horizontally
|
||||
cell1.AddParagraph("Infrared - F16.0");
|
||||
Image imageIR = cell1.AddImage(LDS.MAVPath + LDS.IRTightsavePath);
|
||||
imageIR.LockAspectRatio = true; // Maintain aspect ratio
|
||||
imageIR.Width = Unit.FromCentimeter(6); // Scale as needed
|
||||
|
||||
// Add IR F2 to the second column
|
||||
Cell cell2 = row.Cells[1];
|
||||
cell2.Format.Alignment = ParagraphAlignment.Center; // Center horizontally
|
||||
cell2.AddParagraph("Infrared - F2.0");
|
||||
Image imageIR17 = cell2.AddImage(LDS.MAVPath + LDS.IROpensavePath);
|
||||
imageIR17.LockAspectRatio = true; // Maintain aspect ratio
|
||||
imageIR17.Width = Unit.FromCentimeter(6); // Scale as needed
|
||||
|
||||
// Add Image OV to the third column
|
||||
Cell cell3 = row.Cells[2];
|
||||
cell3.Format.Alignment = ParagraphAlignment.Center; // Center horizontally
|
||||
cell3.AddParagraph("Overview");
|
||||
Image imageOV = cell3.AddImage(LDS.MAVPath + LDS.OVsavePath);
|
||||
imageOV.LockAspectRatio = true; // Maintain aspect ratio
|
||||
imageOV.Width = Unit.FromCentimeter(6); // Scale as needed
|
||||
|
||||
section.AddParagraph().Format.SpaceAfter = "0.5cm";
|
||||
|
||||
// Add signiture
|
||||
Paragraph Signiture = section.AddParagraph("This unit is approved for shipment by:");
|
||||
Signiture.Format.Font.Size = 14;
|
||||
Signiture.Format.Alignment = ParagraphAlignment.Right;
|
||||
|
||||
Paragraph paragraph = section.AddParagraph();
|
||||
Image image = paragraph.AddImage($"{ImageDir}RP-Sig.jpg");
|
||||
image.Height = Unit.FromCentimeter(2);
|
||||
image.LockAspectRatio = true;
|
||||
paragraph.Format.Alignment = ParagraphAlignment.Right;
|
||||
|
||||
Paragraph PostSig = section.AddParagraph($"Richard Porter{Environment.NewLine}Head of Engineering{Environment.NewLine}MAV Systems Ltd");
|
||||
PostSig.Format.Font.Size = 14;
|
||||
PostSig.Format.Alignment = ParagraphAlignment.Right;
|
||||
|
||||
try
|
||||
{
|
||||
// Render PDF
|
||||
PdfDocumentRenderer renderer = new()
|
||||
{
|
||||
Document = document
|
||||
};
|
||||
renderer.RenderDocument();
|
||||
renderer.PdfDocument.Options.Layout = PdfWriterLayout.Compact;
|
||||
|
||||
// Adds RMA number to file namme if there is one
|
||||
string saveLoc = $"{TestRecordDir}{CamOnTest.Model}\\FinalTestReport_{CamOnTest.Model}_{CamOnTest.Serial}_{PCTime:dd-MM-yyyy_HH-mm-ss}" +
|
||||
(CamOnTest.RMANum != 0 ? $" RMA{CamOnTest.RMANum}" : "") + ".pdf";
|
||||
|
||||
if (!Directory.Exists($"{TestRecordDir}{CamOnTest.Model}\\")) // Does the model directory exist?
|
||||
{
|
||||
Directory.CreateDirectory($"{TestRecordDir}{CamOnTest.Model}\\"); // if not then create the directory now
|
||||
}
|
||||
|
||||
renderer.PdfDocument.Save(saveLoc);
|
||||
Logging.LogMessage("Final Test PDF saved to " + saveLoc);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Show a message box to inform the user that PDF creation failed, displaying the exception message.
|
||||
MainForm.Instance.AddToActionsList($"Failed to create PDF:\n{ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public static string CreateSoakTestReport(Camera CamSoak, string userName, DateTime pcTime, string logFilePath)
|
||||
{
|
||||
if (!File.Exists(logFilePath))
|
||||
{
|
||||
MainForm.Instance.AddToActionsList("Soak log file not found. Cannot create Soak Test Report.");
|
||||
return null;
|
||||
}
|
||||
|
||||
List<string> logLines = File.Exists(logFilePath) ? File.ReadAllLines(logFilePath).ToList() : new List<string>();
|
||||
|
||||
List<string> errorLines = logLines.Where(l => l.Contains("[ERROR]")).ToList();
|
||||
List<string> warningLines = logLines.Where(l => l.Contains("[WARNING]")).ToList();
|
||||
|
||||
// Create PDF document
|
||||
Document document = new();
|
||||
Section section = document.AddSection();
|
||||
|
||||
// Header table with logos
|
||||
Table logoTable = section.AddTable();
|
||||
logoTable.Borders.Visible = false;
|
||||
logoTable.AddColumn(Unit.FromCentimeter(13)); // Left column
|
||||
logoTable.AddColumn(Unit.FromCentimeter(3)); // Right column
|
||||
|
||||
Row logoRow = logoTable.AddRow();
|
||||
Cell cellMAV = logoRow.Cells[0];
|
||||
Cell cellAiQ = logoRow.Cells[1];
|
||||
|
||||
Image mavLogo = cellMAV.AddImage($"{ImageDir}MAV-Logo.png");
|
||||
mavLogo.LockAspectRatio = true;
|
||||
mavLogo.Height = Unit.FromCentimeter(1);
|
||||
|
||||
Image aiqLogo = cellAiQ.AddImage($"{ImageDir}AiQ-Logo.png");
|
||||
aiqLogo.LockAspectRatio = true;
|
||||
aiqLogo.Height = Unit.FromCentimeter(1.25);
|
||||
|
||||
section.AddParagraph().Format.SpaceAfter = "0.5cm";
|
||||
|
||||
// Title
|
||||
Paragraph title = section.AddParagraph("Soak Test Certificate");
|
||||
title.Format.Font.Size = 20;
|
||||
title.Format.Font.Bold = true;
|
||||
title.Format.Alignment = ParagraphAlignment.Center;
|
||||
title.Format.SpaceAfter = "0.15cm";
|
||||
|
||||
// Subtitle with RMA number if available
|
||||
string subtitleText = $"AiQ {CamSoak.Model} {CamSoak.Serial}" + (CamSoak.RMANum != 0 ? $" (RMA {CamSoak.RMANum})" : "");
|
||||
Paragraph subtitle = section.AddParagraph(subtitleText);
|
||||
subtitle.Format.Font.Size = 14;
|
||||
subtitle.Format.Alignment = ParagraphAlignment.Center;
|
||||
subtitle.Format.SpaceAfter = "0.5cm";
|
||||
|
||||
// Date and engineer info
|
||||
Paragraph datePara = section.AddParagraph($"Date: {pcTime:dd/MM/yyyy HH:mm:ss}{Environment.NewLine}Engineer: {userName}{Environment.NewLine}Tested in accordance with MAV.146.060.020.01");
|
||||
datePara.Format.Font.Size = 10;
|
||||
datePara.Format.SpaceAfter = "0.5cm";
|
||||
|
||||
// === Add warning/error summary with counts and color ===
|
||||
if (warningLines.Count > 0 || errorLines.Count > 0)
|
||||
{
|
||||
Paragraph logSummary = section.AddParagraph("Log Summary:");
|
||||
logSummary.Format.Font.Size = 12;
|
||||
logSummary.Format.Font.Bold = true;
|
||||
logSummary.Format.SpaceAfter = "0.2cm";
|
||||
|
||||
Paragraph totalCounts = section.AddParagraph();
|
||||
totalCounts.Format.Font.Size = 10;
|
||||
totalCounts.AddText("Total Errors: ");
|
||||
FormattedText errorCountText = totalCounts.AddFormattedText(errorLines.Count.ToString());
|
||||
errorCountText.Font.Color = Colors.Red;
|
||||
totalCounts.AddText("\nTotal Warnings: ");
|
||||
FormattedText warningCountText = totalCounts.AddFormattedText(warningLines.Count.ToString());
|
||||
warningCountText.Font.Color = Colors.Orange;
|
||||
totalCounts.Format.SpaceAfter = "0.2cm";
|
||||
|
||||
Dictionary<string, int> errorCounts = [];
|
||||
Dictionary<string, int> warningCounts = [];
|
||||
|
||||
foreach (string line in errorLines)
|
||||
{
|
||||
string message = ExtractLogMessageContent(line);
|
||||
if (errorCounts.TryGetValue(message, out int value))
|
||||
errorCounts[message] = ++value;
|
||||
else
|
||||
errorCounts[message] = 1;
|
||||
}
|
||||
|
||||
foreach (string line in warningLines)
|
||||
{
|
||||
string message = ExtractLogMessageContent(line);
|
||||
if (warningCounts.TryGetValue(message, out int value))
|
||||
warningCounts[message] = ++value;
|
||||
else
|
||||
warningCounts[message] = 1;
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<string, int> ErrorCounter in errorCounts) // Itterates through the dictionary and Adds Errors and how many times that warning has appeared
|
||||
{
|
||||
Paragraph errorPara = section.AddParagraph();
|
||||
errorPara.Format.Font.Size = 9;
|
||||
errorPara.AddFormattedText("[", TextFormat.NotBold);
|
||||
FormattedText redText = errorPara.AddFormattedText("ERROR", TextFormat.NotBold);
|
||||
redText.Font.Color = Colors.Red;
|
||||
errorPara.AddFormattedText($"] {ErrorCounter.Key} (x{ErrorCounter.Value})");
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<string, int> WarningCounter in warningCounts) // Itterates through the dictionary and Adds warning and how many times that warning has appeared
|
||||
{
|
||||
Paragraph warnPara = section.AddParagraph();
|
||||
warnPara.Format.Font.Size = 9;
|
||||
warnPara.AddFormattedText("[", TextFormat.NotBold);
|
||||
FormattedText orangeText = warnPara.AddFormattedText("WARNING", TextFormat.NotBold);
|
||||
orangeText.Font.Color = Colors.Orange;
|
||||
warnPara.AddFormattedText($"] {WarningCounter.Key} (x{WarningCounter.Value})");
|
||||
}
|
||||
|
||||
section.AddParagraph().Format.SpaceAfter = "0.5cm";
|
||||
}
|
||||
|
||||
// Signature
|
||||
if (errorLines.Count == 0)
|
||||
{
|
||||
Paragraph approval = section.AddParagraph("This unit is approved for shipment by:");
|
||||
approval.Format.Font.Size = 14;
|
||||
approval.Format.Alignment = ParagraphAlignment.Right;
|
||||
|
||||
Paragraph sigPara = section.AddParagraph();
|
||||
Image sigImage = sigPara.AddImage($"{ImageDir}RP-Sig.jpg");
|
||||
sigImage.Height = Unit.FromCentimeter(2);
|
||||
sigImage.LockAspectRatio = true;
|
||||
sigPara.Format.Alignment = ParagraphAlignment.Right;
|
||||
|
||||
Paragraph signoff = section.AddParagraph($"Richard Porter{Environment.NewLine}Head of Engineering{Environment.NewLine}MAV Systems Ltd");
|
||||
signoff.Format.Font.Size = 14;
|
||||
signoff.Format.Alignment = ParagraphAlignment.Right;
|
||||
}
|
||||
|
||||
// New page with full log
|
||||
Section logSection = document.AddSection();
|
||||
Paragraph fullLogTitle = logSection.AddParagraph("Full Log Output:");
|
||||
fullLogTitle.Format.Font.Size = 12;
|
||||
fullLogTitle.Format.Font.Bold = true;
|
||||
fullLogTitle.Format.SpaceAfter = "0.2cm";
|
||||
|
||||
foreach (string line in logLines)
|
||||
{
|
||||
Paragraph logLine = logSection.AddParagraph();
|
||||
logLine.Format.Font.Size = 8;
|
||||
|
||||
if (line.Contains("[ERROR]"))
|
||||
{
|
||||
int index = line.IndexOf("[ERROR]"); // You get rid of error only to add it back a few lines later? // this is because its difficukt to change the colour of text your importing its easier to remove and then make red
|
||||
logLine.AddText(line[..index]);
|
||||
logLine.AddFormattedText("ERROR", TextFormat.NotBold).Font.Color = Colors.Red;
|
||||
logLine.AddText(line[(index + "[ERROR]".Length)..]);
|
||||
}
|
||||
else if (line.Contains("[WARNING]"))
|
||||
{
|
||||
int index = line.IndexOf("[WARNING]"); // You get rid of warning only to add it back a few lines later? // Same here
|
||||
logLine.AddText(line[..index]);
|
||||
logLine.AddFormattedText("WARNING", TextFormat.NotBold).Font.Color = Colors.Orange;
|
||||
logLine.AddText(line[(index + "[WARNING]".Length)..]);
|
||||
}
|
||||
else
|
||||
{
|
||||
logLine.AddText(line);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Render PDF
|
||||
PdfDocumentRenderer renderer = new()
|
||||
{
|
||||
Document = document
|
||||
};
|
||||
renderer.RenderDocument();
|
||||
renderer.PdfDocument.Options.Layout = PdfWriterLayout.Compact;
|
||||
|
||||
// Construct save path
|
||||
string fullPath = TestRecordDir + CamSoak.Model + $"\\SoakTestReport_{CamSoak.Model}_{CamSoak.Serial}_{pcTime:dd-MM-yyyy_HH-mm-ss}" + (CamSoak.RMANum != 0 ? $" RMA{CamSoak.RMANum}" : "") + ".pdf";
|
||||
|
||||
renderer.PdfDocument.Save(fullPath);
|
||||
Logging.LogMessage("Soak Test PDF saved to " + fullPath);
|
||||
return fullPath;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Show a message box to inform the user that PDF creation failed, displaying the exception message.
|
||||
MainForm.Instance.AddToActionsList($"Failed to create PDF:\n{ex.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static string ExtractLogMessageContent(string line)
|
||||
{
|
||||
int tagEnd = line.IndexOf("] ");
|
||||
if (tagEnd != -1)
|
||||
{
|
||||
return line[(tagEnd + 2)..].Trim();
|
||||
}
|
||||
return line.Trim();
|
||||
}
|
||||
|
||||
public static bool LinkPDFs(string pdf1Path, string pdf2Path, string outputPath)
|
||||
{
|
||||
bool hasError = false;
|
||||
|
||||
if (!File.Exists(pdf1Path))
|
||||
{
|
||||
MainForm.Instance.AddToActionsList($"{pdf1Path} does not exist.");
|
||||
hasError = true;
|
||||
}
|
||||
|
||||
if (!File.Exists(pdf2Path))
|
||||
{
|
||||
MainForm.Instance.AddToActionsList($"{pdf2Path} does not exist.");
|
||||
hasError = true;
|
||||
}
|
||||
|
||||
if (hasError)
|
||||
return false;
|
||||
|
||||
using PdfDocument outputDocument = new(); // Create a new PDF document
|
||||
AppendPdf(outputDocument, pdf1Path);
|
||||
AppendPdf(outputDocument, pdf2Path);
|
||||
outputDocument.Save(outputPath); // Save the output document
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void AppendPdf(PdfDocument target, string sourcePath)
|
||||
{
|
||||
using PdfDocument inputDocument = PdfReader.Open(sourcePath, PdfDocumentOpenMode.Import);
|
||||
|
||||
for (int idx = 0; idx < inputDocument.PageCount; idx++) // Iterate through all pages and add them to the output
|
||||
{
|
||||
PdfPage page = inputDocument.Pages[idx];
|
||||
target.AddPage(page);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user