A page of results from a CSV file of electric vehicles: two SimpleBarCharts, the five makes and the model years, a table of the same numbers under them, and a table of one car with its photo and its VIN as a barcode in their cells, in a PDF/UA document.
Example_20.pdf — the PDF this example creates.
using System;
using System.IO;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using PDFjet.NET;
/**
* Example_20.cs
* This example draws a page of results from a CSV file of electric vehicles:
* two simple bar charts, the five makes and the model years, and under them a
* table of the same numbers, then a table of one car with its photo and its
* VIN as a barcode, in their cells.
*/
public class Example_20 {
static readonly String[] MAKES = {"TESLA", "NISSAN", "CHEVROLET", "BMW", "FORD"};
static readonly String[] NAMES = {"Tesla", "Nissan", "Chevrolet", "BMW", "Ford"};
const int FIRST_YEAR = 2019;
const int LAST_YEAR = 2023;
public Example_20() {
PDF pdf = new PDF(new BufferedStream(
new FileStream("Example_20.pdf", FileMode.Create)));
pdf.SetCompliance(Compliance.PDF_UA_1);
pdf.SetTitle("Electric Vehicles by Make and Model Year");
Font f1 = new Font(pdf, IBMPlexSans.SemiBold);
f1.SetSize(11f);
Font f2 = new Font(pdf, IBMPlexSans.Regular);
f2.SetSize(9f);
// The cars of the file: by make, the battery electric ones and the
// electric range of those that give one, and by model year
List<String> lines = Content.LinesOfTextFile("data/Electric_Vehicle_Population_10_Pages.csv");
int[] cars = new int[MAKES.Length];
int[] battery = new int[MAKES.Length];
int[] ranges = new int[MAKES.Length];
int[] ranged = new int[MAKES.Length];
int[] years = new int[LAST_YEAR - FIRST_YEAR + 1];
String[] modelX = null; // The first Tesla Model X of the file
for (int n = 1; n < lines.Count; n++) {
String[] field = lines[n].Split(',');
int year = int.Parse(field[5], CultureInfo.InvariantCulture);
if (year >= FIRST_YEAR && year <= LAST_YEAR) {
years[year - FIRST_YEAR]++;
}
int i = Array.IndexOf(MAKES, field[6]);
if (i >= 0) {
cars[i]++;
if (field[8].StartsWith("Battery", StringComparison.Ordinal)) {
battery[i]++;
}
int range = int.Parse(field[10], CultureInfo.InvariantCulture);
if (range > 0) {
ranges[i] += range;
ranged[i]++;
}
}
if (modelX == null && field[7] == "MODEL X") {
modelX = field;
}
}
int total = lines.Count - 1;
Page page = new Page(pdf, Letter.PORTRAIT);
new TextLine(f1, "Electric Vehicles by Make and Model Year")
.SetStructureType(StructElem.H1).SetFontSize(20f)
.SetLocation(50f, 70f).DrawOn(page);
List<Paragraph> intro = new List<Paragraph>();
intro.Add(new Paragraph(new TextLine(f2, "The " + total + " electric vehicles of the first rows of "
+ "the data file that Example_24 draws whole: the five makes with the most cars, and the "
+ "cars of each model year from " + FIRST_YEAR + " to " + LAST_YEAR + ", with the numbers "
+ "in the table under the charts.").SetFontSize(10f)));
TextFrame frame = new TextFrame(intro).SetLocation(50f, 84f).SetWidth(512f);
frame.DrawOn(page);
float y = frame.GetTextBottom() + 18f;
SimpleBarChart byMake = new SimpleBarChart(f1, f2)
.SetTitle("The five makes").SetSubtitle("cars").SetHighlight(0);
for (int i = 0; i < MAKES.Length; i++) {
byMake.Add(NAMES[i], cars[i]);
}
byMake.SetLocation(50f, y).SetWidth(248f).DrawOn(page);
SimpleBarChart byYear = new SimpleBarChart(f1, f2)
.SetTitle("By model year").SetSubtitle("cars");
int busiest = 0;
for (int i = 0; i < years.Length; i++) {
byYear.Add((FIRST_YEAR + i).ToString(CultureInfo.InvariantCulture), years[i]);
busiest = (years[i] > years[busiest]) ? i : busiest;
}
byYear.SetHighlight(busiest);
byYear.SetLocation(314f, y).SetWidth(248f).DrawOn(page);
y += Math.Max(byMake.GetHeight(), byYear.GetHeight()) + 30f;
// The numbers of the charts
new TextLine(f1, "The five makes").SetStructureType(StructElem.H2)
.SetFontSize(14f).SetLocation(50f, y).DrawOn(page);
List<List<Cell>> data = new List<List<Cell>>();
data.Add(Row(f1, true, "Make", "Cars", "Share of all", "Battery electric", "Average range"));
for (int i = 0; i < MAKES.Length; i++) {
data.Add(Row(f2, false, NAMES[i], cars[i].ToString(CultureInfo.InvariantCulture),
(100f * cars[i] / total).ToString("F1", CultureInfo.InvariantCulture) + "%",
battery[i].ToString(CultureInfo.InvariantCulture),
ranged[i] == 0 ? "" : (ranges[i] / ranged[i]).ToString(CultureInfo.InvariantCulture) + " mi"));
}
Table table = new Table();
table.SetTableData(data, 1);
float[] widths = {142f, 80f, 90f, 100f, 100f};
for (int i = 0; i < widths.Length; i++) {
table.SetColumnWidth(i, widths[i]);
}
table.SetLocation(50f, y + 10f);
y = table.DrawOn(page)[1] + 30f;
// One car of the data, its photo and its VIN in their cells
new TextLine(f1, "One car of the data").SetStructureType(StructElem.H2)
.SetFontSize(14f).SetLocation(50f, y).DrawOn(page);
Image image = new Image(pdf, "images/TeslaX.png");
image.SetAltDescription("A white Tesla Model X with a black glass roof, seen from the front left.");
image.ScaleBy(1f / 3f); // The image is 120 DPI, so 0.6 of its pixels
Barcode vin = new Barcode(Barcode.CODE_128, modelX[0]);
vin.SetModuleLength(0.75f);
vin.SetFont(f2);
data = new List<List<Cell>>();
data.Add(Row(f1, true, "Car", "Model", "VIN"));
foreach (Cell cell in data[0]) {
cell.SetTextAlignment(Alignment.LEFT); // Text, not numbers
}
List<Cell> car = Row(f2, false, "", "Tesla Model X, " + modelX[5] + ", " + modelX[2] + ", "
+ modelX[10] + " mi of range", "");
foreach (Cell cell in car) {
cell.SetTextAlignment(Alignment.LEFT);
}
car[0].SetImage(image);
car[2].SetBarcode(vin);
data.Add(car);
table = new Table();
table.SetTableData(data, 1);
table.SetColumnWidth(0, image.GetWidth() + 8f);
table.SetColumnWidth(1, 220f);
table.SetColumnWidth(2, 512f - image.GetWidth() - 228f);
table.SetLocation(50f, y + 10f);
table.DrawOn(page);
pdf.Complete();
}
// A row of cells of the font at 9 points, one for each text, in the
// look of the charts: a light band behind the header row, a thin gray
// line under each row, and the numbers, the cells after the first,
// aligned right.
static List<Cell> Row(Font font, bool header, params String[] texts) {
List<Cell> row = new List<Cell>();
for (int i = 0; i < texts.Length; i++) {
Cell cell = new Cell(font, texts[i]).SetFontSize(9f);
cell.SetTopPadding(5f).SetBottomPadding(5f).SetLeftPadding(6f).SetRightPadding(6f);
cell.SetBorders(false).SetBorder(Border.BOTTOM, true);
cell.SetBorderWidth(0.5f).SetBorderColor(0xD5D9DE);
if (header) {
cell.SetBackgroundColor(0xF1F3F6);
}
if (i > 0) {
cell.SetTextAlignment(Alignment.RIGHT);
}
row.Add(cell);
}
return row;
}
public static void Main(String[] args) {
Stopwatch sw = Stopwatch.StartNew();
long time0 = sw.ElapsedMilliseconds;
new Example_20();
long time1 = sw.ElapsedMilliseconds;
sw.Stop();
Console.WriteLine($"Example_20 => {time1 - time0,4} ms");
}
} // End of Example_20.cs
©2026 PDFjet Software.