views:

1921

answers:

3

What is the fastest way to fill ListView from query when it has over 15000 lists with 9 subitems. it is taking me about 6 minute to load.

Here is what I wrote to fill ListView control.

Set rs = db.OpenRecordset(strSQL, dbOpenForwardOnly, dbReadOnly)

With Me.listViewData
    .View = lvwReport
    .GridLines = True
    .FullRowSelect = True
    .ListItems.Clear
    .ColumnHeaders.Clear
End With
'Set up column headers
With Me.listViewData.ColumnHeaders
    .Add , , "Client", 1440, lvwColumnLeft
    .Add , , "Contact", 2160, lvwColumnLeft
    .Add , , "Quote #", 720, lvwColumnCenter
    .Add , , "Date", 1140, lvwColumnLeft
    .Add , , "GrandTotal", 1440, lvwColumnRight
    .Add , , "Weighted Value", 1440, lvwColumnRight
    .Add , , "Chance %", 500, lvwColumnRight
    .Add , , "Sales Cycle", 1140, lvwColumnRight
    .Add , , "Won Orders", 1000, lvwColumnRight
    .Add , , "SalesRep", 1000, lvwColumnRight
End With

While Not rs.EOF
    Set lstItem = Me.listViewData.ListItems.Add()
    lstItem.Text = Nz(rs!Name, "")
    lstItem.SubItems(1) = Nz(rs!Company, "")
    lstItem.SubItems(2) = Nz(rs!QuoteNumber, "")
    lstItem.SubItems(3) = Nz(rs!OrderDate, "")
    lstItem.SubItems(4) = Nz(Format(rs!GrandTotal, "Currency"), "0.00")
    lstItem.SubItems(5) = Nz(Format(rs!GrandTotal * rs!Customfield1 / 100, "Currency"), "")
    lstItem.SubItems(6) = Nz(rs!Customfield1, "")
    lstItem.SubItems(7) = Nz(rs!Date1, "none")
    lstItem.SubItems(8) = Nz(rs!Detail, "")
    lstItem.SubItems(9) = Nz(rs!CustomT1, Nz(rs!UserID, ""))

    For I = 1 To Me.listViewData.ColumnHeaders.Count - 1
        Set sb = lstItem.ListSubItems(I)
        If rs!Customfield1 = 100 Or Not IsNull(rs!List) Then
            sb.ForeColor = vbBlue
            lstItem.ForeColor = vbBlue
        ElseIf rs!Cancelled = -1 Then
            sb.ForeColor = vbRed
            lstItem.ForeColor = vbRed
        Else
            sb.ForeColor = vbBlack
            lstItem.ForeColor = vbBlack
        End If
        DoEvents
    Next
    rs.MoveNext
Wend
+2  A: 

The first thing is you should do is get rid of the "doevents" That's a real performance killer.

Do you have to load the listview dynamically? Why not bind it directly to a datasource?

DJ
I took out DoEvents and it got much faster. How Can I directly bind to datasource in MSAccess 2003?
A: 

Check the methods of the Listview control for something like beginupdate / endupdate or set refresh to false (if possible). This means that the UI will not try to refresh the screen after each item is added, thereby making the adding much quicker.

The Listview control is designed to take large numbers of items so it should be possible with a bit of digging.

Toby Allen
A: 

I can think of a couple things:

While...Wend is a slower looping mechanism; use For...Next. For...Next is faster--even if you have to run another command to get the RecordCount. This is what I use:

With rs
  If .RecordCount > 0 Then
    '-- MoveLast...MoveFirst will update the .RecordCount; depending on the type of DAO Recordset, RecordCount might only return "1" when there are more than that.
    .MoveLast
    .MoveFirst

    For lngCounter = 1 To .RecordCount
      '-- Code to add ListItems here

      .MoveNext
    Next lngCounter
  End If
  .Close
End With

Use With...End With for adding your SubItems:

With Me.listViewData.ListItems.Add
  .Text = Nz(rs!Name, "")
  .SubItems(1) = Nz(rs!Company, "")
  .SubItems(2) = Nz(rs!QuoteNumber, "")
  .SubItems(3) = Nz(rs!OrderDate, "")
  .SubItems(4) = Nz(Format(rs!GrandTotal, "Currency"), "0.00")
  .SubItems(5) = Nz(Format(rs!GrandTotal * rs!Customfield1 / 100, "Currency"), "")
  .SubItems(6) = Nz(rs!Customfield1, "")
  .SubItems(7) = Nz(rs!Date1, "none")
  .SubItems(8) = Nz(rs!Detail, "")
  .SubItems(9) = Nz(rs!CustomT1, Nz(rs!UserID, ""))
End With

Wrap the populater code in:

DoCmd.Echo False

'-- Populate code

DoCmd.Echo True

Hope that helps!