使用单元格中的date或Sql查询中命名的范围

我创build了一个工作表来提取Microsoft SQL数据库中的数据,以生成2dateStartDateEndDate之间的客户报告。

我一直在玩一些东西,但一直没有成功。 我已经search,但一直没能find任何我以前或能够理解的东西。

我相信的问题是我在Excel中使用的date的数据types,并试图将它传递给SQL查询。 我知道我需要以某种方式转换这个,以使这个可能和正确。

如果我手动inputdate到查询它工作正常。 但对客户使用不切实际,我没有这方面的经验,只是! 通过它扼杀我的方式。 如果有人会对我如此友善,这将是非常感激。

下面是我正在尝试使用的代码

 Sub DataExtract() ' DataExtract Macro ' ' Create a connection object. Dim cni96X As ADODB.Connection Set cni96X = New ADODB.Connection ' Set Database Range ' Provide the connection string. Dim strConn As String Dim Lan As Integer Dim OS As Integer Dim PointID As String ' Set Variables Lan = Range("Lan").Value OS = Range("OS").Value PointID = Range("PointID").Value StartDate = Range("StartDate").Value EndDate = Range("EndDate").Value 'Use the SQL Server OLE DB Provider. strConn = "PROVIDER=SQLOLEDB;" 'Connect to 963 database on the local server. strConn = strConn & "DATA SOURCE=(local);INITIAL CATALOG=i96X;" 'Use an integrated login. strConn = strConn & " INTEGRATED SECURITY=sspi;" 'Now open the connection. cni96X.Open strConn ' Create a recordset object. Dim rsi96X As ADODB.Recordset Dim rsi96X1 As ADODB.Recordset Set rsi96X = New ADODB.Recordset Set rsi96X1 = New ADODB.Recordset With rsi96X ' Assign the Connection object. .ActiveConnection = cni96X ' Extract the required records1. .Open "SELECT ModuleLabel, originalAlarmTime FROM LastAlarmDetailsByTime WHERE (os = " & OS & " And theModule = N'" & PointID & "'AND AlarmCode = N'DI=1' And lan = " & Lan & " And originalAlarmTime BETWEEN N'" & StartDate & "' AND N'" & EndDate & "') ORDER BY originalAlarmTime DESC" ' Copy the records into sheet. Range("PointLabel, TimeCallInitiated").CopyFromRecordset rsi96X With rsi96X1 .ActiveConnection = cni96X ' Assign the Connection object. .Open "SELECT originalAlarmTime FROM LastAlarmDetailsByTime WHERE (os = " & OS & " And theModule = N'" & PointID & "'AND AlarmCode = N'CDI1' And lan = " & Lan & " And originalAlarmTime BETWEEN N'" & StartDate & "' AND N'" & EndDate & "')ORDER BY originalAlarmTime DESC" ' Copy the records into sheet. Sheet1.Range("TimeCallEnded").CopyFromRecordset rsi96X1 ' Tidy up .Close 

我希望这是有道理的。

您不能指定数据types,Access数据库引擎(以前的Jet)必须猜测。 您可以通过更改某些registry设置(例如MaxScanRows )并在连接string中包含IMEX=1来影响其猜测工作。 有关更多详细信息,请参阅此知识库文章 。


这是我多年前在这个主题上写的东西(如果你是谷歌的“ONEDAYWHEN = 0”,你可以看到它已被广泛阅读,虽然也许不够仔细):

相关的registry项(Jet 4.0)位于:

HKEY_LOCAL_MACHINE / SOFTWARE /微软/喷气/ 4.0 /发动机/ EXCEL /

总是读取ImportMixedTypesregistry项(稍后会讨论它是否被尊重)。 您可以通过将密钥更改为ImportMixedTypes=OneDayWhen并尝试使用ISAM进行testing:您将看到“Windowsregistry引擎部分的Excel密钥中的无效设置”错误。 唯一有效的值是:

  • ImportMixedTypes=Text
  • ImportMixedTypes=Majority Type

数据types是逐列确定的。 “多数types”表示扫描每列中的特定行数(稍后更多),并对数据types进行计数。 单元格的值和格式都用于确定数据types。 多数据types(即具有最多行的数据types)决定整个列的整体数据types。 在平手的情况下,有一个偏好os数字的偏见。 发现来自任何less数数据types的行不能作为大多数数据types将被返回一个空值。

对于ImportMixedTypes=Text ,整个列的数据types为:

 Jet (MS Access UI): 'Text' data type DDL: VARCHAR(255) ADO: adWChar ('a null-terminated Unicode character string') 

请注意,这不同于:

 Jet (MS Access UI): 'Memo' data type DDL: MEMO ADO: adLongVarWChar ('a long null-terminated Unicode string value') 

ImportMixedTypes=Text会将ImportMixedTypes=Text缩减为255个字符,因为Memo被转换为Text 。 对于要识别为Memo的列,必须检测多数types,这意味着大多数检测到的行必须包含256个或更多字符。

但是,在决定混合和/或多数types之前,为每列扫描多less行? 还有第二个registry键, TypeGuessRows 。 这可以是0-16(十进制)的值。 从1到16的值是要扫描的行数。 值为零表示将扫描所有行。

有一个最后的转折。 连接string的扩展属性中IMEX=1设置确定是否ImportMixedTypes值。 IMEX指的是“IMport EXport模式”。 有三个可能的值。 IMEX=0IMEX=2导致ImportMixedTypes被忽略,并使用默认值“多数types”。 IMEX=1是确保ImportMixedTypes=Text的唯一方法。 生成的连接string可能如下所示:

 Provider=Microsoft.Jet.OLEDB.4.0; Data Source=C:\ db.xls; Extended Properties='Excel 8.0;HDR=Yes;IMEX=1' 

最后,虽然在MSDN文章中MAXSCANROWS可以在连接string的扩展属性中使用MAXSCANROWS来覆盖TypeGuessRowsregistry项,但这似乎是一个谬误。 以这种方式使用MAXSCANROWS=0在任何情况下都不会做任何事情。 换句话说,与将ONEDAYWHEN=0放在扩展属性中的效果相同,不存在(甚至不是错误!)同样适用于ImportMixedTypes即不能在连接string中使用来覆盖registry设置。

总之,使用TypeGuessRows来获取Jet来检测是否存在“混合types”的情况,或者使用它来“欺骗”Jet来检测某种数据types是多数types。 在检测到“混合types”的情况下,使用ImportMixedTypes来告诉Jet要么使用多数types,要么强制所有的值作为Text (最多255个字符)。

尝试将您的SQL语句的date部分更改为:

 "[...] originalAlarmTime BETWEEN '" & Format$(StartDate, "yyyy-mm-dd") & "' AND '" & Format$(EndDate, "yyyy-mm-dd") & "' [...]" 

您也可以尝试使用参数化查询 。