kk_lee69
发表于 2018-4-8 12:46:43
回复 15# chzj589
你的理解錯誤重頭到尾都沒讀取 只是知道筆數
然後 當要顯示的時候才讀取該顯示的部分
chzj589
发表于 2018-4-8 12:55:56
回复 16# kk_lee69
没读取数据?那数据条不应该是这样子
kk_lee69
发表于 2018-4-8 13:43:47
本帖最后由 kk_lee69 于 2018-4-8 13:46 编辑
回复 17# chzj589
是阿 這時候只讀取1-14條數據
其他的數據都沒有讀取
不相信 你把
Case $LVN_ODCACHEHINT
Local $tNMLVCACHEHINT = DllStructCreate($tagNMLVCACHEHINT, $lParam), $iColumns
$iFrom = DllStructGetData($tNMLVCACHEHINT, "iFrom")
Local $sSQL = "SELECT * FROM lvdata WHERE item_id >= " & $iFrom & _
" AND item_id <= " & DllStructGetData($tNMLVCACHEHINT, "iTo") & ";"
GUICtrlSendMsg($hLV, $LVM_DELETEALLITEMS, 0, 0)
_SQLite_GetTable2d(-1, $sSQL, $aResult, $iRows, $iColumns)
Local $iFromg = ConsoleWrite($iFrom & " " & DllStructGetData($tNMLVCACHEHINT, "iTo") & @CRLF)
這一行
_SQLite_GetTable2d(-1, $sSQL, $aResult, $iRows, $iColumns)
註釋掉 就不會有任何資料出現
chzj589
发表于 2018-4-8 13:51:43
回复 18# kk_lee69
没错。
下面就有读取与没读取的对比
是这句:
GUICtrlSendMsg($idLV, $LVM_SETITEMCOUNT, $iRows, 0)
;---------------------------------------------------------
While 1
Switch GUIGetMsg()
Case $idTab
If $iRows Then _SQLite_Close(-1);关闭打开的数据库
Switch GUICtrlRead($idTab)
Case 0
GUICtrlSendMsg($idLV, $LVM_SETITEMCOUNT, 0, 0)
$iRows = $iRows1
If $iRows Then _SQLite_Open("Test1.db")
;GUICtrlSendMsg($idLV, $LVM_SETITEMCOUNT, $iRows, 0)
Case 1
GUICtrlSendMsg($idLV, $LVM_SETITEMCOUNT, 0, 0)
$iRows = $iRows2
If $iRows Then _SQLite_Open("Test2.db")
GUICtrlSendMsg($idLV, $LVM_SETITEMCOUNT, $iRows, 0)
Case 2
GUICtrlSendMsg($idLV, $LVM_SETITEMCOUNT, 0, 0)
$iRows = $iRows3
If $iRows Then _SQLite_Open("Test3.db")
GUICtrlSendMsg($idLV, $LVM_SETITEMCOUNT, $iRows, 0)
EndSwitch
;GUICtrlSendMsg($idLV, $LVM_SETITEMCOUNT, $iRows, 0)
Case $GUI_EVENT_CLOSE
ExitLoop
EndSwitch
WEnd
chzj589
发表于 2018-4-8 13:57:08
回复chzj589
是阿 這時候只讀取1-14條數據
其他的數據都沒有讀取
那是窗口大小,你把窗口改大,
GUICreate("Virtual ListViews", 850, 600)
Local $idLV = GUICtrlCreateListView("", 20, 40, 850 - 40, 600 - 60, $LVS_OWNERDATA, BitOR($WS_EX_CLIENTEDGE, $LVS_EX_DOUBLEBUFFER, $LVS_EX_FULLROWSELECT))
$hLV = GUICtrlGetHandle($idLV)
显示就不是1-14条数据?
kk_lee69
发表于 2018-4-8 14:41:52
本帖最后由 kk_lee69 于 2018-4-8 14:49 编辑
回复 20# chzj589
你沒有加入
ConsoleWrite($iFrom&" "&DllStructGetData( $tNMLVCACHEHINT, "iTo" )&@CRLF)
這行吧你加入了你就會知道 放大後所需要的就不會是 0-14它會自己變化 可能是 0-35 那就是 一次讀取35筆資料 往後也是一筆一筆增加
所以你就會重新讀取 幾筆資料
kk_lee69
发表于 2018-4-8 14:51:09
回复 19# chzj589
資料不是從這裡抓取的
是这句:
GUICtrlSendMsg($idLV, $LVM_SETITEMCOUNT, $iRows, 0)
;---------------------------------------------------------
While 1
Switch GUIGetMsg()
Case $idTab
If $iRows Then _SQLite_Close(-1);关闭打开的数据库
Switch GUICtrlRead($idTab)
Case 0
GUICtrlSendMsg($idLV, $LVM_SETITEMCOUNT, 0, 0)
$iRows = $iRows1
If $iRows Then _SQLite_Open("Test1.db")
;GUICtrlSendMsg($idLV, $LVM_SETITEMCOUNT, $iRows, 0)
Case 1
GUICtrlSendMsg($idLV, $LVM_SETITEMCOUNT, 0, 0)
$iRows = $iRows2
If $iRows Then _SQLite_Open("Test2.db")
GUICtrlSendMsg($idLV, $LVM_SETITEMCOUNT, $iRows, 0)
Case 2
GUICtrlSendMsg($idLV, $LVM_SETITEMCOUNT, 0, 0)
$iRows = $iRows3
If $iRows Then _SQLite_Open("Test3.db")
GUICtrlSendMsg($idLV, $LVM_SETITEMCOUNT, $iRows, 0)
EndSwitch
;GUICtrlSendMsg($idLV, $LVM_SETITEMCOUNT, $iRows, 0)
Case $GUI_EVENT_CLOSE
ExitLoop
EndSwitch
WEnd
chzj589
发表于 2018-4-8 14:51:55
回复 21# kk_lee69
搞不懂,这样有什么作用?有什么差别?
kk_lee69
发表于 2018-4-8 14:53:58
回复 23# chzj589
你把我上面範例的 第110行註釋掉
你就會看到 不會有任何東西 出現
我用上面的方法 可以在不到一秒內完成一個 有著一千萬筆資料的 LISTVIEW
你用其他方法都不可能達到 可以在 不到一秒內 讀取一千萬筆資料
chzj589
发表于 2018-4-8 15:00:05
回复 22# kk_lee69
把这句:GUICtrlSendMsg($idLV, $LVM_SETITEMCOUNT, $iRows, 0)
改为:
GUICtrlSendMsg($idLV, $LVM_SETITEMCOUNT, 15, 0)
那就是0-14行了
chzj589
发表于 2018-4-8 15:04:49
回复 24# kk_lee69
_SQLite_GetTable2d
传递包含执行查询的列名和数据的 2 维数组.
哦,明白了。谢谢
kk_lee69
发表于 2018-4-8 15:17:52
回复 26# chzj589
其實 你使用的資料庫 如果是 SQLLITE 或者 MDB 用我原本範例的方法已經是很完美的方法了
因為是小型資料庫只有你自己使用忙碌點查詢 也沒關係
只是我的資料庫通常是 作為ERP 二次開發 使用不是只有我一個人使用 因為我必須要考慮
頻繁的查詢會不會造成主機忙碌影響其他使用者...
chzj589
发表于 2018-4-11 14:34:12
本帖最后由 chzj589 于 2018-4-11 14:37 编辑
回复 27# kk_lee69
今天又捣鼓了一下,再数据条点击可能不行。
Case $Button1
GUICtrlSendMsg($idLV, $LVM_SETITEMCOUNT, 0, 0)
Local $Rab = 10 ;AND $Ra*30
Local $Rab1 = 10
Local $Raba
For $i = 0 To $Rab1
$Raba +=$Rab
Next
Local $Msg = GUICtrlSendMsg($idLV, $LVM_SETITEMCOUNT, $Raba, 0)
If $iRows Then _SQLite_Open("Test3.db")
这样点击一次就可前进一百条。
298311657
发表于 2018-4-12 16:41:48
回复 1# kk_lee69
这份代码其实还是一样的,只是它的数据请求是在$LVN_ODCACHEHINT消息产生时发生的,但数据也是一次全部请求完毕,使用_SQLite_GetTable2d函数,将全部的数据读取到$aResult数组内,然后在$LVN_GETDISPINFOW消息产生时,再显示在listview控件。
之所以你会感觉速度很快,那是因为_SQLite_GetTable2d函数的效率比较好而已。使用这种方式,并不是解决你遇到的问题的关键所在。
你想要分次读取数据的思路是对的,通过分页查询数据库的方式就可以了,但与这份示例代码的思路并不一样。
yhxhappy
发表于 2018-4-13 11:05:32
本帖最后由 yhxhappy 于 2018-4-13 12:32 编辑
我有类似的方案,不是通过下拉滚动条,而是通过翻页的方式
当数据库中有很多行,没办法一次读取,太费时。
默认先返回前 100 (1-100)行显示在 LV
当用户点击下一页时,清空 LV,再从数据库读取 101-200 行显示在 LV,以此类推
下图是微软的一个工具,原理类似:
原理是:
首先要先知道 数据库 表总共有几行,除以 LV显示行数(假设100) 得出 页数
假如当前页是8,当点击 下一页 按钮时,读取“表” (8+1)*100 = 900~1000行的数据
以下是我目前正在使用的,用于MSSQL,因为主键不是连续的,所以有点复杂。如果你的表ID列是连续的要简单很多,使用我注释掉的两行查询。
$Field字段,也可以用 *
$ConditionWHERE条件
$StartIndex开始的行索引,比如从第200行开始读取,$StartIndex = 200
$ItemNum要获取多少行Func _MsSQL_GetNumberOfRows2($Obj, $Table, $Field, $Condition, $StartIndex, $ItemNum) ;返回 表中指定数量的 行
If Not IsObj($Obj) Then
SetError(1)
Return 0
ElseIf $Table = "" Or $StartIndex = "" Or $ItemNum = "" Or $Field = "" Then
SetError(2)
Return 0
EndIf
;$ItemNum -= 1
$FieldNum = _MsSQL_GetColumnNum($Obj, $Table) ;取得列的数量
If @error Or $FieldNum = 0 Then
SetError(3)
Return 0
EndIf
$RowNum = _MsSQL_GetRowNum($Obj, $Table, $Condition)
If $RowNum = 0 Then ;取得行数量,如果为0则退出
SetError(4)
Return 0
EndIf
;MsgBox(0,0,$RowNum)
If $StartIndex > $RowNum Then ;如果起始索引大于总行数,则起始索引等于最后一行
$StartIndex = $RowNum
$ItemNum = 0
ElseIf $StartIndex <= 0 Then
$StartIndex = 1
EndIf
If $StartIndex+$ItemNum-1 > $RowNum Then ;如果开始位数+项目数量,大于总数量,则只能取到最后一个
$ItemNum = $RowNum-$StartIndex+1
EndIf
If $ItemNum <= 0 Then $ItemNum = 1 ;不能小于0
$WHERE = ""
If $Condition <> "" Then $WHERE = " WHERE " & $Condition
$RS = ObjCreate("ADODB.Recordset")
$RS.ActiveConnection = $Obj
;SELECT TOP 100 FROM (SELECT TOP 300 FROM SN_Key ORDER BY ID DESC) AS WK ORDER BY ID ASC
;select top 10 * from (select top 30 * from tablename order by id asc) A order by id desc
ConsoleWrite("SELECT TOP " & $ItemNum & " * FROM (SELECT TOP " & $StartIndex+$ItemNum-1 & " * FROM "& $Table & $WHERE & " ORDER BY " & $Field & " DESC) A ORDER BY " & $Field & " ASC" & @CRLF)
$RS.Open("SELECT TOP " & $ItemNum & " * FROM (SELECT TOP " & $StartIndex+$ItemNum-1 & " * FROM " & $Table & $WHERE & " ORDER BY " & $Field & " DESC) A ORDER BY " & $Field & " ASC")
Local $Num = 0, $Array[$FieldNum] = [], $text = ""
While Not $RS.eof And Not $RS.bof
; If @error Then ExitLoop
For $i = 0 To $FieldNum-1 ;循环读取字段值
$Text &= $RS.Fields($i).value & "|"
Next
_ArrayAdd($Array, StringTrimRight($Text, 1)) ;通常会多加一个|,会导致数组维数不对,删除最后一个 |
$text = ""
$Num += 1
;ToolTip($Num)
$RS.movenext;下一笔资料
WEnd
$RS.close
If $Num = 0 Then
SetError(5)
Return 0
Else
$Array = $Num
$Array = $RowNum
Return $Array
EndIf
EndFunc ;==>_Query