0

I am creating Excel Sheet using Devexpress Exporter and then saving the file at a particular location.

After the creation of file, I have to open it, to add dropdownlist of items and then save it again in same location.

After all the operations, the file has to be emailed automatically to the email address from database.

Now if I have 1000 email addresses, and to automate this process, it is creating more than 10 instances of Excel.

How can I stop creation of those instance and how can I use excel operations without using more memory.

Code is as below:

protected string CreateExcelFile(string FilterName)
{       
    Random ranNumber = new Random();
    int number = ranNumber.Next(0, 10000000);
    string FileName = "TestDoc"+DateTime.Now.Year.ToString()+number.ToString()+DateTime.Now.Second.ToString()+".xls";
    string path = @"c:\TestDocuments\"+FileName;            
    Directory.CreateDirectory(Path.GetDirectoryName(path));
    FileStream fs = new FileStream(path, FileMode.OpenOrCreate);
    XlsExportOptions options = new XlsExportOptions();
    options.ExportHyperlinks = false;
    ASPxExporter.WriteXls(fs, options);
    fs.Close();     
    AddDropDownToExcel(path);   
    return path;    
}
//Adding The Dropdownlist Of Items TO Generated Excel Sheet
protected void AddDropDownToExcel(string path)
{
         Microsoft.Office.Interop.Excel.Application application = new Microsoft.Office.Interop.Excel.Application();     
    string fileName = path.Replace("\\", "\\\\");
    string RowCount = "F" + (testgrid.VisibleRowCount + 1).ToString();
    // Open Excel and get first worksheet.      
    var workbook = application.Workbooks.Open(fileName);
    var worksheet = workbook.Worksheets[1] as Microsoft.Office.Interop.Excel.Worksheet;
    // Set range for dropdownlist
    var rangeNewStatus = worksheet.get_Range("F2", RowCount);
    rangeNewStatus.ColumnWidth = 20;
    rangeNewStatus.Validation.Add(Microsoft.Office.Interop.Excel.XlDVType.xlValidateList, Microsoft.Office.Interop.Excel.XlDVAlertStyle.xlValidAlertStop,
    Microsoft.Office.Interop.Excel.XlFormatConditionOperator.xlBetween, "Item1,Item2,Item3,Item4");
    // Save.
    workbook.Save();
    workbook.Close(Microsoft.Office.Interop.Excel.XlSaveAction.xlSaveChanges, Type.Missing, Type.Missing);
    application.Quit();
}
Ruchi
  • 1,238
  • 11
  • 32
  • I use the following code in VBA to either attach to an existing instance of Excel or create a new one. It might head you in the right direction: Public Sub InitializeExcel(aNewInstance As Boolean) If aNewInstance = False Then On Error Resume Next Set xlApp = GetObject(, "Excel.Application") End If On Error GoTo 0 If xlApp Is Nothing Then Set xlApp = CreateObject("Excel.Application") End If End Sub –  Nov 16 '12 at 18:08

2 Answers2

2

First, I sincerely hope this isn't running on a server.

Then, if your problem is that too many instances of Excel are created, a thought is "don't create an instance every single time". Instead of starting Excel every time AddDropDownToExcel is called, can you reuse the same instance?

The problem you are having shows up regularly in Excel interop scenario; even though you are done and tell Excel to close, it "stays alive". It's usually caused by your app still holding a reference to a COM object that hasn't been disposed, preventing Excel from closing. This StackOverflow answer provides some pointers: https://stackoverflow.com/a/158752/114519

In general, to avoid that problem, you want to follow the "one-dot" rule. For instance, in your code:

var workbook = application.Workbooks.Open(fileName);  

will be a problem, because an "anonymous" wrapper for Workbooks is created, and will likely not be disposed properly. The "one-dot" rule would say "don't use more than one dot when working with Excel interop", in this case:

var workbooks = application.Workbooks;
var workbook = workbooks.Open(fileName);

A totally different thought - instead of using Interop, can't you use OpenXML to generate your Excel file? I have never tried it to create drop downs, but if it supports it, it will be massively faster than Interop, and the type of problems you have won't happen.

Hope this helps.

Community
  • 1
  • 1
Mathias
  • 15,191
  • 9
  • 60
  • 92
  • I understood what you have explained, but my question still prevails, how to use thread to automate the process without creating instances of Excel??? – Ruchi Nov 16 '12 at 22:32
  • What does this have to do with threads? Regardless of whether you use threads or not, your code will still open 1 or more instances of Excel that will hang. Can you explain why you think threads would help? – Mathias Nov 16 '12 at 22:39
  • I can gather all the information needed to generate file and then start a thread calling one instance of excel application >>>>> which would generate multiple files. Correct me if i m wrong. – Ruchi Nov 16 '12 at 22:41
  • You can't call simply the same instance from multiple threads, I believe - I would expect it to crash. What you can do is have one instance open, and sequentially call your AddDropDownToExcel method using that instance. That being said, your code will still leave processes hanging. And from your comment on the other answer, it looks like you are doing this on a server, which you should really avoid doing. – Mathias Nov 16 '12 at 23:37
0

As I know the grow of number of runnig excel.exe processes is 'normal' situation to excel :)
The dumbest advice is just kill sometimes it's processes. BUT, this way will be absolutely unhelpful if you use excel during your app is working because of you rather don't get which one excel.exe is yours.

pkuderov
  • 3,501
  • 2
  • 28
  • 46
  • Thanks for your response. So do you mean to say that if 100 users are using the system, I should have spare time to kill process of each and every one of them so that my server does not give memory exception:) – Ruchi Nov 16 '12 at 18:01
  • Do NOT run this code on a server; in general, do NOT use office interop server side. See Microsoft's comments on this: http://support.microsoft.com/kb/257757 – Mathias Nov 16 '12 at 18:05
  • @RuchiDoshi, sorry :) but you didn't mentioned the word 'server' - it makes changes in a way written by Mathias above. Btw, thx Mathias for link. – pkuderov Nov 20 '12 at 14:39