Click here to Skip to main content
15,881,872 members
Articles / Productivity Apps and Services / Microsoft Office / Microsoft Excel
Article

Using Excel 2019 Features in Aspose.Cells

13 Dec 2019CPOL 4K   1  
In this article, I’ll demonstrate how to use Aspose.Cells to create a spreadsheet that takes advantage of a few new Excel 2019 features.

This article is in the Product Showcase section for our sponsors at CodeProject. These articles are intended to provide you with information on products and services that we consider useful and of value to developers.

It’s no secret that working with Excel documents in .NET is notoriously tricky. In fact, back in the early days, it was downright tough. These days, .NET developers have a much easier job when it comes to generating, modifying, converting, or rendering spreadsheets. But even with modern components for manipulating spreadsheets at your disposal, getting your project completed can be difficult if the component you use doesn’t keep up with the latest Excel features.

With Aspose.Cells, creating spreadsheets is, quite frankly, a cakewalk, and the easy-to-use API now includes the ability to work with Excel 2019 formulas.

In this article, I’ll demonstrate how to use Aspose.Cells to create a spreadsheet that takes advantage of a few new Excel 2019 features. Some of the code I demonstrate might seem long-winded, but I want to be as clear as possible without obfuscating any logic.

Setting Up Your Project

The easiest way to start using Aspose.Cells is to use NuGet to download the required DLLs. I created a simple WinForms application that calls some code for creating the Excel document on a button click.

To add the NuGet package to your project, right-click on your solution and click Manage NuGet Packages. Search for "Aspose.Cells" and NuGet will display it as the first result. Now you can add the latest version of Aspose.Cells to your project.

Image 1

Once NuGet has installed the packages, you’ll see the Aspose.Cells reference added to your project:

Image 2

Now let’s start creating some spreadsheets.

The Complete Solution

The spreadsheet we’re going to create will use the following formulas:

  • MAXIFS
  • MINIFS
  • IFS
  • SWITCH
  • CONCAT
  • TEXTJOIN

The project will also illustrate how to add these charts to a spreadsheet:

  • BoxWhisker
  • Funnel
  • ParetoLine
  • Sunburst
  • Treemap
  • Waterfall
  • Map

Let’s have a look at the formulas first.

We’ll create a spreadsheet that displays student scores for two semesters. Each score will receive a grade.

To display the grade, we’ll use the IFS formula.

Depending on the grade, we’ll use the SWITCH formula to display some text: Try harder, Ok, Good, Great or Excellent.

We’ll then use the CONCAT formula to concatenate the student name, grade, and text result.

Image 3

Next we’ll display the highest and lowest scores for each semester. For this we’ll use the MAXIFS and MINIFS formulas.

Image 4

Finally, we’ll use the TEXTJOIN formula to output the full name of each student, ignoring any blank cells.

Image 5

Writing the Code

The first step is to add the required using statement:

using Aspose.Cells;

Next, we need to create a workbook and the path where the generated Excel document should be saved:

var wbook = new Workbook();
var pth = "C:/temp/aspose/";

Now create a method called SetupFormulaWorkbookData and pass it the worksheet, as follows:

private void SetupFormulaWorkbookData(Worksheet ws)
{
}

We’ll add code to this method in a minute. Let’s finish off the calling code first. Add a call to the SetupFormulaWorkbookData method and set the name of the worksheet to "Formulas". Then save the document in .xlsx format with the file name "1-Formulas.xlsx":

SetupFormulaWorkbookData(wbook.Worksheets[0]);
var ws = wbook.Worksheets[0];
ws.Name = "Formulas";
wbook.Save($"{pth}1-Formulas.xlsx", SaveFormat.Xlsx);

We need to write the code for the SetupFormulaWorkbookData method, but first we need to set up some data to work with. We’ll just hardcode these values for this example, but you could read data from a database or from a file.

Add the heading data needed:

ws.Cells["B2"].PutValue("Name");
ws.Cells["C2"].PutValue("Semester");
ws.Cells["D2"].PutValue("Score");
ws.Cells["E2"].PutValue("Grade");

Here are the hardcoded student names I used:

#region Add Names
ws.Cells["B3"].PutValue("John");
ws.Cells["B4"].PutValue("Lidia");
ws.Cells["B5"].PutValue("Mark");
ws.Cells["B6"].PutValue("Anne");
ws.Cells["B7"].PutValue("Hayley");
ws.Cells["B8"].PutValue("Lane");
ws.Cells["B9"].PutValue("Peter");
ws.Cells["B10"].PutValue("James");
ws.Cells["B11"].PutValue("Mary");
ws.Cells["B12"].PutValue("John");
ws.Cells["B13"].PutValue("Lidia");
ws.Cells["B14"].PutValue("Mark");
ws.Cells["B15"].PutValue("Anne");
ws.Cells["B16"].PutValue("Hayley");
ws.Cells["B17"].PutValue("Lane");
ws.Cells["B18"].PutValue("Peter");
ws.Cells["B19"].PutValue("James");
ws.Cells["B20"].PutValue("Mary");
#endregion

Next, add semesters 1 and 2 to the data:

#region Add Semesters
ws.Cells["C3"].PutValue(1);
ws.Cells["C4"].PutValue(2);
ws.Cells["C5"].PutValue(1);
ws.Cells["C6"].PutValue(2);
ws.Cells["C7"].PutValue(1);
ws.Cells["C8"].PutValue(1);
ws.Cells["C9"].PutValue(2);
ws.Cells["C10"].PutValue(1);
ws.Cells["C11"].PutValue(2);
ws.Cells["C12"].PutValue(2);
ws.Cells["C13"].PutValue(1);
ws.Cells["C14"].PutValue(2);
ws.Cells["C15"].PutValue(1);
ws.Cells["C16"].PutValue(2);
ws.Cells["C17"].PutValue(2);
ws.Cells["C18"].PutValue(1);
ws.Cells["C19"].PutValue(2);
ws.Cells["C20"].PutValue(1);
#endregion

Finally, add the student scores:.

#region Add Scores
ws.Cells["D3"].PutValue(75);
ws.Cells["D4"].PutValue(65);
ws.Cells["D5"].PutValue(15);
ws.Cells["D6"].PutValue(75);
ws.Cells["D7"].PutValue(95);
ws.Cells["D8"].PutValue(56);
ws.Cells["D9"].PutValue(72);
ws.Cells["D10"].PutValue(88);
ws.Cells["D11"].PutValue(24);
ws.Cells["D12"].PutValue(61);
ws.Cells["D13"].PutValue(72);
ws.Cells["D14"].PutValue(97);
ws.Cells["D15"].PutValue(17);
ws.Cells["D16"].PutValue(63);
ws.Cells["D17"].PutValue(84);
ws.Cells["D18"].PutValue(48);
ws.Cells["D19"].PutValue(65);
ws.Cells["D20"].PutValue(68);
#endregion

Of course, you can easily create this code using loops and reading the data from a file or database, but for simplicity sake, I just hardcoded the data.

The IFS Formula

We want to be able to display the grade of the student based on the score received, so we’ll use the IFS function.

Notice that in Excel you use a semicolon in the formula, but in Aspose.Cells, you need to use commas in the code instead of semicolons. To display the grades, we’ll loop through cells D3 to D20 and, if the cell value matches our condition, we’ll output a result of Fail, C, B, A or A+ in column E:

// IFS Formula
// eg: =IFS(D3<60;"Fail";D3<70;"C";D3<80;"B";D3<90;"A";D3>=90;"A+")
for (var i = 3; i <=20; i++)
{
    ws.Cells[$"E{i}"].Formula = $"=IFS(D{i}<60,\"Fail\",D{i}<70,\"C\",D{i}<80,\"B\",D{i}<90,\"A\",D{i}>=90,\"A +\")";
}

The SWITCH Formula

The same looping logic will be used to display some text based on the grade received. The text will be displayed in column F3 to F20 and will be based on the grades in column E3 to E20:

// SWITCH Formula
// eg: =SWITCH(E3;"Fail";"Try harder";"C";"Ok";"B";"Good";"A";"Great";"A+";"Excellent")
for (var i = 3; i <= 20; i++)
{
    ws.Cells[$"F{i}"].Formula = $"=SWITCH(E{i},\"Fail\",\"Try harder\",\"C\",\"Ok\",\"B\",\"Good\",\"A\",\"Great\",\"A +\",\"Excellent\")";
}

The CONCAT Formula

The CONCAT formula will use the name cells, the grade cells, and the text output to create a string that displays a message to the student. Again, we can use a loop to create the formula for each cell:

// CONCAT Formula
// eg: =CONCAT(B3;" - Result: "; E3; " - "; F3)
for (var i = 3; i <= 20; i++)
{
    ws.Cells[$"G{i}"].Formula = $"=CONCAT(B{i},\" - Your result: \", E{i}, \" - \", F{i})";
}

The MAXIFS and MINIFS Formulas

We now want to create the formulas to display the highest and lowest scores for each semester.

First, we need to add the header text and then the values for each semester as follows:

#region Results
ws.Cells["J2"].PutValue("Semester");
ws.Cells["K2"].PutValue("Highest");
ws.Cells["L2"].PutValue("Lowest");

ws.Cells["J3"].PutValue(1);
ws.Cells["J4"].PutValue(2);
#endregion

Next, we create the MAXIFS and MINIFS formulas for the highest and lowest cells for each semester:

var maxFirstSemesterCell = ws.Cells["K3"];
maxFirstSemesterCell.Formula = "=MAXIFS(D3:D20,C3:C20,\"1\")";

var maxSecondSemesterCell = ws.Cells["K4"];
maxSecondSemesterCell.Formula = "=MAXIFS(D3:D20,C3:C20,\"2\")";

var minFirstSemesterCell = ws.Cells["L3"];
minFirstSemesterCell.Formula = "=MINIFS(D3:D20,C3:C20,\"1\")";

var minSecondSemesterCell = ws.Cells["L4"];
minSecondSemesterCell.Formula = "=MINIFS(D3:D20,C3:C20,\"2\")";

The TEXTJOIN Formula

Finally, we want to generate full names for each student, including their first name, last name, and if they have it, a middle name. If they don’t have a middle name, the empty cell needs to be ignored.

Start by creating the data for the headings—the first, middle and last names:

#region Name Details
ws.Cells["B23"].PutValue("First name");
ws.Cells["C23"].PutValue("Middle name");
ws.Cells["D23"].PutValue("Last name");
ws.Cells["E23"].PutValue("Full name");

ws.Cells["B24"].PutValue("John");
ws.Cells["B25"].PutValue("Lidia");
ws.Cells["B26"].PutValue("Mark");
ws.Cells["B27"].PutValue("Anne");
ws.Cells["B28"].PutValue("Hayley");
ws.Cells["B29"].PutValue("Lane");
ws.Cells["B30"].PutValue("Peter");
ws.Cells["B31"].PutValue("James");
ws.Cells["B32"].PutValue("Mary");

ws.Cells["C24"].PutValue("Reginald");
ws.Cells["C27"].PutValue("Mary");
ws.Cells["C28"].PutValue("Lindy");
ws.Cells["C30"].PutValue("Lee");

ws.Cells["D24"].PutValue("Van Zandt");
ws.Cells["D25"].PutValue("Cunningham");
ws.Cells["D26"].PutValue("Lester");
ws.Cells["D27"].PutValue("Joseph");
ws.Cells["D28"].PutValue("Miller");
ws.Cells["D29"].PutValue("Bower");
ws.Cells["D30"].PutValue("Sanders");
ws.Cells["D31"].PutValue("Williams");
ws.Cells["D32"].PutValue("Davis");
#endregion

Now use another loop to create the full name for each student, ignoring any empty cells:

// TEXTJOIN Function
// eg: =TEXTJOIN(" "; TRUE; B24:D24)
for (var i = 24; i <= 32; i++)
{
    ws.Cells[$"E{i}"].Formula = $"=TEXTJOIN(\" \", TRUE, B{i}:D{i})";
}

Once you’ve set up all the data and formulas, running your application will generate an Excel document with the logic displayed earlier.

As you can see, creating Excel documents with formulas is very straightforward with Aspose.Cells.

Charts

Creating charts with Aspose.Cells is also pretty straightforward. What was traditionally a tricky process is much easier with Aspose.Cells. In fact, much of the same code can be used for the different charts.

We’ll create new Excel documents for each chart type. Let’s start off with a BoxWhisker chart.

The BoxWhisker Chart

The data we’ll use to generate the BoxWhisker chart is the volume of produce (Oranges, Apples, Pears and Grapes) for three years (2014, 2015 and 2016):

Image 6

To use this data, start by creating a method called SetupBoxWhiskerChart that takes a Worksheet parameter:

private void SetupBoxWhiskerChart(Worksheet ws)
{
}

Next, create the headings for each column of data:

ws.Cells["B2"].PutValue("Produce");
ws.Cells["C2"].PutValue("Year 2014");
ws.Cells["D2"].PutValue("Year 2015");
ws.Cells["E2"].PutValue("Year 2016");

Now we’ll create the data for the produce (Oranges, Apples, Pears and Grapes). To do this, we’ll change things up a bit and use a loop with if statements to add each produce type four times (assume these are per term).

for (var i = 3; i <= 18; i++)
{
    if (i == 3 || i == 7 || i == 11 || i == 15)
        ws.Cells[$"B{i}"].PutValue("Oranges");

    if (i == 4 || i == 8 || i == 12 || i == 16)
        ws.Cells[$"B{i}"].PutValue("Apples");

    if (i == 5 || i == 9 || i == 13 || i == 17)
        ws.Cells[$"B{i}"].PutValue("Pears");

    if (i == 6 || i == 10 || i == 14 || i == 18)
        ws.Cells[$"B{i}"].PutValue("Grapes");
}

Next we’ll seed the year columns with random values for the amount produced in that year. For this, we’ll just use .NET’s built-in Random class. Note that if you require true random values, you need to create secure random numbers using RNGCryptoServiceProvider. We don’t require that level of randomness, so we’ll just use pseudo-random numbers.

var rnd = new Random();

for (var i = 3; i <= 18; i++)
{
    ws.Cells[$"C{i}"].PutValue(rnd.Next(10000, 70000));
    ws.Cells[$"D{i}"].PutValue(rnd.Next(10000, 70000));
    ws.Cells[$"E{i}"].PutValue(rnd.Next(10000, 70000));
}

Now we tell the worksheet which chart to create and then return the chartIndex for that chart. The values (6, 6, 25, 15) that follow ChartType.BoxWhisker specify the location of the chart in your Excel document.

var chartIndex = ws.Charts.Add(ChartType.BoxWhisker, 6, 6, 25, 15);

Add the series and category data to the chart. The series are each of the columns containing the volume data, and the category data defines the produce types (Oranges, Apples, Pears and Grapes).

var chart = ws.Charts[chartIndex];

_ = chart.NSeries.Add("=C3:C18", true);
_ = chart.NSeries.Add("=D3:D18", true);
_ = chart.NSeries.Add("=E3:E18", true);

chart.NSeries.CategoryData = "=B3:B18";

We now write our calling code:

var wbook = new Workbook();
var pth = "C:/temp/aspose/";
SetupBoxWhiskerChart(wbook.Worksheets[0]);
var ws = wbook.Worksheets[0];
ws.Name = "Charts";
wbook.Save($"{pth}2-BoxWhisker.xlsx", SaveFormat.Xlsx);

If you run the application now, you’ll see that the following BoxWhisker chart has been created:

Image 7

That’s how easy it is to generate a chart in Aspose.Cells!

The Funnel Chart

Let’s mix things up a bit. Modify your SetupBoxWhiskerChart by renaming it to SetupChart and let it take an addition parameter of ChartType.

private void SetupChart(Worksheet ws, ChartType chrtType)
{
}

Now, keeping all the code exactly the same, just change the line that specifies the chart type and use the chrtType parameter passed into the method.

var chartIndex = ws.Charts.Add(chrtType, 6, 6, 25, 15);

If all is correct, your method should look as follows:

private void SetupChart(Worksheet ws, ChartType chrtType)
{
    ws.Cells["B2"].PutValue("Produce");
    ws.Cells["C2"].PutValue("Year 2014");
    ws.Cells["D2"].PutValue("Year 2015");
    ws.Cells["E2"].PutValue("Year 2016");

    for (var i = 3; i <= 18; i++)
    {
        if (i == 3 || i == 7 || i == 11 || i == 15)
            ws.Cells[$"B{i}"].PutValue("Oranges");

        if (i == 4 || i == 8 || i == 12 || i == 16)
            ws.Cells[$"B{i}"].PutValue("Apples");

        if (i == 5 || i == 9 || i == 13 || i == 17)
            ws.Cells[$"B{i}"].PutValue("Pears");

        if (i == 6 || i == 10 || i == 14 || i == 18)
            ws.Cells[$"B{i}"].PutValue("Grapes");
    }

    var rnd = new Random();

    for (var i = 3; i <= 18; i++)
    {
        ws.Cells[$"C{i}"].PutValue(rnd.Next(10000, 70000));
        ws.Cells[$"D{i}"].PutValue(rnd.Next(10000, 70000));
        ws.Cells[$"E{i}"].PutValue(rnd.Next(10000, 70000));
    }

    var chartIndex = ws.Charts.Add(chrtType, 6, 6, 25, 15);
    var chart = ws.Charts[chartIndex];

    _ = chart.NSeries.Add("=C3:C18", true);
    _ = chart.NSeries.Add("=D3:D18", true);
    _ = chart.NSeries.Add("=E3:E18", true);

    chart.NSeries.CategoryData = "=B3:B18";
}

Now you can modify your calling code slightly to create the workbook and set up the chart data, then pass it the chart type to generate. Rename the worksheet before saving the new Excel file.

var wbook = new Workbook();
var pth = "C:/temp/aspose/";
SetupChart(wbook.Worksheets[0], ChartType.Funnel);
var ws = wbook.Worksheets[0];
ws.Name = "Charts";
wbook.Save($"{pth}3-Funnel.xlsx", SaveFormat.Xlsx);

After creating the Excel document, open it and you’ll see the Funnel chart generated from the data for volume produce.

Image 8

We can continue to create different charts using the exact same method, just changing the chart type passed to the method, as you’ll see below.

The ParetoLine Chart

Using the same method as before, let’s create a ParetoLine chart. Our calling code will change as follows:

SetupChart(wbook.Worksheets[0], ChartType.ParetoLine);
var ws = wbook.Worksheets[0];
ws.Name = "Charts";
wbook.Save($"{pth}4-Pareto.xlsx", SaveFormat.Xlsx);

This generates the following chart:

Image 9

Again, the same method has generated a totally different chart type with minimal code changes.

The Sunburst Chart

The next chart type we’ll generate is the Sunburst. Modify the calling code as follows:

SetupChart(wbook.Worksheets[0], ChartType.Sunburst);
var ws = wbook.Worksheets[0];
ws.Name = "Charts";
wbook.Save($"{pth}5-Sunburst.xlsx", SaveFormat.Xlsx);

The resulting chart will be created in the saved Excel document and will look like this:

Image 10

There are two more charts we’ll generate using our SetupChart method: the Treemap and Waterfall charts. I'm sure by this point you'll notice that the code needed to create the charts is simple and consistent. This makes it easy for you to set up code to accommodate whatever chart type your users might need.

The Treemap Chart

Modify the calling code as follows:

SetupChart(wbook.Worksheets[0], ChartType.Treemap);
var ws = wbook.Worksheets[0];
ws.Name = "Charts";
wbook.Save($"{pth}6-Treemap.xlsx", SaveFormat.Xlsx);

The Treemap chart, shown below, is created in the saved Excel document.

Image 11

The Waterfall Chart

As before, modify the calling code to pass the Waterfall chart type:

SetupChart(wbook.Worksheets[0], ChartType.Waterfall);
var ws = wbook.Worksheets[0];
ws.Name = "Charts";
wbook.Save($"{pth}7-Waterfall.xlsx", SaveFormat.Xlsx);

The Waterfall chart, which looks like the following, is created in the saved Excel document.

Image 12

The Map Chart

The last chart type we’ll look at is the Map chart. Here’s the data we’ll use to generate this chart:

Image 13

First, create a method called SetupMapChart that takes a Worksheet as parameter:

private void SetupMapChart(Worksheet ws)
{
}

Next, create the column headings:

ws.Cells["B2"].PutValue("Country");
ws.Cells["C2"].PutValue("Sales");

Then add some countries under the Country heading:

ws.Cells[$"B3"].PutValue("South Africa");
ws.Cells[$"B4"].PutValue("Canada");
ws.Cells[$"B5"].PutValue("India");
ws.Cells[$"B6"].PutValue("France");

Again, we use the Random class to generate random sales volumes for each country. These random numbers will be between 50,000 and 70,000.

var rnd = new Random();

for (var i = 3; i <= 6; i++)
{
    ws.Cells[$"C{i}"].PutValue(rnd.Next(50000, 70000));
}

As before, create a chart type of Map and add the series and category data:

var chartIndex = ws.Charts.Add(ChartType.Map, 6, 6, 25, 15);
var chart = ws.Charts[chartIndex];

_ = chart.NSeries.Add("=C3:C6", true);

chart.NSeries.CategoryData = "=B3:B6";

Now call the SetupMapChart method and save the Excel document as follows:

SetupMapChart(wbook.Worksheets[0]);
var ws = wbook.Worksheets[0];
ws.Name = "Charts";
wbook.Save($"{pth}8-Map.xlsx", SaveFormat.Xlsx);

This will result in the following Map chart being generated.

Image 14

You can see that the countries are highlighted in a darker shade of blue as the sales volumes increase. The lightest blue color indicates the lowest volume in sales.

Conclusion

This article only briefly touches on the different charts and formulas you can create using Aspose.Cells, and this is but a tiny part of what you can do using Aspose.Cells. To learn more about what Aspose.Cells can do for you, have a look at their web page.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
South Africa South Africa
With over 17 years of experience programming with C# and Visual Studio, I have worked for various companies throughout my career. I have been privileged to work with and learn from some of the most brilliant developers in the industry. I have authored several books on topics ranging from Visual Studio and C# to ASP.NET Core. I am passionate about writing code and love learning new tech and imparting what I know to others.

Comments and Discussions

 
-- There are no messages in this forum --