search for text in excel file c# - c#

I'm writing a windows application with c# and in one form I want to use a n excel file in this way.
In the form when the user types the Employee ID in a text box I wanna search the excel file and based on the ID show other information for the employee in some other text boxes(name text box, last name text box ,status textbox ,and food count text box)
please tell me how can I retrieve the info from it .
public List <string>[] RetrieveColumnGeneral(Excel.Worksheet sheet,string FindWhat)
{
int columnCount = sheet.UsedRange.Columns.Count;
List<string>[] columnValue = new List<string>[columnCount];
Excel.Range rngResult = null;
Excel.Range rng = null;
int index = 0;
int rowCount = sheet.UsedRange.Rows.Count;
Excel.Range FindRange = null;
for (int columnIndex = 1; columnIndex <= sheet.UsedRange.Columns.Count;columnIndex++ )
{
FindRange = sheet.UsedRange.Columns[columnIndex] as Excel.Range;
FindRange.Select();
rngResult = FindRange.Find(What: FindWhat, LookIn: Excel.XlFindLookIn.xlValues,
LookAt: Excel.XlLookAt.xlPart, SearchOrder: Excel.XlSearchOrder.xlByRows);
if (rngResult != null)
{
columnValue[index] = new List<string>();
for (int rowIndex = 1; rowIndex <= sheet.UsedRange.Rows.Count;rowIndex++ )
{
rng = sheet.UsedRange[rowIndex, columnIndex] as Excel.Range;
if (rng.Value != null)
{
columnValue[index].Add(rng.Value.ToString());
}
}
index++;
}
}
Array.Resize ( ref columnValue , index);
return columnValue;
}
thanks I found this code . Will you tell me whether this will solve my problem ?(also by some modifications.)

Try this,
You have to passed Sheet object, but in below code SQL statement fire and get all records in DataSet object.
string sql = "SELECT * FROM [" + selectedWorksheetName + "]";
var adapter = new OleDbDataAdapter(sql, excelObject.Connection);
adapter.Fill(activityDataSet, "Results");
if (activityDataSet.Tables[0] != null)
{
//here you will check which data get based on your columns
}

Try some thing like this.
var ds = new DataSet();
var adapter = new OleDbDataAdapter("SELECT * FROM [" + newSheetName + "]", ConnectionString);
adapter.Fill(ds, newSheetName);
Then use the above dataset to filter the rows.
DataRow dataRow = (from DataRow dr in ds.Tables[0].Rows where dr["Id"] == textbox.Text select dr).FirstOrDefault();
if(dataRow != null)
{
// Fill values from this dataRow
}
EDIT
// If excelsheet ends with .xls
string ConnectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\ExcelData\QB Accounts.xls;Extended Properties='Excel 8.0;HDR=Yes;IMEX=1'";
// If excelsheet ends with .xlsx
string ConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\ExcelData\CSENG01.xlsx;Extended Properties='Excel 12.0;HDR=Yes;IMEX=1'";

Related

Faster way of storing Excel worksheet to system.data.datatable using C#

I am trying to find a faster way to read an XML file that can be opened in Excel 2010. I cannot immediately read the XML file using readxml method because it contains Workbook, style, cell, data and other tags. So my approach was to open it in Excel then get the data on sheet 2 only. The sample file contains 9,000+ rows and takes about 2mins 49secs to store in a datatable. The actual file has 25,000+ rows. This is what I have tried:
private void bulkInsert()
{
var s = new Stopwatch();
s.Start();
try
{
KillExcel();
GCollector();
Excel.Application app = null;
app = new Excel.Application();
Excel.Worksheet sheet = null;
Excel.Workbook book = null;
book = app.Workbooks.Open(#"my directory for the file");
sheet = (Worksheet)book.Sheets[2];
sheet.Select(Type.Missing);
var xlRange = (Excel.Range)sheet.Cells[sheet.Rows.Count, 1];
int lastRow = (int)xlRange.get_End(Excel.XlDirection.xlUp).Row;
int newRow = lastRow + 1;
var cellrow = newRow;
int columns = sheet.UsedRange.Columns.Count;
Excel.Range test = sheet.UsedRange;
System.Data.DataTable dt = new System.Data.DataTable();
dt.Columns.Add("Node_SegmentName");
dt.Columns.Add("Type");
dt.Columns.Add("Sub-Type");
dt.Columns.Add("Description");
dt.Columns.Add("Parameter_DataIdentifier");
dt.Columns.Add("RuntimeValue");
dt.Columns.Add("Category");
dt.Columns.Add("Result");
dt.TableName = "SsmXmlTable";
//slow part
for (i = 0; i < lastRow; i++)
{
DataRow excelRow = dt.NewRow();
for (int j = 0; j < columns; j++)
{
excelRow[j] = test.Cells[i + 2, j + 1].Value2;
}
dt.Rows.Add(excelRow);
}
dataGridView1.DataSource = dt;
DataSet ds = new DataSet();
ds.Tables.Add(dt);
ds.WriteXml(AppDomain.CurrentDomain.BaseDirectory + String.Format("\\XMLParserOutput{0}.xml", DateTime.Now.ToString("MM-d-yyyy")));
DataSet reportData = new DataSet();
reportData.ReadXml(AppDomain.CurrentDomain.BaseDirectory + String.Format("\\XMLParserOutput{0}.xml", DateTime.Now.ToString("MM-d-yyyy")));
SqlConnection connection = new SqlConnection("Data Source=YOURCOMPUTERNAME\\SQLEXPRESS;Initial Catalog=YOURDATABASE;Integrated Security=True;Connect Timeout=0");
connection.Open();
SqlBulkCopy sbc = new SqlBulkCopy(connection);
sbc.DestinationTableName = "Test";
sbc.WriteToServer(reportData.Tables["SsmXmlTable"]);
connection.Close();
s.Stop();
var duration = s.Elapsed;
MessageBox.Show(duration.ToString() + " bulk insert way");
MessageBox.Show(ds.Tables["SsmXmlTable"].Rows.Count.ToString());//439 rows
}
catch (Exception ex)
{
KillExcel();
GCollector();
MessageBox.Show(ex.ToString() + i.ToString());
}
}
Without the reading from Excel part, the insertion of data using bulk copy only takes a couple of seconds (0.5secs for 449 rows).
For others who are encountering the same issue, what I did was:
save the xml as an xlsx file
use oledb to read the xlsx file
store in dataset using OleDbAdapter (Fill() method)
bulk insert
Here is the code that I used to do this (change the connection string):
Stopwatch s = new Stopwatch();
s.Start();
string sSheetName = null;
string sConnection = null;
System.Data.DataTable sheetData = new System.Data.DataTable();
System.Data.DataTable dtTablesList = default(System.Data.DataTable);
OleDbConnection oleExcelConnection = default(OleDbConnection);
sConnection = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + #"C:\Users\YOURUSERNAME\Documents\Visual Studio 2012\Projects\TestXmlParser\TestXmlParser\bin\Debug\ConsolidatedSSMFiles.xlsx" + ";Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=1\"";
oleExcelConnection = new OleDbConnection(sConnection);
oleExcelConnection.Open();
dtTablesList = oleExcelConnection.GetSchema("Tables");
if (dtTablesList.Rows.Count > 0)
{
sSheetName = dtTablesList.Rows[0]["TABLE_NAME"].ToString();
}
dtTablesList.Clear();
dtTablesList.Dispose();
if (!string.IsNullOrEmpty(sSheetName))
{
OleDbDataAdapter sheetAdapter = new OleDbDataAdapter("select * from [TEST$]", oleExcelConnection);
sheetAdapter.Fill(sheetData);
} s.Stop();
var duration = s.Elapsed;
oleExcelConnection.Close();
dataGridView1.DataSource = sheetData;
MessageBox.Show(sheetData.Rows.Count.ToString()+"rows - "+ duration.ToString());
This reads 25000+ rows of excel data to a datable in approx. 1.9 to 2.0 seconds.

Excel Sheets into multiple C# datatables

I am trying to import a excel spreadsheet into a an array of datatables. Each table will be a sheet from the spreadsheet. Right now I am seeing that each table contains the information from all sheets. I am thinking this part is not working correctly.
dataSet.Clear();
Let me know if you can see what I am doing wrong.
Here is the rest of the code.
public DataTable[] ReadDoc()
{
string filename = #"C:\Documents and Settings\user\Desktop\Test.xlsx";
DataTable dt = null;
string connectionString = String.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 8.0;HDR=YES\";", filename);
OleDbConnection connection = new OleDbConnection(connectionString);
DataSet dataSet = new DataSet();
DataSet finalDataSet = new DataSet();
DataTable[] table = new DataTable[3];
connection.Open();
dt = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if (dt == null)
{
return null;
}
String[] excelSheets = new String[dt.Rows.Count];
int i = 0;
foreach (DataRow row in dt.Rows)
{
excelSheets[i] = row["TABLE_NAME"].ToString();
i++;
}
// Loop through all of the sheets if you want too...
for (int j = 0; j < excelSheets.Length; j++)
{
string query = String.Format("SELECT * FROM [" + excelSheets[j] + "]");
dataSet.Clear();
OleDbDataAdapter dataAdapter = new OleDbDataAdapter(query, connectionString);
dataAdapter.Fill(dataSet);
table[j] = dataSet.Tables[0];
}
return table;
}
Thanks for the help.
The problem here is your dataSet, is declared outsife the for. Each datatable array item is getting the same information. dataSet.Tables[0]; You must declare inside the for. Each iteration store different information.
for (int j = 0; j < excelSheets.Length; j++)
{
DataSet dataSet = new DataSet();
string query = String.Format("SELECT * FROM [" + excelSheets[j] + "]");
.....
}

How to transfer data from a dataset to existing excel form's particular worksheet with specific row and columns in c#

I am working on a project in which I have to fetch data from DBASE files and then export the data excel form.
That excel form has more than 10 worksheets having buttons to add rows.
I have retrieved data from dbase files in required format (as required in excel form) using OLEDB.
Now the question is how to send data from datatable to excel forms specific worksheet with desired row and columns.
Also how can I send command to worksheet's button to add required rows?
thats how i fetch Data from dbase files and store it into a datatable.
private void button1_Click(object sender, EventArgs e)
{
string a = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=d:\\vat;Extended Properties =dBASE IV; User ID = Admin ;Password =";
OleDbConnection con = new OleDbConnection();
con.ConnectionString = a;
con.Open();
//MessageBox.Show(con.State.ToString());
string qu = "Select * from abc.dbf ";
OleDbDataAdapter oda = new OleDbDataAdapter(qu, con);
DataTable dt = new DataTable();
oda.Fill(dt);
this.dataGridView1.DataSource = dt;
}
There are so many examples are there to export data from data table to excel but almost in each example a new excel form is created. i have to export to an existing excel form which contain near about 10 sheets. Now i want to insert that datatable content to excel sheet named as ABC.XLS and worksheet name is A.
I hope i explained my problem.
Below answer may not satisfy your exact requirement but just verify it.
BTW sorry for the late reply as i was busy with my existing work.
Below code i have used in one of my desktop application. Hope it may help you.
public static void ExportToExcel(DataTable dt)
{
Microsoft.Office.Interop.Excel.Application excelApp = null;
try
{
// instantiating the excel application class
excelApp = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbook currentWorkbook = excelApp.Workbooks.Add(Type.Missing);
Microsoft.Office.Interop.Excel.Worksheet currentWorksheet = (Microsoft.Office.Interop.Excel.Worksheet)currentWorkbook.ActiveSheet;
currentWorksheet.Columns.ColumnWidth = 18;
if (dt.Rows.Count > 0)
{
currentWorksheet.Cells[1, 1] = DateTime.Now.ToString("s");
int i = 1;
foreach (DataColumn dtColumn in dt.Columns)
{
// Excel work sheet indexing starts with 1
currentWorksheet.Cells[2, i] = dtColumn.Name;
++i;
}
Microsoft.Office.Interop.Excel.Range headerColumnRange = currentWorksheet.get_Range("A2", "G2");
headerColumnRange.Font.Bold = true;
headerColumnRange.Font.Color = 0xFF0000;
//headerColumnRange.EntireColumn.AutoFit();
int rowIndex = 0;
for (rowIndex = 0; rowIndex < dt.Rows.Count; rowIndex++)
{
DataRow row = dt.Rows[rowIndex];
for (int cellIndex = 0; cellIndex < row.Cells.Count; cellIndex++)
{
currentWorksheet.Cells[rowIndex + 3, cellIndex + 1] = row.Cells[cellIndex].Value;
}
}
Microsoft.Office.Interop.Excel.Range fullTextRange = currentWorksheet.get_Range("A1", "G" + (rowIndex + 1).ToString());
fullTextRange.WrapText = true;
fullTextRange.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignLeft;
}
else
{
string timeStamp = DateTime.Now.ToString("s");
timeStamp = timeStamp.Replace(':', '-');
timeStamp = timeStamp.Replace("T", "__");
currentWorksheet.Cells[1, 1] = timeStamp;
currentWorksheet.Cells[1, 2] = "No error occured";
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
if (excelApp != null)
{
excelApp.Quit();
}
}
}
For reference just refere this MSDN Link.
Good luck...

Select and Insert command OLEDB Command c#

I have a excel sheet with two tabs so i want to get a row from one tab and insert into another,i thought it would be same like in sqlserver or mysql . Just select and insert..
I am using this query but it says syntax error not sure what is wrong in it.
testCommand.CommandText = "Insert into [ActiveLicenses$]( Select * from [companies$]
where [License Number] = '" + lnumber + "')";
testCommand.ExecuteNonQuery();
UPDATE
Is there any way to delete the rows directly from excel sheet?
You can use SQL to extract the data from Excel:
using (OleDbDataAdapter da = new OleDbDataAdapter(
"SELECT " + columns + " FROM [" + worksheetName + "$]", conn))
{
DataTable dt = new DataTable(tableName);
da.Fill(dt);
ds.Tables.Add(dt);
}
Unfortunately inserting into excel doesn't work this way. I am pretty sure you cant specify a cell to write to using OleDb Insert Command, it will automatically go to the next open row in the specified column. You can workaround it with an update statement:
sql = "Update [Sheet1$A1:A10] SET A10 = 'YourValue'";
myCommand.CommandText = sql;
myCommand.ExecuteNonQuery();
Personally I would use VSTO rather than oleDB. Once you have extracted the cell simply open up the spreadsheet with code and insert the data:
Excel.Workbook wb = xlApp.Workbooks.Open(filePath);
rng = wb.Range["A1"];
rng.Value2 = "data";
A faster method.
I take all the licenses into a DataTable and remove the ones not required takes less than 1 minute. and then simply export DataTable to Csv so i have the file ready in less than 1 minute.
Sample below:
static List<string> licensecAll = new List<string>();
DataTable dt = new DataTable();
OleDbDataAdapter dp = new OleDbDataAdapter("select * from [companies$]", testCnn);
dp.Fill(dt);
if (dt.Rows.Count > 0)
{
for (int i = dt.Rows.Count-1; i >= 0; i--)
{
string lnum = dt.Rows[i][0].ToString();
Console.WriteLine("LICENSE NUMBER" + lnum);
if (!licensecAll.Contains(lnum))
{
Console.WriteLine("ROW REMOVED");
dt.Rows.RemoveAt(i);
}
}
}
Then simply run datatable to csv....
public static void DataTable2CSV(DataTable table, string filename, string seperateChar)
{
StreamWriter sr = null;
try
{
sr = new StreamWriter(filename);
string seperator = "";
StringBuilder builder = new StringBuilder();
foreach (DataColumn col in table.Columns)
{
builder.Append(seperator).Append(col.ColumnName);
seperator = seperateChar;
}
sr.WriteLine(builder.ToString());
foreach (DataRow row in table.Rows)
{
seperator = "";
builder = new StringBuilder();
foreach (DataColumn col in table.Columns)
{
builder.Append(seperator).Append(row[col.ColumnName]);
seperator = seperateChar;
}
sr.WriteLine(builder.ToString());
}
}
finally
{
if (sr != null)
{
sr.Close();
}
}
}

SQL query to select a range

I need to write an sql query (in c#) to select excel sheet data in only the "C" column starting from C19. But i cant specify the ending cell number because more data are getting added to the column. Hence i need to know how to specify the end of the column. Please help. I have mentioned the query that i'm using. And I have attached an image of the excel sheet that i'm using!.And I have attached the output datagridview!
//Generte Oracle Datatable
OleDbConnection conn = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;"
+ #"Data Source=" + textBox1.Text + ";" + #"Extended Properties=""Excel 12.0 Macro;HDR=Yes""");
conn.Open();
OleDbCommand ccmd = new OleDbCommand(#"Select * From [SPAT$]", conn);
OleDbDataAdapter adapter = new OleDbDataAdapter(ccmd);
DataTable Oracle = new DataTable();
adapter.Fill(Oracle);
for (int y = 19; y < Oracle.Rows.Count; y++)
{
var value = Oracle.Rows[y][3].ToString();
}
dataGridView1.DataSource = Oracle.AsEnumerable().Where((row, index) => index > 3).CopyToDataTable();
First Approach, using OLE Query:
OleDbCommand ccmd = new OleDbCommand(#"Select * From [SPAT$]", conn);
OleDbDataAdapter da = new OleDbDataAdapter(ccmd);
DataTable dt = new DataTable();
da.Fill(dt);
for (int i = 19; i < dt.Rows.Count; i++)
{
var value = dt.Rows[i][3].ToString(); // here 3 refers to column 'C'
}
For criteria based DataTable
dataGridView1.DataSource = dt.AsEnumerable()
.Where((row, index) => index >= 19)
.CopyToDataTable();
For Column "C" only
dataGridView1.DataSource = dt.AsEnumerable()
.Where((row, index) => index >= 19)
.Select(t => t[3].ToString()).ToList();
Second Approach, using Excel COM object:
using Excel = Microsoft.Office.Interop.Excel;
Excel.Application xlApp = new Excel.Application();
Excel.Workbook xlWorkbook = xlApp.Workbooks.Open("path to book");
Excel.Worksheet xlSheet = xlWorkbook.Sheets[1]; // get first sheet
Excel.Range xlRange = xlSheet.UsedRange; // get the entire used range
int numberOfRows = xlRange.Rows.Count;
List<string> columnValue = new List<string>();
// loop over each column number and add results to the list
int c = 3; // Column 'C'
for(int r = 19; r <= numberOfRows; r++)
{
if(xlRange.Cells[r,c].Value2 != null) // ADDED IN EDIT
{
columnValue.Add(xlRange.Cells[r,c].Value2.ToString());
}
}

Categories

Resources