Optimized Infragistics Excel - c#

Recently we have encounter this issue about exporting reports to excel file using infragistics library.
Our report table contains more or less 1.26 million records as of now. We are trying to create an excel(2007) file for this, so approximately this will be 2 worksheets because only about 1million rows is supported by excel 2007 per sheet.
We have no problem during the creation of worksheets and during the filling of data into the worksheet, memory is manageable at this point.
Our problem is when writing the excel data into the stream(file, memory).
The memory consumption is just too high and when it reaches 1.8GB it will no longer continue.
P.S. This is a summary report, the client wants this in a single excel file.
Your recommendations are much appreciated!!!
Below is the code that i have pulled out from the actual source but i have replaced the data retrieval part and instead use a dummy data.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Win32;
using System.Runtime;
using System.Diagnostics;
using Infragistics.Excel;
namespace ConsoleApplication1
{
class Program
{
static bool tip = true;
static void Main(string[] args)
{
var xls = Workbook.MaxExcelRowCount;
var xlsx =Workbook.MaxExcel2007RowCount;
var wb = new Workbook(WorkbookFormat.Excel2007, WorkbookPaletteMode.StandardPalette);
var ws = wb.Worksheets.Add("Sheet1");
var sheetCtr = 1;
var limit = 1256898;
var rr = 0;
for (var row = 0; row < limit; row++)
{
if (rr >= xlsx - 1)
{
//create new worksheet if row exceeded the limit
ws = wb.Worksheets.Add("Sheet" + sheetCtr.ToString());
rr = 0;
ClearMemory();
}
for (var col = 0; col < 10; col++)
{
ws.Rows[rr].Cells[col].Value = string.Format("data{0}-{1}", row, col);
}
Console.Write("Row=");
Console.Write(row.ToString());
Console.WriteLine();
rr++;
}
Console.Write("Saving worksheet...");
//this part uses too much memory
wb.Save("wb2.xlsx");
Console.WriteLine("Workbook saved.");
Console.WriteLine("Done");
Console.Read();
}
static void ClearMemory()
{
try
{
System.Diagnostics.Process proc = System.Diagnostics.Process.GetCurrentProcess();
if (tip == true)
{
proc.MaxWorkingSet = (IntPtr)((int)proc.MaxWorkingSet - 1);
proc.MinWorkingSet = (IntPtr)((int)proc.MinWorkingSet - 1);
}
else
{
proc.MaxWorkingSet = (IntPtr)((int)proc.MaxWorkingSet + 1);
proc.MinWorkingSet = (IntPtr)((int)proc.MinWorkingSet + 1);
}
tip = !tip;
}
catch (System.Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}

Related

Read the first 10 lines of a .txt file and print them in a DataTable with non-fixed number of columns C#

I am running the following C# code to read only the first 10 lines of a .txt file:
using MaterialDesignThemes.Wpf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Data;
namespace TestEnvironment
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void BrowseButton_Click(object sender, RoutedEventArgs e)
{
// Create OpenFileDialog
Microsoft.Win32.OpenFileDialog openFileDlg = new Microsoft.Win32.OpenFileDialog();
// Launch OpenFileDialog by calling ShowDialog method
Nullable<bool> result = openFileDlg.ShowDialog();
// Get the selected file name and display in a TextBox.
// Load content of file in a TextBlock
if (result == true)
{
FileNameTextBox.Text = openFileDlg.FileName;
TextBlock1.Text = "Created on: " + System.IO.File.GetCreationTime(openFileDlg.FileName).ToString();
TextBlock1.Text += Environment.NewLine + Environment.NewLine + string.Join("\r\n", System.IO.File.ReadLines(openFileDlg.FileName).Take(10));
//System.IO.File.ReadLines(openFileDlg.FileName).Take(10).ToString()
Debug.WriteLine("Txt file contents!");
}
// Set filter for file extension and default file extension
openFileDlg.DefaultExt = ".txt";
openFileDlg.Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*";
Debug.WriteLine("Txt imported");
// Set initial directory
openFileDlg.InitialDirectory = #"C:\Documents\";
// Multiple selection with all file types
openFileDlg.Multiselect = true;
Debug.WriteLine("End!");
}
private void TabablzControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
}
}
Current output
But this what I want. I actually want to print the content in a table format, with column names and rows.
To do so I have searched for a similar question and found this. However, the answer posted there is using a fixed number of columns. But I want to make this method take a dynamic number of columns because my txt files don't have the same length of columns.
The code I run now:
using MaterialDesignThemes.Wpf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Data;
namespace TestEnvironment
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public 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);
var lines1 = lines.Take(10);
Debug.WriteLine(lines1);
foreach (string line in lines1)
{
var cols = line.Split('\t');
DataRow dr = tbl.NewRow();
for (int cIndex = 0; cIndex < line.Length; cIndex++)
{
dr[cIndex] = cols[cIndex];
}
tbl.Rows.Add(dr);
}
return tbl;
}
private void BrowseButton_Click(object sender, RoutedEventArgs e)
{
// Create OpenFileDialog
Microsoft.Win32.OpenFileDialog openFileDlg = new Microsoft.Win32.OpenFileDialog();
// Launch OpenFileDialog by calling ShowDialog method
Nullable<bool> result = openFileDlg.ShowDialog();
// Get the selected file name and display in a TextBox.
// Load content of file in a TextBlock
if (result == true)
{
FileNameTextBox.Text = openFileDlg.FileName;
TextBlock1.Text = "Created on: " + System.IO.File.GetCreationTime(openFileDlg.FileName).ToString();
var travelTime = ConvertToDataTable(filePath: openFileDlg.FileName, numberOfColumns: 1);
TextBlock1.Text += Environment.NewLine + Environment.NewLine + travelTime;
//TextBlock1.Text += Environment.NewLine + Environment.NewLine + string.Join("\r\n", System.IO.File.ReadLines(openFileDlg.FileName).Take(10));
//System.IO.File.ReadLines(openFileDlg.FileName).Take(10).ToString()
Debug.WriteLine("Txt file contents!");
}
// Set filter for file extension and default file extension
openFileDlg.DefaultExt = ".txt";
openFileDlg.Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*";
Debug.WriteLine("Txt imported");
// Set initial directory
openFileDlg.InitialDirectory = #"C:\Documents\";
// Multiple selection with all file types
openFileDlg.Multiselect = true;
Debug.WriteLine("End!");
}
private void TabablzControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
}
}
I get the following error:
Thank you in advance for any comments and help. Happy to provide more info is something was not clear.
A dummy .txt file I created my self can be found here
[UPDATE] based on the comments
After running this: (credits to: gkulshrestha)
public DataTable ConvertToDataTable(string filePath)
{
DataTable tbl = new DataTable();
string[] lines = System.IO.File.ReadAllLines(filePath);
var lines1 = lines.Take(10);
for (int col = 0; col < lines1.First().Split('\t').Length; col++)
tbl.Columns.Add(new DataColumn("Column" + (col + 1).ToString()));
foreach (string line in lines1)
{
var cols = line.Split('\t');
DataRow dr = tbl.NewRow();
for (int cIndex = 0; cIndex < cols.Length; cIndex++)
{
dr[cIndex] = cols[cIndex];
}
tbl.Rows.Add(dr);
}
return tbl;
}
if (result == true)
{
FileNameTextBox.Text = openFileDlg.FileName;
TextBlock1.Text = "Created on: " + System.IO.File.GetCreationTime(openFileDlg.FileName).ToString();
TextBlock1.Text += Environment.NewLine + Environment.NewLine + ConvertToDataTable(filePath: openFileDlg.FileName);
//TextBlock1.Text += Environment.NewLine + Environment.NewLine + string.Join("\r\n", System.IO.File.ReadLines(openFileDlg.FileName).Take(10));
//System.IO.File.ReadLines(openFileDlg.FileName).Take(10).ToString()
Debug.WriteLine("Txt file contents!");
}
I get nothing in return but only the created on Date which is the first Text of my TextBox
[UPDATE 2: Need for encoding the Row.Add content to UTF-8]
I am trying to encode the content of the Row.Add() into UTF-8. Now its ANSI. Searching online I came across online articles.
So my DataGrid table method looks like:
public DataTable ConvertToDataTable(string filePath)
{
DataTable tbl = new DataTable();
// Take the first 10 lines
var lines = File.ReadLines(filePath).Take(10);
// Split each line and create an integer sequence where each value
// is the number of the splitted elements
// then get the max value present in this sequence
var max = lines.Select(x => x.Split('\t').Length).Max();
// First line contains headers
string[] headers = lines.First().Split('\t');
// Now create the table with the max number of columns present
for (int col = 0; col < max; col++)
tbl.Columns.Add(new DataColumn(headers[col]));
//Use the Rows.Add method that accepts an object array
foreach (string line in lines.Skip(1))
{
//tbl.Rows.Add(line.Split('\t'));
var utf8 = Encoding.UTF8;
byte[] utfBytes = utf8.GetBytes(tbl.Rows.Add(line.Split('\t')));
var myReturnedString = utf8.GetString(utfBytes);
tbl.Rows.Add(myReturnedString);
}
foreach (DataRow dr in tbl.Rows)
{
Debug.WriteLine(dr["Nationality"]);
string s = dr["Nationality"].ToString();
byte[] bytes = Encoding.Default.GetBytes(s);
dr["Nationality"] = Encoding.UTF8.GetString(bytes);
Debug.WriteLine(dr["Nationality"]);
}
return tbl;
}
But inside the Row.Add() method I get an error:
Cannot convert from 'System.Data.DataRow' to 'char[]'
The error message tells you that one of your lines has more columns than the value passed in the numberOfColumns variable. So you build a table with a certain number of columns but then you find a line with more data.
You can simply change the check for the exit condition on the for loop
for (int cIndex = 0; cIndex < cols.Length && cIndex < numberOfColumns; cIndex++)
However this will simply ignore the extra data. You should understand why a line has more data and decide if you want to keep that extra or not.
In case you don't know beforehand the number of columns present in your file, then you can change the ConvertToDataTable and allow it to discover the max number of columns (Always keep in mind that with 10 lines there is no performace problem, but with large files things change)
// No need to pass the number of columns, let the method discover it
public DataTable ConvertToDataTable(string filePath)
{
DataTable tbl = new DataTable();
// Take the first 10 lines
var lines = File.ReadLines(filePath).Take(10);
// Split each line and create an integer sequence where each value
// is the number of the splitted elements
// then get the max value present in this sequence
var max = lines.Select(x => x.Split('\t').Length).Max();
// First line contains headers
string[] headers = lines.First().Split('\t');
// Now create the table with the max number of columns present
for (int col = 0; col < max; col++)
tbl.Columns.Add(new DataColumn(headers[col]));
// You can simplify a lot your loop using the Rows.Add method that
// accepts an object array
foreach (string line in lines.Skip(1))
{
tbl.Rows.Add(line.Split('\t'));
}
return tbl;
}
Since you do not know before hand the number of columns your text file will have, you cannot pass numberOfColumns to ConvertToDataTable function.
Better you determine the column count inside the function itself after file has been read.
Try this:
public DataTable ConvertToDataTable(string filePath)
{
DataTable tbl = new DataTable();
string[] lines = System.IO.File.ReadAllLines(filePath);
var lines1 = lines.Take(10);
for (int col = 0; col < lines1.First().Split('\t').Length; col++)
tbl.Columns.Add(new DataColumn("Column" + (col + 1).ToString()));
foreach (string line in lines1)
{
var cols = line.Split('\t');
DataRow dr = tbl.NewRow();
for (int cIndex = 0; cIndex < cols.Length; cIndex++)
{
dr[cIndex] = cols[cIndex];
}
tbl.Rows.Add(dr);
}
return tbl;
}
For a such a case you can use
public DataTable ConvertToDataTable(string filePath)
{
DataTable tbl = new DataTable();
string[] lines = System.IO.File.ReadAllLines(filePath);
// just use lines.Take(10) if you want only 10 lines
for (int col = 0; col < lines.First().Split('\t').Length; col++)
tbl.Columns.Add(new DataColumn("Column" + (col + 1).ToString()));
foreach (string line in lines)
{
var cols = line.Split('\t');
DataRow dr = tbl.NewRow();
for (int cIndex = 0; cIndex < cols.Length; cIndex++)
{
dr[cIndex] = cols[cIndex];
}
tbl.Rows.Add(dr);
}
return tbl;
}

Custom file parser slows down with every next file

I have built a simple file parser that reads a csv file line by line and adds it to the DB.
i dont commit changes to the DB till after the file is completely parsed.
It works fine but for some reason with every next file - the parsing becomes slower and slower
here is the code any suggestions on how to speed it up are very welcome.
using Microsoft.VisualBasic.FileIO;
using System;
using System.IO;
namespace CsvToSQL
{
internal class Program
{
private static void Main(string[] args)
{
TransactionsEntities entities = new TransactionsEntities();
string targetFolderPath = "C:\\Transactions\\";
string[] allFiles = Directory.GetFiles(targetFolderPath);
//Loop through files in folder
foreach (var file in allFiles)
{
//parse file
Console.WriteLine(file);
using (TextFieldParser parser = new TextFieldParser(file))
{
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(",");
int lineNo = 0;
while (!parser.EndOfData)
{
TransactionList transaction = new TransactionList();
//processing row
string[] fields = parser.ReadFields();
try
{
if(lineNo % 20 == 0)
{
Console.WriteLine(file + " Parsed line no: " + lineNo);
}
transaction.Account = fields[0];
transaction.Timestamp = fields[1];
transaction.TransactionType = fields[2];
transaction.Status = fields[3];
transaction.Product = fields[4];
transaction.Price = fields[5];
transaction.BuySell = fields[6];
transaction.Series = fields[7];
transaction.Volume = fields[8];
transaction.FillVolume = fields[9];
transaction.OrderID = fields[10];
transaction.BestBid = fields[11];
transaction.BestAsk = fields[12];
entities.TransactionLists.Add(transaction);
lineNo++;
}
catch(Exception e)
{
Console.WriteLine(e.ToString());
Console.ReadKey();
}
}
try
{
entities.SaveChanges();
}catch(Exception e)
{
Console.WriteLine(e.ToString());
Console.ReadKey();
}
}
}
}
}
}
Hi all i found the memory issue with this - if anyone comes across a similar problem.
TransactionsEntities entities = new TransactionsEntities();
This is what is causing it to slow down so incredibly. It uses the same connection to DB replaced it with:
using (TransactionsEntities entities = new TransactionsEntities()){
//Transaciton parsing code for 1 file
}
and the application is flying through the files at 100x the speed it was before :)
Your problem is:
TransactionsEntities entities = new TransactionsEntities();
Because Entity framework was not designed to work with bulk data in mind, it caches the entries in memory to minimize requeries etc. But adding lots of entries in a single context makes maintaining/checking cached data slow, which is your case.
You should better use SQLBulkCopy if you're using SQL server. It will add 100x more speed to your process.

How to read excel file in asp.net

I am using Epplus library in order to upload data from excel file.The code i am using is perfectly works for excel file which has standard form.ie if first row is column and rest all data corresponds to column.But now a days i am getting regularly , excel files which has different structure and i am not able to read
excel file like as shown below
what i want is on third row i wan only Region and Location Id and its values.Then 7th row is columns and 8th to 15 are its values.Finally 17th row is columns for 18th to 20th .How to load all these datas to seperate datatables
code i used is as shown below
I created an extension method
public static DataSet Exceltotable(this string path)
{
DataSet ds = null;
using (var pck = new OfficeOpenXml.ExcelPackage())
{
try
{
using (var stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
pck.Load(stream);
}
ds = new DataSet();
var wss = pck.Workbook.Worksheets;
////////////////////////////////////
//Application app = new Application();
//app.Visible = true;
//app.Workbooks.Add("");
//app.Workbooks.Add(#"c:\MyWork\WorkBook1.xls");
//app.Workbooks.Add(#"c:\MyWork\WorkBook2.xls");
//for (int i = 2; i <= app.Workbooks.Count; i++)
//{
// for (int j = 1; j <= app.Workbooks[i].Worksheets.Count; j++)
// {
// Worksheet ws = app.Workbooks[i].Worksheets[j];
// ws.Copy(app.Workbooks[1].Worksheets[1]);
// }
//}
///////////////////////////////////////////////////
//for(int s=0;s<5;s++)
//{
foreach (var ws in wss)
{
System.Data.DataTable tbl = new System.Data.DataTable();
bool hasHeader = true; // adjust it accordingly( i've mentioned that this is a simple approach)
string ErrorMessage = string.Empty;
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, ws.Dimension.End.Column];
var row = tbl.NewRow();
foreach (var cell in wsRow)
{
//modifed by faras
if (cell.Text != null)
{
row[cell.Start.Column - 1] = cell.Text;
}
}
tbl.Rows.Add(row);
tbl.TableName = ws.Name;
}
DataTable dt = RemoveEmptyRows(tbl);
ds.Tables.Add(dt);
}
}
catch (Exception exp)
{
}
return ds;
}
}
If you're providing the template for users to upload, you can mitigate this some by using named ranges in your spreadsheet. That's a good idea anyway when programmatically working with Excel because it helps when you modify your own spreadsheet, not just when the user does.
You probably know how to name a range, but for the sake of completeness, here's how to name a range.
When you're working with the spreadsheet in code you can get a reference to the range using [yourworkbook].Names["yourNamedRange"]. If it's just a single cell and you need to reference the row or column index you can use .Start.Row or .Start.Column.
I add named ranges for anything - cells containing particular values, columns, header rows, rows where sets of data begin. If I need row or column indexes I assign useful variable names. That protects you from having all sorts of "magic numbers" in your spreadsheet. You (or your users) can move quite a bit around without breaking anything.
If they modify the structure too much then it won't work. You can also use protection on the workbook and worksheet to ensure that they can't accidentally modify the structure - tabs, rows, columns.
This is loosely taken from a test I was working with last weekend when I was learning this. It was just a "hello world" so I wasn't trying to make it all streamlined and perfect. (I was working on populating a spreadsheet, not reading one, so I'm just learning the properties as I go.)
// Open the workbook
using (var package = new ExcelPackage(new FileInfo("PriceQuoteTemplate.xlsx")))
{
// Get the worksheet I'm looking for
var quoteSheet = package.Workbook.Worksheets["Quote"];
//If I wanted to get the text from one named range
var cellText = quoteSheet.Workbook.Names["myNamedRange"].Text
//If I wanted to get the cell's value as some other type
var cellValue = quoteSheet.Workbook.Names["myNamedRange"].GetValue<int>();
//If I had a named range and I wanted to loop through the rows and get
//values from certain columns
var myRange = quoteSheet.Workbook.Names["rangeContainingRows"];
//This is a named range used to mark a column. So instead of using a
//magic number, I'll read from whatever column has this named range.
var someColumn = quoteSheet.Workbook.Names["columnLabel"].Start.Column;
for(var rowNumber = myRange.Start.Row; rowNumber < myRange.Start.Row + myRange.Rows; rowNumber++)
{
var getTheTextForTheRowAndColumn = quoteSheet.Cells(rowNumber, someColumn).Text
}
There might be a more elegant way to go about it. I just started using this myself. But the idea is you tell it to find a certain named range on the spreadsheet, and then you use the row or column number of that range instead of a magic row or column number.
Even though a range might be one cell, one row, or one column, it can potentially be a larger area. That's why I use .Start.Row. In other words, give me the row for the first cell in the range. If a range has more than one row, the .Rows property indicates the number of rows so I know how many there are. That means someone could even insert rows without breaking the code.
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
namespace ReadData
{
public partial class ImportExelDataInGridView : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnUpload_Click(object sender, EventArgs e)
{
//Coneection String by default empty
string ConStr = "";
//Extantion of the file upload control saving into ext because
//there are two types of extation .xls and .xlsx of excel
string ext = Path.GetExtension(FileUpload1.FileName).ToLower();
//getting the path of the file
string path = Server.MapPath("~/MyFolder/"+FileUpload1.FileName);
//saving the file inside the MyFolder of the server
FileUpload1.SaveAs(path);
Label1.Text = FileUpload1.FileName + "\'s Data showing into the GridView";
//checking that extantion is .xls or .xlsx
if (ext.Trim() == ".xls")
{
//connection string for that file which extantion is .xls
ConStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + path + ";Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=2\"";
}
else if (ext.Trim() == ".xlsx")
{
//connection string for that file which extantion is .xlsx
ConStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + ";Extended Properties=\"Excel 12.0;HDR=Yes;IMEX=2\"";
}
//making query
string query = "SELECT * FROM [Sheet1$]";
//Providing connection
OleDbConnection conn = new OleDbConnection(ConStr);
//checking that connection state is closed or not if closed the
//open the connection
if (conn.State == ConnectionState.Closed)
{
conn.Open();
}
//create command object
OleDbCommand cmd = new OleDbCommand(query, conn);
// create a data adapter and get the data into dataadapter
OleDbDataAdapter da = new OleDbDataAdapter(cmd);
DataSet ds = new DataSet();
//fill the excel data to data set
da.Fill(ds);
if (ds.Tables != null && ds.Tables.Count > 0)
{
for (int i = 0; i < ds.Tables[0].Columns.Count; i++)
{
if (ds.Tables[0].Columns[0].ToString() == "ID" && ds.Tables[0].Columns[1].ToString() == "name")
{
}
//else if (ds.Tables[0].Rows[0][i].ToString().ToUpper() == "NAME")
//{
//}
//else if (ds.Tables[0].Rows[0][i].ToString().ToUpper() == "EMAIL")
//{
//}
}
}
//set data source of the grid view
gvExcelFile.DataSource = ds.Tables[0];
//binding the gridview
gvExcelFile.DataBind();
//close the connection
conn.Close();
}
}
}
try
{
System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName("Excel");
foreach (System.Diagnostics.Process p in process)
{
if (!string.IsNullOrEmpty(p.ProcessName))
{
try
{
p.Kill();
}
catch { }
}
}
REF_User oREF_User = new REF_User();
oREF_User = (REF_User)Session["LoggedUser"];
string pdfFilePath = Server.MapPath("~/FileUpload/" + oREF_User.USER_ID + "");
if (Directory.Exists(pdfFilePath))
{
System.IO.DirectoryInfo di = new DirectoryInfo(pdfFilePath);
foreach (FileInfo file in di.GetFiles())
{
file.Delete();
}
Directory.Delete(pdfFilePath);
}
Directory.CreateDirectory(pdfFilePath);
string path = Server.MapPath("~/FileUpload/" + oREF_User.USER_ID + "/");
if (Path.GetExtension(FileUpload1.FileName) == ".xlsx")
{
string fullpath1 = path + Path.GetFileName(FileUpload1.FileName);
if (FileUpload1.FileName != "")
{
FileUpload1.SaveAs(fullpath1);
}
FileStream Stream = new FileStream(fullpath1, FileMode.Open);
IExcelDataReader ExcelReader = ExcelReaderFactory.CreateOpenXmlReader(Stream);
DataSet oDataSet = ExcelReader.AsDataSet();
Stream.Close();
bool result = false;
foreach (System.Data.DataTable oDataTable in oDataSet.Tables)
{
//ToDO code
}
oBL_PlantTransactions.InsertList(oListREF_PlantTransactions, null);
ShowMessage("Successfully saved!", REF_ENUM.MessageType.Success);
}
else
{
ShowMessage("File Format Incorrect", REF_ENUM.MessageType.Error);
}
}
catch (Exception ex)
{
ShowMessage("Please check the details and submit again!", REF_ENUM.MessageType.Error);
System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName("Excel");
foreach (System.Diagnostics.Process p in process)
{
if (!string.IsNullOrEmpty(p.ProcessName))
{
try
{
p.Kill();
}
catch { }
}
}
}
I found this article to be very helpful.
It lists various libraries you can choose from. One of the libraries I used is EPPlus as shown below.
Nuget: EPPlus Library
Excel Sheet 1 Data
Cell A2 Value :
Cell A2 Color :
Cell B2 Formula :
Cell B2 Value :
Cell B2 Border :
Excel Sheet 2 Data
Cell A2 Formula :
Cell A2 Value :
static void Main(string[] args)
{
using(var package = new ExcelPackage(new FileInfo("Book.xlsx")))
{
var firstSheet = package.Workbook.Worksheets["First Sheet"];
Console.WriteLine("Sheet 1 Data");
Console.WriteLine($"Cell A2 Value : {firstSheet.Cells["A2"].Text}");
Console.WriteLine($"Cell A2 Color : {firstSheet.Cells["A2"].Style.Font.Color.LookupColor()}");
Console.WriteLine($"Cell B2 Formula : {firstSheet.Cells["B2"].Formula}");
Console.WriteLine($"Cell B2 Value : {firstSheet.Cells["B2"].Text}");
Console.WriteLine($"Cell B2 Border : {firstSheet.Cells["B2"].Style.Border.Top.Style}");
Console.WriteLine("");
var secondSheet = package.Workbook.Worksheets["Second Sheet"];
Console.WriteLine($"Sheet 2 Data");
Console.WriteLine($"Cell A2 Formula : {secondSheet.Cells["A2"].Formula}");
Console.WriteLine($"Cell A2 Value : {secondSheet.Cells["A2"].Text}");
}
}

System.OutOfMemoryException in SharpDevelop

I am not sure why I am getting a System.OutOfMemoryException in SharpDevelop for my program in C#. My program opens up an Excel worksheet and processes some of the data in the worksheet to check for duplicates.
Here is the complete Exception error message:
System.Runtime.InteropServices.COMException: See inner exception(s) for details. ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.OutOfMemoryException: Not enough storage is available to complete this operation. (Exception from HRESULT: 0x8007000E (E_OUTOFMEMORY))
at static Object NetOffice.Invoker.PropertyGet(NetOffice.COMObject comObject, System.String name, System.Object[] paramsArray)
at Object NetOffice.ExcelApi.Range.get_Value()
at System.Void excelApp.Program.markDuplicates() in c:\Users\HP\Documents\SharpDevelop Projects\excelApp\excelApp\Program.cs:line 80
at static System.Void excelApp.Program.Main(System.String[] args) in c:\Users\HP\Documents\SharpDevelop Projects\excelApp\excelApp\Program.cs:line 41
Here is my complete program:
It is pointing at the following line in the markDuplicates() method:
Line 80:
Object[,] valuesArray = (Object[,])tableRange.Value;
I have no idea why I am getting this exception.
I am using .NET Framework 4.5.1.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Input.Manipulations;
using NetOffice.ExcelApi;
using NetOffice.ExcelApi.Enums;
using Excel = NetOffice.ExcelApi.Application;
namespace excelApp
{
class Program
{
Excel excelApplication;
Workbook workbook;
Worksheet sheet;
HashSet<int> mpanHashCodeList;
[STAThreadAttribute]
public static void Main(string[] args)
{
Program p = new Program();
p.openWorkSheet(#"C:\Users\HP\Desktop\Book1.xlsx", 2);
p.markDuplicates();
Console.ReadKey(true);
}
private void openWorkSheet(string path, int worksheet)
{
excelApplication = new Excel
{
Visible = true,
ScreenUpdating = true
};
try
{
workbook = excelApplication.Workbooks.Open(path);
sheet = (Worksheet)workbook.Worksheets[worksheet];
}
catch
{
Console.WriteLine("File does not exist");
}
}
private void markDuplicates()
{
Range range = sheet.Cells[2,2];
Range rngLastCell = range.get_End(XlDirection.xlToRight)
.get_End(XlDirection.xlDown);
// holds the range of cells in the worksheet
Range tableRange = sheet.Range(range, rngLastCell);
// holds all the values of the range of cells in the worksheet
Object[,] valuesArray = (Object[,])tableRange.Value;
mpanHashCodeList = new HashSet<int>();
int count = 0;
for(var i = 1; i <= valuesArray.GetUpperBound(0); i++)
{
// create a new string for each row
var rowIdBuilder = new StringBuilder(10);
for(var j = 1; j <= valuesArray.GetUpperBound(1); j++)
{
switch(j)
{
case 1:
rowIdBuilder.Append(valuesArray[i,j].ToString());
break;
case 3:
rowIdBuilder.Append(valuesArray[i,j].ToString());
break;
case 4:
rowIdBuilder.Append(valuesArray[i,j].ToString());
break;
case 6:
rowIdBuilder.Append(valuesArray[i,j].ToString());
break;
}
}
Console.WriteLine(rowIdBuilder.ToString());
int hashcode = rowIdBuilder.ToString().GetHashCode();
if(mpanHashCodeList.Contains(hashcode))
{
count++;
mpanHashCodeList.Remove(hashcode);
}
else
{
mpanHashCodeList.Add(hashcode);
}
}
Console.WriteLine(count + " duplicates found");
}
}
}
It's quite common for native code to return error code 0x8007000E (E_OUTOFMEMORY), which is then mapped to OutOfMemory exception in managed code. For example, this is common returned when a native heap allocations fails, or a handle allocation fails.
Such problem is best diagnosed with mixed mode debugging in Visual Studio. Pros would normally use tools like WinDbg/cdb for such tasks with the right symbols properly resolved.
In short: no simple answer. Dirty work expected.

export data to excel file in an asp.net application

Can someone provide a link with a tutorial about exporting data to an excel file using c# in an asp.net web application.I searched the internet but I didn't find any tutorials that will explain how they do it.
You can use Interop http://www.c-sharpcorner.com/UploadFile/Globalking/datasettoexcel02272006232336PM/datasettoexcel.aspx
Or if you don't want to install Microsoft Office on a webserver
I recommend using CarlosAg.ExcelXmlWriter which can be found here: http://www.carlosag.net/tools/excelxmlwriter/
code sample for ExcelXmlWriter:
using CarlosAg.ExcelXmlWriter;
class TestApp {
static void Main(string[] args) {
Workbook book = new Workbook();
Worksheet sheet = book.Worksheets.Add("Sample");
WorksheetRow row = sheet.Table.Rows.Add();
row.Cells.Add("Hello World");
book.Save(#"c:\test.xls");
}
}
There is a easy way to use npoi.mapper with just below 2 lines
var mapper = new Mapper();
mapper.Save("test.xlsx", objects, "newSheet");
Pass List to below method, that will convert the list to buffer and then return buffer, a file will be downloaded.
List<T> resultList = New List<T>();
byte[] buffer = Write(resultList, true, "AttendenceSummary");
return File(buffer, "application/excel", reportTitle + ".xlsx");
public static byte[] Write<T>(IEnumerable<T> list, bool xlsxExtension = true, string sheetName = "ExportData")
{
if (list == null)
{
throw new ArgumentNullException("list");
}
XSSFWorkbook hssfworkbook = new XSSFWorkbook();
int Rowspersheet = 15000;
int TotalRows = list.Count();
int TotalSheets = TotalRows / Rowspersheet;
for (int i = 0; i <= TotalSheets; i++)
{
ISheet sheet1 = hssfworkbook.CreateSheet(sheetName + "_" + i);
IRow row = sheet1.CreateRow(0);
int index = 0;
foreach (PropertyInfo property in typeof(T).GetProperties())
{
ICellStyle cellStyle = hssfworkbook.CreateCellStyle();
IFont cellFont = hssfworkbook.CreateFont();
cellFont.Boldweight = (short)NPOI.SS.UserModel.FontBoldWeight.Bold;
cellStyle.SetFont(cellFont);
ICell cell = row.CreateCell(index++);
cell.CellStyle = cellStyle;
cell.SetCellValue(property.Name);
}
int rowIndex = 1;
// int rowIndex2 = 1;
foreach (T obj in list.Skip(Rowspersheet * i).Take(Rowspersheet))
{
row = sheet1.CreateRow(rowIndex++);
index = 0;
foreach (PropertyInfo property in typeof(T).GetProperties())
{
ICell cell = row.CreateCell(index++);
cell.SetCellValue(Convert.ToString(property.GetValue(obj)));
}
}
}
MemoryStream file = new MemoryStream();
hssfworkbook.Write(file);
return file.ToArray();
}
You can try the following links :
http://www.codeproject.com/Articles/164582/8-Solutions-to-Export-Data-to-Excel-for-ASP-NET
Export data as Excel file from ASP.NET
http://codeissue.com/issues/i14e20993075634/how-to-export-gridview-control-data-to-excel-file-using-asp-net
I've written a C# class, which lets you write your DataSet, DataTable or List<> data directly into a Excel .xlsx file using the OpenXML libraries.
http://mikesknowledgebase.com/pages/CSharp/ExportToExcel.htm
It's completely free to download, and very ASP.Net friendly.
Just pass my C# function the data to be written, the name of the file you want to create, and your page's "Response" variable, and it'll create the Excel file for you, and write it straight to the Page, ready for the user to Save/Open.
class Employee;
List<Employee> listOfEmployees = new List<Employee>();
// The following ASP.Net code gets run when I click on my "Export to Excel" button.
protected void btnExportToExcel_Click(object sender, EventArgs e)
{
// It doesn't get much easier than this...
CreateExcelFile.CreateExcelDocument(listOfEmployees, "Employees.xlsx", Response);
}
(I work for a finanical company, and we'd be lost without this functionality in every one of our apps !!)

Categories

Resources