TableExamples.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Diagnostics;
  5. using System.Drawing;
  6. using System.Globalization;
  7. using System.Linq;
  8. using NUnit.Framework;
  9. using QuestPDF.Drawing;
  10. using QuestPDF.Examples.Engine;
  11. using QuestPDF.Fluent;
  12. using QuestPDF.Helpers;
  13. using QuestPDF.Infrastructure;
  14. using Color = QuestPDF.Infrastructure.Color;
  15. using IContainer = QuestPDF.Infrastructure.IContainer;
  16. namespace QuestPDF.Examples
  17. {
  18. public class TableExamples
  19. {
  20. [Test]
  21. public void BasicPlacement()
  22. {
  23. RenderingTest
  24. .Create()
  25. .ProduceImages()
  26. .PageSize(220, 220)
  27. .ShowResults()
  28. .Render(container =>
  29. {
  30. container
  31. .Padding(10)
  32. .MinimalBox()
  33. .Border(1)
  34. .Table(table =>
  35. {
  36. table.ColumnsDefinition(columns =>
  37. {
  38. columns.RelativeColumn();
  39. columns.RelativeColumn();
  40. columns.RelativeColumn();
  41. columns.RelativeColumn();
  42. });
  43. // by using custom 'Element' method, we can reuse visual configuration
  44. table.Cell().Row(1).Column(4).Element(Block).Text("A");
  45. table.Cell().Row(2).Column(2).Element(Block).Text("B");
  46. table.Cell().Row(3).Column(3).Element(Block).Text("C");
  47. table.Cell().Row(4).Column(1).Element(Block).Text("D");
  48. });
  49. });
  50. }
  51. [Test]
  52. public void PagingSupport()
  53. {
  54. RenderingTest
  55. .Create()
  56. .ProducePdf()
  57. .PageSize(420, 220)
  58. .ShowResults()
  59. .Render(container =>
  60. {
  61. container
  62. .Padding(10)
  63. .MinimalBox()
  64. .Border(1)
  65. .Table(table =>
  66. {
  67. table.ColumnsDefinition(columns =>
  68. {
  69. columns.RelativeColumn();
  70. columns.RelativeColumn();
  71. columns.RelativeColumn();
  72. columns.RelativeColumn();
  73. });
  74. // by using custom 'Element' method, we can reuse visual configuration
  75. table.Cell().Element(Block).Text(Placeholders.Label());
  76. table.Cell().Element(Block).Text(Placeholders.Label());
  77. table.Cell().Element(Block).Text(Placeholders.Paragraph());
  78. table.Cell().Element(Block).Text(Placeholders.Label());
  79. });
  80. });
  81. }
  82. [Test]
  83. public void DefaultCellStyle()
  84. {
  85. RenderingTest
  86. .Create()
  87. .ProduceImages()
  88. .PageSize(220, 120)
  89. .ShowResults()
  90. .Render(container =>
  91. {
  92. container
  93. .Padding(10)
  94. .MinimalBox()
  95. .Border(1)
  96. .DefaultTextStyle(TextStyle.Default.Size(16))
  97. .Table(table =>
  98. {
  99. table.ColumnsDefinition(columns =>
  100. {
  101. columns.RelativeColumn();
  102. columns.RelativeColumn();
  103. columns.RelativeColumn();
  104. columns.RelativeColumn();
  105. });
  106. table.Cell().Row(1).Column(1).Element(Block).Text("A");
  107. table.Cell().Row(2).Column(2).Element(Block).Text("B");
  108. table.Cell().Row(1).Column(3).Element(Block).Text("C");
  109. table.Cell().Row(2).Column(4).Element(Block).Text("D");
  110. });
  111. });
  112. }
  113. [Test]
  114. public void ColumnsDefinition()
  115. {
  116. RenderingTest
  117. .Create()
  118. .ProduceImages()
  119. .PageSize(320, 80)
  120. .ShowResults()
  121. .Render(container =>
  122. {
  123. container
  124. .Padding(10)
  125. .Table(table =>
  126. {
  127. table.ColumnsDefinition(columns =>
  128. {
  129. columns.ConstantColumn(50);
  130. columns.ConstantColumn(100);
  131. columns.RelativeColumn(2);
  132. columns.RelativeColumn(3);
  133. });
  134. table.Cell().ColumnSpan(4).LabelCell("Total width: 300px");
  135. table.Cell().ValueCell("50px");
  136. table.Cell().ValueCell("100px");
  137. table.Cell().ValueCell("100px");
  138. table.Cell().ValueCell("150px");
  139. });
  140. });
  141. }
  142. [Test]
  143. public void PartialAutoPlacement()
  144. {
  145. RenderingTest
  146. .Create()
  147. .ProduceImages()
  148. .PageSize(220, 220)
  149. .ShowResults()
  150. .Render(container =>
  151. {
  152. container
  153. .Padding(10)
  154. .MinimalBox()
  155. .Border(1)
  156. .Table(table =>
  157. {
  158. table.ColumnsDefinition(columns =>
  159. {
  160. columns.RelativeColumn();
  161. columns.RelativeColumn();
  162. columns.RelativeColumn();
  163. columns.RelativeColumn();
  164. });
  165. table.Cell().Element(Block).Text("A");
  166. table.Cell().Row(2).Column(2).Element(Block).Text("B");
  167. table.Cell().Element(Block).Text("C");
  168. table.Cell().Row(3).Column(3).Element(Block).Text("D");
  169. table.Cell().ColumnSpan(2).Element(Block).Text("E");
  170. });
  171. });
  172. }
  173. [Test]
  174. public void ExtendLastCellsToTableBottom()
  175. {
  176. RenderingTest
  177. .Create()
  178. .ProduceImages()
  179. .PageSize(220, 170)
  180. .ShowResults()
  181. .Render(container =>
  182. {
  183. container
  184. .Padding(10)
  185. .MinimalBox()
  186. .Border(1)
  187. .Table(table =>
  188. {
  189. table.ColumnsDefinition(columns =>
  190. {
  191. columns.RelativeColumn();
  192. columns.RelativeColumn();
  193. columns.RelativeColumn();
  194. columns.RelativeColumn();
  195. });
  196. table.ExtendLastCellsToTableBottom();
  197. table.Cell().Row(1).Column(1).Element(Block).Text("A");
  198. table.Cell().Row(3).Column(1).Element(Block).Text("B");
  199. table.Cell().Row(2).Column(2).Element(Block).Text("C");
  200. table.Cell().Row(3).Column(3).Element(Block).Text("D");
  201. table.Cell().Row(2).RowSpan(2).Column(4).Element(Block).Text("E");
  202. });
  203. });
  204. }
  205. [Test]
  206. public void Overlapping()
  207. {
  208. RenderingTest
  209. .Create()
  210. .ProduceImages()
  211. .PageSize(170, 170)
  212. .ShowResults()
  213. .Render(container =>
  214. {
  215. container
  216. .Padding(10)
  217. .MinimalBox()
  218. .Border(1)
  219. .Table(table =>
  220. {
  221. table.ColumnsDefinition(columns =>
  222. {
  223. columns.RelativeColumn();
  224. columns.RelativeColumn();
  225. columns.RelativeColumn();
  226. });
  227. table.Cell().Row(1).RowSpan(3).Column(1).ColumnSpan(3).Background(Colors.Grey.Lighten3).MinHeight(150);
  228. table.Cell().Row(1).RowSpan(2).Column(1).ColumnSpan(2).Background(Colors.Grey.Lighten1).MinHeight(100);
  229. table.Cell().Row(3).Column(3).Background(Colors.Grey.Darken1).MinHeight(50);
  230. });
  231. });
  232. }
  233. [Test]
  234. public void Spans()
  235. {
  236. RenderingTest
  237. .Create()
  238. .ProduceImages()
  239. .PageSize(220, 170)
  240. .ShowResults()
  241. .Render(container =>
  242. {
  243. container
  244. .Padding(10)
  245. .Table(table =>
  246. {
  247. table.ColumnsDefinition(columns =>
  248. {
  249. columns.RelativeColumn();
  250. columns.RelativeColumn();
  251. columns.RelativeColumn();
  252. columns.RelativeColumn();
  253. });
  254. table.Cell().RowSpan(2).ColumnSpan(2).Element(Block).Text("1");
  255. table.Cell().ColumnSpan(2).Element(Block).Text("2");
  256. table.Cell().Element(Block).Text("3");
  257. table.Cell().Element(Block).Text("4");
  258. table.Cell().RowSpan(2).Element(Block).Text("5");
  259. table.Cell().ColumnSpan(2).Element(Block).Text("6");
  260. table.Cell().RowSpan(2).Element(Block).Text("7");
  261. table.Cell().Element(Block).Text("8");
  262. table.Cell().Element(Block).Text("9");
  263. });
  264. });
  265. }
  266. [Test]
  267. public void Stability()
  268. {
  269. RenderingTest
  270. .Create()
  271. .ProduceImages()
  272. .PageSize(300, 300)
  273. .ShowResults()
  274. .Render(container =>
  275. {
  276. container
  277. .Padding(10)
  278. .Table(table =>
  279. {
  280. table.ColumnsDefinition(columns =>
  281. {
  282. columns.RelativeColumn();
  283. columns.RelativeColumn();
  284. columns.RelativeColumn();
  285. columns.RelativeColumn();
  286. columns.RelativeColumn();
  287. columns.RelativeColumn();
  288. });
  289. var image = Placeholders.Image(400, 300);
  290. table.Cell().Image(image);
  291. table.Cell().Image(image);
  292. table.Cell().Image(image);
  293. table.Cell().Image(image);
  294. table.Cell().Image(image);
  295. table.Cell().Image(image);
  296. });
  297. });
  298. }
  299. [Test]
  300. public void Bug_RowSpanWorksIncorrectly()
  301. {
  302. // https://github.com/QuestPDF/QuestPDF/issues/552
  303. RenderingTest
  304. .Create()
  305. .ProduceImages()
  306. .PageSize(PageSizes.A5.Landscape())
  307. .ShowResults()
  308. .Render(container =>
  309. {
  310. container.Padding(20).Table(table =>
  311. {
  312. table.ColumnsDefinition(columns =>
  313. {
  314. columns.RelativeColumn(1);
  315. columns.RelativeColumn(2);
  316. columns.RelativeColumn(2);
  317. columns.RelativeColumn(2);
  318. });
  319. foreach (var i in Enumerable.Range(6, 9))
  320. {
  321. table.Cell().Element(CellStyleMainTable).Text($"{i:00}:00");
  322. foreach (var j in Enumerable.Range(1, 3))
  323. table.Cell().Element(CellStyleMainTable).Text("");
  324. }
  325. static IContainer CellStyleMainTable(IContainer container)
  326. {
  327. return container
  328. .Border(0.5f).BorderColor(Colors.Blue.Lighten4)
  329. .Background(Colors.Blue.Lighten5)
  330. .PaddingVertical(5);
  331. }
  332. table.Cell().Row(1).RowSpan(3).Column(2).Element(BlockAccepted).Text("3 rows");
  333. table.Cell().Row(1).RowSpan(6).Column(3).Element(BlockAccepted).Text("6 rows");
  334. table.Cell().Row(3).RowSpan(5).Column(4).Element(BlockAccepted).Text("5 rows");
  335. static IContainer BlockAccepted(IContainer container)
  336. {
  337. return container
  338. .Border(1.5f).BorderColor(Colors.Green.Lighten2)
  339. .Background(Colors.Green.Lighten4);
  340. }
  341. });
  342. });
  343. }
  344. [Test]
  345. public void TableHeader()
  346. {
  347. RenderingTest
  348. .Create()
  349. .ProduceImages()
  350. .PageSize(500, 200)
  351. .ShowResults()
  352. .EnableDebugging()
  353. .Render(container =>
  354. {
  355. var pageSizes = new List<(string name, double width, double height)>()
  356. {
  357. ("Letter (ANSI A)", 8.5f, 11),
  358. ("Legal", 8.5f, 14),
  359. ("Ledger (ANSI B)", 11, 17),
  360. ("Tabloid (ANSI B)", 17, 11),
  361. ("ANSI C", 22, 17),
  362. ("ANSI D", 34, 22),
  363. ("ANSI E", 44, 34)
  364. };
  365. const int inchesToPoints = 72;
  366. container
  367. .Padding(10)
  368. .MinimalBox()
  369. .Border(1)
  370. .Table(table =>
  371. {
  372. IContainer DefaultCellStyle(IContainer container, Color backgroundColor)
  373. {
  374. return container
  375. .Border(1)
  376. .BorderColor(Colors.Grey.Lighten1)
  377. .Background(backgroundColor)
  378. .PaddingVertical(5)
  379. .PaddingHorizontal(10)
  380. .AlignCenter()
  381. .AlignMiddle();
  382. }
  383. table.ColumnsDefinition(columns =>
  384. {
  385. columns.RelativeColumn();
  386. columns.ConstantColumn(75);
  387. columns.ConstantColumn(75);
  388. columns.ConstantColumn(75);
  389. columns.ConstantColumn(75);
  390. });
  391. table.Header(header =>
  392. {
  393. header.Cell().RowSpan(2).Element(CellStyle).ExtendHorizontal().AlignLeft().Text("Document type");
  394. header.Cell().ColumnSpan(2).Element(CellStyle).Text("Inches");
  395. header.Cell().ColumnSpan(2).Element(CellStyle).Text("Points");
  396. header.Cell().Element(CellStyle).Text("Width");
  397. header.Cell().Element(CellStyle).Text("Height");
  398. header.Cell().Element(CellStyle).Text("Width");
  399. header.Cell().Element(CellStyle).Text("Height");
  400. // you can extend already existing styles by creating additional methods
  401. IContainer CellStyle(IContainer container) => DefaultCellStyle(container, Colors.Grey.Lighten3);
  402. });
  403. foreach (var page in pageSizes)
  404. {
  405. table.Cell().Element(CellStyle).ExtendHorizontal().AlignLeft().Text(page.name);
  406. // inches
  407. table.Cell().Element(CellStyle).Text(page.width.ToString(CultureInfo.InvariantCulture));
  408. table.Cell().Element(CellStyle).Text(page.height.ToString(CultureInfo.InvariantCulture));
  409. // points
  410. table.Cell().Element(CellStyle).Text((page.width * inchesToPoints).ToString(CultureInfo.InvariantCulture));
  411. table.Cell().Element(CellStyle).Text((page.height * inchesToPoints).ToString(CultureInfo.InvariantCulture));
  412. IContainer CellStyle(IContainer container) => DefaultCellStyle(container, Colors.White);
  413. }
  414. });
  415. });
  416. }
  417. [Test]
  418. public void PerformanceText_TemperatureReport()
  419. {
  420. RenderingTest
  421. .Create()
  422. .ProducePdf()
  423. .PageSize(PageSizes.A4)
  424. .MaxPages(10_000)
  425. .EnableCaching()
  426. .EnableDebugging(false)
  427. .ShowResults()
  428. .Render(container => GeneratePerformanceStructure(container, 250));
  429. }
  430. public static void GeneratePerformanceStructure(IContainer container, int repeats)
  431. {
  432. container
  433. .Padding(25)
  434. //.Background(Colors.Blue.Lighten2)
  435. .MinimalBox()
  436. .Border(1)
  437. //.Background(Colors.Red.Lighten2)
  438. .Table(table =>
  439. {
  440. table.ColumnsDefinition(columns =>
  441. {
  442. columns.ConstantColumn(100);
  443. columns.RelativeColumn();
  444. columns.ConstantColumn(100);
  445. columns.RelativeColumn();
  446. });
  447. table.ExtendLastCellsToTableBottom();
  448. foreach (var i in Enumerable.Range(0, repeats))
  449. {
  450. table.Cell().RowSpan(3).LabelCell("Project");
  451. table.Cell().RowSpan(3).ShowEntire().ValueCell(Placeholders.Sentence());
  452. table.Cell().LabelCell("Report number");
  453. table.Cell().ValueCell(i.ToString());
  454. table.Cell().LabelCell("Date");
  455. table.Cell().ValueCell(Placeholders.ShortDate());
  456. table.Cell().LabelCell("Inspector");
  457. table.Cell().ValueCell("Marcin Ziąbek");
  458. table.Cell().ColumnSpan(2).LabelCell("Morning weather");
  459. table.Cell().ColumnSpan(2).LabelCell("Evening weather");
  460. table.Cell().ValueCell("Time");
  461. table.Cell().ValueCell("7:13");
  462. table.Cell().ValueCell("Time");
  463. table.Cell().ValueCell("18:25");
  464. table.Cell().ValueCell("Description");
  465. table.Cell().ValueCell("Sunny");
  466. table.Cell().ValueCell("Description");
  467. table.Cell().ValueCell("Windy");
  468. table.Cell().ValueCell("Wind");
  469. table.Cell().ValueCell("Mild");
  470. table.Cell().ValueCell("Wind");
  471. table.Cell().ValueCell("Strong");
  472. table.Cell().ValueCell("Temperature");
  473. table.Cell().ValueCell("17°C");
  474. table.Cell().ValueCell("Temperature");
  475. table.Cell().ValueCell("32°C");
  476. table.Cell().LabelCell("Remarks");
  477. table.Cell().ColumnSpan(3).ValueCell(Placeholders.Paragraph());
  478. }
  479. });
  480. }
  481. // this method uses a higher order function to define a custom and dynamic style
  482. static IContainer Block(IContainer container)
  483. {
  484. return container
  485. .Border(1)
  486. .Background(Colors.Grey.Lighten3)
  487. .ShowOnce()
  488. .MinWidth(50)
  489. .MinHeight(50)
  490. .Padding(10)
  491. .AlignCenter()
  492. .AlignMiddle();
  493. }
  494. }
  495. }