我目前使用以下ADODB连接字符串从Excel工作簿中检索数据(oConnection已声明为新的ADODB.Connection,oRecordSet已声明为新的ADODB.RecordSet):
With oConnection
.Provider = "Microsoft.ACE.OLEDB.12.0"
.ConnectionString = "Data Source=C:\Myfile.xlsx;Mode=Read;Extended Properties=""Excel 12.0;HDR=Yes;"""
.Open
Set oRecordSet = .Execute(mySqlStatement)
End With
我将记录集添加到数组中,一切似乎都正常。但是,如果Excel工作表中的单元格包含超过255个字符,则文本将被截断/ 255以上的字符将被截断。
我用于连接Excel文件的整个功能如下:
Public Function RecordSet2Matrix(mSqlStatement As String) As Variant
Dim oSettingsFolder As String
Dim oSettingsFile As String
Dim oConnection As New ADODB.Connection
Dim oRecordSet As New ADODB.Recordset
Dim oRecordArray As Variant
Dim oTempArray As Variant
Dim x As Long
Dim y As Long
Dim xUpper As Long
Dim yUpper As Long
'Error handling
On Error GoTo errHandler
'Get location and settings file
oSettingsFolder = GetFolder(xFolderEnum.FolderOther)
oSettingsFile = xSettingsFile
oTempArray = Array()
'Check if settings file exists
If Len(Dir(oSettingsFolder & oSettingsFile)) = 0 Then
RecordSet2Matrix = oTempArray
Exit Function
End If
'Create connection to settings file
With oConnection
.Provider = "Microsoft.ACE.OLEDB.12.0"
.ConnectionString = "Data Source=" & oSettingsFolder & oSettingsFile & _
";Mode=Read;Extended Properties=""Excel 12.0;HDR=Yes;"""
.Open
Set oRecordSet = .Execute(mSqlStatement)
End With
'Read the settings file and add data to an array
If oRecordSet.EOF Then
oTempArray = Array()
Else
oRecordArray = oRecordSet.GetRows
xUpper = UBound(oRecordArray, 2)
yUpper = UBound(oRecordArray, 1)
'Resize array to fit all records
ReDim oTempArray(xUpper, yUpper)
For x = 0 To xUpper
For y = 0 To yUpper
oTempArray(x, y) = oRecordArray(y, x)
Next y
Next x
End If
'Close connection to file
If CBool(oRecordSet.State And adStateOpen) Then
oRecordSet.Close
End If
'Return record set
RecordSet2Matrix = oTempArray
errHandler:
If Err.Number <> 0 Then
ShowErrorMessage Err.Number, Err.Description, "modADO.RecordSet2Matrix"
Set oRecordSet = Nothing
RecordSet2Matrix = oTempArray
End If
cleanUp:
Set oRecordSet = Nothing
Set oTempArray = Nothing
End Function
然后我运行实际的SELECT语句来从Excel获取数据:
Public Function GetFirmDetails(mFirmName As String) As xIniDataRecord
Dim oSqlStatement As String
Dim oDataArray As Variant
Dim oReturnRec As xIniDataRecord
'Error handling
On Error GoTo errHandler
'SQL query for retrieving office details
oSqlStatement = "SELECT [FirmDisplayName], [FirmPrintName], [FirmInfoA]" & _
"FROM [Firms$] " & _
"WHERE [FirmDisplayName] = '" & mFirmName & "';"
'Return query to array
oDataArray = RecordSet2Matrix(oSqlStatement)
'Exit function if array is empty
If UBound(oDataArray) < 0 Then
GetFirmDetails = oReturnRec
Exit Function
End If
'Return array data to return record
With oReturnRec
.FirmDisplayName = oDataArray(0, 0)
.FirmName = oDataArray(0, 1)
.FirmInfoA = oDataArray(0, 2)
End With
'Return data record
GetFirmDetails = oReturnRec
errHandler:
If Err.Number <> 0 Then
ShowErrorMessage Err.Number, Err.Description, "modADO.GetFirmDetails"
GetFirmDetails = oReturnRec
End If
cleanUp:
Set oDataArray = Nothing
End Function
我一直在研究与我类似的其他问题,但并没有真正找到解决方案。
有人知道如何避免255个字符的限制吗?
NB!我正在运行Excel 2007。
答案 0 :(得分:2)
从这里的测试中,我相信你遇到了here所描述的(众所周知的)问题(虽然它谈到了ODBC,但OLEDB中的问题却大致相同)。问题是OLE提供程序想要为工作表中的每个列分配特定的数据类型。然后,它将列中没有该格式的任何单元格转换为指定的格式。
默认情况下,它使用每列的前8行来确定格式。对于仅包含字符串的列,如果列中的前8个单元格包含&lt; 255(或&lt; = 255,无法记住)字符的字符串,则提供程序将使用&gt;截断任何单元格。或&gt; = 255。如果前8个单元中的一个单元格> 255,则提供程序不会截断任何行。
这个问题当然是它看起来完全是任意的 - 有一天你有一个工作表,前8行有一个255个字符的单元格,一切正常。然后修改该数据,系统出错。
修改此行为实际上并非完全不重要。你可以设置&#34; TypeGuessRows&#34;注册表中的值要更高,或将其设置为0,在这种情况下理论上它将检查所有行。
但这会影响使用Jet / ACE提供程序从Excel获取数据的所有其他内容。将值设置为0可能意味着检查需要很长时间,并且据我所知,检查仅应用于前16K(或可能是32K或64K)行,即使在最近版本的Excel中行数也是如此理论上可以更高。
为避免修改其他所有内容的行为,您可以在注册表的私有区域中创建自己的一组Jet / ACE参数,并指向连接字符串中的那些参数。
更简单的替代方法可能是接受在数据开头总是有一个虚拟行,在需要它们的列中长度超过255个字符。就个人而言,这可能就是我要采取的路线。
否则,只要在您的情况下将TypeGuessRows设置为0并且允许您修改注册表是有意义的,那么这可能是您的选择。例如,如果你把值放在这里(你可能还需要修改一些名为&#34; ImportMixedTypes&#34;:
HKEY_LOCAL_MACHINE\SOFTWARE\sample\v1.0\Engines\Excel\TypeGuessRows
HKEY_LOCAL_MACHINE\SOFTWARE\sample\v1.0\Engines\Excel\ImportMixedTypes
然后你需要在你的连接字符串中使用它:
Jet OLE DB:Registry Path="SOFTWARE\sample\v1.0"
您可以导入的一组合适的注册表项如下所示:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\sample]
[HKEY_LOCAL_MACHINE\SOFTWARE\sample\v1.0]
[HKEY_LOCAL_MACHINE\SOFTWARE\sample\v1.0\Engines]
[HKEY_LOCAL_MACHINE\SOFTWARE\sample\v1.0\Engines\Excel]
"ImportMixedTypes"="Text"
"TypeGuessRows"=dword:00000000
您可以使用该方法,但设置
"TypeGuessRows"=dword:00000001
对于您有一个虚拟行的情况,只是为了确保将所有类型分配为该行中指定的类型。但我认为在大多数情况下仅添加行可能就足够了。