用OpenQQ实现网络环境下的编号

我们之前介绍的编号方法,在多用户环境下会出现重复,参考:常用编号生成方法

有了Open,我们可以轻松解决这个问题。

以下例子,在实际测试的时候,如果表中已经有不符合规范的编号,请先删除之,否则会影响编号的生成结果

一、按类别编号

假定有下图所示的一个表,编号根据类别生成,前两位为类别,后三位为顺序号:

这里假定使用的是外部数据源。

服务端的设计

1、在服务端的全局代码中编写代码:

Public flbhs As New Dictionary(of String,Integer)

2、在服务端的AfterOpenProjet事件中编写代码:

Dim dt As DataTable
Dim
cmd As New SQLCommand
cmd
.ConnectionName = "数据源名称"
cmd
.CommandText = "Select 类别, Max(编号) As 编号 From {产品} Group By 类别"
dt
= cmd.ExecuteReader
flbhs.Clear()
For
Each dr As DataRow In dt.DataRows
    Dim qz As String = dr("
类别") '编号前缀
    Dim bh As Stringdr("
编号")
    Dim id As Integer
    If bh.Length = 5 Then
        bh = bh.SubString(2)
        If Integer.TryParse(bh,id) Then
           
flbhs.Add(qz, id)
        End If
   
End If
Next

上述代码在启动项目后,用SQL语句提取每个类别的最大编号,将其整数部分存储在字典flbhs中。

3、在服务端的OpenQQ服务端事件ReceivedMessage中编写代码:

Dim msg As String = e.Message
If
msg.StartsWith(":f") AndAlso msg.EndsWith("f:") Then
    msg = msg.SubString(2, msg.Length - 4)
    If
flbhs.ContainsKey(msg) Then '如果存在这个类别的编号
       
flbhs(msg) = flbhs(msg) + 1 '将该类别最大编号加1
   
Else
       
flbhs.Add(msg,1) '如果是这个列表的首次编号,则编号等于1
   
End If
    e.ReturnValue = flbhs(msg)
'将编号返回给客户端
End If

客户端的设计

选择客户端项目对应的表,在其DataColChanged事件中加上代码:

If e.DataCol.Name = "类别" Then
    If e.DataRow.IsNull("类别") Then
        e.DataRow("编号") = Nothing
    Else
        If QQClient.Ready = False Then
            PopMessage("QQClient未启动,无法生成编号!","提示",PopIconEnum.Infomation,5)
        Else
            Dim bh As String = e.DataRow("类别")
            Dim rt As StringQQClient.SendWait(":f" & bh & "f:")
           
Dim id As Integer
            If rt > "" Then
                If  Integer.TryParse(rt,idThen
                    e.DataRow("
编号") = bh & Format(id,"000")
                Else
                    PopMessage("
服务器返回错误信息:" & rt,"提示",PopIconEnum.Infomation,5)
                End If
            Else
                PopMessage("
服务器无响应,无法生成编号!","提示",PopIconEnum.Infomation,5)
            End If
        End If
    End If

End
If

二、按月生成编号

假定有个订单表,需要按月自动生成编号,四位年,两位月,最后三位是顺序号,如下图所示:

这里假定使用的是外部数据源。

服务端的设计

1、在服务端的全局代码中编写代码:

Public flbhs As new Dictionary(of String,Integer)

2、在服务端的AfterOpenProjet事件中编写代码:

Dim dt As DataTable
Dim
cmd As New SQLCommand
cmd
.ConnectionName = "数据源名称"
cmd
.CommandText = "Select Year(日期) As , Month(日期) As , Max(编号) as 编号 From {订单} Group By Year(日期), Month(日期)"
dt
= cmd.ExecuteReader
flbhs
.Clear()
For
Each dr As DataRow In dt.DataRows
    Dim qz As String = dr(
"
") & Format(dr(""),"00") '编号前缀,4位年,2位月
    Dim bh As String = dr(
"
编号")
    Dim id As Integer
    If bh.Length = 10 Then
        bh = bh.SubString(7)
        If Integer.TryParse(bh,id) Then
            flbhs.Add(qz, id)
        End If
   
End If
Next

上述代码在启动项目后,用SQL语句提取现有数据的每月最大编号,将其整数部分存储在字典flbhs中。

3、在服务端的OpenQQ服务端事件ReceivedMessage中编写代码:

Dim msg As String = e.Message
If
msg.StartsWith(":p") AndAlso msg.EndsWith("p:") Then
    msg = msg.SubString(2, msg.Length - 4)
    If flbhs.ContainsKey(msg) Then
'
如果存在这个月的编号
        flbhs(msg) = flbhs(msg) + 1
'
将该月最大编号加1
   
Else
        flbhs.Add(msg,1) '如果是这个月的首次编号,则编号等于1
    End If
    e.ReturnValue = flbhs(msg)
'将编号返回给客户端

End
If

客户端的设计

选择客户端项目的订单表,在其DataColChanged事件中加上代码:

If e.DataCol.Name = "日期" Then
    If e.DataRow.IsNull(
"
日期") Then
        e.DataRow(
"
编号") = Nothing
    Else
        If QQClient.Ready = False Then
            PopMessage(
"QQClient
未启动,无法生成编号!","提示",PopIconEnum.Infomation,5)
        Else
            Dim bh As String = Format(e.DataRow(
"
日期"),"yyyyMM")
            Dim rt As StringQQClient.SendWait(":p" & bh & "p:")
            Dim id As Integer
            If rt > "" Then
                If  Integer.TryParse(rt,idThen
                    e.DataRow(
"
编号") = bh & "-" & Format(id,"000")
                Else
                    PopMessage(
"
服务器返回错误信息:" & rt,"提示",PopIconEnum.Infomation,5)
                End If
            Else
                PopMessage(
"
服务器无响应,无法生成编号!","提示",PopIconEnum.Infomation,5)
            End If
        End If
    End
If

End
If

三、按日期和类别编号

假定有个表,需要按月自动生成编号,根据工程代码按顺序编号,前4位是工程代码,然后是4位年,2位月,最后4位是顺序号,如下图所示:

其实如果你看懂了前面的例子,这个例子就是多余的,无非就是在服务器端记录每一个前缀的最大序号,遇到客户端申请编号的时候,将最大序号加1,然后返回给客户端。
编程的是千变万化的,但万变不离其宗,基本原理明白了,就可以举一反三,以不变应万变。

接下来我们看看是不是和第一个例子一样。

服务端的设计

1、在服务端的全局代码中编写代码:

Public flbhs As new Dictionary(of String,Integer)

2、在服务端的AfterOpenProjet事件中编写代码:

Dim dt As DataTable
Dim
cmd As New SQLCommand
cmd
.ConnectionName = "数据源名称"
cmd
.CommandText = "Select 工程代码,Year(制单日期) As , Month(制单日期) As , Max(单据编号) as 单据编号 From {工程} Group By 工程代码,Year(制单日期), Month(制单日期)"
dt
= cmd.ExecuteReader
flbhs
.Clear()
For
Each dr As DataRow In dt.DataRows
    Dim qz As String = dr(
"
工程代码") & "-"  & dr("") & Format(dr(""),"00") '编号前缀,4位工程代码,4位年,2位月
    Dim bh As Stringdr(
"
单据编号")
    Dim id As Integer
    If bh.Length = 16 Then
        bh = bh.SubString(12)
        If Integer.TryParse(bh,id) Then
            flbhs.Add(qz, id)
        End If
   
End If
Next

上述代码除了表名、列名的变化,以及给编号前缀加上工程代码外,真正发生变化的就是两个数字,你可以想想为什么一个由10改为16,一个由7改为12?

3、在服务端的OpenQQ服务端事件ReceivedMessage中编写代码:

Dim msg As String = e.Message
If
msg.StartsWith(":g") AndAlso msg.EndsWith("g:") Then
    msg = msg.SubString(2, msg.Length - 4)
    If flbhs.ContainsKey(msg) Then
'
如果存在这个月的编号
        flbhs(msg) = flbhs(msg) + 1
'
将该月最大编号加1
   
Else
        flbhs.Add(msg,1) '如果这个月的首次编号,则编号等于1
   
End If
    e.ReturnValue = flbhs(msg)

End
If

上述代码没有任何改变。

客户端的设计

选择客户端项目的对应的表,在其DataColChanged事件中加上代码:

Select e.DataCol.Name
    Case "制单日期","工程代码"
        If e.DataRow.IsNull("制单日期") OrElse e.DataRow.IsNull("工程代码") Then
            e.DataRow("单据编号") = Nothing
        Else
            If QQClient.Ready = False Then
                PopMessage("QQClient未启动,无法生成编号!","提示",PopIconEnum.Infomation,5)
            Else
                Dim bh As String = e.DataRow("工程代码") & "-" &  Format(e.DataRow("制单日期"),"yyyyMM")
                Dim rt As StringQQClient.SendWait(":g" & bh & "g:")
               
Dim id As Integer
                If rt > "" Then
                    If  Integer.TryParse(rt,idThen
                        e.DataRow(
"
单据编号") = bh & "-" & Format(id,"0000")
                    Else
                        PopMessage(
"
服务器返回错误信息:" & rt,"提示",PopIconEnum.Infomation,5)
                    End If
                Else
                    PopMessage(
"
服务器无响应,无法生成编号!","提示",PopIconEnum.Infomation,5)
                End If
            End If
        End
If

End
Select

上述代码除了表名、列名的变化,以及给编号前缀加上工程代码外,唯一发生变化的只是将:

Format(id,"000")

改成了

Format(id,"0000")

因为顺序号原来是3位,现在是4位。


本页地址:http://www.foxtable.com/webhelp/topics/3008.htm