I have a code that it's purpose is to export a grid to excel.
The Grid is created in runtime (without a form) and so does the ulraGridExcelExporter...
If I create the grid on a different Thread other than the main GUI thread, export it to a file and then double click on the created file in order to open it, then my computer will lock.
I mean, I cannot do "Go to Desktop" or open "My Copmuter" and the disktop itself is not repoponding.
The Excel file will also not open...
The system will be released only after I close the application that tried to export to excel.
Here is small code that shows the problem:
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using Infragistics.Win.UltraWinGrid;using Infragistics.Win.UltraWinGrid.ExcelExport;
namespace ExcelExportProblem{ public partial class Form1 : Form { UltraGrid grid; string filePath = ""; public Form1() { InitializeComponent(); }
private void button1_Click(object sender, EventArgs e) { SaveFileDialog ofd = new SaveFileDialog() { FileName = "", Title = "Select Destination Excel File", Filter = "Microsoft Excel File (*.xls)|*.xls", InitialDirectory = System.Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), };
if (ofd.ShowDialog() != DialogResult.OK) { filePath = ""; return; }
filePath = ofd.FileName;
MethodInvoker mi = delegate() { grid = new UltraGrid(); grid.BindingContext = new BindingContext();
DataTable dt = new DataTable(); dt.Columns.Add("Col1"); dt.Columns.Add("Col2"); dt.Columns.Add("Col3");
for (int i = 0; i < 10; i++) { dt.Rows.Add(new object[] { 1, 2, 3 }); }
grid.SuspendLayout(); grid.SetDataBinding(dt, "");
foreach (var col in grid.DisplayLayout.Bands[0].Columns) { col.AutoSizeMode = Infragistics.Win.UltraWinGrid.ColumnAutoSizeMode.AllRowsInBand; col.Width = col.CalculateAutoResizeWidth(Infragistics.Win.UltraWinGrid.PerformAutoSizeType.AllRowsInBand, true); col.CellClickAction = Infragistics.Win.UltraWinGrid.CellClickAction.CellSelect; }
grid.ResumeLayout(true); };
mi.BeginInvoke(null, null); }
private void button2_Click(object sender, EventArgs e) { SaveFileDialog ofd = new SaveFileDialog() { FileName = "", Title = "Select Destination Excel File", Filter = "Microsoft Excel File (*.xls)|*.xls", InitialDirectory = System.Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), };
grid = new UltraGrid(); grid.BindingContext = new BindingContext();
grid.ResumeLayout(true); }
private void button3_Click(object sender, EventArgs e) { UltraGridExcelExporter ultraGridExcelExporter1 = new UltraGridExcelExporter(); ultraGridExcelExporter1.Export(grid, filePath); ultraGridExcelExporter1.Dispose(); } }}
Am I doing something wrong?
Is it a bug?
Is there a better way to do this? (I tried using InvokeRequired and grid.Invoke whenever I accessed the grid on the code of Button1, but it didn't help).
Thanks.
Hi,
I'm not sure why the file is locking up your machine, but there are quite a number of issues with that you are doing here.
For one thing, the grid variable is on the UI thread, and you are using this variable inside the second thread. So this is already a really bad idea.
For another, you are never adding the grid to the Controls collection of the form. So the grid never gets disposed.
Another, even worse issue, is that the ExcelExporter is created on the UI thread and it's using the grid which was created on the second thread.
Also, you are creating the grid on the second thread and once the thread finishes executing, it will simply go away. You are not doing anything to keep it alive, so the grid will be gone.
And, there's nothing to stop you from pushing Button1 and then pushing Button3 before the first thread has completed. Or pushing Button1 twice in rapid succession.
This is only an example!
On the real situation there are no buttons!. It is created that way that the export to excel will only be done after the grid was created and filled.
I've changed the code so the grid will be created on the UI thread, instead of the background worker and it does help with the locks.
However, I didn't write the original code. The original code is a huge and complex code that used to create DataGridView and use a method of Copy and Paste into Excel.
It was not using data binding, it was slow and it had some bugs.
I simply replaced some parts of the code so it will work with Infragistics grid and do some data binding.
The problem is that sometime the code I've edited is being called from a different thread, so I can't totally solve that problem.
I'm calling m_Grid.Dispose when I'm done with it.
I see no point of creating a form and adding the grid to a form if I don't need it. (The grid is just a method of exporting data to Excel).
Ok, so let me ask you a question....
Assuming I want to export a big grid that contain 256 columns and 65536 rows.
Using UltraGridExcelExporter in the main GUI might take like 30 seconds, or at least several seconds.
This will lock the GUI. How would someone can export it to excel without locking the GUI?
Ok, I just tested something....
It took 96 seconds to export a 31 columns on 20,000 rows table.
about 1 second for creating the DataTable from a file and 95 seconds on attaching the data source and exporting to Excel.
The creation of the DataTable was made on a different thread and setting the data source and exporting to Excel was made on the main GUI thread.
You don't expect the GUI to be irresponsive for 95 seconds, do you?
What other solutions do I have?
Because I needed a short example that can demonstrate the lockups that I got.
As I already wrote, I now don't use the grid and the ultra grid exporter in order to export to excel, and I'm working directly on the Data Table and the Infragistics2.Excel Dll.
It works fast, but when exporting lots of rows is takes more time compared to codes that I found on the internet that use DataGridView Copy yo Clipboard and then paste to excel sheet.
I think that most of the same is wasted on the Workbook.Save function :-( so I don't think I can do anything to improve the speed.
If you are exporting 20,000 rows and 30 columns, I'm not surprised that this takes a bit of time and locks up the UI.
I imagine that if you did everything on a different thread, then it would work fine. But that means the data, the grid, and the Excel Exporter would all need to be on the same thread. The code you have here is doing all sorts of bad stuff, jumping across threads without marshalling. I understand, now, that this was just some example code. But why post this code and then ask what's wrong with it if you are already aware it's no good?
I'm at a bit of a loss as to how I can help you with this.
OK, mike, I've managed to export a DataTable into Excel without using UltraGrid and the UltraGridExcelExported (just by using the Infragistics2.Excel), and it works well.
However, when comparing the speed of exporting 30 Cols x 20000 Rows using DataGrid View --> Copy Paste into Excel To Workboot.Save of the same Data Table, the results are:
Using DataGridView and Copy Paste take 16 Seconds
Using Infragistics solution takes over 1 minute.
Why that happens?
Is there another solution?