I have the following code .I sucessfully extract data from each sheet in a workbook :
foreach (var sheetName in GetExcelSheetNames(connectionString))
{
if (sheetName.Contains("_"))
{
}
else
{
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);
ds.Tables.Add(dataTable);
}
}
}
My goal is to extract sheetname in ds.
I try the following code but it doesn't work
string query = string.Format("SELECT sheetName, * FROM [{0}]", sheetName);
How should I modify it ?
It seems a useless thing to do to me, but this should work:
string.Format("SELECT '{0}' as sheetName, * FROM [{0}]", sheetName);
It just pasts the sheet name as the first field in the query.
That would assume you already know the name, which makes the method useless. OLEDB doesn't have a way to get the sheet names in Excel, so you would need another method to do so if you don't know the names.
For having single-quoted sheet names, use this:
string.Format("SELECT '{1}' as sheetName, * FROM [{0}]", sheetName, sheetName.Replace("'", "'''"));
How about using OfficeOpenXml?
using (var pck = new OfficeOpenXml.ExcelPackage(file))
{
List<string> sheets = pck.Workbook.Worksheets.Select(x=>x.Name).ToList();
var ws = pck.Workbook.Worksheets[sheet];
DataTable tbl = new DataTable();
foreach (var firstRowCell in ws.Cells[1, 1, 1, ws.Dimension.End.Column])
{
tbl.Columns.Add(hasHeader ? firstRowCell.Text : string.Format("Column {0}", firstRowCell.Start.Column));
}
var startRow = hasHeader ? 2 : 1;
for (var rowNum = startRow; rowNum <= ws.Dimension.End.Row; rowNum++)
{
var wsRow = ws.Cells[rowNum, 1, rowNum, tbl.Columns.Count];
var row = tbl.NewRow();
foreach (var cell in wsRow)
{
row[cell.Start.Column - 1] = cell.Text;
}
tbl.Rows.Add(row);
}
return tbl;
}
Related
I need to read a single cell from an xsl excel file to a string withing the web application i am building. I was previously pulling cell ranges from the file to a table using the following code:
string PullFromExcell(string CellNo)
{
string cell;
string properties = String.Format(#"Provider = Microsoft.Jet.OLEDB.4.0; Data Source = C:\Users\User\Desktop\file.xls; Extended Properties = 'Excel 8.0;'");
using (OleDbConnection conn = new OleDbConnection(properties))
{
string worksheet = "Sheet";
conn.Open();
DataSet ds = new DataSet();
using (OleDbDataAdapter da = new OleDbDataAdapter("SELECT * FROM [" + worksheet + "$" + CellNo + "]", properties))
{
DataTable dt = new DataTable();
cell = dt.ToString();
da.Fill(dt);
ds.Tables.Add(dt);
grdComponent.DataSource = dt;
grdComponent.DataBind();
}
}
return cell;
}
How would i send that to a string? The code that i would use when pulling from a database is similar to this:
Sqlstring = "Select data from variable where name = 'fred' and ssn = 1234";
var cmd0 = new SqlCommand(Sqlstring, Class_Connection.cnn);
string Data = cmd0.ExecuteScalar().ToString();
i'm just not sure if any of that is compatible.
After filling DataTable, you can search the row like this:
foreach (DataRow dr in dt.Rows)
{
if (dr["name"] == "fred" && dr["ssn"] == "1234")
{
cell = dr["data"].ToString();
break;
}
}
I extract data from all sheets in a workbook using the following code :
foreach (var sheetName in GetExcelSheetNames(connectionString))
{
if (sheetName.Contains("_"))
{
}
else
{
using (OleDbConnection con = new OleDbConnection(connectionString))
{
var dataTable = new DataTable();
string query = string.Format("SELECT * ,{0} as sheetName FROM [{0}]", sheetName);
con.Open();
OleDbDataAdapter adapter = new OleDbDataAdapter(query, con);
try
{
adapter.Fill(dataTable);
ds.Tables.Add(dataTable);
}
catch { }
}
}
I can't just figure how data are stocked in DataTable : sheetname is added as column ? how can I extract it ?
foreach (DataTable dt in ds.Tables)
{
using (SqlConnection con = new SqlConnection(consString))
{
con.Open();
for (int i = 0; i < dt.Rows.Count; i++)
{
for (int j = 0; j < dt.Columns.Count; j ++)
{
//what should I write here ?
}
}
}
In order to get the sheet name, using oledb, you will need to use code that looks something like this (thanks to this SO post and answer):
DataTable dtSheets = con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
List<string> sheets= new List<string>();
foreach (DataRow dr in dtSheets.Rows)
{
if (dr["TABLE_NAME"].ToString().Contains("$"))//checks whether row contains '_xlnm#_FilterDatabase' or sheet name(i.e. sheet name always ends with $ sign)
{
sheets.Add(dr["TABLE_NAME"].ToString());
}
}
Below is how you access the values from a datatable:
var someValue = dt.Rows[i][j]
You need to get the item at the column index (j) of the row, at the row index (i), of the current datatable (dt).
Conversely, you can use the name of the column as well.
var someValue = dt.Rows[i]["columnName"]
assuming dt is your datatable variable,
do dt.Rows[row index][column index]
like
dt[2][4] -> will reference the 2nd row, 4th cell
I am not sure, but perhaps the sheetname might be stored at dt.TableName
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] + "]");
.....
}
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();
}
}
}
What i need id to take the first column of an excel file and put that column in a string variable but numbers that will be taken from excel to be separated with blank space.
For Example:
Excel file:
1
3
4
56
76
7
876
23
43
(in column)
and string in C#
string number = "1 3 4 56 76 7 876 23 43"
Any code will help me
I have made the connection with excel file and i have created the dataset/datatable
but now i can not take those numbers as the sample above ?
If you have the data in a datset...you can do something like this....
////TRY THIS!!!
DataSet dsExcelContent = new DataSet();
//Fill from db
//
StringBuilder builder = new StringBuilder();
foreach (DataRow row in dsExcelContent.Tables[0].Rows)
{
builder.Append(row[0].ToString());
builder.Append(" ");
}
Console.WriteLine(builder.ToString());
.....More exact to your code....
OleDbConnection objConn = new OleDbConnection(sConnectionString);
objConn.Open();
OleDbCommand objCmdSelect = new OleDbCommand("SELECT * FROM [sheet1$]", objConn);
OleDbDataAdapter objAdapter1 = new OleDbDataAdapter();
objAdapter1.SelectCommand = objCmdSelect;
DataSet dsExcelContent = new DataSet();
DataTable dsExcelContent1 = new DataTable();
objAdapter1.Fill(dsExcelContent);
dataGridView1.DataSource = dsExcelContent1;
objConn.Close();
int test = dsExcelContent.Tables[0].Rows.Count;
StringBuilder builder = new StringBuilder();
foreach (DataRow row in dsExcelContent.Tables[0].Rows)
{
builder.Append(row[0].ToString());
builder.Append(" ");
}
//s has the data you want.....
string s = builder.ToString();
//REST OF YOUR CODE.....
Have a link - Reading Excel Document
Here's what I would do...first open the spreadsheet with this code.
xlApp = New Excel.Application
filePath = "FILENAME"
xlWorkBook = xlApp.Workbooks.Open(filePath)
xlWorkSheet = xlWorkBook.Worksheets(1)
Then read through the column like this
For data As Integer = 0 To 8
Dim obj As Excel.Range = CType(xlWorkSheet.Cells(data, 1), Range)
If obj.Value IsNot Nothing Then
MyArray(data) = obj.Value
Else
Exit Do
End If
Next
Then you should have all your data in MyArray then loop through and create a string with spaces and you should be good. This code is in VB but it should give you a good idea of the commands and structure to use.
private void Form1_Load(object sender, EventArgs e)
{
String sConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0; Data Source=unsorted.xls;Extended Properties=""Excel 12.0;HDR=NO;""";
OleDbConnection objConn = new OleDbConnection(sConnectionString);
objConn.Open();
OleDbCommand objCmdSelect = new OleDbCommand("SELECT * FROM [sheet1$]", objConn);
OleDbDataAdapter objAdapter1 = new OleDbDataAdapter();
objAdapter1.SelectCommand = objCmdSelect;
DataSet dsExcelContent = new DataSet();
DataTable dsExcelContent1 = new DataTable();
objAdapter1.Fill(dsExcelContent);
dataGridView1.DataSource = dsExcelContent1;
objConn.Close();
int test = dsExcelContent.Tables[0].Rows.Count;
foreach(DataRow row in dsExcelContent.Tables[0].Rows)
{
StringBuilder builder = new StringBuilder();
foreach (DataColumn col in dsExcelContent.Tables[0].Columns)
{
builder.Append(row[col].ToString());
builder.Append(" ");
}
string s = builder.ToString();
this.label1.Text = s;
string[] numbers = s.Split(' ');
ArrayList numberList = new ArrayList();
int i;
foreach (String num in numbers)
{
if (Int32.TryParse(num, out i))
{
numberList.Add(i);
}
else
Console.WriteLine("'{0}' is not a number!", num);
}
this.listBox1.DataSource = numberList;
}
}
}
You just want to loop through the rows in the Dataset now:
var numberStr = EmptyStr;
foreach (DataRow dr in MyDataSet.Tables[0].Rows)
{
numberStr = EmptyStr ? numberStr += dr[0].ToString() : numberStr += " " + dr[0].ToString();
}
Updated Solution
private void Form1_Load(object sender, EventArgs e)
{
String s = String.Empty;
String sConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;DataSource=unsorted.xls;Extended Properties=""Excel 12.0;HDR=NO;""";
using (OleDbConnection conn = new OleDbConnection(sConnectionString))
{
conn.Open();
DataTable schemaTable = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
foreach (DataRow schemaRow in schemaTable.Rows)
{
string sheet = schemaRow["TABLE_NAME"].ToString();
OleDbCommand cmd = new OleDbCommand("SELECT * FROM [" + sheet + "]", conn);
cmd.CommandType = CommandType.Text;
DataTable outputTable = new DataTable(sheet);
output.Tables.Add(outputTable);
new OleDbDataAdapter(cmd).Fill(outputTable);
}
// populate string with value from rows
foreach (DataRow dr in MyDataSet.Tables[0].Rows)
{
s = String.Empty ? s += dr[0].ToString() : s += " " + dr[0].ToString();
}
dataGridView1.DataSource = dsExcelContent1;
objConn.Close();
}
this.label1.Text = s;
string[] numbers = s.Split(' ');
ArrayList numberList = new ArrayList();
int i;
foreach (String num in numbers)
{
if (Int32.TryParse(num, out i))
{
numberList.Add(i);
}
else
{
Console.WriteLine("'{0}' is not a number!", num);
}
}
this.listBox1.DataSource = numberList;
}