As per my requirements, I have modified few part of code of 'ExcelUtility' Read() from the best answer by D.L.MAN.
Also added saveDataTablesToExcel() and ExportDataSet() method to save multiple DataTables in xlsx file.
Following is the full code of new 'ExcelUtility' class and it's usage.
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
namespace myNamespace
{
static class ExcelUtility
{
// SS Note: isHeaderOnTopRow functionality is to set column names as the first row of 'sheet'
public static DataTable[] Read(string path, bool isHeaderOnTopRow = false)
{
try
{
using (var ssDoc = SpreadsheetDocument.Open(path, false))
{
var sheets = ssDoc.WorkbookPart.Workbook.GetFirstChild<Sheets>().Elements<Sheet>();
DataTable[] dtArray = new DataTable[sheets.ToList().Count];
int counti = 0;
foreach (Sheet sheet in sheets)
{
var dt = new DataTable();
var relationshipId = sheet.Id.Value;
var worksheetPart = (WorksheetPart)ssDoc.WorkbookPart.GetPartById(relationshipId);
var workSheet = worksheetPart.Worksheet;
var sheetData = workSheet.GetFirstChild<SheetData>();
var rows = sheetData.Descendants<Row>().ToList();
int rowIndex = 0;
foreach (var row in rows) //this will also include your header row...
{
var tempRow = dt.NewRow();
var colCount = row.Descendants<Cell>().Count();
int colIndex = 0;
foreach (var cell in row.Descendants<Cell>())
{
var index = GetIndex(cell.CellReference);
// SS Note: ADDED next line as we were getting cell.CellReference (or index) as -1 in our provided xlsx file.
index = (index < 0 ? colIndex++ : index);
// Add Columns
for (var i = dt.Columns.Count; i <= index; i++)
dt.Columns.Add();
if (isHeaderOnTopRow && rowIndex == 0)
{
string heading = GetCellValue(ssDoc, cell);
heading = (heading.Length > 0 ? heading : $"Column{index + 1}");
dt.Columns[index].ColumnName = heading;
}
else
{
tempRow[index] = GetCellValue(ssDoc, cell);
}
}
if (rowIndex > 0 || isHeaderOnTopRow == false)
{
dt.Rows.Add(tempRow);
}
rowIndex++;
}
dtArray[counti++] = dt;
}
return dtArray;
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
return null;
}
private static string GetCellValue(SpreadsheetDocument document, Cell cell)
{
var stringTablePart = document.WorkbookPart.SharedStringTablePart;
var value = cell.CellValue.InnerXml;
if (cell.DataType != null && cell.DataType.Value == CellValues.SharedString)
return stringTablePart.SharedStringTable.ChildElements[int.Parse(value)].InnerText;
return value;
}
public static int GetIndex(string name)
{
if (string.IsNullOrWhiteSpace(name))
return -1;
int index = 0;
foreach (var ch in name)
{
if (char.IsLetter(ch))
{
int value = ch - 'A' + 1;
index = value + index * 26;
}
else
break;
}
return index - 1;
}
public static void ExportDataSet(DataSet ds, string destination)
{
try
{
using (var workbook = SpreadsheetDocument.Create(destination, DocumentFormat.OpenXml.SpreadsheetDocumentType.Workbook))
{
var workbookPart = workbook.AddWorkbookPart();
workbook.WorkbookPart.Workbook = new DocumentFormat.OpenXml.Spreadsheet.Workbook();
workbook.WorkbookPart.Workbook.Sheets = new DocumentFormat.OpenXml.Spreadsheet.Sheets();
foreach (System.Data.DataTable table in ds.Tables)
{
var sheetPart = workbook.WorkbookPart.AddNewPart<WorksheetPart>();
var sheetData = new DocumentFormat.OpenXml.Spreadsheet.SheetData();
sheetPart.Worksheet = new DocumentFormat.OpenXml.Spreadsheet.Worksheet(sheetData);
DocumentFormat.OpenXml.Spreadsheet.Sheets sheets = workbook.WorkbookPart.Workbook.GetFirstChild<DocumentFormat.OpenXml.Spreadsheet.Sheets>();
string relationshipId = workbook.WorkbookPart.GetIdOfPart(sheetPart);
uint sheetId = 1;
if (sheets.Elements<DocumentFormat.OpenXml.Spreadsheet.Sheet>().Count() > 0)
{
sheetId =
sheets.Elements<DocumentFormat.OpenXml.Spreadsheet.Sheet>().Select(s => s.SheetId.Value).Max() + 1;
}
DocumentFormat.OpenXml.Spreadsheet.Sheet sheet = new DocumentFormat.OpenXml.Spreadsheet.Sheet() { Id = relationshipId, SheetId = sheetId, Name = table.TableName };
sheets.Append(sheet);
DocumentFormat.OpenXml.Spreadsheet.Row headerRow = new DocumentFormat.OpenXml.Spreadsheet.Row();
List<String> columns = new List<string>();
foreach (System.Data.DataColumn column in table.Columns)
{
columns.Add(column.ColumnName);
DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell();
cell.DataType = DocumentFormat.OpenXml.Spreadsheet.CellValues.String;
cell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(column.ColumnName);
headerRow.AppendChild(cell);
}
sheetData.AppendChild(headerRow);
foreach (System.Data.DataRow dsrow in table.Rows)
{
DocumentFormat.OpenXml.Spreadsheet.Row newRow = new DocumentFormat.OpenXml.Spreadsheet.Row();
foreach (String col in columns)
{
DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell();
cell.DataType = DocumentFormat.OpenXml.Spreadsheet.CellValues.String;
cell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(dsrow[col].ToString()); //
newRow.AppendChild(cell);
}
sheetData.AppendChild(newRow);
}
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
public static void saveDataTablesToExcel(DataTable[] dataTables, string saveToFilePath)
{
// Create a DataSet
DataSet dataSet = new DataSet("Tables");
// We can add multiple DataTable to DataSet
foreach (DataTable dt in dataTables)
{
dataSet.Tables.Add(dt);
}
ExportDataSet(dataSet, saveToFilePath);
}
}
}
Usage :
// save three datatables in xlsx file
DataTable[] dataTables = new DataTable[3];
dataTables[0] = firstDataTable;
dataTables[1] = secondDataTable;
dataTables[2] = thirdDataTable;
string fileName = "saved.xlsx";
saveDataTablesToExcel(dataTables, $"{ExcelFileSaveFolder}{fileName}");
// retrieve data from first sheet and set it to 'returnTable'
DataTable returnTable = null;
var path = $"{ExcelFileSaveFolder}{fileName}";
DataTable[] getDataTables = ExcelUtility.Read(path, true);
if (getDataTables != null && getDataTables.Length > 0)
returnTable = getDataTables[0];