Office中国论坛/Access中国论坛

标题: 主子窗体批量保存,发现的问题,(原来是2010的问题,换为07就好了,谢谢T小宝版主提醒 [打印本页]

作者: dlack    时间: 2012-4-16 01:50
标题: 主子窗体批量保存,发现的问题,(原来是2010的问题,换为07就好了,谢谢T小宝版主提醒
本帖最后由 dlack 于 2012-4-21 23:58 编辑

[attach]48990[/attach][attach]48991[/attach]t小宝 版主发布的[ADO/DAO] 主子窗体批量保存(http://www.office-cn.net/thread-72836-1-1.html),非常有用,在使用过程中发现如下问题:[attach]48989[/attach],使用ADO方式的时候,在子表中的统计以及好多其他的表功能都没法使用(在DAO模式下Me.frmsub.Form.rsChildClone可以使用,ADO时候也没法使用),使用DAO的时候一切功能正常,但是如果数据多于50行或者项次多于15列左右,在第二次打开的时候就会出现假死状态。现在正在使用这个做一个数据库,感觉T小宝版主做的这个是最适合的,请了解的朋友帮忙改一下,谢谢了。


作者: dlack    时间: 2012-4-16 09:37
谁能帮忙看一下,谢谢了!
作者: dlack    时间: 2012-4-16 09:59
是不是函数在载入关闭后没有卸载掉,所以多开几次就会导致崩溃。请高手帮忙看看,谢谢!


'--------------------------------------------------------------------------------------------------
'类    名:  ADOTransForm
'功    能:  应用于主子窗体(子可以是数据表或连续窗体),实现主子窗体所有数据修改的同步批量保存或取消,
'           可用于 ACCESS 2000 以上版本.
'
'方    法:  InitForm      加载窗体和数据
'           UndoAll       取消所有数据更改
'           SaveAll       保存所有数据更改,成功返回真
'
'属    性:  FormDataMode  返回窗体的允许添加属性, 添加:true  修改:false
'
'事    件:  BeforeUnload  主窗体卸载前发生,可确定是否保存记录和关闭窗体
'           BeforeSaveAll 保存所有数据之前发生,可确定是否允许保存记录
'           AfterSaveAll  保存所有数据之后发生
'
'使用注意:  指定给主窗体的记录不要超过1条.
'           将窗体的模式属性设为是,因为启动事务之后会影响其它打开的记录集.
'
'相关说明:  这个类使用了DAO事务.
'
'作    者:  t小雨 (tcl013@126.com)
'创建日期:  2009-7-22
'--------------------------------------------------------------------------------------------------
Option Compare Database
Option Explicit

Public Event BeforeUnload(ByVal Dirty As Boolean, Cancel As VbMsgBoxResult)       ' 窗体卸载前
Public Event BeforeSaveAll(Cancel As Boolean, Response As Integer)                ' 保存前
Public Event AfterSaveAll(ByVal DataMode As Boolean)                              ' 保存后

Dim WithEvents frmMain As Form                    ' 主窗体
Dim WithEvents frmChild As Form                   ' 子窗体
Dim mblDataMode As Boolean                        ' 数据模式,添加:true 修改:false
Dim mblBeginTrans As Boolean                      ' 是否已开启事务
Dim mblDataChange As Boolean                      ' 数据是否已更改
Dim mblChildDel As Boolean                        ' 用于判断子窗体取消删除


'===========================================================
' 加载窗体和数据
'===========================================================
Public Sub InitForm(Main As Form, MainRcSource As String, Child As SubForm, ChildRcSource As String)

    Set frmMain = Main
    Set frmChild = Child.Form
   
    With frmMain
        .AllowDeletions = False                ' 强制主窗体不能删除记录
        .AfterInsert = "[Event Procedure]"
        .AfterUpdate = "[Event Procedure]"
        .OnUnload = "[Event Procedure]"
    End With
    With frmChild
        .AfterUpdate = "[Event Procedure]"
        .AfterDelConfirm = "[Event Procedure]"
        .OnDelete = "[Event Procedure]"
    End With

    mblDataMode = (CreateFormRst(frmMain, MainRcSource) = 0)
    frmMain.AllowAdditions = mblDataMode
    CreateFormRst frmChild, ChildRcSource

    DBEngine.BeginTrans    ' 开启事务
    mblBeginTrans = True

End Sub


'===========================================================
' 主窗体 事件
'===========================================================
Private Sub frmMain_AfterInsert()
    frmMain.AllowAdditions = False       ' 一次只能添加一条记录
End Sub

Private Sub frmMain_AfterUpdate()
    If mblDataChange = False Then mblDataChange = True
End Sub

Private Sub frmMain_Unload(Cancel As Integer)
' 卸载前提示
    Dim msg As VbMsgBoxResult
    msg = vbNo                                        ' 默认不保存
    RaiseEvent BeforeUnload(mblDataChange, msg)
    Cancel = (msg = vbCancel)
    If mblDataChange Then
        If msg = vbNo Then
            UndoAll
        ElseIf msg <> vbCancel Then
            SaveAll
        End If
    ElseIf mblBeginTrans Then
        If msg <> vbCancel Then DBEngine.Rollback
    End If
End Sub


'===========================================================
' 子窗体 事件
'===========================================================
Private Sub frmChild_AfterDelConfirm(Status As Integer)
    If Status = acDeleteOK Then
        If mblDataChange = False Then mblDataChange = True
    Else
        If mblChildDel Then
            ' 如删除不成功且是第一次更改窗体数据
            mblDataChange = False
            mblChildDel = False
        End If
    End If
End Sub

Private Sub frmChild_AfterUpdate()
    If mblDataChange = False Then mblDataChange = True
End Sub

Private Sub frmChild_Delete(Cancel As Integer)
    If mblDataChange = False Then
       ' 第一次更改窗体数据
        mblDataChange = True
        mblChildDel = True
    End If
End Sub


'===========================================================
' 取消所有数据更改
'===========================================================
Public Sub UndoAll()
    If mblDataMode Then frmMain.AllowAdditions = True
    If frmMain.Dirty Or frmChild.Dirty Then DoCmd.RunCommand acCmdUndo
    DBEngine.Rollback
    mblBeginTrans = False
    mblDataChange = False
End Sub

'===========================================================
' 保存所有数据更改
'===========================================================
Public Function SaveAll() As Boolean

    Dim b As Boolean, i As Integer
    If frmMain.Dirty Or frmChild.Dirty Then DoCmd.RunCommand acCmdSaveRecord
    If mblDataChange Then
        RaiseEvent BeforeSaveAll(b, i)
        If b Then
            If i = 0 Then MsgBox "无法保存数据!", vbExclamation, "系统提示"
            Exit Function
        End If
        DBEngine.CommitTrans
        RaiseEvent AfterSaveAll(mblDataMode)
        mblDataMode = False
        mblDataChange = False
    Else
        DBEngine.Rollback
    End If
    mblBeginTrans = False
    SaveAll = True
   
End Function


'===========================================================
' 主窗体数据模式 添加或修改
'===========================================================
Public Property Get FormDataMode() As Boolean
    FormDataMode = mblDataMode
End Property


'===========================================================
' 子函数 设置窗体记录集
'===========================================================
Private Function CreateFormRst(frm As Form, RecSource As String) As Integer
    Dim rs As DAO.Recordset
    Set rs = CurrentDb.OpenRecordset(RecSource, dbOpenDynaset)
    Set frm.Recordset = rs
    CreateFormRst = rs.RecordCount
    Set rs = Nothing
End Function


作者: dlack    时间: 2012-4-16 10:04
采用DAO时,数据多一点,下面的语句就会出问题!
Set mDAOTransForm = New DAOTransForm
    mDAOTransForm.InitForm Me, "Select * From 订单 Where 订单ID='" & stID & "'", _
        Me.订单明细_子窗体, "Select * From 订单明细 Where 订单ID='" & stID & "'"
作者: dlack    时间: 2012-4-16 10:54
实例改为低版本的了,烦请了解的朋友帮忙看一下,谢谢了
作者: 风中漫步    时间: 2012-4-16 16:56
看着挺复杂的,你用些简单的不行吗?
作者: dlack    时间: 2012-4-16 19:06
风中漫步 发表于 2012-4-16 16:56
看着挺复杂的,你用些简单的不行吗?

主要是这个功能挺好的,不用建临时表就可以实现批量保存。能帮忙看看吗?
作者: t小宝    时间: 2012-4-21 13:57
本帖最后由 t小宝 于 2012-4-21 13:58 编辑
dlack 发表于 2012-4-16 10:54
实例改为低版本的了,烦请了解的朋友帮忙看一下,谢谢了


5楼的例子没发现问题呀,你把有问题的传上来
作者: dlack    时间: 2012-4-21 16:31
本帖最后由 dlack 于 2012-4-21 19:05 编辑
t小宝 发表于 2012-4-21 13:57
5楼的例子没发现问题呀,你把有问题的传上来



T小宝版主,我尝试过了很多次,当表 请购单ID 设置为主键的时候,数据一多,多点几次修改请购单,程序马上崩溃
。如果请购单ID不设置为主键,那么请购单ID  s0000中如果有数据,S0000多点几次修改,程序会直接退出。修改s0001,不会出现这个问题。如果删除请购单ID S0000,那么S0001在多次点击修改后也会直接退出。
   一直不知道是啥原因,请版主帮忙修改一下,谢谢了。


作者: t小宝    时间: 2012-4-21 16:49
dlack 发表于 2012-4-21 16:31
T小宝版主,我尝试过了很多次,当表 请购单ID 设置为主键的时候,数据一多,多点几次修改请购单,程序 ...

你把引起出错的操作过程讲清楚,让我按照你说的步骤操作就会出现你所说的错误!
作者: dlack    时间: 2012-4-21 17:08
t小宝 发表于 2012-4-21 16:49
你把引起出错的操作过程讲清楚,让我按照你说的步骤操作就会出现你所说的错误!

双击 s0000那行数据,第一次正常弹出窗口,关闭弹出窗口后,再次点击--关闭,如此循环几次后程序就会直接退出了。但是按照此方法试验S0001就不会有问题。把S0000那行删除后,双击S0001那行又会出现像S0000崩溃那种情况。
作者: dlack    时间: 2012-4-21 17:11
t小宝 发表于 2012-4-21 16:49
你把引起出错的操作过程讲清楚,让我按照你说的步骤操作就会出现你所说的错误!

t版主,示例中S0000无数据,你添加几行数据进去就能发现问题了
作者: dlack    时间: 2012-4-21 17:19
t小宝 发表于 2012-4-21 16:49
你把引起出错的操作过程讲清楚,让我按照你说的步骤操作就会出现你所说的错误!

[attach]49056[/attach]

在请购单S0000里面添加了数据,我试了一下,一般点到第四下就会出现问题。


作者: dlack    时间: 2012-4-21 17:39
t小宝 发表于 2012-4-21 16:49
你把引起出错的操作过程讲清楚,让我按照你说的步骤操作就会出现你所说的错误!

晕,我去同事电脑试了一下,应该是我电脑的问题。气死我了,差点崩溃了。
非常感谢热心的t版主!




欢迎光临 Office中国论坛/Access中国论坛 (http://www.office-cn.net/) Powered by Discuz! X3.3