vba ListView 控件加载非常缓慢

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/604643/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 10:15:31  来源:igfitidea点击:

ListView Control loads very slowly

vbalistviewms-accessaccess-vbarecordset

提问by

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.

当 ListView 有超过 15000 个包含 9 个子项的列表时,从查询填充 ListView 的最快方法是什么。加载大约需要 6 分钟。

Here is what I wrote to fill ListView control.

这是我为填充 ListView 控件而编写的内容。

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

采纳答案by DJ.

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:

While...Wend 是一种较慢的循环机制;使用 For...Next。For...Next 更快——即使您必须运行另一个命令来获取 RecordCount。这是我使用的:

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...End With 添加您的子项目:

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!

希望有帮助!

回答by DJ.

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

第一件事是你应该做的是摆脱“doevents”,这是一个真正的性能杀手。

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

您是否必须动态加载列表视图?为什么不直接将其绑定到数据源?

回答by Toby Allen

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.

检查 Listview 控件的方法是否有 beginupdate / endupdate 之类的内容或将 refresh 设置为 false(如果可能)。这意味着 UI 不会在添加每个项目后尝试刷新屏幕,从而使添加速度更快。

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

Listview 控件旨在获取大量项目,因此应该可以通过一些挖掘来实现。