Excel VBA在两个日期之间进行SQL查询时出错

时间:2019-03-14 16:16:12

标签: sql excel vba ms-access

我正在使用以下提供程序在Excel工作表中使用SQL

Set m_Connection = CreateObject("ADODB.Connection")

m_Connection.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
                  "Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0;HDR=Yes;"";"

我有两个文本框(从和到),用户在其中输入两个日期从,到,以选择与此日期选择相对应的记录

我面临以下问题:

首先,我尝试了这段代码,我从工作表中获取所有字段,无论日期是什么,除非我有空白工作表,否则在列日期中单元格为空的那些都是空的,所以我没有出现错误,但是我在两个日期之间的状况不起作用

SELECT [ListName] AS [List name] 
FROM [Database$] 
WHERE CDATE([ClipDate]) BETWEEN #01/09/2017# AND #14/03/2019#;

我尝试不使用BETWEEN,但是得到了相同的错误结果(除了空的记录,所有记录都被选择为ClipDate)

SELECT [ListName] AS [List name] 
FROM [Database$] 
WHERE CDATE([ClipDate]) >= #01/09/2017# AND CDATE([ClipDate]) <= #14/03/2019#;

我尝试了以下操作,通过将#替换为“”,这次我得到了很好的日期选择(我想要的日期选择),但是如果有任何单元格,我将收到一个错误消息,提示“无效使用Null”日期列为空。

SELECT [ListName] AS [List name] 
FROM [Database$] 
WHERE CDATE([ClipDate]) >= "01/09/2017" AND CDATE([ClipDate]) <= "14/03/2019";

最后我尝试了一下,并得到了与上一个相同的结果,即在空白单元格的情况下无效使用Null

SELECT [ListName] AS [List name] 
FROM [Database$] 
WHERE CDATE([ClipDate]) BETWEEN "01/09/2017" AND "11/03/2019";

这是“发件人”到“

”的屏幕

enter image description here

在我的Excel工作表中,我有这些日期

enter image description here

我认为问题在于CDATENULL值上不起作用,这是正常的,我必须找到一种仅在不为null的情况下进行转换的方法,但我不知道如何。 任何人都可以帮忙吗?

2 个答案:

答案 0 :(得分:3)

考虑parameterization,它受ADO支持,并允许将VBA值绑定到准备好的SQL查询中,以实现可维护性和可读性,并避免使用诸如#等类型的附件。

Sub RunSQL()
On Error GoTo ErrHandle
    Dim m_Connection As Object, cmd As Object, rst As Object
    Dim sqlStr As String
    Const adCmdText = 1, adDate = 7, adParamInput = 1

    ' CONNECTION
    Set m_Connection = CreateObject("ADODB.Connection")

    m_Connection.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
                      "Data Source=" & ThisWorkbook.FullName & _
                      ";Extended Properties=""Excel 12.0;HDR=Yes;"";"

    ' PREPARED STATEMENT WITH NO DATA BUT PLACE HOLDERS
    sqlStr = "SELECT [ListName] AS [List name]  " _
              & " FROM [Database$]" _
              & " WHERE CDATE([ClipDate]) BETWEEN ? AND ?"

    ' CONFIGURE ADO COMMAND
    Set cmd = CreateObject("ADODB.Command")
    With cmd
        .ActiveConnection = m_Connection
        .CommandText = sqlStr
        .CommandType = adCmdText

        ' BIND VALUES
        .Parameters.Append .CreateParameter("fromdate", adDate, adParamInput, , _
                                            CDate(Search.txtClipFrom.value))
        .Parameters.Append .CreateParameter("todate", adDate, adParamInput, , _
                                            CDate(Search.txtClipTo.value))
    End With

    ' CREATE RECORDSET FROM COMMAND EXECUTION
    Set rst = cmd.Execute
    ThisWorkbook.Worksheets("RESULTS").Range("A2").CopyFromRecordset rst
    rst.Close: m_Connection.Close

    MsgBox "Successfully completed!"

ExitHandle:
    Set cmd = Nothing: Set rst = Nothing: Set m_Connection = Nothing
    Exit Sub

ErrHandle:
    MsgBox Err.Number & " - " & Err.Description, vbCritical, "RUNTIME ERROR"
    Resume ExitHandle
End Sub

答案 1 :(得分:2)

使用 CVDate -和 ISO序列作为值:

SELECT [ListName] AS [List name] 
FROM [Database$] 
WHERE CVDate([ClipDate]) BETWEEN #2017/09/01# AND #2019/03/14#;

修改。过滤掉无效的日期字符串:

SELECT [ListName] AS [List name] 
FROM [Database$] 
WHERE 
    IsDate([ClipDate]) AND
    CVDate(IIf(IsDate([ClipDate]), [ClipDate], Null)) BETWEEN #2017/09/01# AND #2019/03/14#;

编辑2 :要分割dd / mm / yyyy格式的文本日期:

WHERE 
    IsDate([ClipDate]) AND
    DateSerial(Mid([ClipDate], 7, 4), Mid([ClipDate], 4, 2), Mid([ClipDate], 1, 2)) BETWEEN #2017/09/01# AND #2019/03/14#;