TableExamples.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. using QuestPDF.Fluent;
  2. using QuestPDF.Helpers;
  3. using QuestPDF.Infrastructure;
  4. namespace QuestPDF.DocumentationExamples;
  5. public class TableExamples
  6. {
  7. [Test]
  8. public void Basic()
  9. {
  10. Document
  11. .Create(document =>
  12. {
  13. document.Page(page =>
  14. {
  15. page.MinSize(new PageSize(0, 0));
  16. page.MaxSize(new PageSize(500, 1000));
  17. page.DefaultTextStyle(x => x.FontSize(20));
  18. page.Margin(25);
  19. page.Content()
  20. .Table(table =>
  21. {
  22. table.ColumnsDefinition(columns =>
  23. {
  24. columns.ConstantColumn(50);
  25. columns.RelativeColumn();
  26. columns.ConstantColumn(125);
  27. });
  28. table.Header(header =>
  29. {
  30. header.Cell().BorderBottom(2).Padding(8).Text("#");
  31. header.Cell().BorderBottom(2).Padding(8).Text("Product");
  32. header.Cell().BorderBottom(2).Padding(8).AlignRight().Text("Price");
  33. });
  34. foreach (var i in Enumerable.Range(0, 6))
  35. {
  36. var price = Math.Round(Random.Shared.NextDouble() * 100, 2);
  37. table.Cell().Padding(8).Text($"{i + 1}");
  38. table.Cell().Padding(8).Text(Placeholders.Label());
  39. table.Cell().Padding(8).AlignRight().Text($"${price}");
  40. }
  41. });
  42. });
  43. })
  44. .GenerateImages(x => "table-simple.webp", new ImageGenerationSettings() { ImageFormat = ImageFormat.Webp, ImageCompressionQuality = ImageCompressionQuality.VeryHigh, RasterDpi = 144 });
  45. }
  46. [Test]
  47. public void CellStyleExample()
  48. {
  49. Document
  50. .Create(document =>
  51. {
  52. document.Page(page =>
  53. {
  54. page.MinSize(new PageSize(0, 0));
  55. page.MaxSize(new PageSize(500, 1000));
  56. page.DefaultTextStyle(x => x.FontSize(20));
  57. page.Margin(25);
  58. string[] weatherIcons = ["cloudy.svg", "lightning.svg", "pouring.svg", "rainy.svg", "snowy.svg", "windy.svg"];
  59. page.Content()
  60. .Table(table =>
  61. {
  62. table.ColumnsDefinition(columns =>
  63. {
  64. columns.RelativeColumn();
  65. columns.ConstantColumn(125);
  66. columns.ConstantColumn(125);
  67. });
  68. table.Header(header =>
  69. {
  70. header.Cell().Element(CellStyle).Text("Day");
  71. header.Cell().Element(CellStyle).AlignCenter().Text("Weather");
  72. header.Cell().Element(CellStyle).AlignRight().Text("Temp");
  73. static IContainer CellStyle(IContainer container)
  74. {
  75. return container
  76. .Background(Colors.Blue.Darken2)
  77. .DefaultTextStyle(x => x.FontColor(Colors.White).Bold())
  78. .PaddingVertical(8)
  79. .PaddingHorizontal(16);
  80. }
  81. });
  82. foreach (var i in Enumerable.Range(0, 7))
  83. {
  84. var weatherIndex = Random.Shared.Next(0, weatherIcons.Length);
  85. table.Cell().Element(CellStyle)
  86. .Text(new DateTime(2025, 2, 26).AddDays(i).ToString("dd MMMM"));
  87. table.Cell().Element(CellStyle).AlignCenter().Height(24)
  88. .Svg($"Resources/WeatherIcons/{weatherIcons[weatherIndex]}");
  89. table.Cell().Element(CellStyle).AlignRight()
  90. .Text($"{Random.Shared.Next(-10, 35)}°");
  91. IContainer CellStyle(IContainer container)
  92. {
  93. var backgroundColor = i % 2 == 0
  94. ? Colors.Blue.Lighten5
  95. : Colors.Blue.Lighten4;
  96. return container
  97. .Background(backgroundColor)
  98. .PaddingVertical(8)
  99. .PaddingHorizontal(16);
  100. }
  101. }
  102. });
  103. });
  104. })
  105. .GenerateImages(x => "table-cell-style.webp", new ImageGenerationSettings() { ImageFormat = ImageFormat.Webp, ImageCompressionQuality = ImageCompressionQuality.VeryHigh, RasterDpi = 144 });
  106. }
  107. [Test]
  108. public void OverlappingCells()
  109. {
  110. Document
  111. .Create(document =>
  112. {
  113. document.Page(page =>
  114. {
  115. page.MinSize(new PageSize(0, 0));
  116. page.MaxSize(new PageSize(700, 1000));
  117. page.DefaultTextStyle(x => x.FontSize(16));
  118. page.Margin(25);
  119. string[] dayNames = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"];
  120. page.Content()
  121. .Border(1)
  122. .BorderColor(Colors.Grey.Lighten1)
  123. .Table(table =>
  124. {
  125. table.ColumnsDefinition(columns =>
  126. {
  127. // hour column
  128. columns.ConstantColumn(60);
  129. // day columns
  130. foreach (var i in Enumerable.Range(0, 5))
  131. columns.RelativeColumn();
  132. });
  133. // even/odd columns background
  134. foreach (var column in Enumerable.Range(0, 7))
  135. {
  136. var backgroundColor = column % 2 == 0 ? Colors.Grey.Lighten3 : Colors.White;
  137. table.Cell().Column((uint)column).RowSpan(24).Background(backgroundColor);
  138. }
  139. // hours and hour lines
  140. foreach (var hour in Enumerable.Range(6, 10))
  141. {
  142. table.Cell().Column(1).Row((uint)hour)
  143. .PaddingVertical(5).PaddingHorizontal(10).AlignRight()
  144. .Text($"{hour}");
  145. table.Cell().Row((uint)hour).ColumnSpan(6)
  146. .Border(1).BorderColor(Colors.Grey.Lighten1).Height(20);
  147. }
  148. // dates and day names
  149. foreach (var i in Enumerable.Range(0, 5))
  150. {
  151. table.Cell()
  152. .Column((uint) i + 2).Row(1).Padding(5)
  153. .Column(column =>
  154. {
  155. column.Item().AlignCenter().Text($"{17 + i}").FontSize(24).Bold();
  156. column.Item().AlignCenter().Text(dayNames[i]).Light();
  157. });
  158. }
  159. // standup events
  160. foreach (var i in Enumerable.Range(1, 4))
  161. AddEvent((uint)i, 8, 1, "Standup", Colors.Blue.Lighten4, Colors.Blue.Darken3);
  162. // other events
  163. AddEvent(2, 11, 2, "Interview", Colors.Red.Lighten4, Colors.Red.Darken3);
  164. AddEvent(3, 12, 3, "Demo", Colors.Red.Lighten4, Colors.Red.Darken3);
  165. AddEvent(5, 5, 17, "PTO", Colors.Green.Lighten4, Colors.Green.Darken3);
  166. void AddEvent(uint day, uint hour, uint length, string name, Color backgroundColor, Color textColor)
  167. {
  168. table.Cell()
  169. .Column(day + 1).Row(hour).RowSpan(length)
  170. .Padding(5).Background(backgroundColor).Padding(5)
  171. .AlignCenter().AlignMiddle()
  172. .Text(name).FontColor(textColor);
  173. }
  174. });
  175. });
  176. })
  177. .GenerateImages(x => "table-overlapping-cells.webp", new ImageGenerationSettings() { ImageFormat = ImageFormat.Webp, ImageCompressionQuality = ImageCompressionQuality.VeryHigh, RasterDpi = 144 });
  178. }
  179. [Test]
  180. public void ManualCellPlacement()
  181. {
  182. Document
  183. .Create(document =>
  184. {
  185. document.Page(page =>
  186. {
  187. page.MinSize(new PageSize(0, 0));
  188. page.MaxSize(new PageSize(700, 1000));
  189. page.DefaultTextStyle(x => x.FontSize(16 ));
  190. page.Margin(25);
  191. page.Content()
  192. .Table(table =>
  193. {
  194. table.ColumnsDefinition(columns =>
  195. {
  196. columns.ConstantColumn(75);
  197. columns.ConstantColumn(150);
  198. columns.ConstantColumn(200);
  199. columns.ConstantColumn(200);
  200. });
  201. table.Cell().Row(1).Column(3).ColumnSpan(2)
  202. .Element(HeaderCellStyle)
  203. .Text("Predicted condition").Bold();
  204. table.Cell().Row(3).Column(1).RowSpan(2)
  205. .Element(HeaderCellStyle).RotateLeft()
  206. .Text("Actual\ncondition").Bold().AlignCenter();
  207. table.Cell().Row(2).Column(3)
  208. .Element(HeaderCellStyle)
  209. .Text("Positive (PP)");
  210. table.Cell().Row(2).Column(4)
  211. .Element(HeaderCellStyle)
  212. .Text("Negative (PN)");
  213. table.Cell().Row(3).Column(2)
  214. .Element(HeaderCellStyle).Text("Positive (P)");
  215. table.Cell().Row(4).Column(2)
  216. .Element(HeaderCellStyle)
  217. .Text("Negative (N)");
  218. table.Cell()
  219. .Row(3).Column(3).Element(GoodCellStyle)
  220. .Text("True positive (TP)");
  221. table.Cell()
  222. .Row(3).Column(4).Element(BadCellStyle)
  223. .Text("False negative (FN)");
  224. table.Cell().Row(4).Column(3)
  225. .Element(BadCellStyle).Text("False positive (FP)");
  226. table.Cell().Row(4).Column(4)
  227. .Element(GoodCellStyle).Text("True negative (TN)");
  228. static IContainer CellStyle(IContainer container, Color color)
  229. => container.Border(1).Background(color).PaddingHorizontal(10).PaddingVertical(15).AlignCenter().AlignMiddle();
  230. static IContainer HeaderCellStyle(IContainer container)
  231. => CellStyle(container, Colors.Grey.Lighten4 );
  232. static IContainer GoodCellStyle(IContainer container)
  233. => CellStyle(container, Colors.Green.Lighten4).DefaultTextStyle(x => x.FontColor(Colors.Green.Darken2));
  234. static IContainer BadCellStyle(IContainer container)
  235. => CellStyle(container, Colors.Red.Lighten4).DefaultTextStyle(x => x.FontColor(Colors.Red.Darken2));
  236. });
  237. });
  238. })
  239. .GenerateImages(x => "table-manual-cell-placement.webp", new ImageGenerationSettings() { ImageFormat = ImageFormat.Webp, ImageCompressionQuality = ImageCompressionQuality.VeryHigh, RasterDpi = 144 });
  240. }
  241. [Test]
  242. public void ColumnsDefinition()
  243. {
  244. Document
  245. .Create(document =>
  246. {
  247. document.Page(page =>
  248. {
  249. page.MinSize(new PageSize(0, 0));
  250. page.MaxSize(new PageSize(700, 1000));
  251. page.DefaultTextStyle(x => x.FontSize(16));
  252. page.Margin(25);
  253. page.Content()
  254. .Width(450)
  255. .Table(table =>
  256. {
  257. table.ColumnsDefinition(columns =>
  258. {
  259. columns.ConstantColumn(150);
  260. columns.RelativeColumn(2);
  261. columns.RelativeColumn(3);
  262. });
  263. table.Cell().ColumnSpan(3)
  264. .Background(Colors.Grey.Lighten2).Element(CellStyle)
  265. .Text("Total width: 450px");
  266. table.Cell().Element(CellStyle).Text("Constant: 150px");
  267. table.Cell().Element(CellStyle).Text("Relative: 2*");
  268. table.Cell().Element(CellStyle).Text("Relative: 3*");
  269. table.Cell().Element(CellStyle).Text("150px");
  270. table.Cell().Element(CellStyle).Text("120px");
  271. table.Cell().Element(CellStyle).Text("180px");
  272. static IContainer CellStyle(IContainer container)
  273. => container.Border(1).Padding(10);
  274. });
  275. });
  276. })
  277. .GenerateImages(x => "table-columns-definition.webp", new ImageGenerationSettings() { ImageFormat = ImageFormat.Webp, ImageCompressionQuality = ImageCompressionQuality.VeryHigh, RasterDpi = 144 });
  278. }
  279. [Test]
  280. public void HeaderAndFooter()
  281. {
  282. Document
  283. .Create(document =>
  284. {
  285. document.Page(page =>
  286. {
  287. page.MinSize(new PageSize(0, 0));
  288. page.MaxSize(new PageSize(600, 250));
  289. page.DefaultTextStyle(x => x.FontSize(16));
  290. page.Margin(25);
  291. page.Content()
  292. .Border(1)
  293. .BorderColor(Colors.Grey.Lighten1)
  294. .Table(table =>
  295. {
  296. var pageSizes = new List<(string name, double width, double height)>()
  297. {
  298. ("Letter (ANSI A)", 8.5f, 11),
  299. ("Legal", 8.5f, 14),
  300. ("Ledger (ANSI B)", 11, 17),
  301. ("Tabloid (ANSI B)", 17, 11),
  302. ("ANSI C", 22, 17),
  303. ("ANSI D", 34, 22),
  304. ("ANSI E", 44, 34)
  305. };
  306. const int inchesToPoints = 72;
  307. IContainer DefaultCellStyle(IContainer container, string backgroundColor)
  308. {
  309. return container
  310. .Border(1)
  311. .BorderColor(Colors.Grey.Lighten1)
  312. .Background(backgroundColor)
  313. .PaddingVertical(5)
  314. .PaddingHorizontal(10)
  315. .AlignCenter()
  316. .AlignMiddle();
  317. }
  318. table.ColumnsDefinition(columns =>
  319. {
  320. columns.RelativeColumn();
  321. columns.ConstantColumn(80);
  322. columns.ConstantColumn(80);
  323. columns.ConstantColumn(80);
  324. columns.ConstantColumn(80);
  325. });
  326. table.Header(header =>
  327. {
  328. // please be sure to call the 'header' handler!
  329. header.Cell().RowSpan(2).Element(CellStyle).ExtendHorizontal().AlignLeft()
  330. .Text("Document type").Bold();
  331. header.Cell().ColumnSpan(2).Element(CellStyle).Text("Inches").Bold();
  332. header.Cell().ColumnSpan(2).Element(CellStyle).Text("Points").Bold();
  333. header.Cell().Element(CellStyle).Text("Width");
  334. header.Cell().Element(CellStyle).Text("Height");
  335. header.Cell().Element(CellStyle).Text("Width");
  336. header.Cell().Element(CellStyle).Text("Height");
  337. // you can extend existing styles by creating additional methods
  338. IContainer CellStyle(IContainer container) =>
  339. DefaultCellStyle(container, Colors.Grey.Lighten3);
  340. });
  341. foreach (var page in pageSizes)
  342. {
  343. table.Cell().Element(CellStyle).ExtendHorizontal().AlignLeft().Text(page.name);
  344. // inches
  345. table.Cell().Element(CellStyle).Text(page.width);
  346. table.Cell().Element(CellStyle).Text(page.height);
  347. // points
  348. table.Cell().Element(CellStyle).Text(page.width * inchesToPoints);
  349. table.Cell().Element(CellStyle).Text(page.height * inchesToPoints);
  350. IContainer CellStyle(IContainer container) =>
  351. DefaultCellStyle(container, Colors.White).ShowOnce();
  352. }
  353. });
  354. });
  355. })
  356. .GenerateImages(x => $"table-header-and-footer-{x}.webp", new ImageGenerationSettings() { ImageFormat = ImageFormat.Webp, ImageCompressionQuality = ImageCompressionQuality.VeryHigh, RasterDpi = 144 });
  357. }
  358. }