I am using OpenXML to import excel to a DataTable. My first row is merged to display only Title information and the second row is the header row. While populating DataTable from an excel file, I am getting incorrect data. The DataTable is populating correctly until any blank cell is present. When there are blank cells they are moving to the adjacent data presenting cell. Why is this happening? What is the problem in the code? Could you please help me to get the data in a proper way using OpenXML. Here are my Excel file and Data Table once data is imported.
My code sample is as below:
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace OpenXMLDemo
{
class Program
{
static void Main(string[] args)
{
Program p = new Program();
var data = p.ExtractExcel(@"C:\TempData\");
}
public System.Data.DataTable ExtractExcel(string fullPath)
{
var excelFileToImport = Directory.GetFiles(fullPath, "Data_Import.xlsx", SearchOption.AllDirectories);
//Create a new DataTable.
System.Data.DataTable dt = new System.Data.DataTable();
//Open the Excel file in Read Mode using OpenXML
using (SpreadsheetDocument doc = SpreadsheetDocument.Open(excelFileToImport[0], false))
{
WorksheetPart titlesWorksheetPart = GetWorksheetPart(doc.WorkbookPart, "Titles");
Worksheet titlesWorksheet = titlesWorksheetPart.Worksheet;
//Fetch all the rows present in the worksheet
IEnumerable<Row> rows = titlesWorksheet.GetFirstChild<SheetData>().Descendants<Row>();
//Loop through the Worksheet rows
foreach (Row row in rows)
{
//Use the first row to add columns to DataTable.
if (row.RowIndex.Value == 1)
{
}
else if (row.RowIndex.Value == 2)
{
foreach (Cell cell in row.Descendants<Cell>())
{
dt.Columns.Add(GetValue(doc, cell));
}
}
else
{
//Add rows to DataTable.
dt.Rows.Add();
int i = 0;
foreach (Cell cell in row.Descendants<Cell>())
{
dt.Rows[dt.Rows.Count - 1][i] = GetValue(doc, cell);
i++;
}
}
}
}
return dt;
}
private string GetValue(SpreadsheetDocument doc, Cell cell)
{
string value = cell.CellValue.InnerText;
if (cell.DataType != null && cell.DataType.Value == CellValues.SharedString)
{
return doc.WorkbookPart.SharedStringTablePart.SharedStringTable.ChildElements.GetItem(int.Parse(value)).InnerText;
}
return value;
}
public WorksheetPart GetWorksheetPart(WorkbookPart workbookPart, string sheetName)
{
string relId = workbookPart.Workbook.Descendants<Sheet>().First(s => sheetName.Equals(s.Name)).Id;
return (WorksheetPart)workbookPart.GetPartById(relId);
}
}
}