Word Charts in C# and VB.NET
Chart
elements are drawings used for graphical data representation. GemBox.Document provides support for working with charts programmatically with the help of the GemBox.Spreadsheet component.
- With GemBox.Spreadsheet, GemBox.Document can create and update charts in Word documents. It can also export documents with graphs to PDF, XPS, or image formats.
- Without GemBox.Spreadsheet, GemBox.Document is only able to preserve charts in Word documents.
Create chart
To enable GemBox.Document's support and work with Chart
objects, you'll need to add a reference to GemBox.Spreadsheet library and call its SpreadsheetInfo.SetLicense
method.
Note, if you don't have a GemBox.Spreadsheet license you can use its Free mode.
You can choose to create charts from the following types:
- Area
- Bar
- Column
- Combo
- Line
- Pie
- Scatter
The following example shows how to create a document with a bar chart using C# and VB.NET.

using GemBox.Document;
using GemBox.Spreadsheet;
using GemBox.Spreadsheet.Charts;
class Program
{
static void Main()
{
// If using the Professional version, put your GemBox.Document serial key below.
ComponentInfo.SetLicense("FREE-LIMITED-KEY");
// If using the Professional version, put your GemBox.Spreadsheet serial key below.
SpreadsheetInfo.SetLicense("FREE-LIMITED-KEY");
var document = new DocumentModel();
// Create Word chart and add it to document.
var chart = new Chart(document, GemBox.Document.ChartType.Bar,
new FloatingLayout(
new HorizontalPosition(HorizontalPositionType.Center, HorizontalPositionAnchor.Margin),
new VerticalPosition(VerticalPositionType.Top, VerticalPositionAnchor.Paragraph),
new Size(14, 7, GemBox.Document.LengthUnit.Centimeter)));
document.Sections.Add(
new Section(document,
new Paragraph(document, "New document with chart element."),
new Paragraph(document, chart)));
// Get underlying Excel chart.
ExcelChart excelChart = (ExcelChart)chart.ExcelChart;
ExcelWorksheet worksheet = excelChart.Worksheet;
// Add data for Excel chart.
worksheet.Cells["A1"].Value = "Name";
worksheet.Cells["A2"].Value = "John Doe";
worksheet.Cells["A3"].Value = "Fred Nurk";
worksheet.Cells["A4"].Value = "Hans Meier";
worksheet.Cells["A5"].Value = "Ivan Horvat";
worksheet.Cells["B1"].Value = "Salary";
worksheet.Cells["B2"].Value = 3600;
worksheet.Cells["B3"].Value = 2580;
worksheet.Cells["B4"].Value = 3200;
worksheet.Cells["B5"].Value = 4100;
// Select data.
excelChart.SelectData(worksheet.Cells.GetSubrange("A1:B5"), true);
document.Save("Created Chart.%OutputFileType%");
}
}
Imports GemBox.Document
Imports GemBox.Spreadsheet
Imports GemBox.Spreadsheet.Charts
Module Program
Sub Main()
' If using the Professional version, put your GemBox.Document serial key below.
ComponentInfo.SetLicense("FREE-LIMITED-KEY")
' If using the Professional version, put your GemBox.Spreadsheet serial key below.
SpreadsheetInfo.SetLicense("FREE-LIMITED-KEY")
Dim document As New DocumentModel()
' Create Word chart and add it to document.
Dim chart As New Chart(document, GemBox.Document.ChartType.Bar,
New FloatingLayout(
New HorizontalPosition(HorizontalPositionType.Center, HorizontalPositionAnchor.Margin),
New VerticalPosition(VerticalPositionType.Top, VerticalPositionAnchor.Paragraph),
New Size(14, 7, GemBox.Document.LengthUnit.Centimeter)))
document.Sections.Add(
New Section(document,
New Paragraph(document, "New document with chart element."),
New Paragraph(document, chart)))
' Get underlying Excel chart.
Dim excelChart As ExcelChart = DirectCast(chart.ExcelChart, ExcelChart)
Dim worksheet As ExcelWorksheet = excelChart.Worksheet
' Add data for Excel chart.
worksheet.Cells("A1").Value = "Name"
worksheet.Cells("A2").Value = "John Doe"
worksheet.Cells("A3").Value = "Fred Nurk"
worksheet.Cells("A4").Value = "Hans Meier"
worksheet.Cells("A5").Value = "Ivan Horvat"
worksheet.Cells("B1").Value = "Salary"
worksheet.Cells("B2").Value = 3600
worksheet.Cells("B3").Value = 2580
worksheet.Cells("B4").Value = 3200
worksheet.Cells("B5").Value = 4100
' Select data.
excelChart.SelectData(worksheet.Cells.GetSubrange("A1:B5"), True)
document.Save("Created Chart.%OutputFileType%")
End Sub
End Module
For more information about charts, visit the Chart Components and Chart Formatting examples.
Update chart
The following example shows how you can update line chart data in a Word document.

using System.Linq;
using GemBox.Document;
using GemBox.Spreadsheet;
using GemBox.Spreadsheet.Charts;
class Program
{
static void Main()
{
// If using the Professional version, put your GemBox.Document serial key below.
ComponentInfo.SetLicense("FREE-LIMITED-KEY");
// If using the Professional version, put your GemBox.Spreadsheet serial key below.
SpreadsheetInfo.SetLicense("FREE-LIMITED-KEY");
var document = DocumentModel.Load("%#Chart.docx%");
// Get Word chart.
var chart = (Chart)document.GetChildElements(true, ElementType.Chart).First();
// Get underlying Excel chart and cast it as LineChart.
var lineChart = (LineChart)chart.ExcelChart;
// Get underlying Excel sheet and add new cell values.
var sheet = lineChart.Worksheet;
sheet.Cells["D1"].Value = "Series 3";
sheet.Cells["D2"].Value = 8.6;
sheet.Cells["D3"].Value = 5;
sheet.Cells["D4"].Value = 7;
sheet.Cells["D5"].Value = 9;
// Add new line series to the LineChart.
lineChart.Series.Add(sheet.Cells["D1"].StringValue, "Sheet1!D2:D5");
document.Save("Updated Chart.%OutputFileType%");
}
}
Imports System.Linq
Imports GemBox.Document
Imports GemBox.Spreadsheet
Imports GemBox.Spreadsheet.Charts
Module Program
Sub Main()
' If using the Professional version, put your GemBox.Document serial key below.
ComponentInfo.SetLicense("FREE-LIMITED-KEY")
' If using the Professional version, put your GemBox.Spreadsheet serial key below.
SpreadsheetInfo.SetLicense("FREE-LIMITED-KEY")
Dim document = DocumentModel.Load("%#Chart.docx%")
' Get Word chart.
Dim chart = DirectCast(document.GetChildElements(True, ElementType.Chart).First(), Chart)
' Get underlying Excel chart and cast it as LineChart.
Dim lineChart = DirectCast(chart.ExcelChart, LineChart)
' Get underlying Excel sheet and add new cell values.
Dim sheet = lineChart.Worksheet
sheet.Cells("D1").Value = "Series 3"
sheet.Cells("D2").Value = 8.6
sheet.Cells("D3").Value = 5
sheet.Cells("D4").Value = 7
sheet.Cells("D5").Value = 9
' Add new line series to the LineChart.
lineChart.Series.Add(sheet.Cells("D1").StringValue, "Sheet1!D2:D5")
document.Save("Updated Chart.%OutputFileType%")
End Sub
End Module
Some chart types are not supported through an API (like 3D charts) and won't be represented with Chart
object.
You can find a list of supported chart types on GemBox.Spreadsheet's Charts help page.
Create chart from array data
Usually, the chart's data is provided as a reference to a worksheet's cell range or a named range. But you can also directly assign an array of numeric values that you want to plot.
Using array data may in some cases be an easier and more convenient way to work with charts, such charts are independent of their parent worksheet. However, note that you cannot add or modify such series with Microsoft Word.
The following example shows how to create chart series using array values directly.

using GemBox.Document;
using GemBox.Spreadsheet.Charts;
class Program
{
static void Main()
{
// If using the Professional version, put your GemBox.Document serial key below.
ComponentInfo.SetLicense("FREE-LIMITED-KEY");
// If using the Professional version, put your GemBox.Spreadsheet serial key below.
SpreadsheetInfo.SetLicense("FREE-LIMITED-KEY");
var document = new DocumentModel();
var chart = new Chart(document, GemBox.Document.ChartType.Column,
new FloatingLayout(
new HorizontalPosition(HorizontalPositionType.Center, HorizontalPositionAnchor.Margin),
new VerticalPosition(VerticalPositionType.Top, VerticalPositionAnchor.Paragraph),
new Size(10, 5, GemBox.Document.LengthUnit.Centimeter)));
document.Sections.Add(
new Section(document,
new Paragraph(document, chart)));
// Get underlying Excel chart.
var columnChart = (ColumnChart)chart.ExcelChart;
// Set chart's category labels from array.
columnChart.SetCategoryLabels(new string[] { "Columns 1", "Columns 2", "Columns 3" });
// Add chart's series from arrays.
columnChart.Series.Add("Values 1", new double[] { 3.4, 1.1, 3.7 });
columnChart.Series.Add("Values 2", new double[] { 4.4, 3.9, 3.5 });
columnChart.Series.Add("Values 3", new double[] { 2.9, 4.1, 1.9 });
document.Save("Created Chart from Array.%OutputFileType%");
}
}
Imports GemBox.Document
Imports GemBox.Spreadsheet.Charts
Module Program
Sub Main()
' If using the Professional version, put your GemBox.Document serial key below.
ComponentInfo.SetLicense("FREE-LIMITED-KEY")
' If using the Professional version, put your GemBox.Spreadsheet serial key below.
SpreadsheetInfo.SetLicense("FREE-LIMITED-KEY")
Dim document As New DocumentModel()
Dim chart As New Chart(document, GemBox.Document.ChartType.Column,
New FloatingLayout(
New HorizontalPosition(HorizontalPositionType.Center, HorizontalPositionAnchor.Margin),
New VerticalPosition(VerticalPositionType.Top, VerticalPositionAnchor.Paragraph),
New Size(10, 5, GemBox.Document.LengthUnit.Centimeter)))
document.Sections.Add(
New Section(document,
New Paragraph(document, chart)))
' Get underlying Excel chart.
Dim columnChart = DirectCast(chart.ExcelChart, ColumnChart)
' Set chart's category labels from array.
columnChart.SetCategoryLabels(New String() {"Columns 1", "Columns 2", "Columns 3"})
' Add chart's series from arrays.
columnChart.Series.Add("Values 1", New Double() {3.4, 1.1, 3.7})
columnChart.Series.Add("Values 2", New Double() {4.4, 3.9, 3.5})
columnChart.Series.Add("Values 3", New Double() {2.9, 4.1, 1.9})
document.Save("Created Chart from Array.%OutputFileType%")
End Sub
End Module
Export chart
To export a document with a chart to PDF or image format using GemBox.Document, you need to enable WPF. To enable WPF, you need to use a Windows-specific TFM in the project file, and you need to have .NET Windows Desktop Runtime installed.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0-windows</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="GemBox.Document" Version="*" />
<PackageReference Include="GemBox.Spreadsheet" Version="*" />
</ItemGroup>
</Project>
However, using GemBox.Pdf, you can save documents with charts to PDF without using WPF. This is currently the only way to save Word files with charts to PDF on Linux or macOS. The code below demonstrates how to do that.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using GemBox.Document;
using GemBox.Pdf;
using GemBox.Pdf.Content;
using GemBox.Spreadsheet;
using GemBox.Spreadsheet.Charts;
class Program
{
static void Main()
{
// If using the Professional versions, put your serial keys below.
GemBox.Document.ComponentInfo.SetLicense("FREE-LIMITED-KEY");
GemBox.Pdf.ComponentInfo.SetLicense("FREE-LIMITED-KEY");
GemBox.Spreadsheet.SpreadsheetInfo.SetLicense("FREE-LIMITED-KEY");
var document = DocumentModel.Load("%InputFileName%");
var placeholdersMapping = ReplaceChartsWithPlaceholders(document);
document.Save("Chart.pdf");
using (var pdf = PdfDocument.Load("Chart.pdf"))
{
ReplacePlaceholdersWithCharts(pdf, placeholdersMapping);
pdf.Save();
}
}
static readonly string PlaceholderNameFormat = "GemBox_Chart_Placeholder_{0}";
static readonly Regex PlaceholderNameRegex = new Regex("GemBox_Chart_Placeholder_\\d+");
static readonly MemoryStream PlaceholderImage = new MemoryStream(File.ReadAllBytes("%#placeholder.png%"));
static Dictionary<string, MemoryStream> ReplaceChartsWithPlaceholders(DocumentModel document)
{
var placeholdersMapping = new Dictionary<string, MemoryStream>();
int counter = 0;
foreach (Chart chart in document.GetChildElements(true, ElementType.Chart).Reverse())
{
// Replace Word chart with placeholder image that has specific title.
var placeholder = new Picture(document, PlaceholderImage, PictureFormat.Png, chart.Layout);
string placeholderName = string.Format(PlaceholderNameFormat, ++counter);
placeholder.Metadata.Title = placeholderName;
chart.Content.Start.InsertRange(placeholder.Content);
chart.Content.Delete();
// Retrieve Excel chart and export it as PDF.
var excelChart = (ExcelChart)chart.ExcelChart;
excelChart.Position.Width = chart.Layout.Size.Width;
excelChart.Position.Height = chart.Layout.Size.Height;
var chartAsPdfStream = new MemoryStream();
excelChart.Format().Save(chartAsPdfStream, GemBox.Spreadsheet.SaveOptions.PdfDefault);
// Map PDF that contains Excel chart to placeholder name.
placeholdersMapping.Add(placeholderName, chartAsPdfStream);
}
return placeholdersMapping;
}
static void ReplacePlaceholdersWithCharts(PdfDocument pdfDocument, Dictionary<string, MemoryStream> placeholdersMapping)
{
foreach (var page in pdfDocument.Pages)
{
// Find placeholders by searching for images with specific title.
var placeholders = FindPlaceholders(page);
foreach (var placeholder in placeholders)
{
if (!placeholdersMapping.TryGetValue(placeholder.Key, out MemoryStream chartAsPdfStream))
continue;
PdfImageContent image = placeholder.Value.Item1;
PdfQuad bounds = placeholder.Value.Item2;
// Replace placeholder image with PDF that contains Excel chart.
using (var excelDocument = PdfDocument.Load(chartAsPdfStream))
{
var form = excelDocument.Pages[0].ConvertToForm(pdfDocument);
var formContentGroup = page.Content.Elements.AddGroup();
var formContent = formContentGroup.Elements.AddForm(form);
formContent.Transform = PdfMatrix.CreateTranslation(bounds.Left, bounds.Bottom);
}
image.Collection.Remove(image);
}
}
}
static Dictionary<string, Tuple<PdfImageContent, PdfQuad>> FindPlaceholders(PdfPage page)
{
var placeholders = new Dictionary<string, Tuple<PdfImageContent, PdfQuad>>();
var enumerator = page.Content.Elements.All(page.Transform).GetEnumerator();
while (enumerator.MoveNext())
{
var element = enumerator.Current;
if (element.ElementType != PdfContentElementType.Image)
continue;
var imageElement = (PdfImageContent)element;
var metadata = imageElement.Image.Metadata?.Value;
if (metadata == null)
continue;
var match = PlaceholderNameRegex.Match(metadata);
if (!match.Success)
continue;
var bounds = imageElement.Bounds;
enumerator.Transform.Transform(ref bounds);
placeholders.Add(match.Value, Tuple.Create(imageElement, bounds));
}
return placeholders;
}
}
Imports System
Imports System.Collections.Generic
Imports System.IO
Imports System.Linq
Imports System.Text.RegularExpressions
Imports GemBox.Document
Imports GemBox.Pdf
Imports GemBox.Pdf.Content
Imports GemBox.Spreadsheet
Imports GemBox.Spreadsheet.Charts
Module Program
Sub Main()
' If using the Professional versions, put your serial keys below.
GemBox.Document.ComponentInfo.SetLicense("FREE-LIMITED-KEY")
GemBox.Pdf.ComponentInfo.SetLicense("FREE-LIMITED-KEY")
GemBox.Spreadsheet.SpreadsheetInfo.SetLicense("FREE-LIMITED-KEY")
Dim document = DocumentModel.Load("%InputFileName%")
Dim placeholdersMapping = ReplaceChartsWithPlaceholders(document)
document.Save("Chart.pdf")
Using pdf = PdfDocument.Load("Chart.pdf")
ReplacePlaceholdersWithCharts(pdf, placeholdersMapping)
pdf.Save()
End Using
End Sub
ReadOnly PlaceholderNameFormat As String = "GemBox_Chart_Placeholder_{0}"
ReadOnly PlaceholderNameRegex As Regex = New Regex("GemBox_Chart_Placeholder_\d+")
ReadOnly PlaceholderImage As MemoryStream = New MemoryStream(File.ReadAllBytes("%#placeholder.png%"))
Function ReplaceChartsWithPlaceholders(document As DocumentModel) As Dictionary(Of String, MemoryStream)
Dim placeholdersMapping = New Dictionary(Of String, MemoryStream)()
Dim counter As Integer = 0
For Each chart As Chart In document.GetChildElements(True, ElementType.Chart).Reverse()
' Replace Word chart with placeholder image that has specific title.
Dim placeholder = New Picture(document, PlaceholderImage, PictureFormat.Png, chart.Layout)
counter += 1
Dim placeholderName As String = String.Format(PlaceholderNameFormat, counter)
placeholder.Metadata.Title = placeholderName
chart.Content.Start.InsertRange(placeholder.Content)
chart.Content.Delete()
' Retrieve Excel chart and export it as PDF.
Dim excelChart = CType(chart.ExcelChart, ExcelChart)
excelChart.Position.Width = chart.Layout.Size.Width
excelChart.Position.Height = chart.Layout.Size.Height
Dim chartAsPdfStream = New MemoryStream()
excelChart.Format().Save(chartAsPdfStream, GemBox.Spreadsheet.SaveOptions.PdfDefault)
' Map PDF that contains Excel chart to placeholder name.
placeholdersMapping.Add(placeholderName, chartAsPdfStream)
Next
Return placeholdersMapping
End Function
Sub ReplacePlaceholdersWithCharts(pdfDocument As PdfDocument, placeholdersMapping As Dictionary(Of String, MemoryStream))
Dim chartAsPdfStream As MemoryStream = Nothing
For Each page In pdfDocument.Pages
' Find placeholders by searching for images with specific title.
Dim placeholders = FindPlaceholders(page)
For Each placeholder In placeholders
If Not placeholdersMapping.TryGetValue(placeholder.Key, chartAsPdfStream) Then Continue For
Dim image As PdfImageContent = placeholder.Value.Item1
Dim bounds As PdfQuad = placeholder.Value.Item2
' Replace placeholder image with PDF that contains Excel chart.
Using excelDocument = PdfDocument.Load(chartAsPdfStream)
Dim form = excelDocument.Pages(0).ConvertToForm(pdfDocument)
Dim formContentGroup = page.Content.Elements.AddGroup()
Dim formContent = formContentGroup.Elements.AddForm(form)
formContent.Transform = PdfMatrix.CreateTranslation(bounds.Left, bounds.Bottom)
End Using
image.Collection.Remove(image)
Next
Next
End Sub
Function FindPlaceholders(page As PdfPage) As Dictionary(Of String, Tuple(Of PdfImageContent, PdfQuad))
Dim placeholders = New Dictionary(Of String, Tuple(Of PdfImageContent, PdfQuad))()
Dim enumerator = page.Content.Elements.All(page.Transform).GetEnumerator()
While enumerator.MoveNext()
Dim element = enumerator.Current
If element.ElementType <> PdfContentElementType.Image Then Continue While
Dim imageElement = CType(element, PdfImageContent)
Dim metadata = imageElement.Image.Metadata?.Value
If metadata Is Nothing Then Continue While
Dim match = PlaceholderNameRegex.Match(metadata)
If Not match.Success Then Continue While
Dim bounds = imageElement.Bounds
enumerator.Transform.Transform(bounds)
placeholders.Add(match.Value, Tuple.Create(imageElement, bounds))
End While
Return placeholders
End Function
End Module