views:

325

answers:

5

I have to generate about 800 excel files from an access database.

For the first 10-15 of them it's working nice, a few seconds/excel file but it's constantly taking longer, at the 150th excel file it's taking 10 minutes.

Here is my code:

It's doing this for each nrliste in the access table (about 800 of them)

Dim lista = From ls In Liste _
                        Where ls!Concatenare = nrliste(i) _
                     Select ls
            Dim table = lista.CopyToDataTable
            Dim DataArr(table.Rows.Count, 30)

            For x = 0 To table.Rows.Count - 1
                For y = 0 To 30
                    DataArr(x, y) = table.Rows(x).Item(y)
                Next
            Next


            Dim filetocopy As String
            Dim newcopy As String
            Dim tempname As String = nrliste(i).ToString
            Dim filename As String = "LISTA INV OBI(MF) LA 30.09.2009_" & tempname.Replace("#", "_")
            filetocopy = Environment.CurrentDirectory & "\MACHETA.xls"
            newcopy = FolderBD.SelectedPath & "\" & filename & ".xls"
            If System.IO.File.Exists(newcopy) = True Then
                System.IO.File.Delete(newcopy)
                System.IO.File.Copy(filetocopy, newcopy)
            Else
                System.IO.File.Copy(filetocopy, newcopy)
            End If

            'excel file
            Dim xlWBook As Excel.Workbook = xlApp.Workbooks.Open(newcopy)
            Dim xlSheet As Excel.Worksheet = CType(xlWBook.Worksheets("Lista inventar OBI de natura MF"), Excel.Worksheet)

            'insereaza liniile necesare
            For n = 11 To ((lista.Count - 1) + 11)
                With xlSheet
                    .Rows(n).Insert(Excel.XlDirection.xlDown, 1)
                End With
            Next

            'copiaza datele

            With xlSheet

                .Range(.Cells(11, 1), .Cells(table.Rows.Count + 11, 31)).Value = DataArr

            End With
A: 

I don't know but I would look at how many files you are ending up having open in Excel all at the same time. Do you close the files once you have finished writing to them? Maybe it is keeping them open, so by the time the 150'th worksheet is open it could be struggling for memory usage. Also, I would say, try stepping through the code in a debugger, and see which bit is slow (or getting slower over time) - this will help to narrow down the cause of the problem.

1800 INFORMATION
thanks for the suggestion , I've stepped with the debugger and it's taking a lot of time in this linq statement :Dim lista = From ls In Liste _ Where ls!Concatenare = nrliste(i) _ Select lsThis is where is getting the lines form the access table for export.I have no ideea how can i make this faster.
Iulian
+1  A: 

Are you closing the workbook after you are done with it (inside the loop)?

xlWBook.Close
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWBook)

Look at this thread, that explains the need for releasing all COM interfaces.

EDIT: I saw your comments, in reply to @1800 Information.

Dim lista = From ls In Liste _
                        Where ls!Concatenare = nrliste(i) _
                     Select ls

What does this linq query do?

EDIT2: Try running the SQL inside MS-Access to see how it performs? Also, I will suggest discarding LINQ for now & use plain old ADO.net Command object with parametrized query.

Alternatively, a simple & stupid way would be to pull all records (where ID between your min and max value) into a DataTable and filter it in memory and do some kind of direct transfer (without using array and avoid writing values row by row, cell by cell).

I will try and find out, if that is possible. (i.e. use a filtered dataset and write it to excel file).

Hope that gives you, some hint on how to proceed.

shahkalpesh
it is selecting the data from the access table where concatenare ( a column in the access table ) = liste(i) (selection criteria - i goes from 0 to 768)
Iulian
thanks for the suggestions, I'm gonna try them as soon as I can
Iulian
+1  A: 

You could try using Docmd transfer spreadsheet as this should be faster

DoCmd.Transferspreadsheet ....

Then you can always open the file using Excel automation afterwards

Mark3308
i have another app where i use docmd transfer spreadsheet but it seems slower to me, i'm gonna give it a try thought.
Iulian
It should be faster by far, as it's not a sequential, but a batch operation. And you don't have the overhead of automating a second heavyweight Office app -- it writes the file directly using Jet/ACE.
David-W-Fenton
A: 

A quick look at your code makes me question the call to .Rows(n).Insert(Excel.XlDirection.xlDown, 1) for every row. You should be able to call Insert once for all rows. Inserting rows in a worksheet is expensive even if you just insert 1 row - especially if you are inserting into a large worksheet or into a workbook with many formulas.

SpreadsheetGear for .NET typically speeds up applications such as yours (you can see some quotes confirming this here - on the right hand side of the page). SpreadsheetGear also has an IRange.CopyFromDataTable method so you will not have to copy the data to a temporary array. The SpreadsheetGear API is similar to Excel's API so converting your code is straight forward. You can download a free trial here if you want to try it out.

Disclaimer: I own SpreadsheetGear LLC

Joe Erickson
What is the advantage of your produce over TransferSpreadsheet for a case like this where the automation is not being used to do special formatting of the output data?
David-W-Fenton
It appears to me from the original post that each set of records is being inserted at the top of a workbook (I could have misunderstood it) from VB.NET. My reply is to that original post. I am not familar with DoCmd.TransferSpreadsheet so I cannot comment on how SpreadsheetGear compares to it.
Joe Erickson
A: 

Instead of Rows Insert I'd try CopyFromRecordset to do an entire recordset. You'd have to substantially rework your logic of course.

But more importantly where are you closing the Excel spreadsheet object once you're done with it?

Tony Toews
ok, with copy from recordset I've exported about 400 files in 4 minutes, this is a very very fast method, thanks
Iulian