Recordset循环不返回最后一条记录

时间:2014-05-26 16:13:25

标签: vba ms-access ms-word eof recordset

我使用以下代码循环遍历记录集,该记录集假设以表格格式将所有选定记录传输到Word文档。它工作但它给了我除最后一个以外的所有记录(即我选择了4个记录,它从顶部只返回3个。)

Private Sub cmdWord_Click()
Dim oWord As Object 'Word.Application
Dim doc As Object 'Word.Document
Set oWord = CreateObject("Word.Application")
Set doc = oWord.Documents.Open("D:\Working\Templates\Letter.doc")
oWord.Visible = True
Dim oAccess As Object
Dim dbs As Database
Dim rst As Recordset
Dim strCriteria As String

With oWord.ActiveDocument
    If .Bookmarks.Exists("Date") = True Then
        .Bookmarks("Date").Select
        If Not IsNull([Forms]![frmForReport_Preview]!Date) Then
            oWord.Selection.Text = (CStr(Format([Forms]![frmForReport_Preview]!Date, "mmm d, yyyy")))
        Else
            oWord.Selection.Text = ""
        End If
    End If

    If .Bookmarks.Exists("Table") = True Then

        Set dbs = CurrentDb
        strCriteria = "SELECT tblForLetter.ID, tblForLetter.DID, tblForLetter.AT, tblForLetter.Expr1, tblForLetter.L FROM tblForLetter WHERE (((tblForLetter.Print)=-1=True));"

        Set rst = dbs.OpenRecordset(strCriteria, dbOpenSnapshot)
        oWord.ActiveDocument.Bookmarks("Table").Select
        oWord.Selection.Text = ""

        i = 1
        If Not (rst.EOF And rst.BOF) Then
            rst.MoveFirst
            Do Until rst.EOF = True
                doc.Tables(1).Columns(1).Cells.Add
                doc.Tables(1).Columns(1).Cells(i + 1).range.Text = rst.Fields(0)
                doc.Tables(1).Columns(2).Cells(i + 1).range.Text = rst.Fields(1)
                doc.Tables(1).Columns(3).Cells(i + 1).range.Text = rst.Fields(2)
                doc.Tables(1).Columns(4).Cells(i + 1).range.Text = rst.Fields(3)
                doc.Tables(1).Columns(5).Cells(i + 1).range.Text = rst.Fields(4)
                rst.MoveNext
                i = i + 1
            Loop
        Else
            MsgBox ("There are no records in the recordset.")
        End If

        DoCmd.Close acForm, "frmForReport_Preview", acSaveYes
        DoCmd.SetWarnings False
        DoCmd.RunSQL "Delete * From [tblForLetter]"
        DoCmd.SetWarnings True

        rst.Close
        Set dbs = Nothing
    End If
End With
End Sub

1 个答案:

答案 0 :(得分:1)

您究竟如何选择表单中的记录?

我怀疑这个:

  • 表格是连续的表格
  • 表单的RecordSource为tblForLetterSELECT * FROM tblForLetter或类似的内容
  • 表单上有一个复选框,其中Print列为控制源。
  • 因此,当您通过点击其复选框“选择”某条记录时,相应行中的Print列将设置为True / -1

如果你这样做,你应该考虑以下几点:

  • 当您更改行中的某些内容时(在这种情况下,您选中了一个复选框,但如果您在文本框中输入了文本,那么它将是相同的),此行将更改进入“编辑模式” (不知道Access是否有特殊名称,所以我只是这样称呼它)
  • 只要该行仍处于编辑模式,数据库中没有任何更改。您只是在更改GUI中的控件。
  • 当您将焦点设置为另一行(=通过单击另一行中的控件)时,行将停止处于编辑模式。
  • 时刻,Access实际上会将您的更改保存到数据库中。

因此,当您选择多个复选框时,实际发生的是:

  • 您点击第1行
  • 中的复选框
  • 第1行切换到编辑模式,并在GUI 中检查复选框(但尚未在数据库中)
  • 您点击了第2行
  • 中的复选框
  • 这将结束第1行中的编辑模式,并将更改保存到数据库中。
  • 然后第2行切换到编辑模式,并在GUI 中检查复选框(但尚未在数据库中)
  • ......等等。

现在还有一个额外的问题:
当一行处于编辑模式,并且您单击表单的页眉或页脚中的控件(换句话说,不在“详细信息”区域中,表单的实际连续部分)该行保持编辑模式且更改尚未保存到数据库

所以你看到的奇怪行为可能是由于:

  • 您可以通过单击其复选框选择四个记录。
  • 然后点击cmdWord按钮,触发问题中的代码,但在那一刻,第四行仍然处于编辑模式。
  • 这意味着仅在GUI上选中该复选框...但Access尚未将其保存到数据库中!
  • 因此,当您执行查询并按... WHERE tblForLetter.Print=True进行过滤时,您只会获得前三个选定的行,但不会获得第四个,因为在那一刻,tblForLetter.Print仍然是False数据库中。

解决方案:

一般来说,当您运行从表中获取所选行的查询时,您需要确保没有行仍处于编辑模式。

在不更改代码的情况下,您可以在选择四行时看到差异,将焦点设置为另一行,以便第四行也保存,然后然后点击按钮。

要在代码中自动执行此操作,您只需在从表格中选择之前调用Me.Requery即可重新查询表单的数据源。
Me.Requery将重新加载表单中的数据。如果此时编辑模式中仍有一行,则编辑模式将首先结束,该行中的更改将保存到数据库中。