ADO возвращает неправильный порядок величины

Я пишу макрос VBA для Excel 2003. Я импортирую различные данные из базы данных sql в листы Excel.

Я попробовал два способа сделать это:

  1. QueryTables.Add(...)
  2. с АДО

Я был за ADO, потому что это казалось «лучшим» или «более чистым» решением.

Все работало хорошо, пока я не попытался получить числовое значение с помощью ADO из базы данных. Вместо возврата значения 1842,47078 он вернул 0,01842. (просто чтобы показать, что я имею в виду)

Странно: когда я пробую это с QueryTables.Add(...), я получаю правильное значение.

Я совершенно не знаю, почему это происходит, искал в Интернете решение, но ничего не нашел. Это просто происходит с числовыми значениями. Если я получаю строку из базы данных, все в порядке.

Может ли кто-нибудь помочь мне с этим?

Драйвер — это драйвер Firebird/InterBase(r), подключающийся к ODBC. Вот небольшой пример того, как я делаю вещи:

    '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.

person MiVoth    schedule 19.10.2011    source источник
comment
Я бы сделал перерыв после возврата набора записей и проверил, возвращено ли правильное значение в набор записей, если нет, может быть что-то не так с настройкой соединения. Если значение отображается правильно в наборе записей, это может быть ошибкой при передаче данных из набора записей. Я не знаком с подключениями к firebird, так что тут я не сильно помогу.   -  person Fink    schedule 19.10.2011
comment
В вашем первом блоке With...End With вам не хватает точки в ConnectionString, поэтому, скорее всего, вы на самом деле не устанавливаете это свойство. Не знаю, имеет ли это отношение к тому, что вы видите.   -  person Tim Williams    schedule 19.10.2011
comment
Это .ConnectionString в реальном коде. Просто сделал это неправильно, когда я написал этот пример. И я остановил макрос и проверил набор записей. Значение уже неверно, когда оно возвращается в набор записей. Так что это действительно похоже на проблему со связью. Может Провайдер?   -  person MiVoth    schedule 21.10.2011
comment
Является ли varSol Variant, как следует из префикса? Будет ли иначе, если вы напишете varSol = CStr(adoRecordset.Fields("Price")), а затем проверите значение varSol?   -  person barrowc    schedule 23.10.2011
comment
Да, это вариант, но использование вашего кода дает тот же результат, что и выше. В любом случае спасибо.   -  person MiVoth    schedule 26.10.2011


Ответы (3)


Попробуйте применить числовой формат к ячейке

varSol = adoRecordset.Fields("Price") 
Sheets(3).Cells(1, 1).NumberFormat = "###0,#######0" 
Sheets(3).Cells(1, 1).Value = varSol 
person Michael Riley - AKA Gunny    schedule 30.10.2011

Я ничего не знаю о firebird, но похоже, что рассматриваемый столбец имеет тип Money или Currency (то, что ADO называет adCurrency), и вы не сказали об этом ADO, поэтому он не конвертирует его соответствующим образом.

Посмотрите на adoRecordset.Fields("Price").Type, и держу пари, вы увидите, что это adCurrency или что-то подобное.

person Joel Spolsky    schedule 28.10.2011
comment
adoRecordset.Fields(Price).Type — это «adNumeric». - person MiVoth; 04.11.2011

Я не знаю, в чем проблема/была проблема, но у меня есть решение. Если я изменю свою строку SQL на

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

все работает так, как ожидалось, и я получаю правильный результат.

Итак, мое решение умножается на единицу или добавляет ноль.

person MiVoth    schedule 06.06.2013
comment
Вы вызываете неявное преобразование типа с помощью арифметической операции — A.PRICE преобразуется в CAST как тип, который можно комбинировать с *1 или +0. Очень похоже на эффект SELECT Price as numeric(15, 2)... - person TallTed; 16.04.2019