Excel 2010与2016+ VBA兼容性问题:GetDates函数类型不匹配报错
问题原因分析
在Excel 2016中触发类型不匹配错误,核心原因是ADODB.Recordset的RecordCount属性在不同Excel版本(对应不同ADO驱动版本)中的返回行为存在差异:
- Excel 2010使用的旧版ADO驱动中,RecordCount稳定返回整数类型的记录数;
- Excel 2016对应的新版ADO驱动中,RecordCount可能返回Variant类型,或在游标类型不兼容时返回-1,导致
ReDim lstDates(rs.RecordCount - 1)执行时出现类型不匹配。
另外,若GetResultSet函数默认使用向前游标(adOpenForwardOnly),RecordCount会返回-1(无法获取准确记录数),同样会触发异常。
解决方案
提供三种兼容Excel 2010和2016的修复方案,按推荐优先级排序:
方案1:显式转换RecordCount为数值类型
将ReDim行的RecordCount强制转换为Long类型,直接规避类型不匹配问题:
If (rs.RecordCount > 0) Then ReDim lstDates(CLng(rs.RecordCount) - 1) ' 强制转换为Long类型 Do While (Not rs.EOF) lstDates(rs.AbsolutePosition - 1) = CDate(rs.Fields(0)) rs.MoveNext Loop End If
方案2:改用循环计数确定数组大小(彻底脱离RecordCount依赖)
不依赖RecordCount,通过遍历Recordset统计记录数,兼容性最强:
Private Function GetDates() As Variant Dim strSQL As String Dim rs As New ADODB.Recordset Dim lstDates() As Date Dim recordCount As Long Dim i As Long strSQL = " SELECT DISTINCT(DATE) " & _ " FROM [" & EXTRACTED_FILENAME & "$] " Call GetResultSet(rs, cn, strSQL) ' 先遍历统计记录总数 recordCount = 0 Do While Not rs.EOF recordCount = recordCount + 1 rs.MoveNext Loop rs.MoveFirst ' 回到记录集开头 If recordCount > 0 Then ReDim lstDates(recordCount - 1) i = 0 Do While Not rs.EOF lstDates(i) = CDate(rs.Fields(0)) rs.MoveNext i = i + 1 Loop End If GetDates = lstDates End Function
方案3:修改Recordset游标类型确保RecordCount可用
检查GetResultSet函数中打开Recordset的代码,使用支持RecordCount的游标类型(如静态游标adOpenStatic):
' 在GetResultSet函数内修改rs.Open的参数 rs.Open strSQL, cn, adOpenStatic, adLockReadOnly
注:需确保VBA编辑器中已引用ADO库(路径:工具→引用→勾选"Microsoft ActiveX Data Objects x.x Library")。
内容的提问来源于stack exchange,提问作者VBA Beginner
相关产品推荐
相关产品推荐

