TableExamples.cs 22 KB

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