Table
This example shows how to create a PDF table with rix/pdf.
The example uses the public Rix facade:
#include <rix.hpp>and accesses PDF through:
rix.pdfUse this example when you want to create a PDF report with rows, columns, and a header.
Create the file
mkdir -p ~/rix-pdf-table-example
cd ~/rix-pdf-table-example
touch table.cppAdd:
#include <rix.hpp>
int main()
{
auto doc = rix.pdf.document();
doc.set_title("Rix PDF Table Example");
auto &page = doc.add_page();
auto y = page.heading(
page.x_left(),
page.y_top(),
"Project table",
1);
y -= 20.0F;
rixlib::pdf::Table table;
table.set_column_widths({
160.0F,
160.0F,
160.0F});
table.add_header({
"Name",
"Language",
"Project"});
table.add_row({
"Ada",
"C++",
"Rix"});
table.add_row({
"Gaspard",
"C++",
"Vix.cpp"});
table.add_row({
"Grace",
"Systems",
"PDF"});
page.table(
page.x_left(),
y,
table);
auto saved = rix.pdf.save(doc, "rix_pdf_table.pdf");
if (saved.failed())
{
rix.debug.eprint(
"pdf error:",
rix.pdf.error.to_string(saved.error()),
saved.error().message());
return 1;
}
rix.debug.print("created:", "rix_pdf_table.pdf");
return 0;
}Run it:
vix run table.cppIf Rix is not available yet for single-file usage:
vix install -g rix/rix
vix run table.cppThis creates:
rix_pdf_table.pdfWhat this example does
The example creates a document:
auto doc = rix.pdf.document();It adds a page:
auto &page = doc.add_page();It creates a table:
rixlib::pdf::Table table;It sets column widths:
table.set_column_widths({
160.0F,
160.0F,
160.0F});It adds a header row:
table.add_header({
"Name",
"Language",
"Project"});It adds data rows:
table.add_row({
"Ada",
"C++",
"Rix"});Then it draws the table on the page:
page.table(
page.x_left(),
y,
table);Create a table
Use:
rixlib::pdf::Table table;The table model stores:
column widths
rows
cells
styleA table is drawn when you pass it to:
page.table(...)Set column widths
Use:
table.set_column_widths({
160.0F,
160.0F,
160.0F});Column widths are expressed in PDF points.
One inch is 72 points.
The total table width should fit inside the page content width.
You can check the available width with:
page.content_width()Add a header
Use:
table.add_header({
"Name",
"Language",
"Project"});A header is a table row marked as a header row.
It is rendered with the table header style.
Add rows
Use:
table.add_row({
"Ada",
"C++",
"Rix"});Each value becomes a cell.
Rows should normally have the same number of values as the number of columns.
Draw the table
Use:
auto y_after_table = page.table(
page.x_left(),
y,
table);The arguments are:
x position
starting y position
tablepage.table returns the Y position below the table.
This lets you continue drawing after the table.
Continue after a table
auto y_after_table = page.table(
page.x_left(),
y,
table);
y_after_table -= 20.0F;
page.text(
page.x_left(),
y_after_table,
"End of report");Use this pattern when a report has text before and after a table.
Complete table report
#include <rix.hpp>
int main()
{
auto doc = rix.pdf.document();
doc.set_title("Table Report")
.set_author("Rix");
auto &page = doc.add_page();
auto y = page.heading(
page.x_left(),
page.y_top(),
"Table Report",
1);
y -= 20.0F;
rixlib::pdf::Table table;
table.set_column_widths({
160.0F,
160.0F,
160.0F});
table.add_header({
"Name",
"Language",
"Project"});
table.add_row({
"Ada",
"C++",
"Rix"});
table.add_row({
"Gaspard",
"C++",
"Vix.cpp"});
table.add_row({
"Grace",
"Systems",
"PDF"});
auto y_after_table = page.table(
page.x_left(),
y,
table);
y_after_table -= 20.0F;
page.text(
page.x_left(),
y_after_table,
"Generated through the public Rix facade.");
auto saved = rix.pdf.save(doc, "table-report.pdf");
if (saved.failed())
{
rix.debug.eprint(
"pdf error:",
rix.pdf.error.to_string(saved.error()),
saved.error().message());
return 1;
}
rix.debug.print("created:", "table-report.pdf");
return 0;
}Run:
vix run table.cppTable rows
You can create a row manually:
rixlib::pdf::TableRow row;
row.add_cell("Ada");
row.add_cell("C++");
row.add_cell("Rix");
table.add_row(std::move(row));Use manual rows when you need more control over row-level settings.
Header rows
A row can be marked as a header:
rixlib::pdf::TableRow row;
row.set_header(true);
row.add_cell("Name");
row.add_cell("Language");
row.add_cell("Project");
table.add_row(std::move(row));The helper:
table.add_header(...)is shorter for normal header rows.
Table cells
You can create cells manually:
rixlib::pdf::TableCell cell{"Ready"};
cell.set_align(rixlib::pdf::Align::Center);
cell.set_text_color(rixlib::pdf::Color::green_color());Then add it to a row:
rixlib::pdf::TableRow row;
row.add_cell(std::move(cell));Use manual cells when you need alignment, color, background, or colspan control.
Align a cell
rixlib::pdf::TableCell cell{"C++"};
cell.set_align(rixlib::pdf::Align::Center);Available alignments are:
Left
Center
Right
JustifyIn code:
rixlib::pdf::Align::Left
rixlib::pdf::Align::Center
rixlib::pdf::Align::Right
rixlib::pdf::Align::JustifySet cell text color
rixlib::pdf::TableCell cell{"Ready"};
cell.set_text_color(
rixlib::pdf::Color::green_color());Use this when some values need a visual status.
Set cell background
rixlib::pdf::TableCell cell{"Header"};
cell.set_background_color(
rixlib::pdf::Color::light_gray());Clear it with:
cell.clear_background_color();Use colspan
rixlib::pdf::TableCell cell{"Full row"};
cell.set_colspan(3);Use colspan when one cell should span several columns.
Style the table
Access the table style with:
table.style()Example:
table.style()
.set_font(rixlib::pdf::Font::Helvetica)
.set_font_size(10.0F)
.set_header_font(rixlib::pdf::Font::HelveticaBold)
.set_header_size(10.0F)
.set_row_height(24.0F)
.set_cell_padding(6.0F)
.set_stripe_rows(true);Use table styles when building reports with a repeated look.
Border style
Use BorderStyle to control table borders:
rixlib::pdf::BorderStyle border{
0.75F,
rixlib::pdf::Color::gray(),
rixlib::pdf::LineStyle::Solid};
table.style().set_border(border);Disable borders:
table.style().set_border(
rixlib::pdf::BorderStyle::none());Use a thin default border:
table.style().set_border(
rixlib::pdf::BorderStyle::thin());Stripe rows
Enable alternating row backgrounds:
table.style().set_stripe_rows(true);Set the stripe color:
table.style().set_stripe_color(
rixlib::pdf::Color::light_gray());Styled table example
#include <rix.hpp>
int main()
{
auto doc = rix.pdf.document();
auto &page = doc.add_page();
auto y = page.heading(
page.x_left(),
page.y_top(),
"Styled table",
1);
y -= 20.0F;
rixlib::pdf::Table table;
table.set_column_widths({
180.0F,
160.0F,
140.0F});
table.style()
.set_font(rixlib::pdf::Font::Helvetica)
.set_font_size(10.0F)
.set_header_font(rixlib::pdf::Font::HelveticaBold)
.set_header_size(10.0F)
.set_row_height(24.0F)
.set_cell_padding(6.0F)
.set_stripe_rows(true);
table.add_header({
"Name",
"Language",
"Status"});
{
rixlib::pdf::TableRow row;
row.add_cell("Ada");
row.add_cell("C++");
rixlib::pdf::TableCell status{"Ready"};
status.set_align(rixlib::pdf::Align::Center);
status.set_text_color(rixlib::pdf::Color::green_color());
row.add_cell(std::move(status));
table.add_row(std::move(row));
}
table.add_row({
"Gaspard",
"C++",
"Building"});
page.table(
page.x_left(),
y,
table);
auto saved = rix.pdf.save(doc, "styled-table.pdf");
if (saved.failed())
{
rix.debug.eprint(
"pdf error:",
rix.pdf.error.to_string(saved.error()),
saved.error().message());
return 1;
}
rix.debug.print("created:", "styled-table.pdf");
return 0;
}Run:
vix run table.cppTable from CSV data
You can parse CSV data and render it as a PDF table.
#include <rix.hpp>
int main()
{
const auto csv = rix.csv.parse(
"Name,Language,Project\n"
"Ada,C++,Rix\n"
"Gaspard,C++,Vix.cpp\n"
"Grace,Systems,PDF\n");
auto doc = rix.pdf.document();
auto &page = doc.add_page();
auto y = page.heading(
page.x_left(),
page.y_top(),
"CSV table",
1);
y -= 20.0F;
rixlib::pdf::Table table;
table.set_column_widths({
160.0F,
160.0F,
160.0F});
if (!csv.empty())
{
table.add_header({
csv[0][0],
csv[0][1],
csv[0][2]});
}
for (std::size_t i = 1; i < csv.size(); ++i)
{
const auto &row = csv[i];
if (row.size() >= 3)
{
table.add_row({
row[0],
row[1],
row[2]});
}
}
page.table(
page.x_left(),
y,
table);
auto saved = rix.pdf.save(doc, "csv-table.pdf");
if (saved.failed())
{
rix.debug.eprint(
"pdf error:",
rix.pdf.error.to_string(saved.error()),
saved.error().message());
return 1;
}
rix.debug.print("created:", "csv-table.pdf");
return 0;
}Run:
vix run table.cppTable size helpers
You can inspect a table:
rix.debug.print("rows:", table.row_count());
rix.debug.print("columns:", table.column_count());Check whether the table is empty:
if (table.empty())
{
rix.debug.print("table is empty");
}Save the document
Use:
auto saved = rix.pdf.save(doc, "table.pdf");Check errors:
if (saved.failed())
{
rix.debug.eprint(
"pdf error:",
rix.pdf.error.to_string(saved.error()),
saved.error().message());
return 1;
}Write bytes instead of saving
Use:
auto bytes = rix.pdf.write(doc);Example:
auto bytes = rix.pdf.write(doc);
if (bytes.failed())
{
rix.debug.eprint(
"pdf error:",
rix.pdf.error.to_string(bytes.error()),
bytes.error().message());
return 1;
}
rix.debug.print("pdf bytes:", bytes.value().size());Use write for HTTP responses or custom output handling.
Use save for direct file output.
Use in a Vix project
Create a project:
vix new rix-pdf-table --app
cd rix-pdf-tableAdd Rix:
vix add rix/rix
vix installMake sure vix.app contains:
deps = [
"rix/rix",
]A minimal vix.app can look like this:
name = "rix-pdf-table"
type = "executable"
standard = "c++20"
output_dir = "bin"
sources = [
"src/main.cpp",
]
include_dirs = [
"include",
"src",
]
deps = [
"rix/rix",
]
packages = [
"vix",
]
links = [
"vix::vix",
]Put the example code in:
src/main.cppBuild and run:
vix build
vix runSingle-file usage
For examples, tests, and quick experiments:
vix run table.cppIf needed:
vix install -g rix/rix
vix run table.cppFor project usage, prefer:
vix add rix/rix
vix installand keep the dependency in vix.app:
deps = [
"rix/rix",
]Use only PDF with the facade
If you want the rix.* facade style but only want PDF mounted, define the feature macro before including rix.hpp:
#define RIX_ENABLE_PDF
#include <rix.hpp>
int main()
{
auto doc = rix.pdf.document();
auto &page = doc.add_page();
rixlib::pdf::Table table;
table.set_column_widths({
160.0F,
160.0F});
table.add_header({
"Name",
"Project"});
table.add_row({
"Ada",
"Rix"});
page.table(
page.x_left(),
page.y_top(),
table);
auto saved = rix.pdf.save(doc, "table.pdf");
return saved.ok() ? 0 : 1;
}When at least one RIX_ENABLE_* macro is defined, only selected modules are mounted.
If you also want debug output:
#define RIX_ENABLE_PDF
#define RIX_ENABLE_DEBUG
#include <rix.hpp>
int main()
{
auto doc = rix.pdf.document();
auto &page = doc.add_page();
rixlib::pdf::Table table;
table.set_column_widths({
160.0F,
160.0F});
table.add_header({
"Name",
"Project"});
table.add_row({
"Ada",
"Rix"});
page.table(
page.x_left(),
page.y_top(),
table);
auto saved = rix.pdf.save(doc, "table.pdf");
if (saved.failed())
{
rix.debug.eprint(
"pdf error:",
rix.pdf.error.to_string(saved.error()),
saved.error().message());
return 1;
}
rix.debug.print("created:", "table.pdf");
return 0;
}Use the independent package
For independent usage, install:
vix add rix/pdf
vix installIn vix.app:
deps = [
"rix/pdf",
]Then include:
#include <rix/pdf.hpp>Example:
#include <rix/pdf.hpp>
int main()
{
auto pdf = rixlib::pdf::module();
auto doc = pdf.document();
auto &page = doc.add_page();
rixlib::pdf::Table table;
table.set_column_widths({
160.0F,
160.0F});
table.add_header({
"Name",
"Project"});
table.add_row({
"Ada",
"Rix"});
page.table(
page.x_left(),
page.y_top(),
table);
auto saved = pdf.save(doc, "table.pdf");
return saved.ok() ? 0 : 1;
}The examples in this documentation prefer the public facade:
#include <rix.hpp>and:
rix.pdfCommon mistakes
Forgetting to install Rix
If rix.hpp is not found, install Rix first.
For a project:
vix add rix/rix
vix installFor single-file usage:
vix install -g rix/rixPutting Rix in packages
Wrong:
packages = [
"rix/rix",
]Correct:
deps = [
"rix/rix",
]deps is for Vix Registry packages.
packages is for CMake package discovery.
Making columns wider than the page
The sum of column widths should fit inside:
page.content_width()If the table is too wide, reduce column widths.
Forgetting to draw the table
Creating the table is not enough:
rixlib::pdf::Table table;You must draw it:
page.table(
page.x_left(),
y,
table);Accessing CSV rows without checking size
Wrong:
table.add_row({
row[0],
row[1],
row[2]});Better:
if (row.size() >= 3)
{
table.add_row({
row[0],
row[1],
row[2]});
}Not checking save errors
Wrong:
rix.pdf.save(doc, "table.pdf");Correct:
auto saved = rix.pdf.save(doc, "table.pdf");
if (saved.failed())
{
rix.debug.eprint(
"pdf error:",
rix.pdf.error.to_string(saved.error()),
saved.error().message());
return 1;
}What you should remember
Create a table:
rixlib::pdf::Table table;Set columns:
table.set_column_widths({
160.0F,
160.0F,
160.0F});Add a header:
table.add_header({
"Name",
"Language",
"Project"});Add rows:
table.add_row({
"Ada",
"C++",
"Rix"});Draw the table:
page.table(
page.x_left(),
y,
table);Save:
auto saved = rix.pdf.save(doc, "table.pdf");For project usage:
vix add rix/rix
vix installand keep:
deps = [
"rix/rix",
]Next step
Continue with PDF drawing.
Next: Drawing