-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPdfMaker.cs
204 lines (174 loc) · 6.58 KB
/
PdfMaker.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
using DinkToPdf;
using DinkToPdf.Contracts;
using PdfSharpCore.Pdf.IO;
using System.Text;
namespace HTPDF;
public class PdfMaker : IPdfMaker
{
private readonly IConverter _converter;
public PdfMaker(IConverter converter)
{
_converter = converter;
}
/// <inheritdoc />
public byte[] CreatePDF()
{
List<dynamic> data = GetData();
string htmlTable = GenerateTable(data);
var document = GetObjectSettings(htmlTable);
return _converter.Convert(document);
}
/// <inheritdoc />
public byte[] CreateChunkedPDF()
{
var data = GetData();
var pdfChunks = PaginateAndConvertPDF(data, 5);
using MemoryStream finalPdfStream = JoinChunkedPDF(pdfChunks);
return finalPdfStream.ToArray();
}
/// <summary>
/// Retrieves the data to be used in the PDF.
/// </summary>
/// <returns>A list of dynamic objects containing the data.</returns>
private static List<dynamic> GetData()
{
return
[
new { Info = "Student 1", Math = 85, Science = 90, English = 88, History = 76, Geography = 89 },
new { Info = "Student 2", Math = 78, Science = 92, English = 85, History = 80, Geography = 91 },
new { Info = "Student 3", Math = 82, Science = 88, English = 79, History = 84, Geography = 87 },
new { Info = "Student 3", Math = 82, Science = 88, English = 79, History = 84, Geography = 87 },
new { Info = "Student 3", Math = 82, Science = 88, English = 79, History = 84, Geography = 87 },
new { Info = "Student 3", Math = 82, Science = 88, English = 79, History = 84, Geography = 87 },
new { Info = "Student 3", Math = 82, Science = 88, English = 79, History = 84, Geography = 87 },
new { Info = "Student 3", Math = 82, Science = 88, English = 79, History = 84, Geography = 87 },
];
}
/// <summary>
/// Generates an HTML table from the provided data.
/// </summary>
/// <param name="data">The data to be included in the table.</param>
/// <returns>A string containing the HTML table.</returns>
private static string GenerateTable(List<dynamic> data)
{
StringBuilder html = new();
// Start the table
html.Append(@"
<table border='1' cellspacing='0' cellpadding='5'>
<thead>
<tr>
<th rowspan='2'>General Info</th>
<th colspan='2'>Performance</th>
<th colspan='3'>Scores</th>
</tr>
<tr>
<th>Math</th>
<th>Science</th>
<th>English</th>
<th>History</th>
<th>Geography</th>
</tr>
</thead>
<tbody>");
// Loop through the data to create rows
foreach (var row in data)
{
html.Append($@"
<tr>
<td>{row.Info}</td>
<td>{row.Math}</td>
<td>{row.Science}</td>
<td>{row.English}</td>
<td>{row.History}</td>
<td>{row.Geography}</td>
</tr>");
}
// End the table
html.Append(@"
</tbody>
</table>");
return html.ToString();
}
/// <summary>
/// Joins multiple PDF chunks into a single PDF document.
/// </summary>
/// <param name="pdfChunks">The list of PDF chunks to be joined.</param>
/// <returns>A MemoryStream containing the final PDF document.</returns>
private static MemoryStream JoinChunkedPDF(List<byte[]> pdfChunks)
{
var finalPdfStream = new MemoryStream();
using (var finalPdfDocument = new PdfSharpCore.Pdf.PdfDocument())
{
foreach (var chunkChunk in pdfChunks)
{
using var tempDocument = PdfReader.Open(new MemoryStream(chunkChunk), PdfDocumentOpenMode.Import);
foreach (var page in tempDocument.Pages)
{
finalPdfDocument.AddPage(page);
}
}
finalPdfDocument.Save(finalPdfStream, false);
}
return finalPdfStream;
}
/// <summary>
/// Paginates the data and converts each page to a PDF chunk.
/// </summary>
/// <param name="data">The data to be paginated and converted.</param>
/// <param name="rowsPerPage">The number of rows per page.</param>
/// <returns>A list of byte arrays representing the PDF chunks.</returns>
/// <exception cref="ArgumentException">Thrown when rowsPerPage is less than or equal to zero.</exception>
private List<byte[]> PaginateAndConvertPDF(List<dynamic> data, int rowsPerPage)
{
if (rowsPerPage <= 0)
{
throw new ArgumentException("Rows per page must be greater than zero.", nameof(rowsPerPage));
}
var pdfChunks = new List<byte[]>();
int totalRows = data.Count;
int totalPageCount = (int)Math.Ceiling((double)totalRows / rowsPerPage);
for (int currentPage = 0; currentPage < totalPageCount; currentPage++)
{
var pageData = data.Skip(currentPage * rowsPerPage).Take(rowsPerPage).ToList();
var htmlContent = GenerateTable(pageData);
if (string.IsNullOrWhiteSpace(htmlContent))
{
break;
}
var document = GetObjectSettings(htmlContent);
var bytes = _converter.Convert(document);
pdfChunks.Add(bytes);
}
return pdfChunks;
}
/// <summary>
/// Creates the settings for the HTML to PDF conversion.
/// </summary>
/// <param name="htmlContent">The HTML content to be converted.</param>
/// <returns>An HtmlToPdfDocument object containing the settings.</returns>
private static HtmlToPdfDocument GetObjectSettings(string htmlContent)
{
var globalSettings = new GlobalSettings
{
ColorMode = ColorMode.Color,
Orientation = Orientation.Portrait,
PaperSize = PaperKind.A4,
Margins = new MarginSettings { Top = 10, Bottom = 10, Left = 10, Right = 10 },
DocumentTitle = "TABLE",
};
var objectSettings = new ObjectSettings
{
HtmlContent = htmlContent,
WebSettings =
{
DefaultEncoding = "utf-8",
}
};
var document = new HtmlToPdfDocument()
{
GlobalSettings = globalSettings,
Objects = { objectSettings }
};
return document;
}
}