找回密码
 加入
搜索
查看: 8061|回复: 35

[AU3基础] 关于listview虚表直接读取数据库的方法,求助修改范例成MSSQL的!!

 火..   [复制链接]
发表于 2018-4-1 23:28:01 | 显示全部楼层 |阅读模式
本帖最后由 kk_lee69 于 2018-4-1 23:48 编辑

关于listview虚表直接读取数据库的方法,求助修改范例成SQL的!!

官网有个范例 是listview虚表 直接拿SQLlite 的数据库 当作 listview虚表的数据 直接使用,这样的好处是 即使你的数据再多 也是分次 读取 就不会卡了
无奈 小弟 对于 SQLLITE的 UDF 实在没辙,我研究了半天 总是搞不懂原理
无法改成 把SQL DB 当作数据库来源的方法 ,所以上来求助

listview虚表 我已经很熟了  所以理论上不应该是我不会使用,只是以前的方法都是读进
数组  然后 利用数组 当作listview虚表 的数据源

只是最近遇到了 数据太多 读进数组太慢  想要改成 分次读取 分次秀出的方法

所以才把脑筋动到了 数据库上……

以下是 范例程序 与 数据库  麻烦 高手帮我改个范例

資料庫檔案如下:



或者 也可以利用 下面的檔案 建立資料庫





範例程式如下:

#include <GUIConstants.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <SQLite.au3>

Opt( "MustDeclareVars", 1 )

Global Const $tagNMLVCACHEHINT = $tagNMHDR & ";int iFrom;int iTo"

Global $hLV

Example()


Func Example()
        _SQLite_Startup()

        ; Check databases
        Local $iRows1 = CheckDB( "Test1.db" )
        Local $iRows2 = CheckDB( "Test2.db" )
        Local $iRows3 = CheckDB( "Test3.db" )
        Local $iRows

        ; Create GUI
        GUICreate( "Virtual ListViews", 850, 400 )

        ; Create Tab
        Local $idTab = GUICtrlCreateTab( 10, 10, 850-20, 400-20 )
        GUICtrlCreateTabItem( "Test1.db: " & Format( $iRows1 ) & " rows" )
        GUICtrlCreateTabItem( "Test2.db: " & Format( $iRows2 ) & " rows" )
        GUICtrlCreateTabItem( "Test3.db: " & Format( $iRows3 ) & " rows" )
        GUICtrlCreateTabItem( "" )

        ; Create ListView
        Local $idLV = GUICtrlCreateListView( "", 20, 40, 850-40, 400-60, $LVS_OWNERDATA, BitOR( $WS_EX_CLIENTEDGE, $LVS_EX_DOUBLEBUFFER, $LVS_EX_FULLROWSELECT ) )
        $hLV = GUICtrlGetHandle( $idLV ) ;                               Virtual listview                          Reduces flicker
        For $i = 0 To 9
                _GUICtrlListView_AddColumn( $hLV, "Col" & $i, 75 )
        Next

        GUIRegisterMsg( $WM_NOTIFY, "WM_NOTIFY" )
        GUISetState( @SW_SHOW )

        ; Data for first tab
        $iRows = $iRows1
        If $iRows Then _SQLite_Open( "Test1.db" )
        GUICtrlSendMsg( $idLV, $LVM_SETITEMCOUNT, $iRows, 0 )

        ; Message loop
        While 1
                Switch GUIGetMsg()
                        Case $idTab
                                If $iRows Then _SQLite_Close( -1 )
                                Switch GUICtrlRead( $idTab )
                                        Case 0
                                                $iRows = $iRows1
                                                If $iRows Then _SQLite_Open( "Test1.db" )
                                        Case 1
                                                $iRows = $iRows2
                                                If $iRows Then _SQLite_Open( "Test2.db" )
                                        Case 2
                                                $iRows = $iRows3
                                                If $iRows Then _SQLite_Open( "Test3.db" )
                                EndSwitch
                                GUICtrlSendMsg( $idLV, $LVM_SETITEMCOUNT, $iRows, 0 )

                        Case $GUI_EVENT_CLOSE
                                ExitLoop
                EndSwitch
        WEnd

        If $iRows Then _SQLite_Close( -1 )
        _SQLite_Shutdown()
        GUIDelete()
EndFunc

Func WM_NOTIFY( $hWnd, $iMsg, $wParam, $lParam )
        Local Static $tText = DllStructCreate( "wchar[50]" )
        Local Static $pText = DllStructGetPtr( $tText )
        Local Static $aResult, $iRows, $iFrom

        Local $tNMHDR, $hWndFrom, $iCode
        $tNMHDR = DllStructCreate( $tagNMHDR, $lParam )
        $hWndFrom = HWnd( DllStructGetData( $tNMHDR, "hWndFrom" ) )
        $iCode = DllStructGetData( $tNMHDR, "Code" )

        Switch $hWndFrom

                Case $hLV

                        Switch $iCode

                                Case $LVN_GETDISPINFOW
                                        Local $tNMLVDISPINFO = DllStructCreate( $tagNMLVDISPINFO, $lParam )
                                        If BitAND( DllStructGetData( $tNMLVDISPINFO, "Mask" ), $LVIF_TEXT ) Then
                                                Local $iIndex = DllStructGetData( $tNMLVDISPINFO, "Item" ) - $iFrom + 1
                                                If $iIndex > 0 And $iIndex < $iRows + 1 Then
                                                        Local $sItem = $aResult[$iIndex][DllStructGetData($tNMLVDISPINFO,"SubItem")]
                                                        DllStructSetData( $tText, 1, $sItem )
                                                        DllStructSetData( $tNMLVDISPINFO, "Text", $pText )
                                                        DllStructSetData( $tNMLVDISPINFO, "TextMax", StringLen( $sItem ) )
                                                EndIf
                                        EndIf

                                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" ) & ";"
                                        _SQLite_GetTable2d( -1, $sSQL, $aResult, $iRows, $iColumns )

                        EndSwitch

        EndSwitch

        Return $GUI_RUNDEFMSG
EndFunc

Func CheckDB( $sDBname )
        Local $aRow, $iRows = 0
        If FileExists( $sDBname ) Then
                _SQLite_Open( $sDBname )
                _SQLite_QuerySingleRow( -1, "SELECT max(item_id) FROM lvdata;", $aRow )
                _SQLite_Close( -1 )
        EndIf
        If IsArray( $aRow ) Then _
                $iRows = $aRow[0] + 1
        Return $iRows
EndFunc

Func Format( $iInt )
        Return StringRegExpReplace( $iInt, "(\A\d{1,3}(?=(\d{3})+\z)|\d{3}(?=\d))", "\1," )
EndFunc

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
发表于 2018-4-3 13:05:46 | 显示全部楼层
回复 1# kk_lee69



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
发表于 2018-4-3 16:14:33 | 显示全部楼层
最近一直用MYsql ,感觉很方便 。mssql还不会
 楼主| 发表于 2018-4-7 17:06:47 | 显示全部楼层
既然這題 沒辦法改成 MSSQL  那有沒有人 可以 改變一下 不要一次取的一筆資料  我希望一次可以讀取一 百筆資料  當作緩衝呢???
 楼主| 发表于 2018-4-7 17:32:32 | 显示全部楼层
回复 2# chzj589

就用SQL LISTE 好了 能否將範例中 每次讀取一筆到兩筆的緩衝   改成每次讀取100筆嗎??
发表于 2018-4-7 17:41:23 | 显示全部楼层
回复 5# kk_lee69
你有看一下 CreateDB.au3吗?
範例程式,是读取三个数据库

Local $iRows1 = CheckDB( "Test1.db" )
Local $iRows2 = CheckDB( "Test2.db" )
Local $iRows3 = CheckDB( "Test3.db" )

数据库里有几笔,就读几笔,不是吗?
 楼主| 发表于 2018-4-7 17:55:54 | 显示全部楼层
回复 6# chzj589

當然數據庫有幾筆 就讀取幾筆

但是這個虛擬表的概念是  先決定資料庫有 幾筆  假設有1萬筆 就先設定 有一萬筆資 料

然後  第一次 讀取 0-15 資料  往後 你往下滑一格  它就往後讀取資料庫裡面的下一筆資料

一次只讀取一筆  然後 你往上了 捲動了 就從資料庫裡 再往前 讀取 一筆 資料


我不要一次 只讀取一筆資料  這樣對資料庫來說  重複的讀取 負擔太重  
我希望一次 可以讀取 100筆資料
发表于 2018-4-7 18:27:07 | 显示全部楼层
回复 7# kk_lee69
哪个範例程式?
 楼主| 发表于 2018-4-7 19:42:10 | 显示全部楼层
回复 8# chzj589

就是上面的範例程式
发表于 2018-4-7 20:24:23 | 显示全部楼层
回复 9# kk_lee69
不理解。
上面的範例程式历,不就是读取三个数据库?
我没安装SQL LISTE数据库编辑器,不知道建立的"Test1.db"是什么结构。
 楼主| 发表于 2018-4-7 20:43:02 | 显示全部楼层
回复 10# chzj589

你沒有實際跑資料庫....你下載 資料庫3 就好  跟我的範例程式  放在一起

執行後  切換到 第三個 TAB  你就會知道
发表于 2018-4-7 21:27:32 | 显示全部楼层
回复 11# kk_lee69
还是不理解,有什么不同

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
 楼主| 发表于 2018-4-7 21:44:59 | 显示全部楼层
本帖最后由 kk_lee69 于 2018-4-7 21:48 编辑

回复 12# chzj589

你有注意到
WM_NOTIFY 裡面的  $LVN_ODCACHEHINT 這個變化嗎??

你在 $LVN_ODCACHEHINT 下面 加上

ConsoleWrite($iFrom&" "&DllStructGetData( $tNMLVCACHEHINT, "iTo" )&@CRLF)

你就會看到  一開始是
0  15
15 16
16 17
17 18



你每按往下  它就會從資料庫裡面抓一筆資料出來
所以上面的程式 才能做到  資料庫裡面幾十萬筆資料  但是都不會卡頓
因為它一次  只抓一筆資料

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
发表于 2018-4-8 09:34:24 | 显示全部楼层
回复 13# kk_lee69
主要控制是这里:
                                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
传递包含执行查询的列名和数据的 2 维数组.

#include <SQLite.au3>
_SQLite_GetTable2d ( $hDB, $sSQL, ByRef $aResult, ByRef $iRows, ByRef $iColumns [, $iCharSize = -1 [, $bSwichDimensions = False]] )

参 数
$hDB 打开的数据库, 如为 -1, 则使用最后打开的数据库
$sSQL 要执行的 SQL 语句
$aResult 传递的结果
$iRows 传递的数据行数
$iColumns 传递的列数
$iCharSize [可选] 指定数据字段的最大尺寸
$bSwichDimensions [可选] 切换 $aResult 尺寸
发表于 2018-4-8 10:03:36 | 显示全部楼层
回复 14# chzj589
我的理解是本来己经全部读取,只是控制显示条目而己。
不知对不?
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-4-25 15:36 , Processed in 0.078208 second(s), 20 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表