========================== Tables, Rows and Cells ========================== Scryber supports the use of tables with rows, cells and allows nesting, overflow, headings, footers and column-spans. It also supports the use of binding and repeating at the row and/or the cell level. .. figure:: ../images/samples_tabledatabound.png :alt: Tables bound to data. :width: 600px :class: with-shadow By default a table will consume as much width as needed, measured for the first 5 rows, but can be full width (`width:100%``). The thead and tbody are optional as in html, but help separate the content, and header rows will by default repeat across breaks. .. code:: html
Header 1 Header 2
Content 1 Content 2
Wide footer
Using the header, row and cell classes in code allows creation of tables too. .. code:: csharp //using Scryber.Components; var table = new TableGrid() { FullWidth = true }; var head = new TableHeaderRow(); var h1 = new TableHeaderCell(); h1.Contents.Add(new TextLiteral("Header 1")); head.Cells.Add(h1); var h2 = new TableHeaderCell(); h2.Contents.Add(new TextLiteral("Header 2")); head.Cells.Add(h2); table.Rows.Add(head); for(var r = 0; r < 2; r++) { var row = new TableRow(); for(var c = 0; c < 2; c++) { var cell = new TableCell(); cell.Contents.Add(new TextLiteral("Content " + c)); row.Cells.Add(cell); } table.Rows.Add(row); } var foot = new TableFooterRow(); var fd = new TableFooterCell() { CellColumnSpan = 2 }; fd.Contents.Add(new TextLiteral("Wide footer")); foot.Cells.Add(fd); table.Rows.Add(foot); Generation methods ------------------- All methods and files in these samples use the standard testing set up as outlined in :doc:`../overview/samples_reference` Simple Tables ------------- A simple table with no style or formatting will be output with a single point gray border and 4pt padding on each cell. Each column will take up as much room as needed (or possible). And the table will be be sized for the widths. .. code-block:: html Simple Tables
Cell 1.1 Wider Cell 1.2 Cell 1.3
Cell 2.1 Cell 2.2 Cell 2.3
Cell 3.1 Cell 3.2 Cell 3.3
.. code:: csharp //using Scryber.Components; //Scryber.UnitSamples/TableSamples.cs public void Table1_SimpleTable() { var path = GetTemplatePath("Tables", "TableSimple.html"); using (var doc = Document.ParseDocument(path)) { using(var stream = GetOutputStream("Tables", "TableSimple.pdf")) { doc.SaveAsPDF(stream); } } } .. figure:: ../images/samples_tables_simple.png :target: ../_images/samples_tables_simple.png :alt: Simple table. :width: 600px :class: with-shadow `Full size version <../_images/samples_tables_simple.png>`_ For speed the first 5 rows are tested for desired width, if they are not explicitly set. This allows for giving good measurement of a desired layout without having to double measure an entire table. If the 6th row on a table has a particularly large flowing content, then this will be ignored - set an explicit width on that column, or all the others. Table width and cell spans -------------------------- Applying the full-width (``width:100%``) will make the table use all available space in it's container, obeying any fixed column widths. The cells support a column-span attribute to allow multiple column content. .. code:: html Simple Tables
Cell 1.1 Wider Cell 1.2 Cell 1.3
Cell 2.1 Cell 2.2
Cell 3.1 Cell 3.2 Cell 3.3
.. code:: csharp //Scryber.UnitSamples/TableSamples.cs public void SpannedTable() { var path = GetTemplatePath("Tables", "TableSpanned.html"); using (var doc = Document.ParseDocument(path)) { using (var stream = GetOutputStream("Tables", "TableSpanned.pdf")) { doc.SaveAsPDF(stream); } } } .. figure:: ../images/samples_tables_spanned.png :target: ../_images/samples_tables_spanned.png :alt: Spanning full width tables. :width: 600px :class: with-shadow `Full size version <../_images/samples_tables_spanned.png>`_ Tables in code ---------------- Tables can be created just as easily through code. The ``table`` has a ``Rows`` property and each ``row`` has a ``Cells`` property. These properties wrap the protected ``InnerContent`` property from the ``PDFContainerComponent`` class. .. code:: csharp //Scryber.UnitSamples/TableSamples.cs public void CodedTable() { var doc = new Document(); var pg = new Page(); doc.Pages.Add(pg); pg.Padding = new PDFThickness(20); var tbl = new TableGrid(); pg.Contents.Add(tbl); //Full width is equivalent to width:100% tbl.FullWidth = true; for (int i = 0; i < 3; i++) { var row = new TableRow(); tbl.Rows.Add(row); for (int j = 0; j < 3; j++) { if (i == 1 && j == 2) { //We make the previous cell 2 columns wide rather than add a new one. row.Cells[1].CellColumnSpan = 2; continue; } else { var cell = new TableCell() { BorderColor = PDFColors.Aqua, FontItalic = true }; row.Cells.Add(cell); var txt = new TextLiteral("Cell " + (i + 1) + "." + (j + 1)); cell.Contents.Add(txt); } } } using (var stream = DocStreams.GetOutputStream("Samples_TableInCode.pdf")) { doc.SaveAsPDF(stream); } } .. figure:: ../images/samples_tableincode.png :target: ../_images/samples_tableincode.png :alt: Spanning full width tables. :width: 600px :class: with-shadow `Full size version <../_images/samples_tableincode.png>`_ .. note:: The property for the number of columns spanned by a cell is CellColumnSpan. The ColumnCount property will refer to the number of columns to layout inner content with. It is also possible to access a parsed table to alter the content as needed. .. code:: csharp //Scryber.UnitSamples/TableSamples.cs public void ModifyTable() { //Use the simple table sample var path = GetTemplatePath("Tables", "TableSimple.html"); using (var doc = Document.ParseDocument(path)) { //Make full width and add a footer to the table if(doc.TryFindAComponentByID("FirstTable", out TableGrid tbl)) { tbl.FullWidth = true; var row = new TableRow(); tbl.Rows.Add(row); var span = tbl.Rows[0].Cells.Count; var cell = new TableCell(); cell.Contents.Add(new TextLiteral("Adding a bottom row to the table with a span of " + span)); cell.CellColumnSpan = span; row.Cells.Add(cell); } using (var stream = GetOutputStream("Tables", "TableWithNewRow.pdf")) { doc.SaveAsPDF(stream); } } } .. figure:: ../images/samples_tablewithnewrow.png :target: ../_images/samples_tablewithnewrow.png :alt: Spanning full width tables. :width: 600px :class: with-shadow `Full size version <../_images/samples_tablewithnewrow.png>`_ Headers, Footers and overflow ----------------------------- Tables support both headers and footers (single or multiple). The header cells, by default, will repeat across columns and or pages and be in bold, but can be set not to repeat with the ``repeat='none'`` attribute. (Alternatively, any row can simply be set to repeat with the ``repeat='RepeatAtTop'``, and will do so after they have initially been laid out). Rows support the block styles, except margins, padding and positioning. Empty cells will still show size and borders, but can be hidden with the ``border:none`` style. .. code-block:: html Table Headers and Footers
Header 1 Header 2 Header 3
Header 1 Header 2 Header 3
Cell 1Cell 2Cell 3
Cell 1Cell 2Cell 3
Cell 1Cell 2Cell 3
Cell 1Cell 2Cell 3
Cell 1Cell 2Cell 3
Cell 1Cell 2Cell 3
Cell 1Cell 2Cell 3
Cell 1Cell 2Cell 3
Cell 1Cell 2Cell 3
Cell 1Cell 2Cell 3
Cell 1Cell 2Cell 3
Cell 1Cell 2Cell 3
Cell 1Cell 2Cell 3
Cell 1Cell 2Cell 3
Cell 1Cell 2Cell 3
Cell 1Cell 2Cell 3
Cell 1Cell 2Cell 3
Cell 1Cell 2Cell 3
Footer
.. code:: csharp //Scryber.UnitSamples/TableSamples.cs public void TableHeaderAndFooter() { var path = GetTemplatePath("Tables", "TableHeaders.html"); using (var doc = Document.ParseDocument(path)) { using (var stream = GetOutputStream("Tables", "TableHeaders.pdf")) { doc.SaveAsPDF(stream); } } } .. figure:: ../images/samples_tableheaders.png :target: ../_images/samples_tableheaders.png :alt: Tables with headers and footers. :width: 600px :class: with-shadow `Full size version <../_images/samples_tableheaders.png>`_ The Component classes for Header and Footer rows and cells are ``TableHeaderRow``, ``TableFooterRow``, ``TableHeaderCell`` and ``TableFooterCell``. They simply inherit from ``TableRow`` and ``TableCell`` and can be added to a ``TableGrid`` and ``TableRow`` at any point. .. note:: Because of the layout mechanism, repeating cells cannot be accessed or modified between layout itterations (columns or pages). The next table header is from the layout of the original. Mixed content, styling and nesting ---------------------------------- All table cells can contain any content, just like other block components, including other tables, and they also support sizing and alignment of content. .. code:: html Table Headers and Footers
Table with mixed content and another nested table
Left Side Right Side
Cell 1Cell 2

The image above is a beautiful landscape in the Cheshire countryside.

123
123
123
123
123

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus pulvinar, ipsum eu molestie elementum, nibh ante ultricies dui, et euismod nulla sapien ac purus. Morbi suscipit elit tellus, nec elementum lacus dignissim a. Aliquam molestie turpis consectetur rutrum pretium. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Quisque varius vitae erat sagittis facilisis. Vivamus quis tellus quis augue fringilla posuere vitae ac ante. Aliquam ultricies sodales cursus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
Vestibulum dolor libero, faucibus quis tristique at, euismod vitae nunc. Donec vel volutpat urna, eget tristique nunc. Quisque vitae iaculis dolor. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Fusce fermentum odio ac feugiat pharetra. Integer sit amet elit a urna maximus sollicitudin sit amet sed mauris. Proin finibus nec diam blandit porttitor.

Footer
.. code:: csharp //Scryber.UnitSamples/TableSamples.cs public void TableMixedNestedContent() { var path = GetTemplatePath("Tables", "TableNested.html"); using (var doc = Document.ParseDocument(path)) { using (var stream = GetOutputStream("Tables", "TableNested.pdf")) { doc.SaveAsPDF(stream); } } } .. figure:: ../images/samples_tablenested.png :target: ../_images/samples_tablenested.png :alt: Tables with headers and footers. :width: 600px :class: with-shadow `Full size version <../_images/samples_tablenested.png>`_ Binding to Data --------------- As with all things in scryber. Tables, rows and cells are fully bindable. It is very common to want to layout data in tables so that it can easily be compared. Tables support the use of the data binding with the ``template`` tag and ``data-bind`` attribute. See :doc:`binding_databinding` for more information on the data binding capabilities of scryber. .. code:: html Table data bound

Binding content over 2 columns for {{count(model)}} items

# Name Value
.. code:: csharp //Scryber.UnitSamples/TableSamples.cs public void TableBoundContent() { var path = GetTemplatePath("Tables", "TableDatabound.html"); using (var doc = Document.ParseDocument(path)) { List all = new List(); for(int i = 0; i < 1000; i++) { all.Add(new { Key = "Item " + (i + 1).ToString(), Value = i * 50.0 }); } doc.Params["model"] = all; using (var stream = GetOutputStream("Tables", "TableDatabound.pdf")) { doc.SaveAsPDF(stream); } } } .. figure:: ../images/samples_tabledatabound.png :target: ../_images/samples_tabledatabound.png :alt: Tables bound to data. :width: 600px :class: with-shadow `Full size version <../_images/samples_tabledatabound.png>`_ Alternating row styles ----------------------- The conditional function ``if(index(), [true expression], [false expression])`` was applied above for an alternating class to the table rows, even when we don't know how many items there are. We could have combined this with the ``concat()`` function to apply multiple classes. See :doc:`binding/binding_functions` for more examples and information. .. note:: Scryber also includes the data-style-identifier which can improve the speed of output for data bound repeats but can impact the styles within repeating content. Not (Currently) Supported -------------------------- There are some things that are not supported on tables. 1. Scryber does not support the ``rowspan`` property. This is simply a case of complex calculation, and we do expect to implement in the future. 2. Table rows cannot be split across pages. Due to page layout constraints rows should not flow. It has an impact on the column layout, but we may implement in the future. 3. Rows do not support margins, padding, or position. This is a constraint of the layout. 4. Cells do not work well with inner content in multiple columns. It may be that once balanced columns are sorted this automatically resolves itself.