у меня есть MS Access 2007
База данных с таблицей, которая имеет string
поле и numerical
один. numerical
поле имеет тип double
и может быть отрицательным или положительным.
я использую ADO
подключиться к базе данных и загрузить ее данные в edit
контролирует с SetDialogItemText
API-edit
элементы управления находятся в dialog box
,
Пользователь может редактировать значения существующих данных (при сохранении изменений я получаю данные из edit
контролирует с GetDialogItemText
API).
Все отлично работает в моей программе если у пользователя английский или американский язык, но если пользователь выбирает европейский язык, то мой ADO
string
неверно и сообщает об ошибке.
Это ожидается, так как в английской версии он имеет 2 параметра:string
и double
но так как европейцы использовать запятую в качестве десятичной точки (например США 123.456
является 123,456
) ADO
интерпретирует это как наличие 3 параметра вместо двух — например:
INSERT INTO table VALUES ( 'some string', 12.5 );
—> США локаль
INSERT INTO table VALUES ( 'some string', 12,5 );
—> ОШИБКА! 3 параметра вместо 2
Чтобы объяснить более подробно:
Допустим, мы загрузили данные из базы данных в элементы управления редактирования, используя Европейская локали:
Первый держит string
( Some string
) и второе десятичное число ( 123,456
).
Допустим, пользователь изменяет string
значение в Some other string
и нажимает Сохранить кнопка.
Теперь мой код получает значения от edit
контролирует, но ошибка должна произойти, так как я получил 123,456
из второго элемента редактирования ( помните, пользователь оставил десятичные данные без изменений ), и мой ADO string
неправильно настроен, так как теперь это выглядит так:
INSERT INTO table VALUES ( 'Some other string', 123,456 );
-> ОШИБКА! 3 параметра
Если пользователь установил европейскую локаль, есть ли способ загрузить десятичный значения из MS Access 2007
база данных в редактировании управления с запятой изменено в точку?
Или, может быть, я могу как-то subclass edit control
изменить запятую на точку?
Пользовательский ввод может быть ограничен точкой и буквами sublclassing
edit
контроль, так что это не проблема. Я просто хочу правильно загрузить данные из базы данных, поэтому мой ADO string
может быть выполнен без ошибок, если пользователь решит не редактировать десятичные данные как в примере, который я описал выше.
Спасибо.
С наилучшими пожеланиями.
Здесь есть две проблемы. Я проиллюстрирую, используя две локали:
Английский (Канада) — EN-CA: который использует .
в качестве десятичного разделителя
Французский (Канада) — FR-CA: который использует ,
в качестве десятичного разделителя
и крошечные кусочки кода VBScript (так как у меня нет C ++).
VBScript
x = 3/2
WScript.Echo x
дисплеи 1.5
когда языковой стандарт Windows EN-CA, и он отображает 1,5
когда языковой стандарт Windows — FR-CA Этот текст — то, что вы видите в окне редактирования.
Скажем, пользователь оставляет строку без изменений. Вместо того, чтобы пытаться использовать строковое представление десятичного числа вам нужно использовать метод локализации с преобразованием строки обратно в фактическое десятичное число:
Для EN-CA:
x = CDbl("1.5") + 1
WScript.Echo x
дисплеи 2.5
указывает, что строка «1.5» была успешно преобразована в Double
перед добавлением 1.
Для FR-CA:
x = CDbl("1,5") + 1
WScript.Echo x
дисплеи 2,5
указывает, что строка «1,5» была успешно преобразована в Double
перед добавлением 1.
Сводка: когда вы получаете текстовое представление числа от пользователя, вам необходимо преобразовать (т.е. проанализировать) эту строку в фактический числовой тип данных, и механизм синтаксического анализа должен учитывать региональные параметры.
Проблема здесь в том, что Access SQL не поддерживает локали; он только «говорит» на английском. Так что если вы попытаетесь «склеить» команду SQL под FR-CA
x = 3/2
sql = "INSERT INTO Table1 (DoubleField) VALUES (" & x & ")"WScript.Echo sql
ты получаешь INSERT INTO Table1 (DoubleField) VALUES (1,5)
и это терпит неудачу, как вы обнаружили.
Решение здесь состоит в том, чтобы НЕ «склеивать» команды SQL (что в любом случае является плохой вещью из-за уязвимостей SQL-инъекций и других неприятностей). Вместо этого используйте параметризованный запрос:
Option Explicit
Dim con ' ADODB.Connection
Dim cmd ' ADODB.Command
Dim prm ' ADODB.Parameter
Dim x
Const adDouble = 5
Const adParamInput = 1
' test data:
' the following statement is valid when
' the Windows locale uses "," as the decimal separator
x = CDbl("1,5")
Set con = CreateObject("ADODB.Connection")
con.Open _
"Driver={Microsoft Access Driver (*.mdb, *.accdb)};" & _
"Dbq=C:\__tmp\main.accdb;"Set cmd = CreateObject("ADODB.Command")
cmd.ActiveConnection = con
cmd.CommandText = "INSERT INTO Table1 (DoubleField) VALUES (?)"Set prm = cmd.CreateParameter("?", adDouble, adParamInput, , x)
cmd.Parameters.Append prm
cmd.Execute
Set prm = Nothing
Set cmd = Nothing
con.Close
Set con = Nothing
Других решений пока нет …