VFP连接MSSQL执行TSQL,如何显示一个进度条

2022-04-07 19:58:24 浏览数 (1)

作者:瓜哥

准备工具 VFP SP7423 MYFLL

主角:MFYLL,瓜哥提供了一个函数,可以完美完成这个功能。

函数名:SQLCallback(nFuncType, cFuncName[,nFreq]) 缩写:sqlc SQL回调函数。采用一种插入技术,在VFP使用ODBC连接远程数据源过程中,能够调用vfp的程序。

同时支持SPT和CA,支持SQLIdleDisconnect。

目前支持两个回调函数,Fetch和RecordCount,可以用来在SPT下载数据过程产生一个进度信息。使用简便,性能要远高于异步方式。

注意 1.SQLCallback()函数必需在ODBC连接建立完后才能调用 2.不需要监控ODBC过程时,将cFuncName设为空串即可,如SQLCallback(1,"")关闭Fetch回调

返回值: 无 参数: nFuncType:要挂勾的函数类型,可为下面的值

#define SQL_CALLBACK_FETCH 1 #define SQL_CALLBACK_RECORD_COUNT 2

SQL_CALLBACK_FETCH:

此回调函数是VFP在下载数据时发生,每下载一条记录,回调一次函数,在此函数内部,可以使用Recno()来确定已下载的记录数量。

回调函数的格式为 Func(),没有参数。

SQL_CALLBACK_RECORD_COUNT:

此回调在向服务器发送SQL语句前发生,FLL内部将生成一条select count(*) from (your select cmd)向服务器索取记录总数,然后将记录总数做为参数调用你的函数。

此回调函数的格式为Func(nMaxRecord),接收一个整型的参数,此函数只会被调用一次。

cFuncName:字符型,指定函数名,支持对像,如 MyFunc()或 thisform.UpdateProgress

不同回调类型可以指定相同的函数,但你要检查参数来区分是谁调用了你的回调函数。

[nFreq]:仅针对SQL_CALLBACK_RECORD_COUNT有效,设置回调的频率。默认值为1

最初没有这个参数,每下载一条数据产生一条回调,会降底性能。后来测试发现,此值设为100或更大的值时,如果数据量大能明显改善性能,与不使用回调函数时的速度相差无几。

*下面示例均以本机SQL的nothwind数据库为例,请行修改SQL连接串

代码语言:javascript复制
*示例 1 一个简单的SPT获取下载记录数量示例

#define        SQL_CALLBACK_FETCH    1
#define        SQL_CALLBACK_RECORD_COUNT    2

Set Library To myfll
Clear 
nHdl= SQLStringConnect("Driver=Sql Server;Server=localhost;database=northwind")
If nHdl <1
    MessageBox("无法连接数据源……")
    Return 
EndIf 
*加载一个CallBack
SQLCallback(SQL_CALLBACK_FETCH,"MyCallBack()")    

SQLExec(nHdl,"select * from orders")

SQLDisconnect(nHdl)
Set Library To 
Return

Procedure MyCallBack()
    Wait window Transform(Recno()) nowait 
EndProc 

*------------------------------------------------------------------------------------

*示例 2 CA示例

#define        SQL_CALLBACK_FETCH    1
#define        SQL_CALLBACK_RECORD_COUNT    2

Set Library To myfll
Clear 
nHdl= SQLStringConnect("Driver=Sql Server;Server=localhost;database=northwind")
If nHdl <1
    MessageBox("无法连接数据源……")
    Return 
EndIf 
*加载一个CallBack
SQLCallback(SQL_CALLBACK_FETCH,"MyCallBack()")    

Local oCa as CursorAdapter 
oCa=NewObject("CursorAdapter")
oCa.DataSourceType="ODBC"
oCa.DataSource=nHdl
oCa.SelectCmd="Select * from employees"
?"第一次填充……"
oCa.CursorFill()


*带索引测试CursorRefresh
?"创建索引……"
Index on FirstName to tmp
Set Order To Tag tmp 

?"后台插入数据……"
SQLExec(nHdl,"insert into employees(LastName,FirstName)" ;
            " values( ?Sys(2015),?Sys(2015))")

?"前台刷新数据……"
?oCa.CursorRefresh()


SQLDisconnect(nHdl)
Set Library To 
Return

Procedure MyCallBack()
    ?Alias(),Recno() &&如果数据量多,?号速度相当慢
EndProc 

*------------------------------------------------------------------------------------


*示例3 一个完整示例

oForm = NewObject("TestForm")
oForm.Show(1)

DEFINE CLASS TestForm AS form
    Height = 315
    Width = 422
    DoCreate = .T.
    AutoCenter = .T.
    Caption = "Form1"
    Name = "Form1"

    ADD OBJECT progressbar1 AS progressbar WITH ;
        Anchor = 10, ;
        Top = 216, ;
        Left = 12, ;
        Width = 396, ;
        Height = 24, ;
        Name = "Progressbar1", ;
        Shape.Name = "Shape", ;
        Label.Name = "Label", ;
        Mark.Name = "Mark"


    ADD OBJECT edit1 AS editbox WITH ;
        Anchor = 10, ;
        Height = 61, ;
        Left = 12, ;
        Top = 36, ;
        Width = 396, ;
        Name = "Edit1"


    ADD OBJECT label1 AS label WITH ;
        Caption = "连接串", ;
        Height = 16, ;
        Left = 12, ;
        Top = 12, ;
        Width = 38, ;
        Name = "Label1"


    ADD OBJECT command1 AS commandbutton WITH ;
        Top = 264, ;
        Left = 192, ;
        Height = 25, ;
        Width = 60, ;
        Anchor = 160, ;
        Caption = "Command1", ;
        Name = "Command1"


    ADD OBJECT label2 AS label WITH ;
        Caption = "SQL Select Cmd", ;
        Height = 16, ;
        Left = 12, ;
        Top = 108, ;
        Width = 156, ;
        Name = "Label2"


    ADD OBJECT edit2 AS editbox WITH ;
        Anchor = 10, ;
        Height = 61, ;
        Left = 12, ;
        Top = 132, ;
        Width = 396, ;
        Name = "Edit2"


    PROCEDURE updateprogress
        Lparameters nRecCount
        If IsNum(nRecCount)
            thisform.progressbar1.MaxValue= nRecCount
            thisform.progressbar1.Value=0
            Return 
        EndIf 
        thisform.progressbar1.Value =Recno()
        *如果你看不到进度,需要下面这句代码
        *UpdateWindow(thisform.HWnd)
    ENDPROC


    PROCEDURE Init
        Set Library To myfll

        thisform.edit1.Value ="Driver=Sql Server;Server=localhost;database=northwind"
        thisform.edit2.Value ="Select * from Orders"
    ENDPROC


    PROCEDURE command1.Click
        #define        SQL_CALLBACK_FETCH                1
        #define        SQL_CALLBACK_RECORD_COUNT        2

        SQLCallback(SQL_CALLBACK_RECORD_COUNT,"thisform.UpdateProgress")
        SQLCallback(SQL_CALLBACK_FETCH,"thisform.UpdateProgress")

        nHdl= SQLStringConnect(thisform.edit1.Value)
        If nHdl <1
            MessageBox("无法连接数据源……")
            Return 
        EndIf 

        SQLExec(nHdl,thisform.edit2.Value,"temp")

        SQLDisconnect(nHdl)
        If Used("temp")
            Browse
        EndIf 
    ENDPROC


EndDefine
*======================================================================================================
DEFINE CLASS progressbar AS container

    Width = 288
    Height = 120
    BackColor = RGB(235,235,235)
    BorderColor = RGB(192,192,192)
    maxvalue = 100
    value = 0
    _memberdata = [ ]
    Name = "progressbar"


    ADD OBJECT shape AS shape WITH ;
        Top = 0, ;
        Left = 0, ;
        Height = 120, ;
        Width = 108, ;
        BorderStyle = 0, ;
        BackColor = RGB(56,217,38), ;
        Name = "Shape"


    ADD OBJECT label AS label WITH ;
        AutoSize = .T., ;
        BackStyle = 0, ;
        Caption = "30%", ;
        Height = 16, ;
        Left = 133, ;
        Top = 54, ;
        Width = 20, ;
        Name = "Label"


    ADD OBJECT mark AS label WITH ;
        BackStyle = 0, ;
        Caption = "30%", ;
        Height = 16, ;
        Left = 133, ;
        Top = 54, ;
        Visible = .F., ;
        Width = 0, ;
        ForeColor = RGB(255,255,255), ;
        Name = "Mark"


    PROCEDURE value_assign
        LPARAMETERS vNewVal

        IF vNewVal<=0
            this.Shape.Width=0
            this.Label.Caption="0%"
            this.Mark.Caption="0%"
            RETURN
        ENDIF 

        If m.vNewVal>this.MaxValue 
            m.vNewVal=this.MaxValue
        EndIf 

        LOCAL nWidth  &&记录进度的宽度
        nWidth=m.vNewVal / this.MaxValue * this.Width - 2

        IF nWidth>this.Width 
           nWidth=this.Width-2
        ENDIF 
        ***
        this.Value=m.vNewVal
        &&形状更新
        this.Shape.Width=nWidth

        &&百分数更新
        IF this.value>=this.maxvalue 
            this.Label.Caption="100%"
        ELSE
            this.Label.Caption=Alltrim(STR(vNewVal/this.MaxValue * 100)) "%" 
        ENDIF 


        &&处理反色显示
        IF this.shape.Width>this.label.Left
            this.mark.Visible=.t.
            this.mark.Caption=this.label.Caption
            this.mark.Width=this.Shape.Width-this.Mark.Left 

        Else
            this.mark.Visible=.f.
        ENDIF 
    ENDPROC


    HIDDEN PROCEDURE maxvalue_assign
        LPARAMETERS vNewVal
        IF m.vNewVal<1 &&不能小于1,否则会出错
            m.vNewVal=1
        ENDIF 
        THIS.maxvalue = m.vNewVal
        this.Value=this.Value
    ENDPROC


    PROCEDURE Resize
        If this.Height>=2
            this.shape.Height=this.Height-2
        EndIf 
        this.Label.Left=(this.Width-this.Label.Width )/2
        this.Label.Top=(this.Height-this.Label.Height)/2 1
        this.mark.Left=this.label.Left 
        this.mark.Top=this.label.Top 
        this.shape.Top=1
        this.shape.Left=1 
        this.Value=this.Value
    ENDPROC


    PROCEDURE Init
        this.Resize 
    ENDPROC


ENDDEFINE

0 人点赞