DataTable to Excel export - c#

I m developing a web project in asp.net 3.5
I want to export datatable to Excel. But there are 20.000 rows in datatable. Sometimes timeout problem happens..
protected string Worksheet97_Header()
{
string s = "<tr>";
foreach (ExcelColumn col in Columns)
{
s += "<th>" + col.Header_Text + "</th>";
}
s+="</tr>";
return s;
}
protected string Worksheet97_Data()
{
string s = "";
try
{
for (int i = 0; i < data.Rows.Count; i++)
{
s += "<tr>";
foreach (ExcelColumn col in Columns)
{
if (col.Column_Type == "System.String")
s += "<td>" + data.Rows[i][col.Field_Name].ToString() + "</td>";
if (col.Column_Type == "System.DateTime")
s += "<td>" + Convert.ToDateTime(data.Rows[i][col.Field_Name]).ToString("dd.MM.yyyy HH:mm:ss") + "</td>";
if (col.Column_Type == "System.Int32")
s += "<td>" + data.Rows[i][col.Field_Name].ToString() + "</td>";
if ((col.Column_Type == "System.Double") |
(col.Column_Type == "System.Decimal") |
(col.Column_Type == "System.Int16") |
(col.Column_Type == "System.Int32") |
(col.Column_Type == "System.Int64"))
s += "<td>" + Convert.ToDouble(data.Rows[i][col.Field_Name]).ToString("0.00") + "</td>";
}
}
}
catch (Exception ex)
{
string a = ex.ToString();
}
return s;
}
public string Export_Excel97()
{
string s = "";
s = "<table border=\"1\">";
s += Worksheet97_Header();
s += Worksheet97_Data();
s += "</table>";
return s;
}
Thanks.

IMHO, i think you should page the query so that you don't load everything into memory.
To write the excel file you may want to try this solution too and compare results of performance: http://msmvps.com/blogs/deborahk/archive/2009/07/23/writing-data-from-a-datatable-to-excel.aspx which will use Microsoft Excel Object Library, so you'll need to have Excel installed in the machine where you're running your code.
HTH somehow.
Regards!

This might help... http://www.dotnetjohn.com/PrintFriend.aspx?articleid=36
It is in VB.NET but you should be able to convert it anyway ;-)

Related

OutOfMemoryException while parsing a file

I am retrieving an System.OutOfMemoryException while parsing an image file. Please see the code below.
Additional information:
The image size is about 10 mb.
64 bit architecture with 8GB RAM
DataTable contains more then 8000 records
if(dt.Rows.Count > 0)
{
for ( int i=0; i< dt.Rows.Count; i++ )
{
string photoId = #"\\192.168.123.123\MwPict\" + dt.Rows[i]["DmCtg"] + "\\DM 3D " + dt.Rows[i]["dmcd"] + ".jpg";
string base64 = "";
string images = "";
byte[] byteArray = null;
try
{
// byteArray = File.ReadAllBytes(photoId);
base64 = Convert.ToBase64String(File.ReadAllBytes(photoId));
images = string.Format("data:image/gif;base64,{0}", base64);
}
catch (FileNotFoundException ee)
{
images = "#";
}
byteArray = null;
base64 = null;
photoId = null;
data += "<tr>";
data += "<td>" + dt.Rows[i]["SR"] + "</td>";
data += "<td><img src = '" + images + "' height = '60px' width = '60px' alt = 'photo' /></ td>";
data += "<td>" + dt.Rows[i]["dmcd"] + "</td>";
data += "<td>"+dt.Rows[i]["DmCtg"] +"</td>";
data += "<td>" + dt.Rows[i]["DmPrdCtg"] + "</td>";
data += "<td>" + dt.Rows[i]["DmSalCtg"] + "</td>";
data += "<td>" + dt.Rows[i]["DsgDate"] + "</td>";
data += "</tr>";
}

How to insert a table in an SMTP email? And the list includes a double

The following code does not put everything in an email. The only result is the word test. When I run all code, there is data from the database. What am I missing to get the data to populate in the email table?
performanceCompare += "<table>";
//Compares last hour today......need to compare to another day results
var performDate = ErrDb.PerformanceDatas.Where(d => d.loggedAt > hourlyBegin && d.loggedAt < hourlyEnd).ToList();
var performanceDataOneDay = ErrDb.PerformanceDatas.Where(o => o.loggedAt > dayBegin && o.loggedAt < dayEnd).ToList();
performanceCompare += "<tr>";
performanceCompare += "<td><b>test</b></td>";
performanceCompare += "</tr>";
var avgTimeList = new List<AvgTime>();
var specialIDS = performDate.Select(x => new {x.sitename, x.functionName }) .Distinct();
foreach (var key in specialIDS)
{
var funComapre = performDate.Where(g => g.functionName == key.functionName && g.sitename == key.sitename);
AvgTime avgTime = new AvgTime();
avgTime.siteName = "<tr>" + key.sitename + "</tr>";
avgTime.functionName = "<td>" + funComapre.Select(x => x.functionName).First() + "</td>";
avgTime.avgFunctTime = "<td>" + (funComapre.Select(x => x.functionTime).Average()) + "</td>";//needs to be a string, not a double
avgTimeList.Add(avgTime);
var anotherFunComapre = performanceDataOneDay.Where(g => g.functionName == key.functionName && g.sitename == key.sitename);
if (anotherFunComapre != null)
{
AvgTime anotherAvgTime = new AvgTime();
avgTime.siteName = "<tr>" + key.sitename + "</tr>";
avgTime.functionName = "<td>" + funComapre.Select(x => x.functionName).First() + "</td>";
anotherAvgTime.avgFunctTime = funComapre.Select(x => x.functionTime).Average();
avgTimeList.Add(anotherAvgTime);
}
}
performanceCompare += "</table>";

How to save DataGrid data to CSV file without enumerating the query result again?

I am using this command to get data from my query:
private void loadData()
{
numRows = 0;
try
{
data = gpso.gpEntitiesObject.ExecuteStoreQuery<My_Class>(sql);
dataGrid.ItemsSource = data;
dataGrid.IsReadOnly = true;
numRows = dataGrid.Items.Count;
numRowsTB.Text = "Number of rows: " + numRows;
}
catch (Exception ex)
{
statusBarTB.Text = "exception: " + ex.Message;
}
}
Although this works and I see the data in my DataGrid, I am not able to save the data to a CSV file since I am trying to reenumerate the query result again, which is not allowed.
What would be the right way to get the data and save it to CSV?
Should I use the DataGrid API to scroll trough the rows and get the data in a foreach() loop?
Here is my CSV function:
public static string exportToCSV(IEnumerable<My_Class> data, string separator)
{
string ishod = "";
string csvRed = "";
ishod += "Key1" + separator + "Key2" + separator;
ishod += "Key3" + separator + "Key4" + separator;
ishod += "\n";
foreach (My_Class item in data)
{
csvRed += item.Key1+ separator + item.Key2+ separator;
csvRed += item.Key3+ separator + item.Key4+ separator;
csvRed += "\n";
ishod += csvRed;
csvRed = "";
}
return ishod;
}
I followed #Clemens advice. I used
IEnumerable dataList = data.ToList<My_Class>();
dataGrid.ItemSource = dataList;
I then called
exportToCSV(dataList, "\t");
with dataList as parameter and it worked!

HTML generate rowspan in html table string

I have the following code, which adds rowspan to a datatable in an html string, but I want it not to receive as a parameter a datatable, but instead to receive as a parameter an html string in C#.
protected void Page_Load(object sender, EventArgs e)
{
DataTable dt = new DataTable();
dt.Columns.Add("Subject");
dt.Columns.Add("Code");
dt.Columns.Add("Test");
dt.Columns.Add("Class");
dt.Rows.Add("Math", "9", "ABC", "D1");
dt.Rows.Add("Math", "9", "ABD", "D2");
dt.Rows.Add("Math", "9", "ABE", "D3");
dt.Rows.Add("Math", "9", "ABF", "D4");
dt.Rows.Add("Science", "91", "ABG", "D1");
dt.Rows.Add("Science", "91", "ABH", "D2");
dt.Rows.Add("Science", "91", "ABI", "D3");
dt.Rows.Add("English", "191", "ABJ", "D1");
Label1.Text = ConvertDataTableToHTML(dt);
}
public static string ConvertDataTableToHTML(DataTable dt)
{
string html = "<table border=1>";
//add header row
html += "<tr>";
for (int i = 0; i < dt.Columns.Count; i++)
{
html += "<td>" + dt.Columns[i].ColumnName + "</td>";
}
html += "</tr>";
//add rows
string sub = "";
for (int i = 0; i < dt.Rows.Count; i++)
{
html += "<tr>";
int count = dt.Select("Subject ='" + dt.Rows[i][0].ToString() + "'").Count();
for (int j = 0; j < dt.Columns.Count; j++)
{
if (j < 2)
{
if (sub != dt.Rows[i][0].ToString())
{
html += "<td rowspan='" + count + "'>" + dt.Rows[i][j].ToString() + "</td>";
}
continue;
}
html += "<td>" + dt.Rows[i][j].ToString() + "</td>";
}
sub = dt.Rows[i][0].ToString();
html += "</tr>";
}
html += "</table>";
return html;
}
This is the result that I hope
There are a few things wrong with the code, and a few ways you can improve your code:
<table border=1> is missing the quotes around the 1. It should be <table border='1'>.
You are missing the <thead> and <tbody> tags around the row tags.
Instead of constantly using +=, use a StringBuilder.
To make your code cleaner, you can change some of your for loops to foreach loops.
Your code should be changed to something like this:
public static string ConvertDataTableToHTML(DataTable dt)
{
StringBuilder builder = new StringBuilder();
//add header row
builder.Append("<table border='1'><thead><tr>");
foreach (DataColumn col in dt.Columns)
{
builder.Append("<td>");
builder.Append(col.ColumnName);
builder.Append("</td>");
}
builder.Append("</tr></thead><tbody>");
//add rows
string sub = "";
...
builder.Append("</tbody></table>");
return builder.ToString();
}
(Just apply the same concepts to the middle code that I removed.)

Accessing Application and Service logs with C#

I was wondering if there is a way to reach the logs under the section named Application and Service Logs in the Event viewer utility in Windows. The thing is, I can read the entries under Windows Logs with the code below. I read the whole entry, and get the items with the necessary id, getting top 20 results. But I couldn't find anything on accessing the Application and Service logs section. Should I change the LogType in the EventLog constructor? Or is there a different method or class to access Application and Service logs? Trying "Application" as the logType variable doesnt work.
string str = "";
EventLog ev = new EventLog(logType, System.Environment.MachineName);
int LastLogToShow = ev.Entries.Count;
if (LastLogToShow <= 0)
Console.WriteLine("No Event Logs in the Log :" + logType);
int i;
int k = 0;
for (i = ev.Entries.Count - 1; i >= 0; i--)
{
EventLogEntry CurrentEntry = ev.Entries[i];
if (CurrentEntry.EventID == id)
{
if (id == 1)
{
str += "Son Açılma \n";
str += "Olay Zamanı: " + CurrentEntry.TimeGenerated.ToLongDateString() + " " + CurrentEntry.TimeGenerated.ToShortTimeString() + "\n";
}
else if (id == 42)
{
str += "Son Kapatılma \n";
str += "Olay Zamanı: " + CurrentEntry.TimeGenerated.ToLongDateString() + " " + CurrentEntry.TimeGenerated.ToShortTimeString() + "\n";
}
else
{
str += "Event type: " + CurrentEntry.EntryType.ToString() + "\n";
str += "Event Message: " + CurrentEntry.Message + CurrentEntry + "\n";
str += "Event : " + CurrentEntry.UserName + "\n" + "\n";
str += "Olay Zamanı: " + CurrentEntry.TimeGenerated.ToLongDateString() + " " + CurrentEntry.TimeGenerated.ToShortTimeString() + "\n";
}
k++;
}
if (k > 20)
break;
}
ev.Close();
return str;
What I am looking for is under
Application and Service Logs/
Microsoft/
Windows/
TerminalServices-RemoteConnectionManager/
Operational/
Event ID 1149
I'm not sure you can access them using the EventLog class, or at least I couldn't figure out how. I did it using the EventLogQuery class instead.
I've provided an example below which I adapted from this post (C#: How to Query for an event log details with a given event id?), and should work for what you need:
using System.Diagnostics.Eventing.Reader;
string logType = "Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational";
string query = "*[System/EventID=1149]";
var elQuery = new EventLogQuery(logType, PathType.LogName, query);
var elReader = new EventLogReader(elQuery);
for (EventRecord eventInstance = elReader.ReadEvent(); eventInstance != null; eventInstance = elReader.ReadEvent())
{
// .. do stuff here
}

Categories

Resources