I want to display message if data table is empty but label is not printing text.
I tried ScriptManager.RegisterStartupScript(this, GetType(), "message", "alert('No data found');", true); But still its not printing any message.
I believe I am downloading file from server in ZIP folder may be that's why I am not able print message ?
Please guide me where I am doing mistake ?
#Adyson Please check my updated code
Business Logic Explanation :
Here we have requirement is: To store multiples file on one button click and it is not possible Because for one HTTP request One Response we can generate so alternatively what I do is : First I Create csv File and store on server latter after completion of csv file generation I am zipping all csv in a single file and able to download. and on page load I am deleting old csv files to avoid duplicacate files.
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string[] files = Directory.GetFiles(Server.MapPath("~/Order_Files/"));
int iCnt = 0;
foreach (string file in files)
{
FileInfo info = new FileInfo(file);
info.Refresh();
if (info.LastWriteTime <= DateTime.Now)
{
info.Delete();
iCnt += 1;
}
}
btnGenerate.Attributes.Add("onclick", "waitdownload();");
if (!Page.IsPostBack)
{
BindRegion();
//lblINQ.Text = "";
//lblQUO.Text = "";
}
}
public void BindRegion()
{
//Binding Code
}
protected void ddlregion_SelectedIndexChanged(object sender, EventArgs e)
{
//Select Index change code
}
protected void btnGenerate_Click(object sender, EventArgs e)
{
#region CSV Generation
DateTime Order_Date = Convert.ToDateTime(deOrderDate.Text);
var Order_Date_Datemodified = Order_Date.ToString("yyyyMMdd");
foreach (ListItem listItem in ddlDepot.Items)
{
int OrderSum = 0;
int LineSum = 0;
if (listItem.Selected)
{
#region for INQ
if (ddlInqfileType.SelectedItem.Text == "INQ" || ddlInqfileType.SelectedItem.Text == "QUO")
{
OracleCommand CmdB = new OracleCommand(String.Format(#"//Select Query"
, ddlInqfileType.SelectedItem.Text, listItem.Value,
(ddlInqfileType.SelectedItem.Text.Equals("ÏNQ") ? deInqDate.Text.ToString() : deQuoDate.Text.ToString()),
deOrderDate.Text.ToString()), con);
CmdB.CommandType = CommandType.Text;
OracleDataAdapter daBINQ = new OracleDataAdapter();
DataTable dtINQ = new DataTable();
dtINQ.Columns.Add("DEPOT_CODE", typeof(string));
dtINQ.Columns.Add("ROUTE_CODE", typeof(string));
dtINQ.Columns.Add("UPLOAD_DATE", typeof(string));
dtINQ.Columns.Add("SAP_REGION_CODE", typeof(string));
dtINQ.Columns.Add("SAP_SUB_REGION_CODE", typeof(string));
dtINQ.Columns.Add("SAP_CUSTOMER_CODE", typeof(string));
dtINQ.Columns.Add("SALES_DATE", typeof(string));
dtINQ.Columns.Add("PRODUCT_CODE", typeof(string));
dtINQ.Columns.Add("ORDER_QTY", typeof(string));
dtINQ.Columns.Add("UOM_CODE", typeof(string));
dtINQ.Columns.Add("LINE_TOTAL", typeof(string));
daBINQ.SelectCommand = CmdB;
daBINQ.Fill(dtINQ);
if (dtINQ.Rows.Count <= 0)
{
lblINQ.Text = "No data found for Selected Inquiry date, Please select other date";
lblINQ.ForeColor = System.Drawing.Color.Red;
}
else
{
foreach (DataRow dr in dtINQ.Rows)
{
OrderSum += Convert.ToInt32(dr["ORDER_QTY"]);
}
foreach (DataRow dr in dtINQ.Rows)
{
LineSum += Convert.ToInt32(dr["LINE_TOTAL"]);
}
DataRow row = dtINQ.NewRow();
row["DEPOT_CODE"] = "TOT";
row["ORDER_QTY"] = OrderSum;
row["LINE_TOTAL"] = LineSum;
dtINQ.Rows.Add(row);
string fileName = "INQ" + listItem.Value + Order_Date_Datemodified + ".CSV";
string filePath = HttpContext.Current.Server.MapPath("~/Order_Files/" + fileName);
Almarai.AlmTextReadWrite.GenerateCSV(filePath.Replace(fileName, ""), fileName, dtINQ, false, false);
}
}
#endregion FOR INQ
#region For QUO
if (ddlqoutatfileType.SelectedItem.Text == "INQ" || ddlqoutatfileType.SelectedItem.Text == "QUO")
{
OracleCommand CmdB = new OracleCommand(String.Format(#"//Select Query"
, ddlqoutatfileType.SelectedItem.Text, listItem.Value,
(ddlqoutatfileType.SelectedItem.Text.Equals("QUO") ? deInqDate.Text.ToString() : deQuoDate.Text.ToString()),
deOrderDate.Text.ToString()), con);
CmdB.CommandType = CommandType.Text;
OracleDataAdapter daQUO = new OracleDataAdapter();
DataTable dtQUO = new DataTable();
dtQUO.Columns.Add("DEPOT_CODE", typeof(string));
dtQUO.Columns.Add("ROUTE_CODE", typeof(string));
dtQUO.Columns.Add("UPLOAD_DATE", typeof(string));
dtQUO.Columns.Add("SAP_REGION_CODE", typeof(string));
dtQUO.Columns.Add("SAP_SUB_REGION_CODE", typeof(string));
dtQUO.Columns.Add("SAP_CUSTOMER_CODE", typeof(string));
dtQUO.Columns.Add("SALES_DATE", typeof(string));
dtQUO.Columns.Add("PRODUCT_CODE", typeof(string));
dtQUO.Columns.Add("ORDER_QTY", typeof(string));
dtQUO.Columns.Add("UOM_CODE", typeof(string));
dtQUO.Columns.Add("LINE_TOTAL", typeof(string));
daQUO.SelectCommand = CmdB;
daQUO.Fill(dtQUO);
if (dtQUO.Rows.Count <= 0)
{
lblQUO.Visible = true;
}
else
{
foreach (DataRow dr in dtQUO.Rows)
{
OrderSum += Convert.ToInt32(dr["ORDER_QTY"]);
}
foreach (DataRow dr in dtQUO.Rows)
{
LineSum += Convert.ToInt32(dr["LINE_TOTAL"]);
}
DataRow row = dtQUO.NewRow();
row["DEPOT_CODE"] = "TOT";
row["ORDER_QTY"] = OrderSum;
row["LINE_TOTAL"] = LineSum;
dtQUO.Rows.Add(row);
string fileName = "QUO" + listItem.Value + Order_Date_Datemodified + ".CSV";
string filePath = HttpContext.Current.Server.MapPath("~/Order_Files/" + fileName);
Almarai.AlmTextReadWrite.GenerateCSV(filePath.Replace(fileName, ""), fileName, dtQUO, false, false);
}
}
#endregion For QUO
}
}
#endregion CSV Generation
#region ZIP Generation
using (ZipFile zip = new ZipFile())
{
//string fileName = ddlqoutatfileType.SelectedItem.Text + ".csv";
string filePath = HttpContext.Current.Server.MapPath("~/Order_Files/");
zip.AlternateEncodingUsage = ZipOption.AsNecessary;
zip.AddDirectoryByName("Orders");
string directoryName = Path.GetDirectoryName(filePath);
foreach (String filename in Directory.GetFiles(directoryName, "*.csv"))
{
zip.AddFile(filename, "Orders");
}
// cookies
HttpCookie cookie = new HttpCookie("ExcelDownloadFlag");
cookie.Value = "Flag";
cookie.Expires = DateTime.Now.AddDays(1);
Response.AppendCookie(cookie);
//cookies
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.BufferOutput = false;
string zipName = String.Format("Zip_{0}.zip", DateTime.Now.ToString("yyyy-MMM-dd-HHmmss"));
HttpContext.Current.Response.ContentType = "application/zip";
HttpContext.Current.Response.AddHeader("content-disposition", "attachment; filename=" + zipName);
zip.Save(HttpContext.Current.Response.OutputStream);
HttpContext.Current.Response.End();
}
#endregion ZIP Generation
}
ASPX:
<asp:Label ID="lblQUO" runat="server"></asp:Label>
If the request returns a file to download, it cannot also return content for the web page in the same response. The browser will treat it as either a file to download, or something to display, not both (it uses the headers to decide). A HTTP response can only have one content type.
If you want to return a message to the user when there is no data to download, then you should arrange the code so that it doesn't initiate the file download in that situation.
Currently your code is creating a zip file and setting the HTTP headers which tell the browser to treat the response as an attachment. It does this regardless of whether there is actually any data to download or not.
To prevent this behaviour, simply move that code into your else block, so it only does that when the query returned some rows:
foreach (ListItem listItem in ddlDepot.Items)
{
if (listItem.Selected)
{
OracleCommand CmdB = new OracleCommand(String.Format(#"SELECT Query"
OracleDataAdapter daBINQ = new OracleDataAdapter();
DataTable dtINQ = new DataTable();
//adding data table columns
dtINQ.Columns.Add("DEPOT_CODE", typeof(string));
dtINQ.Columns.Add("ROUTE_CODE", typeof(string));
daBINQ.SelectCommand = CmdB;
daBINQ.Fill(dtINQ);
if (dtINQ.Rows.Count <= 0)
{
//ScriptManager.RegisterStartupScript(this, GetType(), "message", "alert('No data found for Selected Inquiry date, Please select other date');", true);
lblQUO.Text = "No data found for Selected Inquiry date, Please select other date";
lblQUO.ForeColor = System.Drawing.Color.Red;
}
else
{
//calculating SUM of column
foreach (DataRow dr in dtINQ.Rows)
{
OrderSum += Convert.ToInt32(dr["ORDER_QTY"]);
}
DataRow row = dtINQ.NewRow();
row["DEPOT_CODE"] = "TOT";
row["ORDER_QTY"] = OrderSum;
//Crating CSV and storing on server
string fileName = "INQ" + listItem.Value + Order_Date_Datemodified + ".CSV";
string filePath = HttpContext.Current.Server.MapPath("~/Order_Files/" + fileName);
//using dll
Almarai.AlmTextReadWrite.GenerateCSV(filePath.Replace(fileName, ""), fileName, dtINQ, false, false);
using (ZipFile zip = new ZipFile())
{
fileName = ddlqoutatfileType.SelectedItem.Text + ".csv";
filePath = HttpContext.Current.Server.MapPath("~/Order_Files/");
zip.AlternateEncodingUsage = ZipOption.AsNecessary;
zip.AddDirectoryByName("Orders");
string directoryName = Path.GetDirectoryName(filePath);
foreach (String filename in Directory.GetFiles(directoryName, "*.csv"))
{
zip.AddFile(filename, "Orders");
}
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.BufferOutput = false;
string zipName = String.Format("Zip_{0}.zip", DateTime.Now.ToString("yyyy-MMM-dd-HHmmss"));
HttpContext.Current.Response.ContentType = "application/zip";
HttpContext.Current.Response.AddHeader("content-disposition", "attachment; filename=" + zipName);
zip.Save(HttpContext.Current.Response.OutputStream);
HttpContext.Current.Response.End();
}
}
}
Now in the case where there's no data, the server will return a "normal" response containing the HTML generated by the aspx code, and the standard headers to go with it. This should mean that the browser takes the HTML and displays it as a web page, instead of trying to download a zip file.
Related
I have a program to parse a CSV file from local filesystem to a specified SQL Server table.
Now when i execute the program i get error :
System.IndexOutOfRangeException: 'Cannot find column 1' exception on the line where i the program attempts to populate the datatable.
On closer inspection the error shows that its emanating from row number 3 as shown on this link :
CSV_ERROR
This is how i am reading and saving the CSV file :
static void Main(string[] args)
{
var absPath = #"C:\Users\user\Documents\Projects\MastercardSurveillance\fbc_mc_all_cards.csv";
ProcessFile();
void ProcessFile()
{
string realPath = #"C:\Users\user\Documents\CSV";
string appLog = "CSVERRORS";
var logPath = realPath + Convert.ToString(appLog) + DateTime.Today.ToString("dd -MM-yy") + ".txt";
if (!File.Exists(logPath))
{
File.Create(logPath).Dispose();
}
var dt = GetDATATable();
if (dt == null)
{
return;
}
if (dt.Rows.Count == 0)
{
using (StreamWriter sw = File.AppendText(logPath))
{
sw.WriteLine("No rows imported after reading file " + absPath);
sw.Flush();
sw.Close();
}
return;
}
ClearData();
InsertDATA();
}
DataTable GetDATATable()
{
var FilePath = absPath;
string TableName = "Cards";
string realPath = #"C:\Users\user\Documents\CSV";
string appLog = "CSVERRORS";
var logPath = realPath + Convert.ToString(appLog) + DateTime.Today.ToString("dd -MM-yy") + ".txt";
if (!File.Exists(logPath))
{
File.Create(logPath).Dispose();
}
var dt = new DataTable(TableName);
using (var csvReader = new TextFieldParser(FilePath))
{
csvReader.SetDelimiters(new string[] { "," });
csvReader.HasFieldsEnclosedInQuotes = true;
var readFields = csvReader.ReadFields();
if (readFields == null)
{
using (StreamWriter sw = File.AppendText(logPath))
{
sw.WriteLine("Could not read header fields for file " + FilePath);
sw.Flush();
sw.Close();
}
return null;
}
foreach (var dataColumn in readFields.Select(column => new DataColumn(column, typeof(string)) { AllowDBNull = true, DefaultValue = string.Empty }))
{
dt.Columns.Add(dataColumn);
}
while (!csvReader.EndOfData)
{
var data = csvReader.ReadFields();
if (data == null)
{
using (StreamWriter sw = File.AppendText(logPath))
{
sw.WriteLine(string.Format("Could not read fields on line {0} for file {1}", csvReader.LineNumber, FilePath));
sw.Flush();
sw.Close();
}
continue;
}
var dr = dt.NewRow();
for (var i = 0; i < data.Length; i++)
{
if (!string.IsNullOrEmpty(data[i]))
{
dr[i] = data[i];
}
}
dt.Rows.Add(dr);
}
}
return dt;
}
void ClearData()
{
string SqlSvrConn = #"Server=XXXXXX-5QFK4BL\MSDEVOPS;Database=McardSurveillance;Trusted_Connection=True;MultipleActiveResultSets=true;";
using (var sqlConnection = new SqlConnection(SqlSvrConn))
{
sqlConnection.Open();
// Truncate the live table
using (var sqlCommand = new SqlCommand(_truncateLiveTableCommandText, sqlConnection))
{
sqlCommand.ExecuteNonQuery();
}
}
}
void InsertDATA()
{
string SqlSvrConn = #"Server=XXXXXX-5QFK4BL\MSDEVOPS;Database=McardSurveillance;Trusted_Connection=True;MultipleActiveResultSets=true;";
DataTable table = GetDATATable();
using (var sqlBulkCopy = new SqlBulkCopy(SqlSvrConn))
{
sqlBulkCopy.DestinationTableName = "dbo.Cards";
for (var count = 0; count < table.Columns.Count; count++)
{
sqlBulkCopy.ColumnMappings.Add(count, count);
}
sqlBulkCopy.WriteToServer(table);
}
}
}
How can i identify and possibly exclude the extra data columns being returned from the CSV file?
It appears there is a mismatch between number of columns in datatable and number of columns being read from the CSV file.
Im not sure however how i can account for this with my logic. For now i did not want to switch to using a CSV parse package but rather i need insight on how i can remove the extra column or rather ensure that the splitting takes account of all possible dubious characters.
For clarity i have a copy of the CSV file here :
CSV_FILE
I'm writing a code that can be dragged and drop to the program that can get it's directory (which must be a csv file) and will filter out the data. But I'm having trouble passing a string object(which is the path of the csv file) to a class which would make the filtering process. So here's the code:
private void Form1_DragDrop(object sender, DragEventArgs e)
{
//Takes dropped items and store in string array which is the path
string[] droppedFile = (string[])e.Data.GetData(DataFormats.FileDrop);
//passing the string object and this is where I get the error
CsvParser run = new CsvParser(droppedFile[0]);
MessageBox.Show("file path: " + droppedFile[0],"Message");
}
and the receiving class looks like this:
public CsvParser(string filePath)
{
//use of StreamReader to get csv file
using (var sr = new StreamReader(filePath))
using (DataTable dt = new DataTable("Table"))
{
//variable to be able to read csv file
var reader = new CsvReader(sr,true);
//some logic
}
}
I've also tried converting the string to a StringReader which look like this:
private void Form1_DragDrop(object sender, DragEventArgs e)
{
string[] droppedFile = (string[])e.Data.GetData(DataFormats.FileDrop);
//taking path of the file string to stringreader object
var textReader = new StringReader(droppedFile[0]);
CsvParser run = new CsvParser(textReader);
MessageBox.Show("file path: " + textReader,"Message");
}
when I coded this it actually bypasses the error but when it comes to the process where it should filter out the data nothing happens and the value of the converted string is only System.IO.StringReader. I'm still learning on C# so I'll be glad if you guys can help me out.
//update
This is what my CsvParser looks like for broad view:
using CsvHelper;
using CsvHelper.Configuration;
using System;
using System.Collections.Generic;
using System.IO;
using System.Data;
namespace Project
{
class CsvParser
{
public CsvParser(string filePath)
{
//use of library StreamReader to get csv file
using (var sr = new StreamReader(filePath))
using (DataTable dt = new DataTable("Table"))
{
//variable to be able to read csv file
var reader = new CsvReader(sr,true);
//csv configurations
reader.Configuration.RegisterClassMap<DataRecordMap>();
//CSVReader will now read the whole file into an enumerable
IEnumerable<DataRecord> records = reader.GetRecords<DataRecord>();
dt.Columns.Add("Create Date", typeof(string));
dt.Columns.Add("IR Initial Response", typeof(string));
dt.Columns.Add("FR Fix Response", typeof(string));
dt.Columns.Add("Summary", typeof(string));
dt.Columns.Add("Ticket #", typeof(string));
dt.Columns.Add("Company", typeof(string));
dt.Columns.Add("Assigned to", typeof(string));
dt.Columns.Add("Caller", typeof(string));
dt.Columns.Add("Case Type", typeof(string));
dt.Columns.Add("Close Date", typeof(string));
dt.Columns.Add("Days Open", typeof(string));
dt.Columns.Add("Department", typeof(string));
dt.Columns.Add("Infrastructure Type", typeof(string));
dt.Columns.Add("Location", typeof(string));
dt.Columns.Add("Priority", typeof(string));
dt.Columns.Add("IncidentType", typeof(string));
dt.Columns.Add("Resolution", typeof(string));
dt.Columns.Add("Status", typeof(string));
dt.Columns.Add("Shift", typeof(string));
foreach (DataRecord record in records)
{
dt.Rows.Add(record.CreateDate.Replace("\n", "").Replace(" ", "").Replace("\"", "").Replace("#", " # ").Replace("AM", " AM").Replace("PM", " PM"),
record.IRInitialResponse.Replace("\n", "").Replace(" ", "").Replace("\"", "").Replace("at", " # ").Replace("AM", " AM").Replace("PM", " PM"),
record.FRFixResponse.Replace("\n", "").Replace(" ", "").Replace("\"", "").Replace("at", " # ").Replace("AM", " AM").Replace("PM", " PM"),
record.Summary, record.TicketNo, record.Company, record.Assignedto, record.Caller, record.CaseType,
record.CloseDate.Replace("\n", "").Replace(" ", "").Replace("\"", "").Replace("at", " # ").Replace("AM", " AM").Replace("PM", " PM"),
record.DaysOpen, record.Department, record.InfrastructureType, record.Location,
record.Priority, record.IncidentType, record.Resolution, record.Status, record.Shift);
}
sr.Close();
WriteCsv wcsv = new WriteCsv(dt, filePath);
Console.WriteLine(dt.Rows.Count);
}
Console.WriteLine("FINISHED");
}
public sealed class DataRecordMap : ClassMap<DataRecord>
{
public DataRecordMap()
{
AutoMap();
Map(m => m.TicketNo).Name("Ticket #");
}
}
}
}
I'm developing an app which can generate a excel file using html table. Up to now I developed html table download as excel file part. (This happens in client side with javascript). Now I need to send email with that attachment (The excel file) to particular person's email address. So I'm confuse how to do this, because up to now I generate excel in client side and need to send that file via email. In this case is it needed to copy client side excel to the server? If so how to do this?
Please give me a direction.
Update 1 (Adding codes)
This is the javascript, that I used to download html table as excel to client side.
var tablesToExcel = (function () {
var uri = 'data:application/vnd.ms-excel;base64,'
, tmplWorkbookXML = '<?xml version="1.0"?><?mso-application progid="Excel.Sheet"?><Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">'
+ '<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office"><Author>Axel Richter</Author><Created>{created}</Created></DocumentProperties>'
+ '<Styles>'
+ '<Style ss:ID="Currency"><NumberFormat ss:Format="Currency"></NumberFormat></Style>'
+ '<Style ss:ID="Date"><NumberFormat ss:Format="Medium Date"></NumberFormat></Style>'
+ '</Styles>'
+ '{worksheets}</Workbook>'
, tmplWorksheetXML = '<Worksheet ss:Name="{nameWS}"><Table>{rows}</Table></Worksheet>'
, tmplCellXML = '<Cell{attributeStyleID}{attributeFormula}><Data ss:Type="{nameType}">{data}</Data></Cell>'
, base64 = function (s) { return window.btoa(unescape(encodeURIComponent(s))) }
, format = function (s, c) { return s.replace(/{(\w+)}/g, function (m, p) { return c[p]; }) }
return function (tables, wsnames, wbname, appname) {
var ctx = "";
var workbookXML = "";
var worksheetsXML = "";
var rowsXML = "";
for (var i = 0; i < tables.length; i++) {
if (!tables[i].nodeType) tables[i] = document.getElementById(tables[i]);
for (var j = 0; j < tables[i].rows.length; j++) {
rowsXML += '<Row>'
for (var k = 0; k < tables[i].rows[j].cells.length; k++) {
var dataType = tables[i].rows[j].cells[k].getAttribute("data-type");
var dataStyle = tables[i].rows[j].cells[k].getAttribute("data-style");
var dataValue = tables[i].rows[j].cells[k].getAttribute("data-value");
dataValue = (dataValue) ? dataValue : tables[i].rows[j].cells[k].innerHTML;
var dataFormula = tables[i].rows[j].cells[k].getAttribute("data-formula");
dataFormula = (dataFormula) ? dataFormula : (appname == 'Calc' && dataType == 'DateTime') ? dataValue : null;
ctx = {
attributeStyleID: (dataStyle == 'Currency' || dataStyle == 'Date') ? ' ss:StyleID="' + dataStyle + '"' : ''
, nameType: (dataType == 'Number' || dataType == 'DateTime' || dataType == 'Boolean' || dataType == 'Error') ? dataType : 'String'
, data: (dataFormula) ? '' : dataValue
, attributeFormula: (dataFormula) ? ' ss:Formula="' + dataFormula + '"' : ''
};
rowsXML += format(tmplCellXML, ctx);
}
rowsXML += '</Row>'
}
ctx = { rows: rowsXML, nameWS: wsnames[i] || 'Sheet' + i };
worksheetsXML += format(tmplWorksheetXML, ctx);
rowsXML = "";
}
ctx = { created: (new Date()).getTime(), worksheets: worksheetsXML };
workbookXML = format(tmplWorkbookXML, ctx);
var link = document.createElement("A");
link.href = uri + base64(workbookXML);
link.download = wbname || 'Workbook.xls';
link.target = '_blank';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
})();
Still I do not have idea to save generated excel to server and send it as email.
AS per our discussion:
1. you need to send data from client to server
you can use this code to do this sending headers and values to server using ajax and you can also filter columns as you want
function SaveToServer() {
var gov = GetHeaders('tbl');
$.ajax({
url: '#Url.Content("~/Home/ReciveData")',
data: { headers: JSON.stringify(gov.heasers), data: JSON.stringify(gov.data) },
success: function (data) {
// Success
},
error: function (xhr) {
}
});
}
function GetHeaders(tableName) {
table = document.getElementById(tableName);
var tbl_Hdata = [];
var tbl_Data = [];
for (var i = 0, row; row = table.rows[i]; i++) {
var rowData = [];
for (var j = 0, col; col = row.cells[j]; j++) {
// add column filter
if (i == 0) {
tbl_Hdata.push(col.innerHTML);
}
else {
rowData.push(col.innerHTML);
}
}
if (i > 0) {
tbl_Data.push(rowData);
}
}
return { heasers: tbl_Hdata, data: tbl_Data };
}
now we want to recive this data and convert it to datatable to save it to excel in server side
using NPOI
public void ReciveData(string headers, string data)
{
#region Read Data
List<string> tbl_Headers = new List<string>();
List<List<string>> tbl_Data = new List<List<string>>();
tbl_Headers = Newtonsoft.Json.JsonConvert.DeserializeObject<List<string>>(headers);
tbl_Data = Newtonsoft.Json.JsonConvert.DeserializeObject<List<List<string>>>(data);
#endregion
#region Create Data Table
DataTable dataTable = new DataTable("Data");
foreach (var prop in tbl_Headers)
{
dataTable.Columns.Add(prop);
}
DataRow row;
foreach (var rw in tbl_Data)
{
row = dataTable.NewRow();
for (int i = 0; i < rw.Count; i++)
{
row[tbl_Headers[i]] = rw[i];
}
dataTable.Rows.Add(row);
}
#endregion
#region Save To excel
string path = #"D:\";
string fileName = "";
GenerateExcelSheetWithoutDownload(dataTable, path, out fileName);
#endregion
}
public bool GenerateExcelSheetWithoutDownload(DataTable dataTable, string exportingSheetPath, out string exportingFileName)
{
#region Validate the parameters and Generate the excel sheet
bool returnValue = false;
exportingFileName = Guid.NewGuid().ToString() + ".xls";
if (dataTable != null && dataTable.Rows.Count > new int())
{
string excelSheetPath = string.Empty;
#region Check If The directory is exist
if (!Directory.Exists(exportingSheetPath))
{
Directory.CreateDirectory(exportingSheetPath);
}
excelSheetPath = exportingSheetPath + exportingFileName;
FileInfo fileInfo = new FileInfo(excelSheetPath);
#endregion
#region Write stream to the file
MemoryStream ms = DataToExcel(dataTable);
byte[] blob = ms.ToArray();
if (blob != null)
{
using (MemoryStream inStream = new MemoryStream(blob))
{
FileStream fs = new FileStream(excelSheetPath, FileMode.Create);
inStream.WriteTo(fs);
fs.Close();
}
}
ms.Close();
returnValue = true;
#endregion
}
return returnValue;
#endregion
}
private static MemoryStream DataToExcel(DataTable dt)
{
MemoryStream ms = new MemoryStream();
using (dt)
{
#region Create File
HSSFWorkbook workbook = new HSSFWorkbook();//Create an excel Workbook
ISheet sheet = workbook.CreateSheet("data");//Create a work table in the table
int RowHeaderIndex = new int();
#endregion
#region Table Headers
IRow headerTableRow = sheet.CreateRow(RowHeaderIndex);
if (dt != null)
{
foreach (DataColumn column in dt.Columns)
{
headerTableRow.CreateCell(column.Ordinal).SetCellValue(column.Caption);
}
RowHeaderIndex++;
}
#endregion
#region Data
foreach (DataRow row in dt.Rows)
{
IRow dataRow = sheet.CreateRow(RowHeaderIndex);
foreach (DataColumn column in dt.Columns)
{
dataRow.CreateCell(column.Ordinal).SetCellValue(row[column].ToString());
}
RowHeaderIndex++;
}
#endregion
workbook.Write(ms);
ms.Flush();
//ms.Position = 0;
}
return ms;
}
Now you can send this file as attachment in mail
You can't create Excel files with HTML tables. This is a hack that's used to fake actual Excel files. Excel isn't fooled, it recognizes the HTML file and tries to import the data using defaults. This will easily break for any number of reasons, eg different locale settings for decimals and dates.
Excel files are just zipped XML files. You can create them using XML manipulation, the Open XML SDK or a library like EPPlus.
Creating an Excel file with EPPlus is as easy as calling the LoadFromCollection or LoadFromDatatable method. The sheet can be saved to any stream, including FileStream or MemoryStream. A MemoryStream can be used to send the data to a web browser as shown in this answer:
public ActionResult ExportData()
{
//Somehow, load data to a DataTable
using (ExcelPackage package = new ExcelPackage())
{
var ws = package.Workbook.Worksheets.Add("My Sheet");
//true generates headers
ws.Cells["A1"].LoadFromDataTable(dataTable, true);
var stream = new MemoryStream();
package.SaveAs(stream);
string fileName = "myfilename.xlsx";
string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
stream.Position = 0;
return File(stream, contentType, fileName);
}
}
Mail attachments can also be created from a MemoryStream. The Attachment(Stream, string,string) constructor accepts any stream as input. The example above could be modified to create an attachment instead of sending the data to the browser:
public void SendData(string server, string recipientList)
{
//Same as before
using (ExcelPackage package = new ExcelPackage())
{
var ws = package.Workbook.Worksheets.Add("My Sheet");
ws.Cells["A1"].LoadFromDataTable(dataTable, true);
var stream = new MemoryStream();
package.SaveAs(stream);
string fileName = "myfilename.xlsx";
string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
stream.Position = 0;
SendExcel(server,recipientList);
}
}
void SendExcel(string server, string recipientList)
{
//Send the file
var message = new MailMessage("logMailer#contoso.com", recipientList);
message.Subject = "Some Data";
Attachment data = new Attachment(stream, name, contentType);
// Add the attachment to the message.
message.Attachments.Add(data);
// Send the message.
// Include credentials if the server requires them.
var client = new SmtpClient(server);
client.Credentials = CredentialCache.DefaultNetworkCredentials;
client.Send(message);
}
}
UPDATE
Generating an XSLX table on the client side becomes a lot easier if you use a library like js-xlsx. There's even a sample that generates an XLSX file from an HTML table
I am trying to convert string to DataTable using the ffollowing method , But It did"nt work
public static DataTable convertStringToDataTable(string data)
{
DataTable dataTable = new DataTable();
bool columnsAdded = false;
foreach (string row in data.Split('\n'))
{
DataRow dataRow = dataTable.NewRow();
foreach (string cell in row.Split(','))
{
string[] keyValue = cell.Split('"');
if (!columnsAdded)
{
DataColumn dataColumn = new DataColumn(keyValue[0]);
dataTable.Columns.Add(dataColumn);
}
dataRow[keyValue[0]] = keyValue[1];
}
columnsAdded = true;
dataTable.Rows.Add(dataRow);
}
return dataTable;
}
Code that contains data string :
StringWriter sw = new StringWriter();
sw.WriteLine("\"NumClient\",\"Raisons Sociale\",\"DateDocument\",\"NumCommandeNAV\",\"Réference\",\"Designation\",\"QteCommandée\",\"QteLivrée\",\"QteAnnulée\",\"Reste à Livrer\",\"Type Disponibilite\",\"DateDisponibilite\"");
var EnTete =
db.AURES_GROS_EnTeteCommande.Where(e => e.NumCommandeNAV != " " && e.NumCommandeNAV != "_")
.OrderBy(x => x.CodeMagasin)
.ThenBy(s => s.NumClient)
.ThenBy(c => c.DateDocument)
.OrderByDescending(x => x.NumCommandeNAV)
.ToList();
foreach (var element in EnTete)
{
string statut = RecuperStatut(element.NumCommandeNAV);
if (statut == "A livrer")
{
Raison = context.Users.First(x => x.No_ == element.NumClient).RaisonSociale;
lignes = db.AURES_GROS_LigneCommande.Where(x => x.NumDocument == element.NumDocument).ToList();
foreach (var elt in lignes)
{
sw.WriteLine(string.Format("\"{0}\",\"{1}\",\"{2}\",\"{3}\",\"{4}\",\"{5}\",\"{6}\",\"{7}\",\"{8}\",\"{9}\",\"{10}\",\"{11}\"",
element.NumClient,
Raison,
element.DateDocument,
element.NumCommandeNAV,
elt.CodeArticle,
elt.Designation,
elt.Quantite,
0,
elt.QteANNULEE,
elt.Quantite,
element.Couleur,
elt.DateDisponibilite
));
}
}
}
DataTable t = convertStringToDataTable(sw.ToString());
Response.ClearContent();
Response.ClearHeaders();
Response.BufferOutput = true;
Response.ContentType = "text/excel";
Response.AddHeader("Content-Disposition", "attachment; filename=Reliquat" + DateTime.Now.ToString("yyyy_MM_dd") + ".csv");
Response.Write(t);
Response.Flush();
Response.Close();
//Response.End();
In this code I want I wnat to export data to Excel file
Any one have solutions
Thanks,
I think you want to create a DataTable from a string. So first split the "rows" and then the "columns". You are adding the DataColumns in the row-loop. You need that only once before the loop. Here is another implementation which handles this and other edge cases you haven't considered yet:
public static DataTable ConvertStringToDataTable(string data)
{
DataTable dataTable = new DataTable();
// extract all lines:
string[] lines = data.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries);
string header = lines.FirstOrDefault();
if (header == null)
return dataTable;
// first create the columns:
string[] columns = header.Split(','); // using commas as delimiter is brave ;)
foreach (string col in columns)
dataTable.Columns.Add(col.Trim());
foreach (string line in lines.Skip(1))
{
string[] fields = line.Split(',');
if(fields.Length != dataTable.Columns.Count)
continue; // should not happen
DataRow dataRow = dataTable.Rows.Add();
for (int i = 0; i < fields.Length; i++)
dataRow.SetField(i, fields[i]);
}
return dataTable;
}
You can convert your column foreach to a for loop.
public static DataTable convertStringToDataTable(string data)
{
DataTable dataTable = new DataTable();
bool columnsAdded = false;
foreach (string row in data.Split('\n'))
{
DataRow dataRow = dataTable.NewRow();
string[] cell = row.Split(',');
for (int i = 0; i < cell.Length; i++)
{
string[] keyValue = cell[i].Split('"');
if (!columnsAdded)
{
DataColumn dataColumn = new DataColumn();
dataTable.Columns.Add(dataColumn);
}
dataRow[i] = keyValue[1];
}
columnsAdded = true;
dataTable.Rows.Add(dataRow);
}
return dataTable;
}
However if your split string[] keyValue = cell.Split('"'); is not returning what you are expecting you may need to investigate further.
I have this code which export data from GridView to csv. It works with other sites but not on this current one I've been developing.
The GridView is binded with DataTable in code behind. Following is the event that binds the fetch and bind the data to GridView.
private void bindGridView()
{
//Fetching data from DB goes here
myTable.Columns.Add("type", typeof(int));
myTable.Columns.Add("rate", typeof(int));
foreach (DataRow rows in myTable.Rows)
{
if (rows["dst"].ToString() == "1875")
{
rows["type"] = 1;
rows["rate"] = 500;
rows.AcceptChanges();
}
else if (rows["dst"].ToString() == "1876")
{
rows["type"] = 0;
rows["rate"] = 30;
rows.AcceptChanges();
}
}
gridViewData.DataSource = myTable;
gridViewData.AllowPaging = true;
gridViewData.PageSize = 10;
gridViewData.DataBind();
}
Following is the button click event to export data from GridView
protected void btnExportCDR_Click(object sender, EventArgs e)
{
if (gridViewData.Rows.Count == 0)
{
lblStatus.Text = "Data is empty. Can not export CDR. Please check your filtering dates.";
}
else
{
Response.Clear();
Response.Buffer = true;
Response.AddHeader("content-disposition", "attachment;filename=CDRMMCC_" + System.DateTime.Now.ToShortDateString() + ".csv");
Response.Charset = "";
Response.ContentType = "application/text";
bindGridView();
gridViewData.AllowPaging = false;
StringBuilder sb = new StringBuilder();
//I did a trace here, gridViewData.Columns.Count is 0. That's why it got skipped, I think.
for (int k = 0; k < gridViewData.Columns.Count; k++)
{
sb.Append(gridViewData.Columns[k].HeaderText + ",");
}
sb.Append("\r\n");
for (int i = 0; i < gridViewData.Rows.Count; i++)
{
for (int k = 0; k < gridViewData.Columns.Count; k++)
{
sb.Append(gridViewData.Rows[i].Cells[k].Text + ",");
}
sb.Append("\r\n");
}
Response.Output.Write(sb.ToString());
Response.Flush();
Response.End();
}
}
Please advice.
If you use the AutoGenerateColumns property of the GridView set to true the Columns collection will be empty. The MSDN documentation for this property says:
"Automatically generated bound column fields are not added to the Columns collection".
This is the reason your Columns collection is empty. As Henk Holterman pointed out use your DataTable directly to generate your CSV file.
An alternative approach would be to set the AutoGenerateColumns property to false and define the Columns explicitly.
In addition to Hans answer, you can use RenderControl of the GridView which reduces your work.
StringWriter strWriter = new StringWriter();
HtmlTextWriter htmlWriter = new HtmlTextWriter(strWriter);
MyGridView.RenderControl(htmlWriter);
Response.Write(strWriter.ToString());