【问题标题】:ADO returns wrong order of magnitudeADO 返回错误的数量级
【发布时间】:2019-04-16 22:42:17
【问题描述】:

我正在为 Excel 2003 编写 VBA 宏。我正在将各种数据从 sql 数据库导入 Excel 工作表。

我尝试了两种方法:

  1. QueryTables.Add(...)
  2. 使用 ADO

我赞成 ADO,因为它似乎是“更好”或“更清洁”的解决方案。

在我尝试使用 ADO 从数据库中获取数值之前,一切都运行良好。它没有返回值1842,47078,而是返回了0,01842。 (只是为了说明我的意思)

奇怪的是:当我尝试使用 QueryTables.Add(...) 时,我得到了正确的值。

我完全不知道为什么会发生这种情况,在互联网上搜索了解决方案,但没有找到任何东西。它只发生在数值上。如果我从数据库中得到一个字符串,一切都很好。

谁能帮我解决这个问题?

Driver 是与 ODBC 连接的 Firebird/InterBase(r) 驱动程序。 这是我如何做事的一个小例子:

    'ADO solution = wrong value
    With adoConnection
      .Provider = "MSDASQL"
      sConnection = "ODBC;DSN=ABC;Driver=Firebird/InterBase(r) driver;Dbname=blaName.gdb;"
      ConnectionString = sConnection
      .Open
    End With
    SQL_Import = "SELECT A.PRICE AS ""Price"" FROM TABLE A WHERE A.KEY ='x1234' "
    adoRecordset.ActiveConnection = adoConnection
    adoRecordset.Open SQL_Import
    varSol = adoRecordset.Fields("Price")
    Sheets(3).Cells(1, 1).Value = varSol
    adoRecordset.Close
    adoRecordset.ActiveConnection = Nothing
    adoConnection.Close
    'QueryTables solution = right value
    Set QueryTbl = Sheets(3).QueryTables.Add(Connection:=sConnection, Destination:=Sheets(3).Cells(1, 2))
    With QueryTbl
        .CommandText = SQL_Import
        .AdjustColumnWidth = True
        .Refresh BackgroundQuery:=False
        .Delete
    End With

希望有人能帮助我。

更新:

  • 我得到了它的工作,但我不知道出了什么问题。
  • 如果我使用查询 SELECT Price as numeric(15, 2)...,我会得到正确的结果。
  • 奇怪的是,我在我的计算机上使用 C# 尝试了整个过程,并且没有任何问题。因此,该错误似乎是由 Excel 和/或 VBA 中的任何内容引起的。

【问题讨论】:

  • 我会在记录集返回后中断并测试是否将正确的值返回到记录集中,如果不是,则连接的设置方式可能有问题。如果值在记录集中显示正确,则可能是从记录集中传递数据时出错。我不熟悉 firebird 连接,所以我帮不上什么忙。
  • 在您的第一个 With...End With 块中,您缺少 ConnectionString 上的点,因此很可能您实际上并未设置该属性。不知道这是否与您所看到的有关。
  • 实际代码中是.ConnectionString。当我写这个例子时,只是做错了。我停止了宏并检查了记录集。返回记录集时该值已经错误。因此,连接似乎确实存在问题。也许是提供者?
  • 正如前缀所暗示的那样,varSolVariant 吗?如果你写varSol = CStr(adoRecordset.Fields("Price"))然后检查varSol的值有什么不同吗?
  • 是的,它是一个变体,但使用您的代码会得到与上面相同的结果。无论如何,谢谢。

标签: vba ado firebird


【解决方案1】:

尝试将 NumberFormat 应用于单元格

varSol = adoRecordset.Fields("Price") 
Sheets(3).Cells(1, 1).NumberFormat = "###0,#######0" 
Sheets(3).Cells(1, 1).Value = varSol 

【讨论】:

    【解决方案2】:

    我对 firebird 一无所知,但听起来有问题的列是货币或货币类型(ADO 称之为 adCurrency),而您还没有告诉 ADO,所以它没有适当地转换它。

    看看 adoRecordset.Fields("Price").Type 我敢打赌你会看到它是 adCurrency 之类的。

    【讨论】:

    • adoRecordset.Fields("Price").Type 是 'adNumeric'。
    【解决方案3】:

    我真的不知道什么问题是/曾经是什么,但我有一个解决方案。 如果我将我的 SQL 字符串更改为

    SQL_Import = "SELECT A.PRICE*1  FROM TABLE A WHERE A.KEY ='x1234' "
    

    一切都按预期进行,我得到了正确的结果。

    所以我的解决方案是乘以一或加零。

    【讨论】:

    • 您正在通过算术运算导致隐式类型转换——A.PRICE 被 CAST 为可以与 *1+0 组合的类型。和SELECT Price as numeric(15, 2)...的效果很像
    猜你喜欢
    • 1970-01-01
    • 2011-10-13
    • 2014-08-21
    • 2019-04-21
    • 2017-12-08
    • 2017-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多