currently I able to import an excel file into gridview by using exceldatareader library. Now, I want to further improve to import multiple excel sheet into gridview. This is the output I wish to do. ImageOutput
I able to get the excel sheet name into the dropdownlist but I have no idea how to get the data from the second sheet. I tried google but still cant found any answer yet.
So now my problem how can I select the sheet name from the dropdownlist and show that sheet data in the gridview.
Below is my code:
public partial class ReadExcel : System.Web.UI.Page
{
DataSet result;
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnLoad_Click(object sender, EventArgs e)
{
dataUpload();
}
protected void dataUpload()
{
if (FileUpload1.HasFile)
{
string path = Path.GetFileName(FileUpload1.PostedFile.FileName);
string Extension = Path.GetExtension(FileUpload1.PostedFile.FileName);
string filepath = Server.MapPath("~/" + path);
FileUpload1.SaveAs(filepath);
FileStream stream = File.Open(filepath, FileMode.Open, FileAccess.Read);
//for excel 2003
// IExcelDataReader excelReader = ExcelReaderFactory.CreateBinaryReader(stream);
// for Excel 2007
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
excelReader.IsFirstRowAsColumnNames = true;
result = excelReader.AsDataSet();
ddlSheet.Items.Clear();
foreach(DataTable dt in result.Tables)
{
ddlSheet.Items.Add(dt.TableName);
}
//excelReader.IsFirstRowAsColumnNames = true;
while (excelReader.Read())
{
// int i = excelReader.GetInt32(0);
GridView1.DataSource = result;
GridView1.DataBind();
}
}
else
{
lblError.Text = "Unable to upload the selected file. Please check the selected file path or confirm that the file is not blank!";
}
}
protected void ddlSheet_SelectedIndexChanged(object sender, EventArgs e)
{
GridView1.DataSource = result;
GridView1.DataBind();
}
}
Hummm, interesting. I've never tried what you described here, but I think the link below will help you get started.
https://msdn.microsoft.com/en-us/library/aa480727.aspx?f=255&MSPPError=-2147217396
Also, below is a small sample of code to get things going.
You can use the excel library from this link http://code.google.com/p/excellibrary/. There is actually an example code provided on this page, it demonstrates how to read from an excel file.
using ExcelLibrary.SpreadSheet;
// open xls file
Workbook book = Workbook.Load(file);
Worksheet sheet = book.Worksheets[0];
// iterate with a proper condition, at the moment it will iterate with a given length!
for (int i = 0; i < length; i++)
{
comboBox.Items.Add(sheet.Cells[i,column_index].Value);
}
Your result is a DataSet object that has Tables[] property and ExcelDataReader stores each sheet as a table.
So, I think you should change
GridView1.DataSource = result;
to
GridView1.DataSource = result.Tables[ddlSheet.SelectedText];
Related
i am creating VSTO in excel , for this i am converting the existing macro to c# where have to find minimun of the column , i have converted this far as shown below :
using Microsoft.Office.Tools.Ribbon;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Excel = Microsoft.Office.Interop.Excel;
using Office = Microsoft.Office.Core;
using Microsoft.Office.Tools.Excel;
using Microsoft.Office.Interop.Excel;
namespace CpCpk
{
public partial class Ribbon1
{
private void Ribbon1_Load(object sender, RibbonUIEventArgs e)
{
}
private void button1_Click(object sender, RibbonControlEventArgs e)
{
var excelApp = Globals.ThisAddIn.Application.ActiveSheet;
//excelApp.Workbooks.Add();
excelApp.Range["P2"].Select();
excelApp.ActiveCell.FormulaR1C1 = "=MIN(C[-14])";
excelApp.Range["Q2"].Select();
excelApp.Visible = true;
}
}
}
now i am not getting any error in syntax , but during execution i am getting below rror:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: ''System.__ComObject' does not contain a definition for 'ActiveCell''
in the line :
excelApp.ActiveCell.FormulaR1C1 = "=MIN(C[-14])";
somebody please help me how to correct this..
You need to set FormulaR1C1 directly from specific cell
excelApp.Range["P2"].FormulaR1C1 = "=MIN(C[-14])";
You could just convert the spreadsheet to a datatable via closed xml (via nuget) like so:
public static DataTable GetDataFromExcel(string path, dynamic worksheet)
{
//Save the uploaded Excel file.
DataTable dt = new DataTable();
//Open the Excel file using ClosedXML.
using (XLWorkbook workBook = new XLWorkbook(path))
{
//Read the first Sheet from Excel file.
IXLWorksheet workSheet = workBook.Worksheet(worksheet);
//Create a new DataTable.
//Loop through the Worksheet rows.
bool firstRow = true;
foreach (IXLRow row in workSheet.Rows())
{
//Use the first row to add columns to DataTable.
if (firstRow)
{
foreach (IXLCell cell in row.Cells())
{
if (!string.IsNullOrEmpty(cell.Value.ToString()))
{
dt.Columns.Add(cell.Value.ToString());
}
else
{
break;
}
}
firstRow = false;
}
else
{
int i = 0;
DataRow toInsert = dt.NewRow();
foreach (IXLCell cell in row.Cells(1, dt.Columns.Count))
{
try
{
toInsert[i] = cell.Value.ToString();
}
catch (Exception ex)
{
}
i++;
}
dt.Rows.Add(toInsert);
}
}
return dt;
}
Then get the minimum via linq:
var min = dt.AsEnumerable()
.Min(r => r.Field<Decimal>(col));
Reminder, you'll need using System.Linq; and using ClosedXML.Excel;
I've probably worded the question wrongly but it is easier to explain.
Basically on my form I have a button where if you click it, it opens up an OpenFileDialog search box and you are able to open an excel file and it gets displayed on various datagridview boxes in the form. And then you can input data into the excel worksheets. However because i'm a novice programmer, I can only update those datagridview's by clicked the button again and going through the OpenFileDialog again.
Here is the code I use to initially read the excel worksheets.
private void button18_Click(object sender, EventArgs e)
{
using (OpenFileDialog ofd = new OpenFileDialog() { Filter = "Excel Workbook|*.xlsx", ValidateNames = true })
{
if (ofd.ShowDialog() == DialogResult.OK)
{
FileStream fs = File.Open(ofd.FileName, FileMode.Open, FileAccess.Read);
IExcelDataReader reader = ExcelReaderFactory.CreateOpenXmlReader(fs);
reader.IsFirstRowAsColumnNames = true;
result = reader.AsDataSet();
cboSheet.Items.Clear();
cboSheet_mirror.Items.Clear();
resultSheet.Items.Clear();
foreach (System.Data.DataTable dt in result.Tables)
{
cboSheet.Items.Add(dt.TableName);
cboSheet_mirror.Items.Add(dt.TableName);
resultSheet.Items.Add(dt.TableName);
}
reader.Close();
}
(...)
The cboSheet and resultSheets aren't relevant they are just what I use to navigate the different worksheets.
What I want to do is create a method where it updates the datagridview's with the edited excel worksheet but without the user having to go through the OpenFileDialog process every time, the program just knows the path to the excel file.
Hopefully that makes sense.
The simplest approach to just remembering the file path would be to save it inside a class member after the user successfully selects a file:
string currentFilePath {get;set;} //Class member that will hold the path
private void button18_Click(object sender, EventArgs e)
{
using (OpenFileDialog ofd = new OpenFileDialog() { Filter = "Excel Workbook|*.xlsx", ValidateNames = true })
{
if (ofd.ShowDialog() == DialogResult.OK)
{
this.currentFilePath = ofd.FullName; //remember the path here
(...)
Then in any other method or event handler inside your class you can read that path and open the excel file again without the need of another file selection process:
private void someOtherButton_Click(object sender, EventArgs e)
{
//read the file from the remembered path
FileStream fs = File.Open(this.currentFilePath, FileMode.Open, FileAccess.Read);
IExcelDataReader reader = ExcelReaderFactory.CreateOpenXmlReader(fs);
(...)
For more information about this topic I'd recommend reading some articles (like this one) about Variable scopes
I think you should have a TextBox -e.g. ExcelFileTextBox- where you browse for your Excel file that after checking for DialogResult.OK set its Text property, This will also inform user about Excel path and filename.
You should move your Excel reading data to a - private - method instead, something like this:
private void ReadExcelData(string filename)
{
FileStream fs = File.Open(filename, FileMode.Open, FileAccess.Read);
IExcelDataReader reader = ExcelReaderFactory.CreateOpenXmlReader(fs);
reader.IsFirstRowAsColumnNames = true;
result = reader.AsDataSet();
cboSheet.Items.Clear();
cboSheet_mirror.Items.Clear();
resultSheet.Items.Clear();
foreach (System.Data.DataTable dt in result.Tables)
{
cboSheet.Items.Add(dt.TableName);
cboSheet_mirror.Items.Add(dt.TableName);
resultSheet.Items.Add(dt.TableName);
}
reader.Close();
}
And your browse button code will become:
private void button18_Click(object sender, EventArgs e)
{
using (OpenFileDialog ofd = new OpenFileDialog() { Filter = "Excel Workbook|*.xlsx", ValidateNames = true })
{
if (ofd.ShowDialog() == DialogResult.OK)
{
ExcelFileTextBox.Text = ofd.FileName;
ReadExcelData(ofd.FileName);
}
}
}
Then add a refresh button that it also calls ReadExcelData like this:
private void RefreshButton_Click(object sender, EventArgs e)
{
ReadExcelData(ExcelFileTextBox.Text);
}
HTH
I've used one module to read excel files and fill the data from them into a DataTable. This DataTable gets then displayed into a DataGridView form.
With that I have no problems, but the thing is that I want to catch any changes made to that DataTable while it was displayed in the GridView and to save them.
In other words, I want to call a function each time something has been changed on the updated new DataTable (I have no problems, if this would require an additional button (e.g. "Save Changes") as well).
I've read about binding source and adapters, but I am quite confused and cannot get them to work properly. So any help would be appreciated, here's the code.
public partial class MainForm : Form
{
DataTable dTable = new DataTable();
BindingSource bSource = new BindingSource();
public MainForm()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();
//
// TODO: Add constructor code after the InitializeComponent() call.
//
}
void Button1Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.InitialDirectory = "d:\\" ;
openFileDialog1.Filter = /*txt files (*.txt)|*.txt|xcel files (*.xcel*)|*.xcel*|*/ "All files (*.*)|*.*" ;
openFileDialog1.FilterIndex = 1;
openFileDialog1.RestoreDirectory = true ;
openFileDialog1.Title = "Choose a file to read";
if(openFileDialog1.ShowDialog() == DialogResult.OK)
{
string szChosenFileNameDirectory = openFileDialog1.FileName;
string szChosenFileExtension = szChosenFileNameDirectory.Substring(szChosenFileNameDirectory.LastIndexOf("."), szChosenFileNameDirectory.Length - szChosenFileNameDirectory.LastIndexOf("."));
SpreadsheetInfo.SetLicense("FREE-LIMITED-KEY");
ExcelFile ef = ExcelFile.Load(szChosenFileNameDirectory);
foreach (ExcelWorksheet sheet in ef.Worksheets)
{
foreach(ExcelColumn column in sheet.Columns)
{
if(column.Index == sheet.CalculateMaxUsedColumns())
break;
DataColumn col = new DataColumn();
col.ColumnName = column.Name;
dTable.Columns.Add(col);
}
foreach (ExcelRow row in sheet.Rows)
{
DataRow r = dTable.NewRow();
r.BeginEdit();
foreach (ExcelCell cell in row.AllocatedCells)
{
r[cell.Column.Name] = cell.Value;
}
r.EndEdit();
dTable.Rows.Add(r);
}
}
//setting the datasource, ok
dataGridView1.DataSource = dTable;
//Handlig a changed row or?
dTable.RowChanged += new DataRowChangeEventHandler(Row_Changed);
}
}
public static void Row_Changed(object sender, DataRowChangeEventArgs e)
{
}
}
P.S.: You should have this :/
using GemBox.Spreadsheet;
There are several ways to do this and several topics that regards this issue.
A quick fix is rebinding your dataSource to the dataGridView via a method attached to a 'refresh' button.
Use the following method, you can assign it to a on_click button event that you must create beforehand:
function bool refresh()
{
dataGridView1.DataSource = null;
dataGridView1.DataSource = dTable;
return true;
}
Alternatively, try looking around the forum, there are several similar topics that show different methods:
How to refresh or show immediately in datagridview after inserting?
How can I refresh c# dataGridView after update ?
I am using Visual Studio 2015, Entity Framework 6 and C#.
I am trying to get my gridview to export to excel. I think I have everything, but when clicking the button my gridview disappears and nothing ever goes to a file.
My gridview is:
gvExOr
The Excel Export code is:
public partial class _Default : Page
{
private void BindFiles()
{
DirectoryInfo di = new DirectoryInfo(tbPath.Text);
gvExOr.DataSource = di.GetFiles();
try {
gvExOr.DataBind();
}
catch { }
}
protected void btnExportToExcel_Click(object sender, EventArgs e)
{
ExportToExcel();
}
//Export to Excel from a GridView
protected void ExportToExcel()
{
Response.Clear();
Response.Buffer = true;
Response.ContentType = "application / vnd.ms - excel";
Response.AddHeader("content - disposition", "attachment; filename = MyFiles.xls");
Response.Charset = "";
this.EnableViewState = false;
System.IO.StringWriter sw = new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter htw = new System.Web.UI.HtmlTextWriter(sw);
gvExOr.RenderControl(htw);
Response.Write(sw.ToString());
Response.End();
}
public override void VerifyRenderingInServerForm(Control control)
{
}
protected void Page_Load(object sender, EventArgs e)
{
BindFiles();
}
}
How do I get the gridview to export to excel?
Looks like you used code from this post https://stackoverflow.com/a/10412559/5786449
I tried the example from that post and it works for me. The only difference I can see is in your Response.ContentType and Response.AddHeader. Try getting rid of the white spaces in those parameters:
Response.ContentType = "application/vnd.ms-excel";
Response.AddHeader("content-disposition", "attachment;filename=MyFiles.xls");
One more thing, your code doesn't actually give you an Excel spreadsheet. It just writes out the GridView HTML markup. Many Excel programs are not expecting HTML in an XLS file and will throw an error when opening the file. If you want an actual Excel spreadsheet I would recommend looking into utilities like EPPlus http://epplus.codeplex.com/
I am having a problem with reading an XML file onto a DataTable. Initially, I am writing a Datatable to an XML file and saving it. Now, when I want to read the XML file back to the DataTable, it's not happening.
The following code is for writing the file:
private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
{
if (myDT_For_DGV.Rows.Count != 0)
{
saveFileDialog1.ShowDialog();
saveFileDialog1.FileName = "checkOutFile.xml";
myDT_For_DGV.TableName = "CheckOutsAndIns";
myDT_For_DGV.WriteXml(saveFileDialog1.FileName, true);
}
else
{
MessageBox.Show("Please add licences to DataGridView, you havent added any licences as of now", "Alert");
}
}
And for reading the file:
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
//write code to open file
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
//myFile = openFileDialog1.FileName;
System.IO.MemoryStream xmlStream = new System.IO.MemoryStream();
xmlStream.Position = 0;
myDT_For_DGV.ReadXml(openFileDialog1.FileName);
//MessageBox.Show(openFileDialog1.FileName);
}
}
It might be easier to just work with the higher-level DataSet, like this:
DataSet dataSet = new DataSet();
DataTable dataTable = new DataTable();
dataSet.Tables.Add(dataTable);
// Save to disk
dataSet.WriteXml(#"C:\MyDataset.xml");
// Read from disk
dataSet.ReadXml(#"C:\MyDataset.xml");
I fixed it, The Problem is, the tablename was assigned while saving but not while reading. So assign the table name globally, which will let it read and write without any problem.
so the code will be,
myDT_For_DGV.TableName = "CheckOutsAndIns";
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
myDT_For_DGV.ReadXml(#openFileDialog1.FileName);
//MessageBox.Show(openFileDialog1.FileName);
}
//TO WRITE TO XML
if (myDT_For_DGV.Rows.Count != 0)
{
saveFileDialog1.ShowDialog();
saveFileDialog1.FileName = "checkOutFile.xml";
myDT_For_DGV.WriteXml(saveFileDialog1.FileName, true);
}