Generate Excel With (NPOI) in C#
Tags: csharp, dotnet
Published: 2020-01-29 10:26:26

Generating an Excel based on some data-set is one of these tasks that you have to do from time to time as a developer.
Normally, I don't get much of these scenarios when I have to generate an excel, and when I do, I almost forgetting about how is done partially at least.

So, I've decided to document a sample and share it out, as it might help someone out there to refresh the vagueness.

Without further due, here we go:

Obviously, the first step would be installing the NPOI library using NuGet which is straight forward process.

NPOI consist of many namespaces, but for now our focus would be on only two:
```c#
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
```
We will need <code>NPOI.HSSF.UserModel</code> to be able to use the <code>HSSFWorkbook</code>,<code>HSSFFont</code>, <code>HSSFCellStyle</code> and others needed objects.
While <code>using NPOI.SS.UserModel;</code> will be used to define <code>ISheet</code>,<code>IRow</code>,<code>ICell</code> and other required objects.

The Logic of creating an excel is simple:
1. Define a Workbook.
2. Create a Sheet to the workbook.
3. Add Rows and Cells to the Sheet.

Now before I dive into creating rows & cells, I'll just write a function to create a cell for us, so instead of writing
```c#
ICell Cell = CurrentRow.CreateCell(CellIndex);
            Cell.SetCellValue(Value);
```
everytime we need to create a cell, we just create this function:
```c#
private void CreateCell(IRow CurrentRow, int CellIndex, string Value, HSSFCellStyle Style)
        {
            ICell Cell = CurrentRow.CreateCell(CellIndex);
            Cell.SetCellValue(Value);
            Cell.CellStyle = Style;
        }
```

So, creating a cell now is just:
```c#
 CreateCell(HeaderRow, CellIndex, "Column Value", CellStyle);
```

Now, let's start creating an excel based on defined headers and given data collection.
```c#
            HSSFWorkbook workbook = new HSSFWorkbook();
            HSSFFont myFont = (HSSFFont)workbook.CreateFont();
            myFont.FontHeightInPoints = 11;
            myFont.FontName = "Tahoma";


            // Defining a border
            HSSFCellStyle borderedCellStyle = (HSSFCellStyle)workbook.CreateCellStyle();
            borderedCellStyle.SetFont(myFont);
            borderedCellStyle.BorderLeft = BorderStyle.Medium;
            borderedCellStyle.BorderTop = BorderStyle.Medium;
            borderedCellStyle.BorderRight = BorderStyle.Medium;
            borderedCellStyle.BorderBottom = BorderStyle.Medium;
            borderedCellStyle.VerticalAlignment = VerticalAlignment.Center;

            ISheet Sheet = workbook.CreateSheet("Report");
            //Creat The Headers of the excel
            IRow HeaderRow = Sheet.CreateRow(0);
        
            //Create The Actual Cells
            CreateCell(HeaderRow, 0, "Batch Name", borderedCellStyle);
            CreateCell(HeaderRow, 1, "RuleID", borderedCellStyle);
            CreateCell(HeaderRow, 2, "Rule Type", borderedCellStyle);
            CreateCell(HeaderRow, 3, "Code Message Type", borderedCellStyle);
            CreateCell(HeaderRow, 4, "Severity", borderedCellStyle);

            // This Where the Data row starts from
            int RowIndex = 1;
            
            //Iteration through some collection
            foreach (BatchErrorReport batchErrorReport in BatchErrorReports)
            {
                //Creating the CurrentDataRow
                IRow CurrentRow = Sheet.CreateRow(RowIndex);
                CreateCell(CurrentRow, 0, batchErrorReport.Name, borderedCellStyle);
                // This will be used to calculate the merge area
                int NumberOfRules = batchErrorReport.Rules.Count;
                if (NumberOfRules > 1)
                {
                    int MergeIndex = (NumberOfRules - 1) + RowIndex;

                //Merging Cells
                    NPOI.SS.Util.CellRangeAddress MergedBatch = new NPOI.SS.Util.CellRangeAddress(RowIndex, MergeIndex, 0, 0);
                    Sheet.AddMergedRegion(MergedBatch);
                }
                int i = 0;
                // Iterate through cub collection
                foreach (BatchDataQuality batchDataQuality in batchErrorReport.Rules)
                {
                    if (i > 0)
                        CurrentRow = Sheet.CreateRow(RowIndex);
                    CreateCell(CurrentRow, 1, batchDataQuality.RuleID, borderedCellStyle);
                    CreateCell(CurrentRow, 2, batchDataQuality.RuleType, borderedCellStyle);
                    CreateCell(CurrentRow, 3, batchDataQuality.CodeMessageType, borderedCellStyle);
                    CreateCell(CurrentRow, 4, batchDataQuality.Severity, borderedCellStyle);
                    RowIndex++;
                    i++;
                }
                RowIndex = NumberOfRules >= 1 ? RowIndex : RowIndex + 1;
            }
          // Auto sized all the affected columns
          int lastColumNum = Sheet.GetRow(0).LastCellNum;
          for (int i = 0; i <= lastColumNum; i++)
          {
              Sheet.AutoSizeColumn(i);
                GC.Collect();
          }
         // Write Excel to disk 
          using (var fileData = new FileStream(Utility.DOCUMENT_PATH + "ReportName.xls", FileMode.Create))
            {
                workbook.Write(fileData);
            }
```

This would produce something like this:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/mvcgnbar6nc7emi9ulfq.jpg)