Read Data from Excel Sheet in C#, .NET - c#

Excel Data reader read data from Excel sheet in order compare it with the UI dropdown values and see if they exists
I am trying to read data from excel sheet using below code
// methods to read data and parse the data into populate collection
using ExcelDataReader;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
namespace GorillaUITests.PageObjects
{
public class ExcelRead
{
public static List<Datacollection> dataCol = new List<Datacollection>();
public static DataTable ExcelToDataTable(string fileName)
{
using (var stream = File.Open(fileName, FileMode.Open, FileAccess.Read))
{
using (var reader = ExcelReaderFactory.CreateReader(stream))
{
var result = reader.AsDataSet(new ExcelDataSetConfiguration()
{
UseColumnDataType = true,
ConfigureDataTable = (data) => new ExcelDataTableConfiguration()
{
UseHeaderRow = true
}
});
//Get all the Tables
DataTableCollection table = result.Tables;
//Store it in DataTable
DataTable resultTable = table["Sheet1"];
//return
return resultTable;
}
}
}
public static void PopulateInCollection(string fileName)
{
DataTable table = ExcelToDataTable(fileName);
//Iterate through the rows and columns of the Table
for (int row = 1; row <= table.Rows.Count; row++)
{
for (int col = 0; col < table.Columns.Count; col++)
{
Datacollection dtTable = new Datacollection()
{
rowNumber = row,
colName = table.Columns[col].ColumnName,
colValue = table.Rows[row - 1][col].ToString()
};
//Add all the details for each row
dataCol.Add(dtTable);
}
}
}
/// <summary>
/// Read data from Collection
/// </summary>
/// <param name="rowNumber"></param>
/// <param name="columnName"></param>
/// <returns></returns>
public static string ReadData(int rowNumber, string columnName)
{
try
{
//Retriving Data using LINQ to reduce much of iterations
string data = (from colData in dataCol
where colData.colName == columnName && colData.rowNumber == rowNumber
select colData.colValue).SingleOrDefault();
//var datas = dataCol.Where(x => x.colName == columnName && x.rowNumber == rowNumber).SingleOrDefault().colValue;
return data.ToString();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return null;
}
}
}
public class Datacollection
{
public int rowNumber { get; set; }
public string colName { get; set; }
public string colValue { get; set; }
}
}
// Test to see if we are able to read data
public void ReadDataFromExcel(string user, string pass)
{
// populate data in collection
try
{
ExcelRead.PopulateInCollection(#"C:\Users\username\Documents\GorillaUITests\GorillaUITests\Tests\Data\ReadDataTest.xlsx");
Debug.WriteLine("UserName:" + ExcelRead.ReadData(1, "UserName"));
Debug.WriteLine("Email:" + ExcelRead.ReadData(1, "Email"));
Debug.WriteLine("***********");
Debug.WriteLine("UserName:" + ExcelRead.ReadData(2, "UserName"));
Debug.WriteLine("Email:" + ExcelRead.ReadData(2, "Email"));
Debug.WriteLine("***********");
Debug.WriteLine("Username:" + ExcelRead.ReadData(2, "UserName"));
Debug.WriteLine("Email:" + ExcelRead.ReadData(2, "Email"));
Debug.WriteLine("***********");
catch (Exception e)
{
Console.WriteLine(e.Message);
}
And I see this error below
“Object reference not set to an instance of an object.”
Not sure what I am missing, Any inputs would be appreciated

Related

Consecutively reading data from Excel in C#/NUnit test cases, returns blank data for 2nd Case

I'm trying to write a parameterized NUnit test that executes twice. Each time it runs, it references a different row in a spreadsheet and gets the username and password based on int rowNum.
class Test
{
//Run the test twice
[Test,TestCase(1),TestCase(2)]
public void T101_LoginTestSuite_Valid(int rowNum)
{
Console.WriteLine(TestContext.CurrentContext.Test.MethodName); //Test Name
Console.WriteLine("Row number "+rowNum);// Value of rowNum
ExcelDataFactory.GetTestDataSet(TestContext.CurrentContext.Test.MethodName);
//Print out the credentials
Console.WriteLine(ExcelDataFactory.ReadData(rowNum,"username"));
Console.WriteLine(ExcelDataFactory.ReadData(rowNum, "password"));
}
}
Here is the excel
The first test case gets username and password correctly.
However the second test case returns blank (If I run this individually it will work!)
Below is the ExcelDataFactory code:
class ExcelDataFactory
{
//Get data from excel
private static DataTable ExcelToDataTable(String filename, String sheetName)
{
//Open file and returns as Stream
FileStream stream = File.Open(filename, FileMode.Open, FileAccess.Read);
//CreateOpenXmlReader via ExcelReaderFactory
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream); //.xlsx
//Return as DataSet and set the frist row as column name
DataSet result = excelReader.AsDataSet(new ExcelDataSetConfiguration()
{
ConfigureDataTable = (_) => new ExcelDataTableConfiguration()
{
UseHeaderRow = true
}
});
DataTableCollection table = result.Tables;
DataTable resultTable = table[sheetName];
//Close FileStream
stream.Close();
//Return
return resultTable;
}
//Put data into a collection
static List<DataCollection> dataCollection = new List<DataCollection>();
public static void PopulateInCollection(string fileName, String sheetName)
{
DataTable table = ExcelToDataTable(fileName,sheetName);
//Iterate through the rows and columns of the Table
for(int row = 1; row <= table.Rows.Count; row++)
{
for (int column = 0; column < table.Columns.Count; column++)
{
DataCollection dataTable = new DataCollection()
{
rowNumber = row,
columnName = table.Columns[column].ColumnName,
columnValue = table.Rows[row - 1][column].ToString()
};
//Add all the details for each row
dataCollection.Add(dataTable);
}
}
}
//Find the correct excel file and sheet
public static void GetTestDataSet(String testName)
{
String[] testNameSplit = testName.Split('_');
String filePath = MyProps.Default.TestData //Add path
+ testNameSplit[1]
+ "."
+ "xlsx";
PopulateInCollection(filePath, testNameSplit[0]);
}
public static string ReadData(int rowNumber, string columnName)
{
try
{
//Retriving Data using LINQ to reduce amount of iterations
string data = (from collectionData in dataCollection
where collectionData.columnName == columnName && collectionData.rowNumber == rowNumber
select collectionData.columnValue).SingleOrDefault();
//var data = dataCollection.Where(collectionData => collectionData.columnName == columnName && collectionData.rowNumber == rowNumber).SingleOrDefault().columnValue;
return data.ToString();
}
catch (Exception e)
{
e.StackTrace.ToString();
return null;
}
}
}
class DataCollection
{
public int rowNumber { get; set; }
public string columnName { get; set; }
public string columnValue { get; set; }
}
I suspect that the ExcelDataFactory.GetTestDataSet method is called in the wrong place, but I really am stumped as to why this is happening. Any ideas would be greatly appreciated.
I did some quick changes to ExcelDataFactory class, I removed the static references and now PopulateInCollection method returns a List that is declared and initialized at the start of the class.
using ExcelDataReader;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Wizuda_Selenium_Test_Automation
{
class ExcelDataFactory
{
List<DataCollection> dataCollection = new List<DataCollection>();
private static DataTable ExcelToDataTable(String filename, String sheetName)
{
//Open file and returns as Stream
FileStream stream = File.Open(filename, FileMode.Open, FileAccess.Read);
//CreateOpenXmlReader via ExcelReaderFactory
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream); //.xlsx
//Return as DataSet and set the frist row as column name
DataSet result = excelReader.AsDataSet(new ExcelDataSetConfiguration()
{
ConfigureDataTable = (_) => new ExcelDataTableConfiguration()
{
UseHeaderRow = true
}
});
DataTableCollection table = result.Tables;
DataTable resultTable = table[sheetName];
//Close FileStream
stream.Close();
//Return
return resultTable;
}
//static List<DataCollection> dataCollection = new List<DataCollection>();
public List<DataCollection> PopulateInCollection(string fileName, String sheetName)
{
dataCollection = new List<DataCollection>();
DataTable table = ExcelToDataTable(fileName,sheetName);
//Iterate through the rows and columns of the Table
for(int row = 1; row <= table.Rows.Count; row++)
{
for (int column = 0; column < table.Columns.Count; column++)
{
DataCollection dataTable = new DataCollection()
{
rowNumber = row,
columnName = table.Columns[column].ColumnName,
columnValue = table.Rows[row - 1][column].ToString()
};
//Add all the details for each row
dataCollection.Add(dataTable);
}
}
return dataCollection;
}
public string ReadData(int rowNumber, string columnName)
{
try
{
//Retriving Data using LINQ to reduce amount of iterations
string data = (from collectionData in dataCollection
where collectionData.columnName == columnName && collectionData.rowNumber == rowNumber
select collectionData.columnValue).SingleOrDefault();
//var data = dataCollection.Where(collectionData => collectionData.columnName == columnName && collectionData.rowNumber == rowNumber).SingleOrDefault().columnValue;
return data.ToString();
}
catch (Exception e)
{
e.StackTrace.ToString();
return null;
}
}
public void GetTestDataSet(String testName)
{
String[] testNameSplit = testName.Split('_');
String filePath = MyProps.Default.TestData //Add path
+ testNameSplit[1] //LoginTestSuite
+ "."
+ "xlsx"; //T101
PopulateInCollection(filePath, testNameSplit[0]);
}
}
class DataCollection
{
public int rowNumber { get; set; }
public string columnName { get; set; }
public string columnValue { get; set; }
}
}
I updated the test to create new instance of ExcelDataFactory
[Test,TestCase(1),TestCase(2)]
public void T101_LoginTestSuite_Valid(int rowNum)
{
ExcelDataFactory excelDataFactory = new ExcelDataFactory();
Console.WriteLine(TestContext.CurrentContext.Test.MethodName);
Console.WriteLine("Row number "+rowNum);
excelDataFactory.GetTestDataSet(TestContext.CurrentContext.Test.MethodName);
Console.WriteLine("username= "+ excelDataFactory.ReadData(rowNum,"username"));
Console.WriteLine("password= "+ excelDataFactory.ReadData(rowNum, "password"));
}
And now the test passes
I guess I need to go back and re-learn about the use static methods, thanks Kritner

Get Data From Excel only shows last row

I'm having some issues ASPxGridView on Getting data from Excel file. It's only showing the last data from Excel. I've tried to create custom unbound but got no luck. Tried to make it to the List<> and give it a try, no success. This is my code so far.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Globalization;
using DevExpress.Spreadsheet;
using DevExpress.Spreadsheet.Export;
using System.Data;
string FilePath
{
get { return Session["FilePath"] == null ? String.Empty : Session["FilePath"].ToString(); }
set { Session["FilePath"] = value; }
}
private DataTable GetTableFromExcel()
{
Workbook book = new Workbook();
book.InvalidFormatException += book_InvalidFormatException;
book.LoadDocument(FilePath);
Worksheet sheet = book.Worksheets.ActiveWorksheet;
Range range = sheet.GetUsedRange();
DataTable table = sheet.CreateDataTable(range, false);
DataTableExporter exporter = sheet.CreateDataTableExporter(range, table, false);
exporter.CellValueConversionError += exporter_CellValueConversionError;
exporter.Export();
return table;
}
void book_InvalidFormatException(object sender, SpreadsheetInvalidFormatExceptionEventArgs e)
{
}
void exporter_CellValueConversionError(object sender, CellValueConversionErrorEventArgs e)
{
e.Action = DataTableExporterAction.Continue;
e.DataTableValue = null;
}
protected void Upload_FileUploadComplete(object sender, DevExpress.Web.FileUploadCompleteEventArgs e)
{
FilePath = Page.MapPath("~/XlsTables/") + e.UploadedFile.FileName;
e.UploadedFile.SaveAs(FilePath);
}
public class invoice
{
public string nomor_invoice { get; set; }
}
protected void Grid_CustomCallback(object sender, DevExpress.Web.ASPxGridViewCustomCallbackEventArgs e)
{
if (!String.IsNullOrEmpty(FilePath))
{
DataTable table = GetTableFromExcel(); // Get The Excel
List<object> inv = new List<object>();
List<object> dekl = new List<object>();
List<invoice> invoiceList = new List<invoice>();
for (int i = 1; i < table.Rows.Count; i++)
{
DataRow row = table.Rows[i];
invoice nomorInvo = new invoice();
nomorInvo.nomor_invoice = row[1].ToString();
invoiceList.Add(nomorInvo);
string noDkl = row[0].ToString().ToUpper().Trim();
string[] nomor = noDkl.Split('-');
Decimal cab = decimal.Parse(nomor[0].ToString());
Decimal pmsrn = decimal.Parse(nomor[1].ToString());
Decimal reg = decimal.Parse(nomor[2].ToString());
string dkl = nomor[3].ToString();
Decimal cob = decimal.Parse(nomor[4].ToString());
Decimal bln = decimal.Parse(nomor[5].ToString());
Decimal thn = decimal.Parse(nomor[6].ToString());
string invo_no = row[1].ToString().Trim();
inv.Add(invo_no); // add to the list
inv.ToList();
SSREAS.DL.AE.Upload.dsImportir.APFDPE17Row invc = new DL.AE.Upload.dsImportirTableAdapters.APFDPE17TableAdapter().GetDataByDkinvc(cab, pmsrn, reg, dkl, cob, bln, thn, invo_no).SingleOrDefault();
// This is my select query. I used dataSet
if (invc != null)
{
for (int z = 0; z < inv.Count; z++)
{
odsGrid.SelectParameters["DKKDCB"].DefaultValue = cab.ToString();
odsGrid.SelectParameters["DKKDPS"].DefaultValue = pmsrn.ToString();
odsGrid.SelectParameters["DKRGDK"].DefaultValue = reg.ToString();
odsGrid.SelectParameters["DKDKL"].DefaultValue = dkl;
odsGrid.SelectParameters["DKCOB"].DefaultValue = cob.ToString();
odsGrid.SelectParameters["DKBLN"].DefaultValue = bln.ToString();
odsGrid.SelectParameters["DKTHN"].DefaultValue = thn.ToString();
odsGrid.SelectParameters["DKINVC"].DefaultValue = invo_no;
Grid.DataBind();
}
}
else if (invc == null)
{
return;
}
Grid.DataBind();
}
}
}
I've set breakpoint and 0 error occured, But when I upload the Excel File, It's show only 1 data instead of 2 and its the last row from excel. What is wrong with my code? A help would be appreciated. Thanks!
Persist the table in the cache or session in the page_prerender() event bind the data it will work.

Importing Excel to DataTable getting data incorrectly using OpenXML

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.
DataTable
Import_Data.xlsx
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);
}
}
}
I rewrote the part of the code with the help of the link provided by PaulF. Thanks!!!
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
namespace OpenXMLDemo
{
class Program
{
static void Main(string[] args)
{
Program p = new Program();
System.Data.DataTable 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>();
foreach (Cell cell in rows.ElementAt(1))
{
dt.Columns.Add(GetCellValue(doc, cell)); // this will include 2nd row a header row
}
//Loop through the Worksheet rows
foreach (Row row in rows)
{
if (row.RowIndex.Value > 2) //this will exclude first two rows
{
System.Data.DataRow tempRow = dt.NewRow();
int columnIndex = 0;
foreach (Cell cell in row.Descendants<Cell>())
{
// Gets the column index of the cell with data
int cellColumnIndex = (int)GetColumnIndexFromName(GetColumnName(cell.CellReference));
cellColumnIndex--; //zero based index
if (columnIndex < cellColumnIndex)
{
do
{
tempRow[columnIndex] = ""; //Insert blank data here;
columnIndex++;
}
while (columnIndex < cellColumnIndex);
}
tempRow[columnIndex] = GetCellValue(doc, cell);
columnIndex++;
}
dt.Rows.Add(tempRow);
}
}
}
return dt;
}
public static string GetCellValue(SpreadsheetDocument document, Cell cell)
{
SharedStringTablePart stringTablePart = document.WorkbookPart.SharedStringTablePart;
if (cell.CellValue == null)
{
return "";
}
string value = cell.CellValue.InnerXml;
if (cell.DataType != null && cell.DataType.Value == CellValues.SharedString)
{
return stringTablePart.SharedStringTable.ChildElements[Int32.Parse(value)].InnerText;
}
else
{
return value;
}
}
/// <summary>
/// Given a cell name, parses the specified cell to get the column name.
/// </summary>
/// <param name="cellReference">Address of the cell (ie. B2)</param>
/// <returns>Column Name (ie. B)</returns>
public static string GetColumnName(string cellReference)
{
// Create a regular expression to match the column name portion of the cell name.
Regex regex = new Regex("[A-Za-z]+");
Match match = regex.Match(cellReference);
return match.Value;
}
/// <summary>
/// Given just the column name (no row index), it will return the zero based column index.
/// Note: This method will only handle columns with a length of up to two (ie. A to Z and AA to ZZ).
/// A length of three can be implemented when needed.
/// </summary>
/// <param name="columnName">Column Name (ie. A or AB)</param>
/// <returns>Zero based index if the conversion was successful; otherwise null</returns>
public static int? GetColumnIndexFromName(string columnName)
{
//return columnIndex;
string name = columnName;
int number = 0;
int pow = 1;
for (int i = name.Length - 1; i >= 0; i--)
{
number += (name[i] - 'A' + 1) * pow;
pow *= 26;
}
return number;
}
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);
}
}
}

how to compare data in two excel sheet, and display the difference in a new excel sheet

how do i compare data in two excel sheet in the same excel worksheet, and display the difference in a new excel sheet using C#, i tried this:
using System.Text;
using System.Data;
using System.Data.OleDb;
using System.IO;
public class ExcelHandler
{
#region Properties
public string Directory { get; set; }
public string FirstFile { get; set; }
public string FirstFileSheetName { get; set; }
public string SecondFile { get; set; }
public string SecondFileSheetName { get; set; }
public DataTable ReturnDataSet { get; set; }
public bool Excel2007 { get; set; }
public bool UseHeader { get; set; }
#endregion
#region Constructor
public ExcelHandler() { }
public ExcelHandler(string Dir, string File1, string File1SheetName, string File2, string File2SheetName)
{
this.Directory = Dir;
this.FirstFile = File1;
this.SecondFile = File2;
this.FirstFileSheetName = File1SheetName;
this.SecondFileSheetName = File2SheetName;
}
#endregion
#region Match Files
public DataTable CheckExcelFiles()
{
DataTable dtRet = new DataTable();
//Read the first excel
try
{
//Read the excel
DataTable dt1 = GetDataTableFromExcel(this.Directory, this.FirstFile, this.FirstFileSheetName);
DataTable dt2 = GetDataTableFromExcel(this.Directory, this.SecondFile, this.SecondFileSheetName);
//Compare two
dtRet = getDifferentRecords(dt1, dt2);
}
catch (Exception ex) { }
return dtRet;
}
//Overload method to write to csv
public void CheckExcelFiles(string strFilePath)
{
DataTable dtRet = new DataTable();
//Read the first excel
try
{
//Read the excel
DataTable dt1 = GetDataTableFromExcel(this.Directory, this.FirstFile, this.FirstFileSheetName);
DataTable dt2 = GetDataTableFromExcel(this.Directory, this.SecondFile, this.SecondFileSheetName);
//Compare two
dtRet = getDifferentRecords(dt1, dt2);
ExportDataTableToExcel(dtRet, strFilePath);
}
catch (Exception ex) { }
}
//Get Datatable reading Excel
private DataTable GetDataTableFromExcel(string strDir, string strFileName, string strSheetName)
{
var fileName = string.Format("{0}\\" + strFileName, strDir);
string connectionString;
//if (Excel2007)
//read a 2007 file
connectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 8.0;HDR=" + (UseHeader == true ? "YES" : "NO") + ";\"", fileName);
//else
//read a 97-2003 file
//connectionString = string.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=\"Excel 8.0;HDR=" + (UseHeader == true ? "YES" : "NO") + ";\"", fileName);
//var connectionString = string.Format("Provider=Microsoft.Jet.OLEDB.4.0; data source={0}; Extended Properties=Excel 8.0;", fileName);
var adapter = new OleDbDataAdapter("SELECT * FROM [" + strSheetName + "$]", connectionString);
var ds = new DataSet();
adapter.Fill(ds, fileName + strSheetName);
return ds.Tables[fileName + strSheetName];
}
//Compare datatables
private DataTable CompareDataTable(DataTable A, DataTable B)
{
A.PrimaryKey = new DataColumn[] { A.Columns["PK"] };
B.PrimaryKey = new DataColumn[] { B.Columns["PK"] };
A.Merge(B, true); // this will add to A any records that are in B but not A
A.AcceptChanges();
return A.GetChanges(DataRowState.Added); // returns records originally only in B
}
//Provided here http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/23703a85-20c7-4759-806a-fabf4e9f5be6/
//Provided by Guo Surfer
#region Compare two DataTables and return a DataTable with DifferentRecords
/// <summary>
/// Compare two DataTables and return a DataTable with DifferentRecords
/// </summary>
/// <param name="FirstDataTable">FirstDataTable</param>
/// <param name="SecondDataTable">SecondDataTable</param>
/// <returns>DifferentRecords</returns>
public DataTable getDifferentRecords(DataTable FirstDataTable, DataTable SecondDataTable)
{
//Create Empty Table
DataTable ResultDataTable = new DataTable("ResultDataTable");
//use a Dataset to make use of a DataRelation object
using (DataSet ds = new DataSet())
{
//Add tables
ds.Tables.AddRange(new DataTable[] { FirstDataTable.Copy(), SecondDataTable.Copy() });
//Get Columns for DataRelation
DataColumn[] firstColumns = new DataColumn[ds.Tables[0].Columns.Count];
for (int i = 0; i < firstColumns.Length; i++)
{
firstColumns[i] = ds.Tables[0].Columns[i];
}
DataColumn[] secondColumns = new DataColumn[ds.Tables[1].Columns.Count];
for (int i = 0; i < secondColumns.Length; i++)
{
secondColumns[i] = ds.Tables[1].Columns[i];
}
//Create DataRelation
DataRelation r1 = new DataRelation(string.Empty, firstColumns, secondColumns, false);
ds.Relations.Add(r1);
DataRelation r2 = new DataRelation(string.Empty, secondColumns, firstColumns, false);
ds.Relations.Add(r2);
//Create columns for return table
for (int i = 0; i < FirstDataTable.Columns.Count; i++)
{
ResultDataTable.Columns.Add(FirstDataTable.Columns[i].ColumnName, FirstDataTable.Columns[i].DataType);
}
//If FirstDataTable Row not in SecondDataTable, Add to ResultDataTable.
ResultDataTable.BeginLoadData();
foreach (DataRow parentrow in ds.Tables[0].Rows)
{
DataRow[] childrows = parentrow.GetChildRows(r1);
if (childrows == null || childrows.Length == 0)
ResultDataTable.LoadDataRow(parentrow.ItemArray, true);
}
//If SecondDataTable Row not in FirstDataTable, Add to ResultDataTable.
foreach (DataRow parentrow in ds.Tables[1].Rows)
{
DataRow[] childrows = parentrow.GetChildRows(r2);
if (childrows == null || childrows.Length == 0)
ResultDataTable.LoadDataRow(parentrow.ItemArray, true);
}
ResultDataTable.EndLoadData();
}
return ResultDataTable;
}
#endregion
private void ExportDataTableToExcel(DataTable dt, string strFilePath)
{
// Create the CSV file to which grid data will be exported.
StreamWriter sw = new StreamWriter(strFilePath, false);
// First we will write the headers.
//DataTable dt = m_dsProducts.Tables[0];
int iColCount = dt.Columns.Count;
for (int i = 0; i < iColCount; i++)
{
sw.Write(dt.Columns[i]);
if (i < iColCount - 1)
{
sw.Write(",");
}
}
sw.Write(sw.NewLine);
// Now write all the rows.
foreach (DataRow dr in dt.Rows)
{
for (int i = 0; i < iColCount; i++)
{
if (!Convert.IsDBNull(dr[i]))
{
sw.Write(dr[i].ToString());
}
if (i < iColCount - 1)
{
sw.Write(",");
}
}
sw.Write(sw.NewLine);
}
sw.Close();
}
#endregion
}
private void button1_Click(object sender, EventArgs e)
{
//Declare the class and set the excel file dir/path and sheet name
ExcelHandler eh = new ExcelHandler() { Directory = "c:\\temp", FirstFile = "Book1.xlsx", FirstFileSheetName = "Sheet1", SecondFile = "Book2.xlsx", SecondFileSheetName = "Sheet1" };
//Get the datatable
DataTable dt = eh.CheckExcelFiles();
//Or write to CSV top open with excel
eh.CheckExcelFiles("c:\\temp\\test123.csv");
}
this works for me only that it is merging the content of the two worksheet into a new excel sheet test123.csv, i want to show only the difference, i will appreciate, if anyone could assist. Thanks in advance

C# Read a particular value from CSV file [duplicate]

This question already has answers here:
Reading CSV file and storing values into an array
(21 answers)
Closed 8 years ago.
I am a learner in C#. I want to read a particular value from the CSV file. I have learned the getting the csv file into a datatable through browsing. Please see the following code (Thanks to surendra jha) and my CSV file format. Say, I want to get what is the 'Volume' for 'ID' = 90.
CSV file
ID:Volume:Name
100:5600:A
95:5000:B
90:4500:C
85:4000:D
Code for getting all the values:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Data;
namespace DVHConsolePrj
{
class Program
{
static void Main(string[] args)
{
readCsvFileData();
}
static void readCsvFileData()
{
string path = #"C:\IDVolumeName.txt";
StreamReader streamreader = new StreamReader(path);
DataTable datatable = new DataTable();
int rowcount = 0;
string[] columnname = null;
string[] streamdatavalue = null;
while (!streamreader.EndOfStream)
{
string streamrowdata = streamreader.ReadLine().Trim();
if (streamrowdata.Length > 0)
{
streamdatavalue = streamrowdata.Split(':');
if (rowcount == 0)
{
rowcount = 1;
columnname = streamdatavalue;
foreach (string csvheader in columnname)
{
DataColumn datacolumn = new DataColumn(csvheader.ToUpper(), typeof(string));
datacolumn.DefaultValue = string.Empty;
datatable.Columns.Add(datacolumn);
}
}
else
{
DataRow datarow = datatable.NewRow();
for (int i = 0; i < columnname.Length; i++)
{
datarow[columnname[i]] = streamdatavalue[i] == null ? string.Empty : streamdatavalue[i].ToString();
}
datatable.Rows.Add(datarow);
}
}
}
streamreader.Close();
streamreader.Dispose();
foreach (DataRow dr in datatable.Rows)
{
string rowvalues = string.Empty;
foreach (string csvcolumns in columnname)
{
rowvalues += csvcolumns + "=" + dr[csvcolumns].ToString() + " ";
}
Console.WriteLine(rowvalues);
}
Console.ReadLine();
}
}
}
Instead of parsing the file manually in a DataTable, then doing some Linq, use Linq directly on it, using this library.
It works pretty well and is very efficient with big files.
For instance.
1) Add nuget package in your project, and the following line to be able to use it:
using LINQtoCSV;
2) define the class that olds the data
public class IdVolumeNameRow
{
[CsvColumn(FieldIndex = 1)]
public string ID { get; set; }
[CsvColumn(FieldIndex = 2)]
public decimal Volume { get; set; }
[CsvColumn(FieldIndex = 3)]
public string Name{ get; set; }
}
3) and search for the value
var csvAttributes = new CsvFileDescription
{
SeparatorChar = ':',
FirstLineHasColumnNames = true
};
var cc = new CsvContext();
var volume = cc.Read<IdVolumeNameRow>(#"C:\IDVolumeName.txt", csvAttributes)
.Where(i => i.ID == "90")
.Select(i => i.Volume)
.FirstOrDefault();
public DataTable CSVToDataTable(string filename, string separator)
{
try
{
FileInfo file = new FileInfo(filename);
OleDbConnection con =
new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=\"" +
file.DirectoryName + "\";
Extended Properties='text;HDR=Yes;FMT=Delimited(" + separator + ")';")
OleDbCommand cmd = new OleDbCommand(string.Format
("SELECT * FROM [{0}]", file.Name), con);
con.Open();
DataTable tbl = new DataTable();
using (OleDbDataAdapter adp = new OleDbDataAdapter(cmd))
{
tbl = new DataTable("MyTable");
adp.Fill(tbl);
}
return tbl;
}
catch(Exception ex)
{
throw ex;
}
finally()
{
con.Close();
}
}
You can try this code, it is build on the fly, it is possible little errors to exist. Check OleDbConnection. When you return the DataTable you can search in the table using LINQ.
var results = from myRow in myDataTable.AsEnumerable()
where myRow.Field<int>("ID") == 90
select myRow;
Here you can take the row with ID=90 !
For filtering DataTable you can use DataTable.Select method like this
var filtered = dataTable.Select("ID = '90'");
filtered above is array of datarow that suitable for the condition, so for get value from first filtered row you can use something like
if(filtered.Length>0){
var Volume = filtered[0]["VOLUME"];
}

Categories

Resources