【问题标题】:Loop Not Running Through Entire Table循环未通过整个表运行
【发布时间】:2012-12-13 01:04:57
【问题描述】:

所以我有一个内置的系统,它设置了一些不同的标志等等,但我想做的一件事是获取临时表的内容并将其发送到另一个用于追踪。我正在尝试使用插入循环来做到这一点,但我根本无法弄清楚如何使其按预期工作。

Private Sub Form_Load()
    DoCmd.SetWarnings False
    DoCmd.OpenQuery ("qryDeleteEmail")
    Dim db As Object
    Dim rst As Object
    Dim test As Object

    Set db = Application.CurrentDb
    Set rst = db.OpenRecordset("qryDate")
    Set test = db.OpenRecordset("tblEmailTemp")

    If Me.RecordsetClone.RecordCount = 0 Then
        MsgBox ("No delinquent accounts. No email will be generated.")
        Me.Refresh
        DoCmd.Close acForm, "qryDate", acSaveNo
        DoCmd.CancelEvent
    Else
        rst.MoveFirst
        Do Until rst.EOF
           rst.Edit
           rst!NeedsEmail = 1
           rst.Update
           rst.MoveNext
        Loop

        'DoCmd.Requery
        'rst.Close


        DoCmd.RunMacro ("StagingTable")
        test.MoveFirst

        Do Until test.EOF
            CurrentDb.Execute "Insert Into EmailTracking (Account, ExpirationDate)" & _
                "Values ('" & AccountName & "', '" & ExpirationDate & "')"
            test.MoveNext              
        Loop

        test.Close
        rst.MoveFirst

        Do Until rst.EOF
            rst.Edit
            rst!EmailSent = 1
            rst.Update
            rst.MoveNext
        Loop

        'DoCmd.Requery
        rst.Close
        DoCmd.RunMacro ("Close")
        'DoCmd.OpenQuery ("qryDeleteEmail")
    End If
    Exit Sub
End Sub

现在发生的事情是将临时表的第一条记录复制两次。例如,我有一个帐户名 A 和一个帐户名 S,但不是插入 A 的记录和 S 的记录,而是简单地插入 A 两次。

任何帮助将不胜感激!

【问题讨论】:

  • 您的代码缩进没有意义,我编辑了它。在这小部分代码中仍然有很多没有意义的地方。
  • 好吧,我将是第一个承认我在这方面很糟糕但仍在努力学习的人。不过,欣赏编辑。它确实使它更易于阅读。
  • 宏“StagingTable”在做什么?此外,您还没有初始化 AccountName 和 ExpirationDate。我建议将Option Explicit 放在模块的顶部。你可能想做的是test!AccountNametest!ExpirationDate
  • stagingtable 宏将信息拉到一个表格中,供我的电子邮件模块阅读。基本上,发生的事情是第一个循环将条目标记为需要电子邮件。 stagingtable 宏然后为我的电子邮件模块提取标记的条目。宏运行后,条目将被标记为已发送电子邮件。那部分工作得很好。我不是 100% 确定您所说的初始化是什么意思,以及在什么上下文中 test!AccountName 语句将被使用。我仍在整体学习 VBA,所以如果我表现得像个白痴,我深表歉意。

标签: vba ms-access loops recordset


【解决方案1】:

创建并测试一个更简单的程序,该程序只专注于您要解决的问题。不幸的是,我不确定那个问题是什么。反正我会建议这个...

Public Sub TestLoopThruTable()
    Dim db As DAO.database
    Dim test As DAO.Recordset
    Dim strInsert As String

    DoCmd.SetWarnings True ' make sure SetWarnings is on
    Set db = CurrentDb
    Set test = db.OpenRecordset("tblEmailTemp")
    Do While Not test.EOF
        strInsert = "INSERT INTO EmailTracking (Account, ExpirationDate)" & vbCrLf & _
            "VALUES ('" & AccountName & "', '" & ExpirationDate & "')"
        Debug.Print strInsert
        'db.Execute strInsert, dbFailOnError
        test.MoveNext
    Loop
    test.Close
    Set test = Nothing
    Set db = Nothing
End Sub

请注意,在您的原始版本中,ExpirationDate)Values 之间没有空格。我使用了换行符 (vbCrLf) 而不是空格,但两者都可以让 db 引擎满意。

我确定SetWarnings 已开启。在您的代码中,您在开始时将其关闭,但从未再次将其重新打开。关闭 SetWarnings 操作会隐藏重要信息,否则您可以使用这些信息来了解代码问题。

当代码循环遍历记录集时,它只是创建了一个INSERT 语句并为每一行显示它。您可以在“立即”窗口中查看输出(使用 Ctrl+g 键盘快捷键转到那里)。复制其中一个 INSERT 语句并通过粘贴到新 Access 查询的 SQL 视图中进行测试。如果它在那里失败,找出你需要改变什么来满足数据库引擎。如果INSERT 成功,请尝试从您的代码中执行它们:通过删除该行开头的单引号来启用db.Execute 行。

按照您编写VALUES 子句的方式,[ExpirationDate] 似乎是一个文本字段。但是,如果它的数据类型实际上是日期/时间,则不要在要插入的值周围加上引号;使用# 日期分隔符而不是引号。

还要确保在代码模块的声明部分中包含Option Explicit,如下所示:

Option Compare Database
Option Explicit

我提到这一点是因为在这个问题的早期版本中,您显示了Option Compare,但没有显示Option Explicit。尝试在没有 Option Explicit 的情况下对代码进行故障排除是浪费时间 IMO。

【讨论】:

  • 在我看来,使用基于参数查询的 QueryDef 会更好。然后每次通过循环,您只需提供参数值并执行 QueryDef。我没有野心了。
  • 感谢您的帮助。当我试图解决这个问题时,我会提到这个。谢谢。
【解决方案2】:

我不确定你想在这里做什么;很难理解 ErrorHandlerElse 语句中所做的事情(即使已评论)。

就循环记录集而言,我建议您阅读一些有关 MS-Access 中 VBA 编程基础的内容。您可以从阅读以下文章开始。它简要介绍了 VBA 记录集以及 VBA 中最常见的错误。

http://allenbrowne.com/ser-29.html

http://www.techrepublic.com/blog/10things/10-mistakes-to-avoid-when-using-vba-recordset-objects/373

它应该可以帮助您改进代码。

【讨论】:

    猜你喜欢
    • 2020-06-28
    • 2019-02-22
    • 1970-01-01
    • 1970-01-01
    • 2011-08-07
    • 1970-01-01
    • 1970-01-01
    • 2018-02-28
    • 2022-09-23
    相关资源
    最近更新 更多