How to import all the Excel sheets to DataSet in C# - c#

I've searched internet for this and couldn't really find a question like it. Everyone was looking for a way to import an individual sheet in the excel file but what I want is to import all the sheets in the file to DataTable's in DataSet without knowing the sheet names.
I've not done much things with Excel before. This a sample and partially working code I've found on the internet and it only parses the given sheet name:
public static DataSet Parse(string fileName, string workSheetName)
{
string connectionString = string.Format("provider=Microsoft.Jet.OLEDB.4.0; data source={0};Extended Properties=Excel 8.0;", fileName);
string query = string.Format("SELECT * FROM [{0}$]", workSheetName);
DataSet data = new DataSet();
using (OleDbConnection con = new OleDbConnection(connectionString))
{
con.Open();
OleDbDataAdapter adapter = new OleDbDataAdapter(query, con);
adapter.Fill(data);
}
return data;
}
In the code above, as you see, workSheetName should be passed in so the query can know where to look at to import. In my case, I want it to traverse all the sheets no matter what they are named like and import them to individual DataTable's of a DataSet.
So in essence, the final thing will be a DataSet in which each DataTable holds rows for each sheet in the imported file.

This is a code I came up with and it works perfect but I saw someone else already added an answer:
static DataSet Parse(string fileName)
{
string connectionString = string.Format("provider=Microsoft.Jet.OLEDB.4.0; data source={0};Extended Properties=Excel 8.0;", fileName);
DataSet data = new DataSet();
foreach(var sheetName in GetExcelSheetNames(connectionString))
{
using (OleDbConnection con = new OleDbConnection(connectionString))
{
var dataTable = new DataTable();
string query = string.Format("SELECT * FROM [{0}]", sheetName);
con.Open();
OleDbDataAdapter adapter = new OleDbDataAdapter(query, con);
adapter.Fill(dataTable);
data.Tables.Add(dataTable);
}
}
return data;
}
static string[] GetExcelSheetNames(string connectionString)
{
OleDbConnection con = null;
DataTable dt = null;
con= new OleDbConnection(connectionString);
con.Open();
dt = con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if (dt == null)
{
return null;
}
String[] excelSheetNames = new String[dt.Rows.Count];
int i = 0;
foreach (DataRow row in dt.Rows)
{
excelSheetNames[i] = row["TABLE_NAME"].ToString();
i++;
}
return excelSheetNames;
}

Because I was bored:
static void Main(string[] args)
{
string filename = #"c:\temp\myfile.xlsx";
System.Data.OleDb.OleDbConnection myConnection = new System.Data.OleDb.OleDbConnection(
"Provider=Microsoft.ACE.OLEDB.12.0; " +
"data source='" + filename + "';" +
"Extended Properties=\"Excel 12.0;HDR=YES;IMEX=1\" ");
myConnection.Open();
DataTable mySheets = myConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
DataSet ds = new DataSet();
DataTable dt;
for (int i = 0; i <= mySheets.Rows.Count; i++)
{
dt = makeDataTableFromSheetName(filename, mySheets.Rows[i]["TABLE_NAME"].ToString());
ds.Tables.Add(dt);
}
}
private static DataTable makeDataTableFromSheetName(string filename, string sheetName)
{
System.Data.OleDb.OleDbConnection myConnection = new System.Data.OleDb.OleDbConnection(
"Provider=Microsoft.ACE.OLEDB.12.0; " +
"data source='" + filename + "';" +
"Extended Properties=\"Excel 12.0;HDR=YES;IMEX=1\" ");
DataTable dtImport = new DataTable();
System.Data.OleDb.OleDbDataAdapter myImportCommand = new System.Data.OleDb.OleDbDataAdapter("select * from [" + sheetName + "$]", myConnection);
myImportCommand.Fill(dtImport);
return dtImport;
}

The function that was suggested by Avitus is correct but it has logica error, you must rewrite in :
DataTable dtImport = new DataTable();
using ( System.Data.OleDb.OleDbConnection myConnection = new System.Data.OleDb.OleDbConnection(
"Provider=Microsoft.ACE.OLEDB.12.0; " +
"data source='" + filename + "';" +
"Extended Properties=\"Excel 12.0;HDR=YES;IMEX=1\" ")){
using ( System.Data.OleDb.OleDbDataAdapter myImportCommand = new System.Data.OleDb.OleDbDataAdapter("select * from [" + sheetName + "$]", myConnection))
myImportCommand.Fill(dtImport);
} return dtImport;
this is correct, otherwise you must dispose connection and dataadapter manually.

This might not be the best and the fastest one, but its another way (Edit- added elimination of blank cells):
public static DataSet ReadWorkbook(string excelFileName, bool useFirstRowAsColumnName = false)
{
var excel = new Microsoft.Office.Interop.Excel.Application();
var workBook = excel.Workbooks.Open(excelFileName, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);//MLHIDE
try
{
System.Data.DataSet ds = new DataSet(excelFileName);
foreach (var sheet0 in workBook.Worksheets)
{
var sheet = (Microsoft.Office.Interop.Excel.Worksheet)sheet0;
try
{
var dt = readSheet(sheet, useFirstRowAsColumnName);
if (dt != null)
ds.Tables.Add(dt);
}
finally
{
releaseObject(sheet);
}
}
return ds;
}
finally
{
workBook.Close(true, null, null);
excel.Quit();
releaseObject(workBook);
releaseObject(excel);
}
}
/// <summary>
/// Returns null for empty sheets or if sheet is not found.
/// </summary>
public static DataTable ReadSheet(string excelFileName, string sheetName, bool useFirstRowAsColumnName = false)
{
var excel = new Microsoft.Office.Interop.Excel.Application();
var workBook = excel.Workbooks.Open(excelFileName, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);//MLHIDE
try
{
foreach (var sheet0 in workBook.Worksheets)
{
var sheet = (Microsoft.Office.Interop.Excel.Worksheet)sheet0;
try
{
if (sheet.Name.Equals_Wildcard(sheetName))
{
var dt = readSheet(sheet, useFirstRowAsColumnName);
if (dt != null)
return dt;
}
}
finally
{
releaseObject(sheet);
}
}
return null;
}
finally
{
workBook.Close(true, null, null);
excel.Quit();
releaseObject(workBook);
releaseObject(excel);
}
}
/// <summary>
/// Returns null for empty sheets
/// </summary>
private static DataTable readSheet(Microsoft.Office.Interop.Excel.Worksheet sheet, bool useFirstRowAsColumnName = false)
{
using (Dece.Common.BeginChangeCurrentCultureBlock_EN_us())
{
var range = sheet.UsedRange;
try
{
object[,] values = (object[,])range.Value2;
int rowCount = values.GetLength(0);
int colCount = values.GetLength(1);
int rowCount0 = rowCount;
int colCount0 = colCount;
#region find row-col count
{
bool ok = false;
for (int row = rowCount; row > 0; row--)
if (!ok)
for (int col = colCount; col > 0; col--)
{
var val = values[row, col];
if ((val != null) && (!System.Convert.ToString(val).IsNullOrEmpty()))
{
rowCount = row;
ok = true;
break;
}
}
else
break;
}
{
bool ok = false;
for (int col = colCount; col > 0; col--)
if (!ok)
for (int row = rowCount; row > 0; row--)
{
var val = values[row, col];
if ((val != null) && (!System.Convert.ToString(val).IsNullOrEmpty()))
{
colCount = col;
ok = true;
break;
}
}
else
break;
}
#endregion
if ((rowCount > 0) && (colCount > 0))
{
var dt = new DataTable(sheet.Name);
dt.BeginLoadData();
try
{
for (int col = 1; col <= colCount; col++)
dt.Columns.Add_RenameIfRequired(useFirstRowAsColumnName ? values[1, col].ToString_NullProof() : col.ToString());
var arr = new object[colCount];
for (int row = useFirstRowAsColumnName ? 1 : 0; row < rowCount; row++)
{
for (int col = 1; col <= colCount; col++)
arr[col - 1] = values[row + 1, col];
dt.Rows.Add(arr);
}
}
finally
{
dt.EndLoadData();
}
return dt;
}
else
return null;
}
finally
{
releaseObject(range);
}
}
}
private static void releaseObject(object obj)
{
try
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
obj = null;
}
catch (Exception ex)
{
obj = null;
throw new Exception("Unable to release the Object " + ex.ToString(), ex);//MLHIDE
}
finally
{
GC.Collect();
}
}

C#
A neat and tidy, minimal version that provides a dataset with tables named as per the sheets (without the trailing dollar):
private static OleDbConnection GetConnection(string filename, bool openIt)
{
// if your data has no header row, change HDR=NO
var c = new OleDbConnection($"Provider=Microsoft.ACE.OLEDB.12.0;Data Source='{filename}';Extended Properties=\"Excel 12.0;HDR=YES;IMEX=1\" ");
if (openIt)
c.Open();
return c;
}
private static DataSet GetExcelFileAsDataSet(OleDbConnection conn)
{
var sheets = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new[] { default, default, default, "TABLE" });
var ds = new DataSet();
foreach (DataRow r in sheets.Rows)
ds.Tables.Add(GetExcelSheetAsDataTable(conn, r["TABLE_NAME"].ToString()));
return ds;
}
private static DataTable GetExcelSheetAsDataTable(OleDbConnection conn, string sheetName)
{
using (var da = new OleDbDataAdapter($"select * from [{sheetName}]", conn))
{
var dt = new DataTable() { TableName = sheetName.TrimEnd('$') };
da.Fill(dt);
return dt;
}
}
Use it like:
DataSet ds;
using(c = GetConnection(#"C:\path\to\your\xl.xlsx", true)
ds = GetExcelFileAsDataSet(c);
Or if you only want one table and you know all the exact sheet name you want (remember that they have a dollar on the end):
DataTable dt;
using(c = GetConnection(#"C:\path\to\your\xl.xlsx", true)
dt = GetExcelSheetAsDataTable(c, "Sheet1$");
VB.NET
Bonus! Note: needs a modern version of VB that understands things like string interpolation, With etc
Private Shared Function GetConnection(filename As String, openIt As Boolean) As OleDbConnection
'if your data has no header row, change HDR=NO
Dim c = New OleDbConnection($"Provider=Microsoft.ACE.OLEDB.12.0;Data Source='{filename}';Extended Properties=""Excel 12.0;HDR=YES;IMEX=1"" ")
If openIt Then c.Open()
Return c
End Function
Private Shared Function GetExcelFileAsDataSet(conn As OleDbConnection) As DataSet
Dim sheets = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, {Nothing, Nothing, Nothing, "TABLE"})
Dim ds = New DataSet()
For Each r As DataRow In sheets.Rows
ds.Tables.Add(GetExcelSheetAsDataTable(conn, r("TABLE_NAME").ToString()))
Next
Return ds
End Function
Private Shared Function GetExcelSheetAsDataTable(conn As OleDbConnection, sheetName As String) As DataTable
Using da = New OleDbDataAdapter($"select * from [{sheetName}]", conn)
Dim dt = New DataTable() With {.TableName = sheetName.TrimEnd("$"c)}
da.Fill(dt)
Return dt
End Using
End Function
Use it like:
Dim ds As DataSet
Using c = GetConnection("C:\path\to\your\xl.xlsx", True)
ds = GetExcelFileAsDataSet(c)
End Using 'closes connection
Or for a single sheet (Remember sheet names end in a dollar) whose name you know:
Dim dt As DataTable
Using c = GetConnection("C:\path\to\your\xl.xlsx", True)
dt = GetExcelSheetAsDataTable(c, "Sheet1$")
End Using 'closes connection

Related

how to check which sheet is empty in excel workbook in C#?

I am accessing excel workbook in c# application. I am showing the sheet names to user by using list lstSheetsEx. But I want to exclude the empty sheet before showing to user.
using (OleDbConnection connExcel = new OleDbConnection(DatabaseObjects.ConnectionStringExcel))
{
connExcel.Open();
DataTable dtSchema = connExcel.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
List<string> lstSheetsEx = dtSchema.AsEnumerable()
.Select(r => r.Field<string>("TABLE_NAME").Trim(new char[] { '\'', '$' })).ToList();
}
You can try the following code to show the sheet name exclude the empty sheet.
Code:
class Program
{
static void Main(string[] args)
{
var list = Checknullsheet("D:\\3.XLSX");
list.ForEach(p => Console.WriteLine(p));
Console.ReadKey();
}
public static List<string> Checknullsheet(string FileName)
{
DataSet set = new DataSet();
int totalSheet = 0; //No of sheets on excel file
using (OleDbConnection objConn = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + FileName + ";Extended Properties='Excel 12.0;HDR=YES;IMEX=1;';"))
{
objConn.Open();
DataTable dt = objConn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
string sheetName = string.Empty;
List<string> sheetlist = new List<string>();
DataTable table = new DataTable();
if (dt != null)
{
var tempDataTable = (from dataRow in dt.AsEnumerable()
where !dataRow["TABLE_NAME"].ToString().Contains("FilterDatabase")
select dataRow).CopyToDataTable();
dt = tempDataTable;
totalSheet = dt.Rows.Count;
for (int i = 0; i < totalSheet; i++)
{
table = makeDataTableFromSheetName(FileName, dt.Rows[i]["TABLE_NAME"].ToString());
table.TableName = dt.Rows[i]["TABLE_NAME"].ToString();
set.Tables.Add(table);
sheetlist.Add(dt.Rows[i]["TABLE_NAME"].ToString());
}
sheetName = dt.Rows[0]["TABLE_NAME"].ToString();
}
foreach (DataTable item in set.Tables)
{
if(item.Rows.Count<=0)
{
sheetlist.Remove(item.TableName);
}
}
objConn.Close();
return sheetlist; //Returning Dattable
}
}
private static DataTable makeDataTableFromSheetName(string filename, string sheetName)
{
System.Data.OleDb.OleDbConnection myConnection = new System.Data.OleDb.OleDbConnection(
"Provider=Microsoft.ACE.OLEDB.12.0; " +
"data source='" + filename + "';" +
"Extended Properties=\"Excel 12.0;HDR=YES;IMEX=1\" ");
DataTable dtImport = new DataTable();
System.Data.OleDb.OleDbDataAdapter myImportCommand = new System.Data.OleDb.OleDbDataAdapter("select * from [" + sheetName + "]", myConnection);
myImportCommand.Fill(dtImport);
return dtImport;
}
}
Result:

Adding data to data table without filling the column names C#

I am trying to add data from an excel spreadsheet to a data table, I am getting the data no worries and adding it to the tables within the datasets but when I do add it, it fills the column names with the top row. I have tried to set the column names but then it just cuts off the top row of data.
I am fairly new to C#, I'm pretty sure I need to alter the fill method objAdapter1.Fill(objDataset1,tableName); but have no idea how to go about it.
public DataSet readExcel()
{
int x = 0;
string[] Individal_Runs = Directory.GetFiles(#"C:\testfiles");
DataSet objDataset1 = new DataSet();
int iso = 0;
foreach (string s in Individal_Runs)
{
x++;
try
{
String theConnString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + s + ";Extended Properties=Excel 12.0 Xml";
OleDbConnection objConn = new OleDbConnection(theConnString);
objConn.Open();
string[] sheetnames = GetExcelSheetNames(String.Format("{0}", s));
int y = 0;
int z = 0;
string tableName;
bool looponce = false;
foreach (string sn in sheetnames)
{
OleDbCommand objCmdSelect = new OleDbCommand(String.Format("SELECT * FROM [{0}]", sn.ToString()), objConn);
OleDbDataAdapter objAdapter1 = new OleDbDataAdapter();
if( looponce == false)
{
tableName = string.Format("isolations_{0}", iso);
objDataset1.Tables.Add(tableName);
objDataset1.Tables[tableName].NewRow();
DataRow newRow = objDataset1.Tables[tableName].NewRow();
objDataset1.Tables[tableName].Rows.InsertAt(newRow, 0);
looponce = true;
}
else
{
tableName = string.Format("isolations_{0}_{1}", iso,y);
objDataset1.Tables.Add(tableName);
DataRow newRow = objDataset1.Tables[tableName].NewRow();
objDataset1.Tables[tableName].Rows.InsertAt(newRow, 0);
y++;
}
objAdapter1.SelectCommand = objCmdSelect;
objAdapter1.Fill(objDataset1,tableName);
int cols = objDataset1.Tables[tableName].Columns.Count;
for (int i = 0; i < cols; i++)
{
objDataset1.Tables[tableName].Columns[i].ColumnName = i.ToString();
}
z++;
}
iso++;
}

excel duplicacy check while upload to sql

i have 2 tables..
i want to check the excel sheet value which is in a dataset with database value:
how to check??
here is the code:
lblmsg.Text = "";
try
{
//System.Threading.Thread.Sleep(5000);
int stateid = 0, cityid = 0;
DataTable dtbank = new DataTable();
DataSet ds = new DataSet();
if (fildetails.HasFile)
{
string fileExtension = System.IO.Path.GetExtension(fildetails.FileName);
if (fileExtension == ".xls" || fileExtension == ".xlsx")
{
string fileLocation = Server.MapPath("/NewFolder1/") + fildetails.FileName;
if (System.IO.File.Exists(fileLocation))
{
// System.IO.File.Delete(fileLocation);
}
fildetails.SaveAs(fileLocation);
string excelConnectionString = string.Empty;
excelConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" +
fileLocation + ";Extended Properties=\"Excel 12.0;HDR=Yes;IMEX=2\"";
//connection String for xls file format.
if (fileExtension == ".xls")
{
excelConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" +
fileLocation + ";Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=2\"";
}
//connection String for xlsx file format.
else if (fileExtension == ".xlsx")
{
excelConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" +
fileLocation + ";Extended Properties=\"Excel 12.0;HDR=Yes;IMEX=2\"";
}
//Create Connection to Excel work book and add oledb namespace
OleDbConnection excelConnection = new OleDbConnection(excelConnectionString);
excelConnection.Open();
DataTable dt = new DataTable();
dt = excelConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if (dt == null)
{
return;
}
String[] excelSheets = new String[dt.Rows.Count];
int t = 0;
//excel data saves in temp file here.
foreach (DataRow row in dt.Rows)
{
string x = row["TABLE_NAME"].ToString();
if (x != "Sheet1$_" && x != "Sheet2$_" && x != "Sheet3$_" && x != "Sheet4$_" && x != "Sheet5$_")
{
excelSheets[t] = row["TABLE_NAME"].ToString();
t++;
}
}
OleDbConnection excelConnection1 = new OleDbConnection(excelConnectionString);
int totalsheet = excelSheets.Length;
for (int i = 0; i < totalsheet; i++)
{
string query = string.Format("Select * from [{0}]", excelSheets[i]);
using (OleDbDataAdapter dataAdapter = new OleDbDataAdapter(query, excelConnection1))
{
dataAdapter.Fill(ds);
}
}
}
if (fileExtension.ToString().ToLower().Equals(".xml"))
{
string fileLocation = Server.MapPath("~/Content/") + Request.Files["FileUpload"].FileName;
if (System.IO.File.Exists(fileLocation))
{
System.IO.File.Delete(fileLocation);
}
Request.Files["FileUpload"].SaveAs(fileLocation);
XmlTextReader xmlreader = new XmlTextReader(fileLocation);
// DataSet ds = new DataSet();
ds.ReadXml(xmlreader);
xmlreader.Close();
}
here i am getting the excel value in ds..what should i do??
how to check??
i have tried this thing:
BL objbankbl=new BL();
for (int j = 0; j < ds.Tables.Count; j++)
{
for (int i = 0; i < ds.Tables[j].Rows.Count; i++)
{
////city_name///
if (!DBNull.Value.Equals(ds.Tables[j].Rows[i][0]))
{
// dtbank = objbankbl.GetReportDate("","","", ds.Tables[j].Rows[i][0].ToString(), "", "", "","","");
dtbank = objbankbl.GetReportDate(ds.Tables[j].Rows[i][0].ToString());
if (dtbank.Rows.Count > 0 && ( ds.Tables[j].Rows[i][0].ToString() == dtbank.Rows[j]["Name"]) )
{
stateid = Convert.ToInt32(dtbank.Rows[0]["ID"]);
}
else
{
string bankname = ds.Tables[j].Rows[i][0].ToString();
if (bankname != " " || bankname != null)
{
//stateid = objbankbl.Insert(1, ds.Tables[j].Rows[i][0].ToString(), "", "", 0, "", 0);
}
}
}
DataTable dt = new DataTable();
dt.Columns.Add();
dt.Columns.Add();
dt.Columns.Add();
dt.Rows.Add(1, "Test1", "Sample1");
dt.Rows.Add(2, "Test2", "Sample2");
dt.Rows.Add(3, "Test3", "Sample3");
dt.Rows.Add(4, "Test4", "Sample4");
dt.Rows.Add(5, "Test5", "Sample5");
var duplicates = dt.AsEnumerable().GroupBy(r => r[0]).Where(gr => gr.Count() > 1).ToList();
Console.WriteLine("Duplicate found: {0}", duplicates.Any());
dt.Rows.Add(1, "Test6", "Sample6"); // Duplicate on 1
dt.Rows.Add(1, "Test6", "Sample6"); // Duplicate on 1
dt.Rows.Add(3, "Test6", "Sample6"); // Duplicate on 3
dt.Rows.Add(5, "Test6", "Sample6"); // Duplicate on 5
duplicates = dt.AsEnumerable().GroupBy(r => r[0]).Where(gr => gr.Count() > 1).ToList();
if (duplicates.Any())
Console.WriteLine("Duplicate found for Classes: {0}", String.Join(", ", duplicates.Select(dupl => dupl.Key)));
Console.ReadLine();
i hope this example help u.
it can be handled easily by using DataView.ToTable Method. The syntax is below.
DataView.ToTable(bool distinct, string[] columnNames)
distinct: If it's true, the returned DataTable contains rows that have distinct values for all its columns specified in the second parameter. Default value is false.
columnNames: A string array that contains a list of the column names to be included in the returned table. The order of columns in returned table would be same as it’s appear in the array.
Ex1
DataTable temp = dt.DefaultView.ToTable(true, "Region");
Ex2
DataTable temp = dt.DefaultView.ToTable(true, "Region", "City");
There are several ways to make it work, the first two that come to my mind are either the use of HashTables or LinQ expressions.
Take a look to this: Best way to remove duplicate entries from a data table but instead of removing the duplicate (look at the second foreach) you print the message.
public void CheckDuplicateRows(DataTable dTable, string colName)
{
Hashtable hTable = new Hashtable();
ArrayList duplicateList = new ArrayList();
//Add list of all the unique item value to hashtable, which stores combination of key, value pair.
//And add duplicate item value in arraylist.
foreach (DataRow drow in dTable.Rows)
{
if (hTable.Contains(drow[colName]))
duplicateList.Add(drow);
else
hTable.Add(drow[colName], string.Empty);
}
//Checks the list dimension to verify if there is any duplicate
if(duplicateList.Count() > 0)
{
//you can print your message here or eventually get info about the duplicate row
}
}

How to compare 2 excel sheet column values and get the similarties in c# using data table

I want to make compare button which compare 2 selected columns from combobox and get the similarities and export them to another excel sheet using datatable in c# .
#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

10 random rows from excel

Help me with my code, because i don't now how to do this simple task. How to select 10 random rows from excel file?
string filepath = #"C:\1.xlsx";
OleDbConnection conn = new OleDbConnection();
conn.ConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filepath + #";Extended Properties=""Excel 12.0 Xml;HDR=YES;IMEX=1;TypeGuessRows=0;ImportMixedTypes=Text""";
OleDbCommand command = new OleDbCommand("SELECT * FROM [Sheet1$]", conn);
DataSet ds = new DataSet();
OleDbDataAdapter adapter = new OleDbDataAdapter(command);
adapter.Fill(ds);
showdata.DataSource = ds.Tables[0];
If you create a DataGridView on your Windows Form called RandomExcelRows, create a button called button1 and put the following code inside the Click event handler for button1:
private void button1_Click(object sender, EventArgs e)
{
Excel.Range[] rows = RandomRows(10, #"C:\test\whatever.xlsx");
DataTable dt = new DataTable();
bool ColumnsCreated = false;
foreach(Excel.Range row in rows)
{
object[,] values = row.Value;
int columnCount = values.Length;
if(!ColumnsCreated)
{
for(int i = 0; i < columnCount; i++)
{
DataColumn dc = new DataColumn(String.Format("Column {0}", i));
dt.Columns.Add(dc);
ColumnsCreated = true;
}
}
DataRow dr = dt.NewRow();
for (int i = 0; i < columnCount; i++)
{
dr[String.Format("Column {0}", i)] = values[1,i+1];
}
dt.Rows.Add(dr);
}
RandomExcelRows.DataSource = dt;
}
And then create a method underneath called RandomRows containing the following:
private Excel.Range[] RandomRows(int randomRowsToGet, string worksheetLocation, int worksheetNumber = 1, int lowestRow = 0, int highestRow = 99)
{
Excel.Range[] rows = new Excel.Range[randomRowsToGet];
Excel.Application excel = new Excel.Application();
Excel.Workbook workbook = excel.Workbooks.Open(worksheetLocation);
Excel.Worksheet worksheet = workbook.Worksheets[worksheetNumber];
List<int> rowNumbers = new List<int>();
bool allUniqueNumbers = false;
Random random = new Random();
while (!allUniqueNumbers)
{
int nextNumber = random.Next(lowestRow, highestRow);
if (!rowNumbers.Contains(nextNumber))
rowNumbers.Add(nextNumber);
if (rowNumbers.Count == randomRowsToGet)
allUniqueNumbers = true;
}
for (int i = 0; i < randomRowsToGet; i++)
{
rows[i] = worksheet.UsedRange.Rows[rowNumbers[i]];
}
Marshal.ReleaseComObject(excel);
return rows;
}
The program will take a random number of rows (this amount is specified by you) from the Spreadsheet you specify and place these rows into your DataGridView.
It's pretty crude, and needs refactoring but it is the basis of what you need. You could also get the string containing the file location from a textbox instead of hardcoding this, the same goes for the number of rows you want, and the other parameters such as minimum and maximum rows.
As well, you could use an OpenFileDialog to allow your user to browse to your excel file, etc etc.
Here is my solution:
string filepath = #"C:\1.xlsx";
OleDbConnection conn = new OleDbConnection();
conn.ConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filepath + #";Extended Properties=""Excel 12.0 Xml;HDR=YES;IMEX=1;TypeGuessRows=0;ImportMixedTypes=Text""";
OleDbCommand command = new OleDbCommand("SELECT * FROM [Sheet1$]", conn);
DataSet ds = new DataSet();
OleDbDataAdapter adapter = new OleDbDataAdapter(command);
adapter.Fill(ds);
// above code block is yours as is.
// below part is for sorting.
DataTable data = ds.Tables[0];
data.Columns.Add(new DataColumn("Guid"));
for (int i = 0; i < data.Rows.Count; i++)
{
data.Rows[i].SetField("Guid", Guid.NewGuid());
}
DataView dv = data.DefaultView;
dv.Sort = "Guid desc";
showdata.DataSource = dv.ToTable();

Categories