Add data from CSV to a SQL Server table column - c#

I want to add data from a CSV file into a column of a table in SQL Server. My code is running but data not reaching the column.
private void btCode_Click(object sender, RoutedEventArgs e)
{
//string constring = "Data Source=.;Initial Catalog=*******;Integrated Security=True";
string filepath = "C:\\code.csv";
StreamReader sr = new StreamReader(filepath);
string line = sr.ReadLine();
string[] value = line.Split(',');
DataTable dt = new DataTable();
DataRow row;
foreach (string Code in value)
{
dt.Columns.Add(new DataColumn(Code));
}
while:
while ( !sr.EndOfStream )
{
value = sr.ReadLine().Split(',');
if(value.Length == dt.Columns.Count)
{
row = dt.NewRow();
row.ItemArray = value;
dt.Rows.Add(row);
}
}
SqlBulkCopy bc = new SqlBulkCopy(sc.ConnectionString, SqlBulkCopyOptions.TableLock);
bc.DestinationTableName = "CodesTable";
bc.BatchSize = dt.Rows.Count;
sc.Open();
bc.WriteToServer(dt);
bc.Close();
sc.Close();

Y dont you try with reading CSV directly using OleDbConnection and then load it to datatable using OleDbDataAdapter.
secondly you can add try catch block to see if its throwing some exception.

Related

How to insert UTC datetimes to closedXML?

In the c# closedXML plugin, I get this message
Unable to set cell value to 10/27/2017 10:14:23 AM +00:00
c#
public static async Task<string> SaveToExcel(string command, Dictionary<string, object> h, string domain, string sheet_name, string[] headers)
{
SqlConnection myConnection = new SqlConnection(GetConnectionString(domain));
await myConnection.OpenAsync();
SqlCommand myCommand = new SqlCommand(command, myConnection);
foreach (KeyValuePair<string, object> entry in h)
{
myCommand.Parameters.AddWithValue(entry.Key, entry.Value ?? DBNull.Value);
}
System.Diagnostics.Debug.WriteLine(myCommand.CommandText);
SqlDataAdapter sda = new SqlDataAdapter();
sda.SelectCommand = myCommand;
DataTable dt = new DataTable();
sda.Fill(dt);
// add headers
DataRow dr = dt.NewRow();
for(int i=0; i<headers.Length; i++)
{
//dr[i] = headers[i];
}
//dt.Rows.InsertAt(dr, 0);
string filepath = Excel.SaveExcel(dt, sheet_name);
dt.Dispose();
sda.Dispose();
myCommand.Dispose();
myConnection.Close();
return filepath;
}
public static string SaveExcel(System.Data.DataTable dt, string SheetName)
{
// create the Excel workbook
var wb = new XLWorkbook();
// creates the worksheet
var ws = wb.AddWorksheet(SheetName);
// add data
ws.Cell(1, 1).InsertTable(dt);
// the range for which you want to add a table style
var range = ws.Range(1, 1, dt.Rows.Count, dt.Columns.Count);
// create the actual table
var table = range.CreateTable();
// adjust size
ws.Columns().AdjustToContents();
// apply style
table.Theme = XLTableTheme.TableStyleMedium5;
// save file as temp
string result = Path.GetTempFileName();
wb.SaveAs(result);
return result;
}
How can I fix this?
Thanks

Get DocumentText from Excel

I need to get all document formatted text from an excel spreadsheet.
I need a better solution that this. This achieves my goal but does not scale at all!
StringBuilder strData = new StringBuilder();
var worksheets = ReferenceDocument.Worksheets;
foreach (Excel._Worksheet worksheet in worksheets)
{
foreach (var cell in worksheet.UsedRange.Cast<Excel.Range>())
{
object value = cell.Text;
string strValue = value == null ? null : value.ToString();
if (!String.IsNullOrWhiteSpace(strValue)) strData.AppendLine(strValue);
}
}
EDIT: I've tried calling worksheet.UsedRange.Text to get an array of strings, but unfortunately it returns System.DbNull and not an array.
I couldn't find anything in the Excel object model I could use. I solved issue by using OleDb
StringBuilder strData = new StringBuilder();
ReferenceDocument.SaveCopyAs(strSomeTempFile);
var cnnStr = String.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended properties=\"Excel 8.0;IMEX=1;HDR=NO\"", strSomeTempFile);
var cnn = new OleDbConnection(cnnStr);
try
{
cnn.Open();
var schemaTable = cnn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
foreach(DataRow schemaRow in schemaTable.Rows)
{
string worksheetName = schemaRow["table_name"].ToString().Replace("'", "");
string sql = String.Format("select * from [{0}]", worksheetName);
var da = new OleDbDataAdapter(sql, cnn);
var dt = new DataTable();
da.Fill(dt);
foreach (DataRow row in dt.Rows)
foreach (DataColumn col in dt.Columns)
{
var value = row[col.ColumnName];
if (!(value is System.DBNull)) strData.AppendLine(value.ToString());
}
}
}
catch (Exception e)
{
// handle error
throw;
}
finally
{
cnn.Close();
}
return strData;

Extract data from datatable

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

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();
}
}
}

Efficient function for reading a delimited file into DataTable

I was wondering if anyone knew of an efficient c# function for reading a tab delimited file into a datatable?
Thanks
This currently uses the LINQ methods .First() and .Skip() both are easy to recreate if you need to use this on .Net 2.0
//even cooler as an extension method
static IEnumerable<string> ReadAsLines(string filename)
{
using (var reader = new StreamReader(filename))
while (!reader.EndOfStream)
yield return reader.ReadLine();
}
static void Main()
{
var filename = "tabfile.txt";
var reader = ReadAsLines(filename);
var data = new DataTable();
//this assume the first record is filled with the column names
var headers = reader.First().Split('\t');
foreach (var header in headers)
data.Columns.Add(header);
var records = reader.Skip(1);
foreach (var record in records)
data.Rows.Add(record.Split('\t'));
}
public System.Data.DataTable GetDataTable(string strFileName)
{
System.Data.OleDb.OleDbConnection conn = new System.Data.OleDb.OleDbConnection("Provider=Microsoft.Jet.OleDb.4.0; Data Source = " + System.IO.Path.GetDirectoryName(strFileName) + ";Extended Properties = \"Text;HDR=YES;FMT=TabDelimited\"");
conn.Open();
string strQuery = "SELECT * FROM [" + System.IO.Path.GetFileName(strFileName) + "]";
System.Data.OleDb.OleDbDataAdapter adapter = new System.Data.OleDb.OleDbDataAdapter(strQuery, conn);
System.Data.DataSet ds = new System.Data.DataSet("CSV File");
adapter.Fill(ds);
conn.Close();
return ds.Tables[0];
}
Here's one way to do it...
var dt = new DataTable();
dt.Columns.Add(new DataColumn("Column1", typeof(string)));
dt.Columns.Add(new DataColumn("Column2", typeof(string)));
dt.Columns.Add(new DataColumn("Column3", typeof(string)));
var lines = File.ReadAllLines(#"c:\tabfile.txt");
foreach( string line in lines )
dt.Rows.Add(line.Split('\t'));
DataTable ConvertToDataTable(string filePath, int numberOfColumns)
{
DataTable tbl = new DataTable();
for (int col = 0; col < numberOfColumns; col++)
tbl.Columns.Add(new DataColumn("Column" + (col + 1).ToString()));
string[] lines = System.IO.File.ReadAllLines(filePath);
foreach (string line in lines)
{
var cols = line.Split(' ');
DataRow dr = tbl.NewRow();
for (int cIndex = 0; cIndex < 3; cIndex++)
{
dr[cIndex] = cols[cIndex];
}
tbl.Rows.Add(dr);
}
return tbl;
}

Categories

Resources