Click here to Skip to main content
15,892,005 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
Hi, I've created a program in VBA that is able to read in excel workbooks and lets me modify and save. However my program takes quite a bit of time to run. I'm looking for something less computationally expensive than my current For-Next loops. Here is my code below. I greatly appreciate any help and feedback you may give. Thanks!

VB
For rowindex = 1 To DataGridView3.RowCount

    For columnindex = 1 To DataGridView3.ColumnCount

        objworksheet3.Cells(rowindex + 3, columnindex + 1) = DataGridView3(columnindex - 1, rowindex - 1).Value

    Next
Next

For rowindex = 1 To DataGridView1.RowCount
    For columnindex = 1 To DataGridView1.ColumnCount
        objWorkSheet1.Cells(rowindex + 4, columnindex + 0) = DataGridView1(columnindex - 1, rowindex - 1).Value
        objWorkSheet1.Cells(rowindex + 4, columnindex + 1) = DataGridView1(columnindex - 1, rowindex - 1).Value
        objWorkSheet1.Cells(rowindex + 4, columnindex + 2) = DataGridView1(columnindex - 1, rowindex - 1).Value
        objWorkSheet1.Cells(rowindex + 4, columnindex + 3) = DataGridView1(columnindex - 1, rowindex - 1).Value
        objWorkSheet1.Cells(rowindex + 4, columnindex + 4) = DataGridView1(columnindex - 1, rowindex - 1).Value
        objWorkSheet1.Cells(rowindex + 4, columnindex + 7) = DataGridView1(columnindex - 1, rowindex - 1).Value
        objWorkSheet1.Cells(rowindex + 4, columnindex + 8) = DataGridView1(columnindex - 1, rowindex - 1).Value

    Next
Next
Posted
Updated 31-May-13 2:01am
v3

There's nothing to change to speed things up. The Excel object model is known to be pretty slow.

If you were using Excel 2010 and above (OpenOfficeXML format workbooks) you could load and write the sheets directly, which would be much faster than going through the Excel oObject model. Though, doing so is FAR more complex than what you have now.
 
Share this answer
 
I realize that you have already accepted an answer for this, but there is something that you can do to speed things up.

Each cell (range) that you set requires a call across the interop boundary; this boundary crossing is the slow part. As you are filling a contiguous range of cells (a rectangular region), you can compute this overall range and set it to an equally dimensioned array.

Here is a simple example (console app) to demonstrate the concept.

On my machine, this yielded the following times:
Each Cell Elapsed Time: 2783 ms
Array Update Elapsed Time: 15 ms

Imports Excel = Microsoft.Office.Interop.Excel

Module Module1

   Sub Main()
      ' make some data to copy to Excel
      Dim data(0 To 99, 0 To 9) As Object
      Dim count As Int32 = 0
      For row As Int32 = 0 To UBound(data, 1)
         For col As Int32 = 0 To UBound(data, 2)
            count += 1
            data(row, col) = count
         Next
      Next

      Dim app As New Excel.Application ' start Excel
      app.Visible = False

      Dim wb As Excel.Workbook = CType(app.Workbooks.Add(), Excel.Workbook)
      Dim sht As Excel.Worksheet = CType(wb.ActiveSheet, Excel.Worksheet)
   '  *******************************************
   '  copy individual values to each cell

      Dim sw1 As New Diagnostics.Stopwatch
      sw1.Start()

      For row As Int32 = 0 To UBound(data, 1)
         For col As Int32 = 0 To UBound(data, 2)
            count += 1
            sht.Cells(row + 1, col + 1) = data(row, col)
         Next
      Next
      sw1.Stop()
      Console.WriteLine("Each Cell Elapsed Time: " & sw1.ElapsedMilliseconds.ToString() & " ms")

   '  *******************************************
   '  Compute range to hold array and copy array

      Dim sw2 As New Diagnostics.Stopwatch
      sw2.Start()

      'set the 1st cell in range
      Dim startcell As Excel.Range = CType(sht.Cells(110, 1), Excel.Range)

      'compute last cell in range
      Dim endcell As Excel.Range = startcell.Offset(UBound(data, 1), UBound(data, 2))

      ' set range data
      sht.Range(startcell, endcell).Value = data

      sw2.Stop()
      Console.WriteLine("Array Update Elapsed Time: " & sw2.ElapsedMilliseconds.ToString() & " ms")

   '  *******************************************

      app.Visible = True

      sht = Nothing
      'wb.Close(False) ' leave Excel open to see results
      wb = Nothing
      'app.Quit()
      app = Nothing
      Console.ReadLine() ' pause to show results

   End Sub

End Module
 
Share this answer
 
Instead of
VB
For rowindex = 1 To DataGridView1.RowCount
            For columnindex = 1 To DataGridView1.ColumnCount
                objWorkSheet1.Cells(rowindex + 4, columnindex + 0) = DataGridView1(columnindex - 1, rowindex - 1).Value
                objWorkSheet1.Cells(rowindex + 4, columnindex + 1) = DataGridView1(columnindex - 1, rowindex - 1).Value
                objWorkSheet1.Cells(rowindex + 4, columnindex + 2) = DataGridView1(columnindex - 1, rowindex - 1).Value
                objWorkSheet1.Cells(rowindex + 4, columnindex + 3) = DataGridView1(columnindex - 1, rowindex - 1).Value
                objWorkSheet1.Cells(rowindex + 4, columnindex + 4) = DataGridView1(columnindex - 1, rowindex - 1).Value
                objWorkSheet1.Cells(rowindex + 4, columnindex + 7) = DataGridView1(columnindex - 1, rowindex - 1).Value
                objWorkSheet1.Cells(rowindex + 4, columnindex + 8) = DataGridView1(columnindex - 1, rowindex - 1).Value
 
            Next
        Next

Just Do
VB
For rowindex = 1 To DataGridView1.RowCount
            For columnindex = 1 To DataGridView1.ColumnCount
                objWorkSheet1.Cells(rowindex + 4, columnindex + 0) = DataGridView1(columnindex - 1, rowindex - 1).Value
            Next
Next
 
Share this answer
 
v3

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900