Question

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
Was it helpful?

Solution 2

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!

OTHER TIPS

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?

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top