C# Problem opening excel file using `OpenXml` from `byte[]` - c#

I have a problem when saving and opening a file with OpenXml library. Here is my code:
public static void SaveExcel(List<Dictionary<string, object>> listData, List<string> entityTypes, string appName)
{
using (var ms = new MemoryStream())
using (var excel = SpreadsheetDocument.Create(ms, SpreadsheetDocumentType.Workbook))
{
var workBookPart = excel.AddWorkbookPart();
workBookPart.Workbook = new Workbook();
var workSheetPart = workBookPart.AddNewPart<WorksheetPart>();
var workSheetData = new SheetData();
workSheetPart.Worksheet = new Worksheet(workSheetData);
var sheets = workBookPart.Workbook.AppendChild(new Sheets());
var index = 1;
foreach (var entityType in entityTypes)
{
var sheet = new Sheet
{
Id = excel.WorkbookPart.GetIdOfPart(workSheetPart),
SheetId = 1U,
Name = entityType
};
sheets.AppendChild(sheet);
}
workBookPart.Workbook.Save(ms);
File.WriteAllBytes("D:/nothing123.xlsx", ms.ToArray());
}
}
I am pretty sure I did the right thing though I have this error when opening the file:
Excel cannot be opened the file 'nothing123.xlsx' because the file format or file extension is not valid. Verify that the file has not been corrupted and the file extension matches the format of the file.
Any idea whats going on with my code?

I don't know if this is relevant to the tag but I made up my mind to use ClosedXml library since it's much easier to use than OpenXml. I can easily create a DataTable and create an Excel file out of the DataTable which is very convenient. Here is my quick sample code:
Sample Data Table
public DataTable getData() {
DataTable dt = new DataTable();
dt.TableName = "SheetName1";
dt.Columns.Add("FirstName");
dt.Columns.Add("LastName");
var row = dt.NewRow();
row["FirstName"] = "Alvin";
row["LastName"] = "Quezon";
dt.Rows.Add(row);
return dt;
}
Sample Code to Excel to Byte Array
public static byte[] GetExcelBytes(DataTable dataTable)
{
using (var ms = new MemoryStream())
using (var workBook = new XLWorkbook())
{
workBook.Worksheets.Add(dataTable);
workBook.SaveAs(ms);
return ms.ToArray();
}
}
I didn't get any issue when opening the file and with superb minimal code usage.
Hopefully this will help anyone would like to use this in the future.

Related

Export to excel returns Blank sheet

I am trying to export a datatable using closed xml but it gives me blank sheet.
Here is my code
[HttpPost]
public FileResult ExportExcel()
{
List<ProductModel> productDetails = (List<ProductModel>)Session["CartItems"];
System.Data.DataTable dtExcel = CategoryDAL.ToDataTable(productDetails);
using (XLWorkbook wb = new XLWorkbook())
{
wb.Worksheets.Add(dtExcel);
using (MemoryStream stream = new MemoryStream())
{
wb.SaveAs(stream);
return File(stream.ToArray(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "Grid.xlsx");
}
}
}
When I debug I can see that datatable has the data but it exports a blank one
Hey I've written an excelexporter for our proposes on my own.
I used this tutorial to get started with excel exporting:
http://www.dispatchertimer.com/tutorial/how-to-create-an-excel-file-in-net-using-openxml-part-2-export-a-collection-to-spreadsheet/
http://www.dispatchertimer.com/tutorial/how-to-create-an-excel-file-in-net-using-openxml-part-3-add-stylesheet-to-the-spreadsheet/ (for styling proposes)
and here is a code snippet how I run an excel export in a controller:
public async Task<FileResult> DownloadExcel(long id, CancellationToken token)
{
var entites= await _someRepository.GetSomethingAsync(id, token).ConfigureAwait(false);
var report = _excelExporter.Export(entites.OrderByDescending(d => d.Date));
return File(report, MimeTypes.GetMimeType("excel.xlsx"), $"entities.xlsx");
}
Generating the excel spreadsheet is done with a memory stream. Here are some lines how I begin creating the excel file:
using (MemoryStream mem = new MemoryStream())
{
using (var document = SpreadsheetDocument.Create(mem, SpreadsheetDocumentType.Workbook))
{
var workbookPart = document.AddWorkbookPart();
workbookPart.Workbook = new Workbook();
var worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
worksheetPart.Worksheet = new Worksheet();
var sheets = workbookPart.Workbook.AppendChild(new Sheets());
var sheet = new Sheet
{
Id = workbookPart.GetIdOfPart(worksheetPart),
SheetId = 1,
Name = "Report"
};
sheets.Append(new[] { sheet });
workbookPart.Workbook.Save();
var sheetData = worksheetPart.Worksheet.AppendChild(new SheetData());
// Constructing header
var row = new Row();
// This needs to get adjusted for your needs
// it returns IEnumerable<Cell>
row.Append(GenerateHeaderCells(/*FillMe*/));
// Insert the header row to the Sheet Data
sheetData.AppendChild(row);
foreach (var entity in data)
{
row = new Row();
//This needs to get adjusted
// it returns IEnumerable<Cell>
row.Append(GenerateCells(/*FillMe*/));
sheetData.AppendChild(row);
}
worksheetPart.Worksheet.Save();
}
return mem.ToArray();
}
I had no MS-Office installed on my system and my requirement was to generate the file and send it to email. So ultimate goal was to send the excel to admin user. When i wrote the code to send it to email and checked email, excel showed the data but when I was returning it from the same code, It was blank sheet. Maybe I should have used interop dlls.

Using ExcelDataReader to read Excel data starting from a particular cell

I am using ExcelDataReader to read data from my Excel workbook in C#.
But structure of my Excel sheet is such that data to be read can start from any particular cell and not necessarily A1.
Can any one Please suggest a way on how this can be achieved using ExcelDataReader?
If you are using ExcelDataReader 3+ you will find that there isn't any method for AsDataSet() for your reader object, You need to also install another package for ExcelDataReader.DataSet, then you can use the AsDataSet() method.
Also there is not a property for IsFirstRowAsColumnNames instead you need to set it inside of ExcelDataSetConfiguration.
Example:
using (var stream = File.Open(originalFileName, FileMode.Open, FileAccess.Read))
{
IExcelDataReader reader;
// Create Reader - old until 3.4+
////var file = new FileInfo(originalFileName);
////if (file.Extension.Equals(".xls"))
//// reader = ExcelDataReader.ExcelReaderFactory.CreateBinaryReader(stream);
////else if (file.Extension.Equals(".xlsx"))
//// reader = ExcelDataReader.ExcelReaderFactory.CreateOpenXmlReader(stream);
////else
//// throw new Exception("Invalid FileName");
// Or in 3.4+ you can only call this:
reader = ExcelDataReader.ExcelReaderFactory.CreateReader(stream)
//// reader.IsFirstRowAsColumnNames
var conf = new ExcelDataSetConfiguration
{
ConfigureDataTable = _ => new ExcelDataTableConfiguration
{
UseHeaderRow = true
}
};
var dataSet = reader.AsDataSet(conf);
// Now you can get data from each sheet by its index or its "name"
var dataTable = dataSet.Tables[0];
//...
}
You can find row number and column number of a cell reference like this:
var cellStr = "AB2"; // var cellStr = "A1";
var match = Regex.Match(cellStr, #"(?<col>[A-Z]+)(?<row>\d+)");
var colStr = match.Groups["col"].ToString();
var col = colStr.Select((t, i) => (colStr[i] - 64) * Math.Pow(26, colStr.Length - i - 1)).Sum();
var row = int.Parse(match.Groups["row"].ToString());
Now you can use some loops to read data from that cell like this:
for (var i = row; i < dataTable.Rows.Count; i++)
{
for (var j = col; j < dataTable.Columns.Count; j++)
{
var data = dataTable.Rows[i][j];
}
}
Update:
You can filter rows and columns of your Excel sheet at read time with this config:
var i = 0;
var conf = new ExcelDataSetConfiguration
{
UseColumnDataType = true,
ConfigureDataTable = _ => new ExcelDataTableConfiguration
{
FilterRow = rowReader => fromRow <= ++i - 1,
FilterColumn = (rowReader, colIndex) => fromCol <= colIndex,
UseHeaderRow = true
}
};
To be more clear, I will begin at the beginning.
I will rely on the sample code found in https://github.com/ExcelDataReader/ExcelDataReader, but with some modifications to avoid inconveniences.
The following code detects the file format, either xls or xlsx.
FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.Read);
IExcelDataReader excelReader;
//1. Reading Excel file
if (Path.GetExtension(filePath).ToUpper() == ".XLS")
{
//1.1 Reading from a binary Excel file ('97-2003 format; *.xls)
excelReader = ExcelReaderFactory.CreateBinaryReader(stream);
}
else
{
//1.2 Reading from a OpenXml Excel file (2007 format; *.xlsx)
excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
}
//2. DataSet - The result of each spreadsheet will be created in the result.Tables
DataSet result = excelReader.AsDataSet();
//3. DataSet - Create column names from first row
excelReader.IsFirstRowAsColumnNames = false;
Now we can access the file contents in a more convenient way. I use DataTable for this. The following is an example to access a specific cell, and print its value in the console:
DataTable dt = result.Tables[0];
Console.WriteLine(dt.Rows[rowPosition][columnPosition]);
If you do not want to do a DataTable, you can do the same as follows:
Console.WriteLine(result.Tables[0].Rows[rowPosition][columnPosition]);
It is important not try to read beyond the limits of the table, for this you can see the number of rows and columns as follows:
Console.WriteLine(result.Tables[0].Rows.Count);
Console.WriteLine(result.Tables[0].Columns.Count);
Finally, when you're done, you should close the reader and free resources:
//5. Free resources (IExcelDataReader is IDisposable)
excelReader.Close();
I hope you find it useful.
(I understand that the question is old, but I make this contribution to enhance the knowledge base, because there is little material about particular implementations of this library).
For ExcelDataReader v3.6.0 and above.
I struggled a bit to iterate over the Rows. So here's a little more to the above code. Hope it helps for few atleast.
using (var stream = System.IO.File.Open(copyPath, FileMode.Open, FileAccess.Read))
{
IExcelDataReader excelDataReader = ExcelDataReader.ExcelReaderFactory.CreateReader(stream);
var conf = new ExcelDataSetConfiguration()
{
ConfigureDataTable = a => new ExcelDataTableConfiguration
{
UseHeaderRow = true
}
};
DataSet dataSet = excelDataReader.AsDataSet(conf);
//DataTable dataTable = dataSet.Tables["Sheet1"];
DataRowCollection row = dataSet.Tables["Sheet1"].Rows;
//DataColumnCollection col = dataSet.Tables["Sheet1"].Columns;
List<object> rowDataList = null;
List<object> allRowsList = new List<object>();
foreach (DataRow item in row)
{
rowDataList = item.ItemArray.ToList(); //list of each rows
allRowsList.Add(rowDataList); //adding the above list of each row to another list
}
}
One way to do it :
FileStream stream = File.Open(#"c:\working\test.xls", FileMode.Open, FileAccess.Read);
IExcelDataReader excelReader = ExcelReaderFactory.CreateBinaryReader(stream);
excelReader.IsFirstRowAsColumnNames = true;
DataSet result = excelReader.AsDataSet();
The result.Tables contains the sheets and the result.tables[0].Rows contains the cell rows.
I found this useful to read from a specific column and row:
FileStream stream = File.Open(#"C:\Users\Desktop\ExcelDataReader.xlsx", FileMode.Open, FileAccess.Read);
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
DataSet result = excelReader.AsDataSet();
excelReader.IsFirstRowAsColumnNames = true;
DataTable dt = result.Tables[0];
string text = dt.Rows[1][0].ToString();
Very easy with ExcelReaderFactory 3.1 and up:
using (var openFileDialog1 = new OpenFileDialog { Filter = "Excel Workbook|*.xls;*.xlsx;*.xlsm", ValidateNames = true })
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
var fs = File.Open(openFileDialog1.FileName, FileMode.Open, FileAccess.Read);
var reader = ExcelReaderFactory.CreateBinaryReader(fs);
var dataSet = reader.AsDataSet(new ExcelDataSetConfiguration
{
ConfigureDataTable = _ => new ExcelDataTableConfiguration
{
UseHeaderRow = true // Use first row is ColumnName here :D
}
});
if (dataSet.Tables.Count > 0)
{
var dtData = dataSet.Tables[0];
// Do Something
}
}
}
public static DataTable ConvertExcelToDataTable(string filePath, bool isXlsx = false)
{
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
//open file and returns as Stream
using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read))
{
using (var reader = ExcelReaderFactory.CreateReader(stream))
{
var conf = new ExcelDataSetConfiguration
{
ConfigureDataTable = _ => new ExcelDataTableConfiguration
{
UseHeaderRow = true
}
};
var dataSet = reader.AsDataSet(conf);
// Now you can get data from each sheet by its index or its "name"
var dataTable = dataSet.Tables[0];
Console.WriteLine("Total no of rows " + dataTable.Rows.Count);
Console.WriteLine("Total no of Columns " + dataTable.Columns.Count);
return dataTable;
}
}
}
You could use the .NET library to do the same thing which i believe is more straightforward.
string ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0; data source={path of your excel file}; Extended Properties=Excel 12.0;";
OleDbConnection objConn = null;
System.Data.DataTable dt = null;
//Create connection object by using the preceding connection string.
objConn = new OleDbConnection(connString);
objConn.Open();
//Get the data table containg the schema guid.
dt = objConn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
string sql = string.Format("select * from [{0}$]", sheetName);
var adapter = new System.Data.OleDb.OleDbDataAdapter(sql, ConnectionString);
var ds = new System.Data.DataSet();
string tableName = sheetName;
adapter.Fill(ds, tableName);
System.Data.DataTable data = ds.Tables[tableName];
After you have your data in the datatable you can access them as you would normally do with a DataTable class.

How to create new sheets on condition in excel file using c#

Following code works for me to generate only single excel file and single sheet in that.
I want to generate separate sheets for every CustomerOrders how can I do it?
List<MyData> Data = //code to get list of data
DataTable reportDataTable = new DataTable();
reportDataTable.Columns.Add("no");
reportDataTable.Columns.Add("Code");
int count =0
if (Data != null)
{
foreach (MyData dataobj in Data)
{
count++;
foreach (var innerdata in dataobj.CustomerData.OrderBy(t => t.Number))
{
foreach (var orderobj in dataobj.CustomerOrders)
{
DataRow row = reportDataTable.NewRow();
row[0] = "No";
row[1] = "Code"+count;
reportDataTable.Rows.Add(row);
}
}
}
}
GridView grid = new GridView();
grid.DataSource = reportDataTable;
grid.DataBind();
return new DownloadFileResult(grid, "MYEXCELFILE.xls");
public DownloadFileResult(GridView gv, string FileName)
{
GridView = gv; // property
fileName = FileName; //property
}
How do I generate those multiple sheets in one MYEXCELFILE.xls file?
For above i have used following link code
http://www.codeproject.com/Articles/325103/MVC-Grid-to-Excel-file-download
Try this source code:
//Create an instance of the object that generates the Excel file
ExcelDocument xls = new ExcelDocument();
//Loop for each CustomerOrders
{
//Add an worksheet for each CustomerOrders sheet
ExcelWorksheet xlsSheet = new ExcelWorksheet();
xlsSheet.setSheetName("CustomerOrders #no");
xls.easy_addWorksheet(xlsSheet);
//Create a dataset that contains the gridview datatable
DataSet dataSet = new DataSet();
dataSet.Tables.Add((DataTable)gridView.DataSource);
//Add the datatable
xlsSheet.easy_insertDataSet(dataSet, "A1", true);
}
//Export Excel file
xls.easy_WriteXLSFile("MYEXCELFILE.xls ");
For formatting the cells see this link:
http://www.easyxls.com/manual/FAQ/export-gridview-to-excel.html
This code uses EasyXLS library for generating Excel files.

how to get excel sheet name using datatable in c#

I am using the following code to get data from excel sheet:-
private static DataTable GetDataFromCSVFile(string csv_file_path)
{
DataTable csvData = new DataTable();
using (TextFieldParser csvReader = new TextFieldParser(csv_file_path))
{
csvReader.SetDelimiters(new string[] { "," });
csvReader.HasFieldsEnclosedInQuotes = true;
string[] colFields = csvReader.ReadFields();
foreach (string column in colFields)
{
DataColumn datecolumn = new DataColumn(column);
datecolumn.AllowDBNull = true;
csvData.Columns.Add(datecolumn);
}
while (!csvReader.EndOfData)
{
string[] fieldData = csvReader.ReadFields();
//Making empty value as null
for (int i = 0; i < fieldData.Length; i++)
{
if (fieldData[i] == "")
{
fieldData[i] = null;
}
}
csvData.Rows.Add(fieldData);
}
return csvData;
}
}
but I need to retrieve same from sheets within same workbook. Any idea how can I do this using datatable in c#.
Thanks
"As users input data in Excel sheets" doesn't mean input into xls or xlsx file. It may mean that users use MS Excel to edit CSV. You can create "true excel" file with data from 4 source csv files and read a new single file, but you need another API, not TextFieldParser. To read new xlsx files i use DocumentFormat.OpenXml assembly. Quick sample is
using (var doc = SpreadsheetDocument.Open(_docPath, false))
{
var sheet = doc.WorkbookPart.Workbook.Sheets.Elements<Sheet>().First()
//Or iterate over all sheets, get sheet name, read it's data etc.
//i'm sure you can find a lot of samples
var worksheetPart = (WorksheetPart)doc.WorkbookPart.GetPartById(sheet.Id);
var sheetData = worksheetPart.Worksheet.GetFirstChild<SheetData>();
foreach (var row in sheetData.Elements<Row>())
{
//some code here
}
}

How to convert xml to excel file programmatically

I have a xml document holding a small data for my project where I want to convert my xml to an excel file (microsoft office excel 2003 and over)
How can I do this programmatically?
It can be achieved by using Microsoft.Office.Interop.Excel as shown below:
First of all declare these necessary references.
using System;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using Microsoft.Office.Tools.Excel;
using Microsoft.VisualStudio.Tools.Applications.Runtime;
using Excel = Microsoft.Office.Interop.Excel;
using Office = Microsoft.Office.Core;
using System.Diagnostics;
using Microsoft.Win32;
Than create excel app as shown:
Excel.Application excel2; // Create Excel app
Excel.Workbook DataSource; // Create Workbook
Excel.Worksheet DataSheet; // Create Worksheet
excel2 = new Excel.Application(); // Start an Excel app
DataSource = (Excel.Workbook)excel2.Workbooks.Add(1); // Add a Workbook inside
string tempFolder = System.IO.Path.GetTempPath(); // Get folder
string FileName = openFileDialog1.FileName.ToString(); // Get xml file name
After that use below code in a loop to ensure all items in xml file are copied
// Open that xml file with excel
DataSource = excel2.Workbooks.Open(FileName, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value);
// Get items from xml file
DataSheet = DataSource.Worksheets.get_Item(1);
// Create another Excel app as object
Object xl_app;
xl_app = GetObj(1, "Excel.Application");
Excel.Application xlApp = (Excel.Application)xl_app;
// Set previous Excel app (Xml) as ReportPage
Excel.Application ReportPage = (Excel.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application");
// Copy items from ReportPage(Xml) to current Excel object
Excel.Workbook Copy_To_Excel = ReportPage.ActiveWorkbook;
Now we have an Excel object named as Copy_To_Excel that contains all items in Xml..
We can save and close the Excel object with the name we want..
Copy_To_Excel.Save("thePath\theFileName");
Copy_To_Excel.Close();
If you have control over the XML generated, just generate an XML Spreadsheet file (the XML file standard for Excel 2002 and 2003).
These open natively in Excel, without having to change the extension. (To open by default in Excel, the file extension XML should be set to open with "XML Editor", which is an Office app that routes the XML file to Excel, Word, PowerPoint, InfoPath, or your external XML editor as needed. This is the default mapping when Office is installed, but it may be out of whack for some users, particularly devs who edit XML files in a text editor.)
Or, use the NPOI library to generate a native (97/2000 BIFF/XLS) Excel file rather than XML.
you can even read the XML file as string and use regular expressions to read the content between the tags and create a CSV file or use xpath expressions to read the XML file data and export to CSV file.
I know of no easy way to do code-based conversion from xml-based spreadsheet to xls/xlsx. But you might look into Microsoft Open Xml SDK which lets you work with xlsx. You might build xlsx spreadsheet and just feed it with your data. On the level of open-xml SDK it's like building xml file.
1.Fill the xml file into dataset,
2.convert dataset to excel by below method in asp.net
These are very simple methods.
public static void Convert(System.Data.DataSet ds, System.Web.HttpResponse response)
{
//first let's clean up the response.object
response.Clear();
response.Charset = "";
//set the response mime type for excel
response.ContentType = "application/vnd.ms-excel";
//create a string writer
System.IO.StringWriter stringWrite = new System.IO.StringWriter();
//create an htmltextwriter which uses the stringwriter
System.Web.UI.HtmlTextWriter htmlWrite = new System.Web.UI.HtmlTextWriter(stringWrite);
//instantiate a datagrid
System.Web.UI.WebControls.DataGrid dg = new System.Web.UI.WebControls.DataGrid();
//set the datagrid datasource to the dataset passed in
dg.DataSource = ds.Tables[0];
//bind the datagrid
dg.DataBind();
//tell the datagrid to render itself to our htmltextwriter
dg.RenderControl(htmlWrite);
//all that's left is to output the html
response.Write(stringWrite.ToString());
response.End();
}
For array elements separate with ',' comma and reuse the same column name
1) XML Functions
public static class XMLFunctions
{
public static List<Tuple<string, string>> GetXMlTagsAndValues(string xml)
{
var xmlList = new List<Tuple<string, string>>();
var doc = XDocument.Parse(xml);
foreach (var element in doc.Descendants())
{
// we don't care about the parent tags
if (element.Descendants().Count() > 0)
{
continue;
}
var path = element.AncestorsAndSelf().Select(e => e.Name.LocalName).Reverse();
var xPath = string.Join("/", path);
xmlList.Add(Tuple.Create(xPath, element.Value));
}
return xmlList;
}
public static System.Data.DataTable CreateDataTableFromXmlFile(string xmlFilePath)
{
System.Data.DataTable Dt = new System.Data.DataTable();
string input = File.ReadAllText(xmlFilePath);
var xmlTagsAndValues = GetXMlTagsAndValues(input);
var columnList = new List<string>();
foreach(var xml in xmlTagsAndValues)
{
if(!columnList.Contains(xml.Item1))
{
columnList.Add(xml.Item1);
Dt.Columns.Add(xml.Item1, typeof(string));
}
}
DataRow dtrow = Dt.NewRow();
var columnList2 = new Dictionary<string, string>();
foreach (var xml in xmlTagsAndValues)
{
if (!columnList2.Keys.Contains(xml.Item1))
{
dtrow[xml.Item1] = xml.Item2;
columnList2.Add(xml.Item1, xml.Item2);
}
else
{ // Here we are using the same column but appending the next value
dtrow[xml.Item1] = columnList2[xml.Item1] + "," + xml.Item2;
columnList2[xml.Item1] = columnList2[xml.Item1] + "," + xml.Item2;
}
}
Dt.Rows.Add(dtrow);
return Dt;
}
}
2) Full Excel class
using Microsoft.Office.Interop.Excel;
using _Excel = Microsoft.Office.Interop.Excel;
public class Excel
{
string path = "";
Application excel = new _Excel.Application();
Workbook wb;
Worksheet ws;
public Range xlRange;
static bool saveChanges = false;
static int excelRow = 0;
static List<string> columnHeaders = new List<string>();
public Excel(string path, int Sheet = 1)
{
this.path = path;
wb = excel.Workbooks.Open(path);
ws = wb.Worksheets[Sheet];
xlRange = ws.UsedRange;
excelRow = 0;
columnHeaders = new List<string>();
}
public void SaveFile(bool save = true)
{
saveChanges = save;
}
public void Close()
{
wb.Close(saveChanges);
System.Runtime.InteropServices.Marshal.ReleaseComObject(wb);
excel.Quit();
}
public void XMLToExcel(string xmlFilePath)
{
var dt = XMLFunctions.CreateDataTableFromXmlFile(xmlFilePath);
AddDataTableToExcel(dt);
}
public void AddDataTableToExcel(System.Data.DataTable table)
{
// Creating Header Column In Excel
for (int i = 0; i < table.Columns.Count; i++)
{
if (!columnHeaders.Contains(table.Columns[i].ColumnName))
{
ws.Cells[1, columnHeaders.Count() + 1] = table.Columns[i].ColumnName;
columnHeaders.Add(table.Columns[i].ColumnName);
}
}
// Get the rows
for (int k = 0; k < table.Columns.Count; k++)
{
var columnNumber = columnHeaders.FindIndex(x => x.Equals(table.Columns[k].ColumnName));
ws.Cells[excelRow + 2, columnNumber + 1] = table.Rows[0].ItemArray[k].ToString();
}
excelRow++;
SaveFile(true);
}
}
3) Call it
var excel = new Excel(excelFilename);
foreach (var filePath in files)
{
excel.XMLToExcel(filePath);
}
excel.Close();
For array elements having appended incremented column names (ex. column_2)
Create Data Table From XmlFile Redone
public static System.Data.DataTable CreateDataTableFromXmlFile(string xmlFilePath)
{
System.Data.DataTable Dt = new System.Data.DataTable();
string input = File.ReadAllText(xmlFilePath);
var xmlTagsAndValues = GetXMlTagsAndValues(input);
var columnList = new List<string>();
foreach (var xml in xmlTagsAndValues)
{
if (!columnList.Contains(xml.Item1))
{
columnList.Add(xml.Item1);
Dt.Columns.Add(xml.Item1, typeof(string));
}
else
{
var columnName = xml.Item1;
do
{
columnName = columnName.Increment();
} while (columnList.Contains(columnName));
columnList.Add(columnName);
Dt.Columns.Add(columnName, typeof(string));
}
}
DataRow dtrow = Dt.NewRow();
var columnList2 = new Dictionary<string, string>();
foreach (var xml in xmlTagsAndValues)
{
if (!columnList2.Keys.Contains(xml.Item1))
{
dtrow[xml.Item1] = xml.Item2;
columnList2.Add(xml.Item1, xml.Item2);
}
else
{
var columnName = xml.Item1;
do
{
columnName = columnName.Increment();
} while (columnList2.Keys.Contains(columnName));
dtrow[columnName] = xml.Item2;
columnList2[columnName] = xml.Item2;
}
}
Dt.Rows.Add(dtrow);
return Dt;
}
String Extensions
public static class StringExtensions
{
public static string Increment(this string str)
{
if (!str.Contains("_"))
{
str += "_2";
return str;
}
var number = int.Parse(str.Substring(str.LastIndexOf('_') + 1));
var stringBefore = StringFunctions.GetUntilOrEmpty(str, "_");
return $"{stringBefore}_{++number}";
}
}
Using GetUntilOrEmpty
How to open an XML file in Excel 2003.
In short, you can simply open it by using File › Open. Then, when you select an XML file, you are prompted to select one of the following methods to import the XML data:
As an XML list
As a read-only workbook
Use the XML Source task pane
Can't you simply open it in Excel? I thought Excel recognized the suffix XML?

Categories