Ошибка в Excel VBA с запросом SQL между двумя датами - PullRequest
0 голосов
/ 14 марта 2019

Я использую SQL внутри листа Excel, используя следующий поставщик

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#;

Я попробовал следующее, заменив # на "", на этот раз я получаю хороший выбор даты (те, которые мне нужны), но я получаю сообщение об ошибке "Недопустимое использование нулевого значения", если какая-либо из ячеек в столбце Дата пуста.

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

Я думаю, что проблема в том, что CDATE не работает на NULL значениях, что нормально, и я должен найти способ конвертировать только если не ноль, но я не знаю как. Кто-нибудь может помочь, пожалуйста?

Ответы [ 2 ]

3 голосов
/ 15 марта 2019

Рассмотрим параметризацию , которая поддерживается 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
2 голосов
/ 14 марта 2019

Используйте 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 : Разделить даты в формате дд / мм / гггг:

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#;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...