Export DataTable to Excel using programmatically created DevExpress GridView - c#

I'm trying to export a DataTable to Excel using a programmatically created DevExpress GridControl. The code I have exports the GridView columns, but without any populated data rows. Here is the sample code (tblErrors is a DataTable parameter passed to the method):
GridControl control = new GridControl();
GridView view = new GridView();
control.ViewCollection.Add(view);
control.MainView = view;
foreach (DataColumn tCol in tblErrors.Columns)
{
GridColumn gCol = new GridColumn();
gCol.Name = "col" + tCol.ColumnName;
gCol.FieldName = tCol.ColumnName;
gCol.UnboundType = DevExpress.Data.UnboundColumnType.Bound;
view.Columns.Add(gCol);
gCol.Visible = true;
}
control.DataSource = tblErrors;
control.Visible = true;
view.ExportToXlsx(String.Format(#"{0}\{1} Error Report.xlsx", Environment.GetFolderPath(Environment.SpecialFolder.Desktop), DateTime.Today.ToString("yyyy-MM-dd")));
Any ideas as to what I'm missing?

At the time you're calling view.ExportToXlsx this view (and the whole GridControl) is not finally initialized and loaded the data.
You can check it very simply - just set breakpoint on view.ExportToXlsx call and you can see that in this moment view.RowCount == 0, so nothing to export yet.
In fact, this "final initialization" will occur when control became visible. But in your code you're not adding control to the Controls collection of Form or UserControl, so in fact it will never be visible, and has no rows.
If it is intended behaviour and you want just to export data from your dataTable to Excel using GridControl as some "adaptor" and without showing this GridControl on form - you can make some trick like
control.DataSource = tblErrors;
Controls.Add(control);
control.ForceInitialize();
view.ExportToXlsx(....
Control.Remove(control);
Note it may cause some "blinking" of control if your data amount in tblErrors is large because control is actually being added to form, then force initialized, exported data and then control being removed from form.
As for me - it is not the best approach to export data from dataTable to Excel. Consider using instead some libraries for direct writing to Excel files, fro example, NPOI.
UPDATE
After some thoughts - you can prevent "blinking" I've mentioned just by setting control.Visible = false; before adding control to form. But this approach using GridControl is still not the best from my point of view.

Related

gridview can't get the last row from the gridview

I have an c sharp desktop application the user wants me to make the same into a web application, i have a datagrid on the desktop application and added a gridview on my webform.
Also have a button named last record when clicked returns the last row of the data grid view:
net_Weight_TrackingDataGridView.FirstDisplayedScrollingRowIndex = net_Weight_TrackingDataGridView.RowCount - 1;
I am trying to get the same functionality to work in grid view:
my grid view has these turned on:
this.GridView1.AllowPaging = true;
this.GridView1.AllowSorting = true;
because i have a lot of data and if i set the above to false the page keeps loading and loading.
for the last row i tried:
GridViewRow LastRow = GridView1.Rows[GridView1.Rows.Count - 1];
The above piece of code is not working....
Any help will be generously appreciated.
From MSDN:
If the GridView control is bound to a data source control that is
capable of returning a single page of data when requested, the
GridView control will take advantage of that capability directly.
If the GridView control is bound to a data source control that does
not support the paging capability directly, or if the GridView control
is bound to a data structure in code through the DataSource property,
the GridView control will perform paging by getting all of the data
records from the source, displaying only the records for the current
page, and discarding the rest.
So,
this.GridView1.AllowPaging = true;
this.GridView1.AllowSorting = true;
work only if you have case #1. If you have case #2, asp.net will request all data and this is why your page is slow. To avoid this situation you either need to use data source control as per case #1 or even better implement custom paging so that your query does not return all rows from the database, but only X required rows.
Read about custom paging (example)

Casting of WPF controls

I am using WindowsFormHost so as to be able to use a gridview in my WPF application
(started with this ,How to instantiate a Datagridview(in code behind)).
And proceeded as
public WindowsFormsHost HOST = new WindowsFormsHost();
my gridview as
System.Windows.Forms.DataGridView gridview = new System.Windows.Forms.DataGridView();
(do not forget the references, follow here- http://www.c-sharpcorner.com/uploadfile/mahesh/using-windows-forms-controls-in-wpf/)
I fill it with a datatable as
table = new System.Data.DataTable();
table.Columns.Add("Object ID");
foreach (string column in columns)
{
table.Columns.Add(column);
}
foreach (string row in rows)
{
drow = table.NewRow();
tit = row.Substring(0, row.IndexOf('$'));
drow[0] = tit.IndexOf('&') > -1 ? tit.Substring(tit.IndexOf('&') + 1) : tit;
table.Rows.Add(drow);
}
//making the native control known to the WPF application
HOST.Child = gridview;
//Displaying the column headers of the listbox(assigned above).
gridview.DataSource = table.DefaultView;
However when I add the gridview to my WPF window as
this.Children.Add(gridview); //error at this line
I get an error saying
cannot convert from 'System.Windows.Forms.DataGridView' to 'System.Windows.UIElement'
Why so ?
I mean what may I do to rectify this ?
DataGridView is a WinForms control. So you can't directly add that to WPF Control's child. Instead add the WindowsFormsHost instance as follows:
RootGrid.Children.Add(HOST);
Is this question and current answer serious??? Why on earth would you want to import the WindowsForms dll and add a CPU intensive WindowsFormsHost element to your WPF application just so that you can use a DataGridView control? You'll find that it's much better just using the equivalent WPF control: DataGrid
You can find out all about the DataGrid class by viewing the DataGrid class page on MSDN. This page has a detailed description and code examples to help you to use the control. Furthermore, the WPF DataGrid Practical Examples page on CodeProject has detailed examples on how to do just about anything that one might want to do with the DataGrid control.
Guys I am posting what did the trick for me for future visitors.
Instead of adding the gridview I added the HOST to the window and it worked.
this.Children.Add(HOST);
SOLVED HERE :Using windows forms controls on a WPF page

How to use autofiltering option of datagrid columns after binding it to a datasource at runtime, in windows form , C#

I need to use the autofiltering option of datagrid column so that users are able to filter out the data, like the option in excel. I have seen the example in Microsoft official site, and I know how that works. But the thing is, I am binding the datasource at runtime, instead of creating a datasource at design view , and editing the columns manually.
And after binding it at runtime, I am trying to add the autofiltering option. But it is not working. The following code is adding extra columns since new columns are created eve after data is bound. I don't want that. I want to change the property of the bound column to be able to support autofiltering.
BindingSource bs = new BindingSource();
//dtenv is a datatable
bs.DataSource = dtenv;
datagridview1.DataSource = bs;
foreach(DataColumn col in dtenv.Columns)
{
if(col.ColumnName.ToString()=="Deploy")
{
DataGridViewCheckBoxColumn txt = new DataGridViewCheckBoxColumn();
txt.HeaderText = "Deploy";
txt.Name = "Deploy";
datagridview1.Columns.Add(txt);
}
else
{
DataGridViewAutofilterTextBoxColumn txt = new DataGridViewAutofilterTextBoxColumn();
txt.HeaderText = col.ColumnName.ToString();
txt.Name = col.ColumnName.ToString();
datagridview1.Columns.Add(txt);
}
Now, I know the above code is incorrect, as it is adding more columns after the data is bound, but the previous code didn't have any binding source and each column was added every loop and then a separate loop was there to add individual rows. Now if I don't use the binding source, the headercolumns show the filtering buttons, but those buttons don't work.
Please let me know how to fix this. I want to avoid creating a datasource at design view as it is not feasible for our project.

Set DataGridView rows after all are created to stop refresh

I'm adding a great deal of rows to a data grid view, and the process is pretty slow because it appears to try to redraw after each addition.
I'm having trouble finding an example online of how to create a List (or array, whichever works) of rows and add them all at once after the list is created. I need to do this to stop it from re-drawing after each addition though.
Can anyone provide a brief example of this or point me to a good doc?
You're probably looking for the DataGridView.DataSource property. See http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.datasource(v=vs.90).aspx
For example:
//Set up the DataGridView either via code behind or the designer
DataGridView dgView = new DataGridView();
//You should turn off auto generation of columns unless you want all columns of
//your bound objects to generate columns in the grid
dgView.AutoGenerateColumns = false;
//Either in the code behind or via the designer you will need to set up the data
//binding for the columns using the DataGridViewColumn.DataPropertyName property.
DataGridViewColumn column = new DataGridViewColumn();
column.DataPropertyName = "PropertyName"; //Where you are binding Foo.PropertyName
dgView.Columns.Add(column);
//You can bind a List<Foo> as well, but if you later add new Foos to the list
//reference they won't be updated in the grid. If you use a binding list, they
//will be.
BindingList<Foo> listOfFoos = Repository.GetFoos();
dgView.DataSource = listOfFoos;
A handy event to bind to at that point is the DataGridView.DataBindingComplete which fires after the data source is bound.
Here are a couple of ideas:
1) Bind a list to the DataGridView. When you set the DataGridView.DataSource = MyList, it immediately updates the entire grid without all the line-by-line action. You can add the items to MyList and then rebind to the DataGridView. (I prefer using a BindingList which will update the DataGridView grid dynamically.)
2) If data binding is not an option, what I've done in the past is set the AutoSizeMode = NotSet for each column before the update and then set it back to whatever it was before. It is the AutoSizeMode that really slows down the drawing.

how to clear gridview

I want to clear my gridview. I have 2 GridViews and Has Select Button On It. on Selecting this button that item goes into the second gridview. now the question is how should i clear the second grid view. I am trying the clear method but clear method is not found in my visual studio..
dataGridView1.DataSource = null;
or
dataGridView1.Rows.Clear();
gridview.DataSource = null;
//rebind to gridview
gridview.DataBind();
Bind the Gridview to an empty list.
Binding it to 'null' like Patrick Kafka mentioned should work - unless you have some column requirements (I'm mentioning it because I have a tendancy to plug in javascript into my gridviews and unless you specify those columns in the markup, they won't be generated and it will cause errors in the js. (This is also relevant to those getting errors after doing Columns.Clear )
In a case like that (as well as in all other cases), you can simply bind the gridview to a new instance (or empty instance) of your datasource. (Below example for a gridview bound to a datatable - it could be bound to new List<T>() as well).
grdiview1.DataSource = new DataTable();
grdiview1.DataBind();
dataGridView1.Columns.Clear(); //this clears the entire Gridview
Simply add the following c# code to clear the GridView:-
gridView.Rows.Clear();

Categories

Resources