Pass table from DataSet as parameter - c#

I'm really new with C# and ASP.Net, I can say that i'm learning over the road. What i need to do is run an stored procedure and create an Excel file with the response. This is my code so far of the controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using ConfigurationSettings = System.Configuration.ConfigurationManager;
using System.IO;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace NewSalesReport.Controllers
{
public class NewSalesReportController : Controller
{
class Program
{
static void Main()
{
string inline = ConfigurationSettings.AppSettings["ConectionString"];
using (SqlConnection toConect = new SqlConnection(inline))
{
using (SqlCommand cmd = new SqlCommand("DaReport", toConect))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#StartDate", SqlDbType.DateTime));
cmd.Parameters.Add(new SqlParameter("#EndDate", SqlDbType.DateTime));
using (SqlDataAdapter adp = new SqlDataAdapter(cmd))
{
DataSet ds = new DataSet();
adp.Fill(ds);
/*if (ds != null)
{
//Console.Write("It is not Empty");
} */
}
}
}
}
private void SetDataExcel(object result)
{
GridView grid = new GridView();
grid.DataSource = result;
StringWriter strwritter = new StringWriter();
HtmlTextWriter htmltextwrtter = new HtmlTextWriter(strwritter);
grid.RenderControl(htmltextwrtter);
Response.ClearContent();
Response.Buffer = true;
Response.AddHeader("content-disposition", "attachment; filename=reportExcel.xls");
Response.ContentType = "application/ms-excel";
Response.Output.Write(strwritter.ToString());
Response.Flush();
Response.End();
strwritter.Dispose();
htmltextwrtter.Dispose();
}
public ActionResult GetAprovedForPay(DateTime? fi = null, DateTime? ff = null)
{
var result = _repo.GetAprovedForPay(fi, ff);
SetDataExcel(result);
return null;
}
}
}
}
Someone is helping me with a few advices, and he told me that i need to pass the first table as a parameter: ds.Tables[0], but he didn't explain how.
Also, when i run the compiler shows an error which says that i need a
reference object for the field, method or property Controller.Response.
Someone can help me, please with this two issues? As i said, i'm new with this hole thing of .Net.
Thanx in advance

An object reference is required for the non-static field, method or property error occurred because you're calling Controller.Response from a method which has return type of void instead of ActionResult.
First, remove inner class Program and rename Main() method to other name (also remove static if necessary). Sounds like the code includes Main() method previously used in console/WinForms application, and you should change it to avoid confusion.
Second, remove Response usage and use FileResult to return file for download as in example below:
public FileResult SetDataExcel(object obj)
{
GridView grid = new GridView();
grid.AutoGeneratedColumns = true; // automatically generate all columns from data source
grid.DataSource = result;
StringWriter strwritter = new StringWriter();
HtmlTextWriter htmltextwrtter = new HtmlTextWriter(strwritter);
grid.RenderControl(htmltextwrtter);
string path = Server.MapPath("~/path/to/filename.xls");
using (var sw = new StreamWriter(path))
{
sw.Write(strwriter.ToString());
}
var savedFile = new FileStream(path, FileMode.Open);
return File(savedFile, "application/ms-excel");
}
Finally, you can use redirection to call SetDataExcel which returns the file:
public ActionResult GetAprovedForPay(DateTime? fi = null, DateTime? ff = null)
{
var result = _repo.GetAprovedForPay(fi, ff);
return RedirectToAction("SetDataExcel", new { obj = result });
}
Note: Regarding data binding for GridView, if AutoGeneratedColumns set to true then you can use ds.Tables[0] as data source (see the reference here):
string inline = ConfigurationSettings.AppSettings["ConectionString"];
using (SqlConnection toConect = new SqlConnection(inline))
{
using (SqlCommand cmd = new SqlCommand("DaReport", toConect))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#StartDate", SqlDbType.DateTime));
cmd.Parameters.Add(new SqlParameter("#EndDate", SqlDbType.DateTime));
using (SqlDataAdapter adp = new SqlDataAdapter(cmd))
{
DataSet ds = new DataSet();
adp.Fill(ds);
grid.DataSource = ds.Tables[0];
grid.DataBind();
}
}
}

Related

C# Export to Excel from class

I am following the following an example to Export data from table/stored proc to Excel.
https://www.c-sharpcorner.com/UploadFile/rahul4_saxena/how-to-export-multiple-data-tables-to-multiple-worksheets-in/
The only difference is that since I have an Angular/MVC project, I am using this code in the class. In the method 'Export_To_Excel()', there is
Response.Clear(); and other Response methods. But I was getting error, "Response does not exist in current context." So I tried changing to fully qualified reference:
HttpContext.Current.Response or
System.Web.HttpContext.Current.Response
but now I get error, "An object reference not set to an instance of Object"
Please guide what to do? Here is my complete code in cs file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using ClosedXML.Excel;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace MyProject.DAL
{
public class CreateWorkBook
{
private DataTable getAllEmployeesList()
{
using (SqlConnection con = Connection.GetConnection())
{
using (SqlCommand cmd = new SqlCommand(#"SELECT * FROM Employee ORDER BY ID;"))
{
using (SqlDataAdapter da = new SqlDataAdapter())
{
DataTable dt = new DataTable();
cmd.CommandType = CommandType.Text;
cmd.Connection = con;
da.SelectCommand = cmd;
da.Fill(dt);
return dt;
}
}
}
}
private DataTable getAllEmployeesOrderList()
{
using (SqlConnection con = Connection.GetConnection())
{
using (SqlCommand cmd = new SqlCommand("SELECT * FROM OrderDetails ORDER BY Order_ID;"))
{
using (SqlDataAdapter da = new SqlDataAdapter())
{
DataTable dt = new DataTable();
cmd.CommandType = CommandType.Text;
cmd.Connection = con;
da.SelectCommand = cmd;
da.Fill(dt);
return dt;
}
}
}
}
public DataSet getDataSetExportToExcel()
{
DataSet ds = new DataSet();
DataTable dtEmp = new DataTable("Employee");
dtEmp = getAllEmployeesList();
DataTable dtEmpOrder = new DataTable("Order List");
dtEmpOrder = getAllEmployeesOrderList();
ds.Tables.Add(dtEmp);
ds.Tables.Add(dtEmpOrder);
return ds;
}
public string SetToExport(string channel, string assets )
{
string status = Export_To_Excel();
return "success";
}
protected string Export_To_Excel()
{
try
{
DataSet ds = getDataSetExportToExcel();
using (XLWorkbook wb = new XLWorkbook())
{
wb.Worksheets.Add(ds);
wb.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
wb.Style.Font.Bold = true;
// Error here –
//An object reference not set to an instance of Object
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.Buffer = true;
System.Web.HttpContext.Current.Response.Charset = "";
System.Web.HttpContext.Current.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
System.Web.HttpContext.Current.Response.AddHeader("content-disposition", "attachment;filename= SubmissionForm.xlsx");
using (MemoryStream MyMemoryStream = new MemoryStream())
{
wb.SaveAs(MyMemoryStream);
MyMemoryStream.WriteTo(System.Web.HttpContext.Current.Response.OutputStream);
System.Web.HttpContext.Current.Response.Flush();
System.Web.HttpContext.Current.Response.End();
}
}
return "success";
}
catch (Exception e)
{
throw e;
//return "Export to Excel failed";
}
}
}
}
As #Scott mentioned in the comments you should break this up into smaller problems.
First create code to successfully generate the excel file. This should return a byte[]. To simplify things you could create a console app that saves the file locally to PC to begin with, test that and make sure its working.
Once part 1 is working copy the code that generates the byte[] into your web project. Then you just need to figure out how to download a file in MVC to the client.
The below code may help.
// CreateWorkBook class
public byte[] Export_To_Excel()
{
DataSet ds = getDataSetExportToExcel();
using (XLWorkbook wb = new XLWorkbook())
{
wb.Worksheets.Add(ds);
wb.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
wb.Style.Font.Bold = true;
using (MemoryStream myMemoryStream = new MemoryStream())
{
wb.SaveAs(myMemoryStream);
// return memory stream as byte array
return myMemoryStream.ToArray();
}
}
}
Then in your controller you can use FileResult to return the excel file. Below is an example of how you might accomplish it in an MVC controller.
// your MVC controller
[HttpGet]
public FileResult DownloadExcel()
{
var createExcel = new CreateWorkBook();
byte[] excelFile = null;
try
{
excelFile = createExcel.Export_To_Excel();
}
catch (Exception ex)
{
// handle exception
}
string fileType = #"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
string fileName = "excel.xlsx";
return File(excelFile, fileType, fileName);
}
just don't use the commented code below which is not relevant with Excel export operation.
//HttpContext.Current.Response.Clear();
//HttpContext.Current.Response.Buffer = true;
//System.Web.HttpContext.Current.Response.Charset = "";
//System.Web.HttpContext.Current.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
//System.Web.HttpContext.Current.Response.AddHeader("content-disposition", "attachment;filename= SubmissionForm.xlsx");
using (MemoryStream MyMemoryStream = new MemoryStream())
{
wb.SaveAs(MyMemoryStream);
//you need to replace below line according to your need. **
//MyMemoryStream.WriteTo(System.Web.HttpContext.Current.Response.OutputStream);
//System.Web.HttpContext.Current.Response.Flush();
//System.Web.HttpContext.Current.Response.End();
}
** Without knowing the structure of your project and your intend it is impossible to tell you the right way of downloading/saving this file.

receive an system.object variable from SSIS and loop on it in foreach parallel loop in C#

Ths code as it appears works fine but here i insert by Add. all the values into the listTables. While what I want is to assing an object variable (User::Hosps) from SSIS (system.object) to the list (or to an array)
How can it be done?
This part:
OleDbDataAdapter A = new OleDbDataAdapter();
System.Data.DataTable dt = new System.Data.DataTable();
A.Fill(dt, Dts.Variables["User::Hosps"].Value);
is something i found online and tryed to use but the values it assigns to the list are not the values i want from the object.
#region Namespaces
using System;
using System.Data;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.Data.OleDb;
using Microsoft.SqlServer.Dts.Runtime;
using System.Diagnostics;
using System.Collections.Generic;
using Oracle.DataAccess.Client;
using Oracle.DataAccess.Types;
#endregion
namespace ST_ef6fc7b20ff94cbfb2587ed23a6520a0
{
[Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute]
public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
{
public void Main()
{
OleDbDataAdapter A = new OleDbDataAdapter();
System.Data.DataTable dt = new System.Data.DataTable();
A.Fill(dt, Dts.Variables["User::Hosps"].Value);
foreach (DataRow row in dt.Rows)
{
Tables.Add(row.ToString());
}
List<string> Tables = new List<string>();
Tables.Add("ABRAVIV");
Tables.Add("FLIMANAVIV");
Tables.Add("BSHAVIV");
Tables.Add("LEVAVIV");
Tables.Add("BEERAVIV");
Tables.Add("TIRAAVIV");
Tables.Add("SHRAVIV");
Tables.Add("MAZAVIV");
Tables.Add("NTNYAAVIV");
Tables.Add("SHMUELAVIV");
Tables.Add("PARDESAVIV");
Tables.Add("RISHONAVIV");
Parallel.ForEach(Tables, Table =>
{
SqlConnection myConnection = new SqlConnection();
myConnection.ConnectionString = "Data Source=vmbi-devdb\\gp;Initial Catalog=GP;Integrated Security=True;Pooling=false;";
SqlDataReader rdr = null;
myConnection.Open();
SqlCommand cmd = new SqlCommand("exec Mirror_Logistic.Load_Table_From_Source " + Table, myConnection);
cmd.CommandTimeout = 0;
rdr = cmd.ExecuteReader();
myConnection.Close();
});
}
#region ScriptResults declaration
enum ScriptResults
{
Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
};
#endregion
}
}
Actually the variable User::Hosps contains the same values i assigned with the Tables.Add
Sorry, you got me confused.
Do you want to assign the values from ur SSIS-Object to a list?
Or do you want to assign ur values from C# to your object?
public void Main()
{
OleDbDataAdapter A = new OleDbDataAdapter();
System.Data.DataTable dt = new System.Data.DataTable();
A.Fill(dt, Dts.Variables["User::Hosps"].Value); List<string> myValues = new list<string>();
foreach (DataRow row in dt.Rows)
{
myValues.Add(row[0].ToString());
}

How to Upload CSV file to sql server table using C#?

I got the error message below when I tried to upload a csv file to a SQL Server table using C# (csv file has no header).
Error Message : "A column named ' ' already belongs to this DataTable"
I tried to find some solutions somewhere on the web but I'm really stuck with it.
My code :
SqlConnection con = new SqlConnection(#"server=.;Initial Catalog=myDtabase;Integrated Security=SSPI;");
string filepath = #"c:\\my_CSV_file.csv";
StreamReader sr = new StreamReader(filepath);
string line = sr.ReadLine();
string[] value = line.Split(',');
DataTable dt = new DataTable();
DataRow row;
foreach (string dc in value)
{
dt.Columns.Add(new DataColumn(dc));
}
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(con.ConnectionString, SqlBulkCopyOptions.TableLock);
bc.DestinationTableName = "my_SQLServer_Table";
bc.BatchSize = dt.Rows.Count;
con.Open();
bc.WriteToServer(dt);
bc.Close();
con.Close();
I think this link will help you get this done.
http://forums.asp.net/t/1695615.aspx
As usual, there is more than one way to skin a cat. So, if yo don't like the solution listed above, try this script, which I know will work for you.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Data.SqlClient;
using System.Data.OleDb;
using System.Configuration;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string server = "EXCEL-PC\\EXCELDEVELOPER";
string database = "AdventureWorksLT2012";
string SQLServerConnectionString = String.Format("Data Source={0};Initial Catalog={1};Integrated Security=SSPI", server, database);
string CSVpath = #"C:\Users\Ryan\Documents\Visual Studio 2010\Projects\Bulk Copy from CSV to SQL Server Table\WindowsFormsApplication1\bin"; // CSV file Path
string CSVFileConnectionString = String.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};;Extended Properties=\"text;HDR=Yes;FMT=Delimited\";", CSVpath);
var AllFiles = new DirectoryInfo(CSVpath).GetFiles("*.CSV");
string File_Name = string.Empty;
foreach (var file in AllFiles)
{
try
{
DataTable dt = new DataTable();
using (OleDbConnection con = new OleDbConnection(CSVFileConnectionString))
{
con.Open();
var csvQuery = string.Format("select * from [{0}]", file.Name);
using (OleDbDataAdapter da = new OleDbDataAdapter(csvQuery, con))
{
da.Fill(dt);
}
}
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(SQLServerConnectionString))
{
bulkCopy.ColumnMappings.Add(0, "MyGroup");
bulkCopy.ColumnMappings.Add(1, "ID");
bulkCopy.ColumnMappings.Add(2, "Name");
bulkCopy.ColumnMappings.Add(3, "Address");
bulkCopy.ColumnMappings.Add(4, "Country");
bulkCopy.DestinationTableName = "AllEmployees";
bulkCopy.BatchSize = 0;
bulkCopy.WriteToServer(dt);
bulkCopy.Close();
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message, "Warning!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
}
}
}
The CsvHelper NuGet library has an implementation for IDataReader which you can pass into the BulkCopy WriteToServer method. This makes for really simple code and allows you to customize the data import.
using CsvHelper;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using System.Globalization;
using System.IO;
public int ReplaceTableWithFile(string table, FileInfo csvFile)
{
using var fileReader = new StreamReader(csvFile.OpenRead());
using var csv = new CsvReader(fileReader, CultureInfo.InvariantCulture);
using var csvDataReader = new CsvDataReader(csv);
var connection = GetDbConnection();
using var command = new SqlBulkCopy(connection);
command.EnableStreaming = true;
command.DestinationTableName = table;
command.WriteToServer(csvDataReader);
return command.RowsCopied;
}
CsvDataReader from CsvHelper NuGet package

Close firefox webpage and debug

My following code has two problems.
1- It doesn't go to the next row in dataset (when I run it, it just run firefox for 2916 times). I change this it from
var test = url.Replace("<userid>", Convert.ToString(row[userID]));
to
var test = url.Replace("<userid>", Convert.ToString(row["userID"]));
but it shows an error (Column 'userid' does not belong to table).
2- I want to close the firefox webpage page at the end of each loop and for next loop it runs again(because of performance issue)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.OleDb;
using System.Net;
namespace test2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
OleDbConnection conn = new OleDbConnection();
conn.ConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\hidden.accdb";
conn.Open();
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = conn;
cmd.CommandText = "Select * from hidden";
DataTable dt = new DataTable();
//To read data from dataset
OleDbDataAdapter adapter = new OleDbDataAdapter();
adapter.SelectCommand = cmd;
//Store the userID
adapter.Fill(dt);
int userid=0,trackid=0;
int counter=0;
foreach(DataRow row in dt.Rows)
{
string url = "http://abcd/<userid>?groups=<userid>";
var test = url.Replace("<userid>", Convert.ToString(row[userid]));
System.Diagnostics.Process.Start(url);
string client = (new WebClient()).DownloadString("http://abcd/userid?groups=userid");
if (client.ToLower() == (Convert.ToString(trackid).ToLower()))
{
counter++;
}
int ave = counter / 2916;
MessageBox.Show("Average = " + counter);
}
conn.Close();
}
}
}
string url = "http://abcd/<userid>?groups=<userid>";
var test = url.Replace("<userid>", Convert.ToString(row["userid"])); // You need ""
System.Diagnostics.Process.Start(test); // You should use variable test, which contains your url with <userid> replaced.

Passing parameter programmatically and displaying in crystal reports

I have a crystal report in which I set the datasource and parameter programmatically. This works when I just display regular data in the report. However, when I try to show the parameter value in the report header (it's a date), I get prompted to enter the parameter.
Any ideas as to what's causing this? I'm new to crystal reports so this might be a very simple problem.
Here's my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Data.SqlClient;
using CrystalDecisions.CrystalReports.Engine;
using CrystalDecisions.Shared;
namespace CrystalReportsTestApp
{
public partial class ReportForm : Form
{
ReportDocument report = new ReportDocument();
public ReportForm()
{
InitializeComponent();
}
private void ConfigureCrystalReports()
{
string reportPath = "mypath\\CrystalReport1.rpt";
report.Load(reportPath);
}
private void RunReportButton_Click(object sender, EventArgs e)
{
DateTime date = dateTimePicker1.Value;
DataSet reportData = new DataSet();
SqlConnection conn = null;
SqlDataAdapter da = null;
try
{
conn = new SqlConnection(connectionString);
conn.Open();
da = new SqlDataAdapter();
SqlCommand cmd = new SqlCommand("cms.GetActiveEntityAccounts", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#EndDate", SqlDbType.DateTime).Value = date;
da.SelectCommand = cmd;
da.Fill(reportData, "DataTable1");
}
finally
{
if (conn != null)
{
conn.Close();
}
}
report.SetDataSource(reportData);
report.SetParameterValue("#EndDate", date);
crystalReportViewer1.ReportSource = report;
crystalReportViewer1.RefreshReport();
}
private void ReportForm_Load(object sender, EventArgs e)
{
ConfigureCrystalReports();
}
}
}
The problem was the following line towards the end:
crystalReportViewer1.RefreshReport();
This caused the report parameters to refresh and not just the report data.
You need to pass the Parameters to CrystalReportViewer control.
Use the below code after report.SetDataSource(reportData);.
CrystalDecisions.Shared.ParameterField parameterField = new CrystalDecisions.Shared.ParameterField();
parameterField.Name = "#EndDate";
//Create a new Discrete Value
CrystalDecisions.Shared.ParameterDiscreteValue parameterDiscreteValue = new CrystalDecisions.Shared.ParameterDiscreteValue();
parameterDiscreteValue.Value = date;
//Add the value
parameterField.CurrentValues.Add( parameterDiscreteValue );
//Add the parameter field
crystalReportViewer1.ParameterFields.Add( parameterField );
crystalReportViewer1.ReportSource = report;
crystalReportViewer1.RefreshReport();

Categories

Resources