【问题标题】:Word VBA ADO connection to Excel file with cells containing more than 255 charactersWord VBA ADO 连接到包含超过 255 个字符的单元格的 Excel 文件
【发布时间】:2014-04-22 11:02:04
【问题描述】:

我目前使用以下 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 个字符的限制吗?

注意!我正在运行 Excel 2007。

【问题讨论】:

  • 您的意思是您的mySqlStatement 的长度超过255 个字符但.Execute() 方法只使用前255 个字符?
  • 这意味着在我的 Excel 文件中,我的单元格包含超过 255 个字符。但由于某种原因,只返回每个单元格的前 255 个字符。
  • 我不确定我是否有足够的信息来重现此问题...您正在执行的 SQL 语句是什么?您如何将数据从记录集中复制到工作表?你能提供你使用的数据样本吗?
  • 我添加了用于从 Excel 中提取的函数。基本上,Excel 文件包含一个名为“Firms”的工作表,其中包含名为 FirmDisplayName、FirmPrintName 和 FirmInfoA 的三列。

标签: vba ms-word


【解决方案1】:

从这里的测试中,我相信您遇到了here 中描述的(众所周知的)问题(虽然它谈到了 ODBC,但在 OLEDB 中的问题大致相同)。问题是 OLE 提供程序想要为工作表中的每一列分配特定的数据类型。然后它将列中没有该格式的任何单元格转换为指定的格式。

默认情况下,它使用每列的前 8 行来决定格式。对于仅包含字符串的列,如果列中的前 8 个单元格包含 或 >=255 的单元格。如果前 8 个单元格中有一个 >255,则提供程序不会截断任何行。

这个问题当然是它看起来完全是任意的 - 有一天你有一个工作表,其中一个单元格在前 8 行中有 255 个字符,并且一切正常。然后你修改那个数据,系统就会出错。

修改此行为实际上并非完全不重要。您可以将注册表中的“TypeGuessRows”值设置为更高,或者将其设置为 0,在这种情况下,理论上它将检查所有行。

但这会影响使用 Jet/ACE 提供程序从 Excel 获取数据的所有其他内容。将值设置为 0 可能意味着检查需要很长时间,据我所知,即使在行数最近的 Excel 版本中,检查也仅适用于前 16K(或者可能是 32K 或 64K)行理论上可以更高。

为避免修改其他所有内容的行为,您可以在注册表的私有区域中创建自己的一组 Jet/ACE 参数,并在连接字符串中指向该参数。

一个更简单的选择可能是接受您始终在数据的开头有一个虚拟行,其中需要它们的列中的文本长度超过 255 个字符。就个人而言,这可能是我会采取的路线。

否则,只要在您的情况下将 TypeGuessRows 设置为 0 是有意义的,并且您可以修改注册表,这可能是您的一个选项。例如,如果您将值放在这里(您可能还需要修改名为“ImportMixedTypes”的内容:

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

对于您有一个虚拟行的情况,只是为了确保将所有类型分配为该行中指定的类型。但我认为在大多数情况下,仅添加行就足够了。

【讨论】:

  • 感谢您非常详细的回答。但是在单元格 G2(第 2 行,第 7 列)中,我添加了长度超过 255 个字符的文本。但我仍然只得到前 255 个字符。在不更改注册表设置的情况下有什么想法吗?
  • (1) 更改值后必须保存 XL 文件 (2) 在您的测试系统的注册表中,TypeGuessRows 的值是否不存在或设置为 8? (3) 我已经在dropbox.com/s/vuyfc2ehwx18go3/firmdata.xlsx 临时放了一个小的 XL 测试文件 - 如果你运行你的代码并查找“firmi”,然后从 C7 中删除一个字符,保存并重试,你可能会看到我描述的问题.总是有可能存在进一步的问题!除了“在开头添加一行”、“自动 Excel”或“从 .docx 中的 XML 获取数据”之外,还需要 IMO 修改注册表。
  • 我尝试将 TypeGuessRows 更改为 0,但这没有帮助。
  • 嗯,这可能与我提到的问题不同。但是您尝试过我发布的测试文件吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-19
相关资源
最近更新 更多