TableExamples.cs 22 KB

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