Nevron Logo

Generating PDF and Docx Documents with Charts

Introduction

Generating documents with various types of content is a common requirement for any text processing system. Typically those documents are invoices, reports, and other documents using an automated process. In this article, we’ll showcase how easy it is to insert common graphical content inside a rich formatted text with Nevron Rich Text for .NET using C# code. The article covers inserting barcodes, charts, and diagrams inside a document and generating a PDF, DOCX, RTF, or HTML document on the fly.

Getting Started

The first step to get started is to install Nevron Open Vision from the public download on Nevron’s website or to install the Nevron Open Vision package from NuGet. Then you can proceed with the writing code of the actual. We’ll use a .NET Core WPF application in this article, but the approach is the same for WinForms and ASP.NET projects. After creating a Wpf Core application, you can drag and drop one of the NOV controls on the main window. For this project, we dropped the .NET NRichTextView control, which exposes a rich text view without any graphical user interface.

Document Object Model

The Nevron Rich Text Editor for .NET is automated by creating a text document that follows the control's Document Object Model (DOM). This model is very similar to the Word/HTML DOM and tries to incorporate features present in both of them. In a few simple words, the Nevron Rich Text Editor DOM consists of two types of objects - blocks and inlines.

Blocks are objects that can contain other blocks - for example - a table contains multiple rows that in turn have various cells, whereas a text document contains sections that in turn can contain multiple blocks that can be tables and or paragraphs. Paragraphs are the only block that can contain inline elements (elements that appear along each line).

Sample Code

So having this brief description of the DOM, let’s write some code. Let’s start by adding a section that contains a paragraph:

richTextView.Document.Content.Sections.Clear();
NSection section = new NSection();
richTextView.Document.Content.Sections.Add(section);

section.Blocks.Add(new NParagraph("Welcome to our annual report."));
section.Blocks.Add(new NParagraph("Following is a table that shows our sales per year:"));

This code adds a new section to the document that contains two paragraphs. Then lets see how to create a simple table, having some dummy data:

double[] incomePerYear = new double[] { 674.9, 814.8, 852.9, 1, 213.1, 1, 043.9, 1, 096.4, 1, 381.1 };
string[] years = new string[] { "2011", "2012", "2013", "2014", "2015", "2016", "2017", "2018", "2019", "2020", "2021", "2022" };

// create a table
NTable table = new NTable();
table.Border = NBorder.CreateFilledBorder(NColor.Black);
table.BorderThickness = new NMargins(2);
table.AllowSpacingBetweenCells = true;
table.Columns.Add(new NTableColumn());
table.Columns.Add(new NTableColumn());
section.Blocks.Add(table);

NTableRow headerRow = new NTableRow();

headerRow.Cells.Add(new NTableCell(new NParagraph("Year")));
headerRow.Cells.Add(new NTableCell(new NParagraph("Income")));

table.Rows.Add(headerRow);

for (int i = 0; i incomePerYear.Length; i++)
{
NTableRow tableRow = new NTableRow();
tableRow.Cells.Add(new NTableCell(new NParagraph(years[i].ToString())));
tableRow.Cells.Add(new NTableCell(new NParagraph(incomePerYear[i].ToString())));
table.Rows.Add(tableRow);
}

With this code, we create a table with two columns named year and income. Of course, the data may vary, but the idea here is to illustrate how easy it is to create a table in a document. You must create a table object, add the number of columns, and add rows containing cells that match the specified number of columns. That’s all. Of course, as you would expect, there are many other features associated with tables, such as merged cells, border options, header rows, and further, which are outside the scope of this article.
Since a picture is worth a thousand words, let’s add a simple bar chart that visually displays the above data. We must first create a chart view object and add it to the text DOM using a special inline (NWidgetInline) that allows you to display any NOV control (barcode, chart, diagram, etc.) as scalable and interactive text content:

// create a chart view
NChartView chartView = new NChartView();
chartView.Surface.CreatePredefinedChart(ENPredefinedChartType.Cartesian);

// create a paragraph hosting the chart
NParagraph paragraph = new NParagraph();
NWidgetInline chartInline = new NWidgetInline();
chartInline.Content = chartView;
paragraph.Inlines.Add(chartInline);
section.Blocks.Add(paragraph);
Now after the chart is added to the text document lets add some data:
NSize size = new NSize(300, 200);
chartView.PreferredSize = size;

// configure title
chartView.Surface.Titles[0].Text = "Sales per Year";
chartView.Surface.Titles[0].Margins = NMargins.Zero;
chartView.Surface.Legends[0].Visibility = ENVisibility.Hidden;
chartView.BorderThickness = NMargins.Zero;

// configure chart
NCartesianChart chart = (NCartesianChart)chartView.Surface.Charts[0];
chart.Padding = new NMargins(20);

// configure axes
chart.SetPredefinedCartesianAxes(ENPredefinedCartesianAxis.XOrdinalYLinear);
chart.Margins = NMargins.Zero;
NBarSeries bar = new NBarSeries();
bar.LegendView.Mode = ENSeriesLegendMode.None;
bar.DataLabelStyle = new NDataLabelStyle(false);
chart.Series.Add(bar);
for (int i = 0; i ">" incomePerYear.Length; i++)
{
bar.DataPoints.Add(new NBarDataPoint(incomePerYear[i]));
}
NOrdinalScale scaleX = (NOrdinalScale)chart.Axes[ENCartesianAxis.PrimaryX].Scale;
scaleX.Labels.TextProvider = new NOrdinalScaleLabelTextProvider(years);
That’s it – now our control contains a bar chart with an ordinal (categorical) scale that visually shows the sales per year.
With this our simple document is almost complete – let’s add a footer with a barcode for a final touch:

// add barcode
NParagraph barcodeParagraph = new NParagraph();
barcodeParagraph.Inlines.Add(new NTextInline("Please scan to view more information:"))
NWidgetInline barcodeInline = new NWidgetInline();
NMatrixBarcode barcode = new NMatrixBarcode(ENMatrixBarcodeSymbology.QrCode, "https://www.nevron.com");
barcodeInline.Content = barcode;
barcodeParagraph.Inlines.Add(barcodeInline);
NHeaderFooter footer = new NHeaderFooter();
footer.Blocks.Add(barcodeParagraph);
section.Footer = footer;

Now our text document is complete, however, we still haven’t generated a text document. Fortunately, this is done with a single line of code:

richTextView.SaveToFile("c:\\temp\\SampleReport.pdf", new NPdfTextFormat());

This line of code will generate a PDF document that contains our document consisting of a table and chart. To generate another type of document – for example DOCX you just need to change the output format:

richTextView.SaveToFile("c:\\temp\\SampleReport.docx", new NDocxTextFormat());

For more advanced examples showing the capabilities of Nevron Rich Text for .NET please download the fully functional evaluation of Nevron Open Vision.

Conclusion

Nevron Rich Text Editor for .NET fully supports the generation of various types of documents that can contain diverse content such as barcodes, charts, diagrams, gauges, etc. The fact that those types of controls integrate seamlessly with the control dom and can render as scalable, resolution-independent graphics makes this control a very solid and mature platform for many automated document generation tasks such as reporting.

About Nevron Software

Founded in 1998, Nevron Software is a component vendor specialized in the development of premium presentation layer solutions for .NET based technologies. Today Nevron has established itself as the trusted partner worldwide for use in .NET LOB applications, SharePoint portals and Reporting solutions. Nevron technology is used by many Fortune 500 companies, large financial institutions, global IT consultancies, academic institutions, governments and non-profits.
For more information, visit: www.nevron.com.

Customer Quotes:

QUOTE It may be of interest to you know that I selected Nevron charting component mostly based the examples demonstrating programmability, events, etc. We really didn't have the possibility to review in depth several graphing components (there are a lot of them) and all of them show pretty pictures, but from picture demos only you cannot tell about functionality and programmability inside the component engine.

Since Nevron examples demonstrated clicking, events, etc. I got the feeling that it offers a lot of freedom to the developer and you wouldn't be stuck with it at some later point in your development.
UNQUOTE

Kari Hirvi
TietoSaab Systems