#sql #excel #ms-access-2007 #vba
#sql #excel #ms-access-2007 #vba
Вопрос:
Один из аспектов моего проекта заключается в сравнении номера детали, введенного оператором, с заранее определенным списком номеров деталей в столбце базы данных. Прямо сейчас моя программа сообщает мне, что каждый номер детали, введенный в электронную таблицу (50 ), не соответствует ни одному из них в базе данных, что, как я проверил, неверно. Я проверил, что и номер элемента электронной таблицы, и номер элемента базы данных имеют строковый тип данных. Я дважды проверил, что моя логика цикла хороша, и мне кажется, что она должна работать. Насколько мне известно, ни в ячейках базы данных, ни в ячейках электронной таблицы нет скрытых символов. На данный момент я совершенно не понимаю, почему моя программа не обнаруживает совпадений между электронной таблицей и базой данных. Ниже приведен подраздел, содержащий код для проверки соответствия номеров деталей:
Sub CheckPN()
'Connect to the E2 database
Call SetPNConnection
'Open a recordset
Set PNRecordset = New ADODB.Recordset
PNRecordset.Open "EstimRpt", PNConnection, adOpenKeyset, adLockOptimistic, adCmdTable
PNSQLCmd = "SELECT DISTINCT [PartNo] FROM EstimRpt;"
'Loop through data, comparing part numbers to E2 database part number records
TotalBadPNCount = 0
With PNRecordset
For DataRowCount = 2 To TrackingLastRow
PNCount = 0
Part_Number = Tracking.Sheets("Operator Data").Range("A" amp; DataRowCount).Value
'MsgBox "The datatype for " amp; Part_Number amp; " is " amp; VarType(Part_Number) amp; "."
Do Until .EOF
'MsgBox "The datatype for " amp; .Fields("PartNo").Value amp; " is " amp; VarType(.Fields("PartNo").Value) amp; "."
If Part_Number = .Fields("PartNo").Value Then
'If .Fields("PartNo").Value = Part_Number Then
MsgBox Part_Number amp; " is a match."
PNCount = PNCount 1
End If
.MoveNext
Loop
If PNCount < 1 Then
MsgBox "The P/N " amp; Part_Number amp; " entered in cell A" amp; DataRowCount amp; " is incorrect. Please correctly enter the P/N and re-run the program."
TotalBadPNCount = TotalBadPNCount 1
End If
Next DataRowCount
If TotalBadPNCount >= 1 Then
Exit Sub
End If
End With
PNRecordset.Close
Set PNRecordset = Nothing
PNConnection.Close
Set PNConnection = Nothing
End Sub
Кроме того, я бы хотел, чтобы вся программа прекратила выполнение, если номер детали не совпадает, а не только непосредственный подраздел. В настоящее время только этот подраздел завершается, если номер детали не совпадает.
Спасибо за помощь по обоим этим вопросам.
Иордания
Ответ №1:
Я бы предложил не использовать цикл для сравнения записей из вашего пользовательского набора данных с вашей постоянной таблицей. Вместо этого загрузите отправленный пользователем набор данных во временную таблицу в вашей БД и используйте SQL для сравнения 2 таблиц.
Вы можете попробовать что-то в этом роде:
'Load spreadsheet into temp table
<your code here>
'open recordset in order to compare PartNos
Dim db As Database
Set db = CurrentDb
Dim rs As Recordset
sSQL = "select count(*) as [count] from temp " _
amp; " where temp.PartNo not in (select distinct EstimRpt.PartNo from EstimRpt)"
Set rs = db.OpenRecordset(sSQL)
ctRecords = rs![Count]
'if records are found in temp table that do not exist
'in the perm table, then end execution of everything.
if ctRecords > 0 then
End
else
'run the rest of your code
<your code here>
end if
'Drop temp table
<your code here>
Комментарии:
1. Есть ли особая причина, по которой сравнение записей в моем пользовательском наборе данных Excel с моей таблицей постоянного доступа не будет работать? Альтернатива этому маршруту кажется довольно громоздкой, условно говоря. Если записи Access и Excel имеют тип string, почему не совпадают те, которые должны совпадать? Есть ли какая-то «скрытая» разница между двумя записями? Спасибо за вашу помощь.
2. Я не могу сказать, почему ваше текущее сравнение не работает, не имея доступа к вашим файлам. Если между версиями Excel / Access существуют какие-либо проблемы с совместимостью, извлечение данных Excel в Access перед запуском сравнения выявит эти проблемы (проверьте типы данных столбцов Excel после их импорта в Access). Как только данные доступны, вы можете запустить сравнение на основе наборов без использования RBAR , что значительно повышает производительность при работе с большими наборами данных.
3. База данных, из которой я читаю, — это та, в которой мне обязательно не изменять / изменять / модифицировать каким-либо образом (это большая база данных, используемая для программы управления магазином).). Поэтому я хочу только считывать данные из него, а не что-либо еще. Итак, исключив это, я снова убедился, что оба значения являются строками, и, согласно окнам сообщений в моей программе Excel, моя программа Excel считывает / интерпретирует значения базы данных точно так, как они записаны в Excel. Похоже, это указывает на то, что мои данные хороши, но мой цикл имеет недостатки, но для меня он выглядит хорошо. Предложения Ant?
4. Хорошо — удачи! Я ничего не могу предложить, потому что я не вижу, что на самом деле происходит «под капотом» в ваших файлах Excel и Access. Если вы не хотите создавать какие-либо новые объекты в существующей базе данных Access, вы можете создать отдельную базу данных, которая извлекает данные из «основной» и выполняет сравнение там.
Ответ №2:
Наконец-то я нашел свою проблему. Сравнение записей между базой данных и электронной таблицей теперь работает. Мне пришлось внести следующие изменения в свой код:
Вместо:
Do Until .EOF
Мне нужно:
Do Until .EOF = True
Мне также нужно было добавить следующее сразу после объявления цикла For:
.MoveFirst
Теперь мой код повторяется правильно.