Всем добрый день. Коллеги, прошу помочь с решением проблемы. Имею таблицу акцесс по продажам и время от времени приходится в ней править отдельные наименования. Когда нужно исправить 1-2 наименования - это не проблема ручками, а когда нужно исправить 70 наименований в базе весом 1-2гига то понял, что без какого нибудь sql запроса никак. Простыми словами нужен ВПР для акцесс))) Есть столбец с наименованием зафиксированной базы и есть таблица с которой нужно выдернуть по коду имена. В аттаче мини файл с двумя таблицам для поля действия. Заранее благодарен за помощь.
Всем добрый день. Коллеги, прошу помочь с решением проблемы. Имею таблицу акцесс по продажам и время от времени приходится в ней править отдельные наименования. Когда нужно исправить 1-2 наименования - это не проблема ручками, а когда нужно исправить 70 наименований в базе весом 1-2гига то понял, что без какого нибудь sql запроса никак. Простыми словами нужен ВПР для акцесс))) Есть столбец с наименованием зафиксированной базы и есть таблица с которой нужно выдернуть по коду имена. В аттаче мини файл с двумя таблицам для поля действия. Заранее благодарен за помощь.DJ_Marker_MC
Если таблица, в которой надо заменить значения ("база") не очень большая (несколько сотен или тысяч записей), то можно одним запросом обновления: [vba]
Код
UPDATE база INNER JOIN подставить ON база.кодТ = подставить.кодТ AND база.Код = подставить.Код SET база.имя = подставить.имя
[/vba] Этот текст нужно ввести в запрос в конструкторе.
Если же таблица "база" имеет размер 2 гига, то такой подход чреват долгим выполнением и большим отжором памяти запросом под свои нужды. В этом случае лучше писать цикл обновления по одной записи, используя DAO или ADO.
Если таблица, в которой надо заменить значения ("база") не очень большая (несколько сотен или тысяч записей), то можно одним запросом обновления: [vba]
Код
UPDATE база INNER JOIN подставить ON база.кодТ = подставить.кодТ AND база.Код = подставить.Код SET база.имя = подставить.имя
[/vba] Этот текст нужно ввести в запрос в конструкторе.
Если же таблица "база" имеет размер 2 гига, то такой подход чреват долгим выполнением и большим отжором памяти запросом под свои нужды. В этом случае лучше писать цикл обновления по одной записи, используя DAO или ADO.Gustav
Сережа, по ссылке что то не совсем то, формы используются и вопрос как я понял именно к формам. Лена, кажется именно то что нужно, пошел тестить на большом файле)))
Сережа, по ссылке что то не совсем то, формы используются и вопрос как я понял именно к формам. Лена, кажется именно то что нужно, пошел тестить на большом файле)))DJ_Marker_MC
Как вариант для тренировки. Запрос (Запрос1) на создание таблицы. Таблица "Obnova" строится при совпадении первых двух полей обеих таблиц - добавляются данные третьего поля. По образу и подобию можно построить запрос на обновление.
Как вариант для тренировки. Запрос (Запрос1) на создание таблицы. Таблица "Obnova" строится при совпадении первых двух полей обеих таблиц - добавляются данные третьего поля. По образу и подобию можно построить запрос на обновление.TimSha
мало того что я практически не знаком с SQL-запросами, вы мне решили контрольный в голову?
Ничего страшного! Цикл выглядит гораздо проще, чем можно было бы предположить: [vba]
Код
Sub upd() Dim rst As DAO.Recordset Set rst = CurrentDb.OpenRecordset("база") Do While Not rst.EOF rst.Edit rst("имя") = DLookup("имя", "подставить", "[код] = " & rst("код") & " And [кодТ] = " & rst("кодТ")) rst.Update rst.MoveNext Loop End Sub
мало того что я практически не знаком с SQL-запросами, вы мне решили контрольный в голову?
Ничего страшного! Цикл выглядит гораздо проще, чем можно было бы предположить: [vba]
Код
Sub upd() Dim rst As DAO.Recordset Set rst = CurrentDb.OpenRecordset("база") Do While Not rst.EOF rst.Edit rst("имя") = DLookup("имя", "подставить", "[код] = " & rst("код") & " And [кодТ] = " & rst("кодТ")) rst.Update rst.MoveNext Loop End Sub
Gustav, это ж его в модуль (макрос?). Если да, то на маленьком примере все отлично сработало. Сейчас запустил на большой таблице 1.8 млн, пошла уже десятая минута как обрабатывает Кстати, а если в таблице подставить не будет какого то кода что есть в базе, оно пропустит и оставит то что есть?
up: похоже что нет((( те которых нет в таблице подстановки просто пусто стало
[offtop]блин, какой он замороченный этот акцес[/offtop]
Gustav, это ж его в модуль (макрос?). Если да, то на маленьком примере все отлично сработало. Сейчас запустил на большой таблице 1.8 млн, пошла уже десятая минута как обрабатывает Кстати, а если в таблице подставить не будет какого то кода что есть в базе, оно пропустит и оставит то что есть?
up: похоже что нет((( те которых нет в таблице подстановки просто пусто стало
[offtop]блин, какой он замороченный этот акцес[/offtop]DJ_Marker_MC
Gustav, поскольку это макрос то, проверку условия добавить смог)))
[vba]
Код
Sub upd() Dim rst As DAO.Recordset Set rst = CurrentDb.OpenRecordset("база") Do While Not rst.EOF rst.Edit rst("имя") = DLookup("имя", "подставить", "[кодТ] = " & rst("кодТ")) If rst("имя") <> "" Then rst.Update rst.MoveNext End If Loop End Sub
[/vba]
Gustav, поскольку это макрос то, проверку условия добавить смог)))
[vba]
Код
Sub upd() Dim rst As DAO.Recordset Set rst = CurrentDb.OpenRecordset("база") Do While Not rst.EOF rst.Edit rst("имя") = DLookup("имя", "подставить", "[кодТ] = " & rst("кодТ")) If rst("имя") <> "" Then rst.Update rst.MoveNext End If Loop End Sub
а если в таблице подставить не будет какого то кода что есть в базе, оно пропустит и оставит то что есть?
В этом случае, если не позаботиться If'ами, DLookup вернет пустое значение и, соответственно, оно же и пропишется, что и получилось. Точнее, DLookup вернет значение Null и чтобы преобразовать его к пустой строке, надо будет обернуть вызов функцией Nz: = Nz(DLookup(...))
Теперь про проверку. Если rst.Edit отработал, то хорошая практика состоит в том, чтобы rst.Update тоже отработал. Ну и конечно rst.MoveNext должен всегда отрабатывать, иначе можно зависнуть на очередной записи и никогда не дойти до конца таблицы. Надо просто результат DLookup брать в промежуточную переменную и уже ее анализировать и присваивать или не присваивать rst("имя").
[vba]
Код
Sub upd() Dim rst As DAO.Recordset Dim tmp as String
Set rst = CurrentDb.OpenRecordset("база") Do While Not rst.EOF tmp = Nz(DLookup("имя", "подставить", "[кодТ] = " & rst("кодТ"))) If tmp <> "" Then rst.Edit rst("имя") = tmp rst.Update End If rst.MoveNext Loop End Sub
а если в таблице подставить не будет какого то кода что есть в базе, оно пропустит и оставит то что есть?
В этом случае, если не позаботиться If'ами, DLookup вернет пустое значение и, соответственно, оно же и пропишется, что и получилось. Точнее, DLookup вернет значение Null и чтобы преобразовать его к пустой строке, надо будет обернуть вызов функцией Nz: = Nz(DLookup(...))
Теперь про проверку. Если rst.Edit отработал, то хорошая практика состоит в том, чтобы rst.Update тоже отработал. Ну и конечно rst.MoveNext должен всегда отрабатывать, иначе можно зависнуть на очередной записи и никогда не дойти до конца таблицы. Надо просто результат DLookup брать в промежуточную переменную и уже ее анализировать и присваивать или не присваивать rst("имя").
[vba]
Код
Sub upd() Dim rst As DAO.Recordset Dim tmp as String
Set rst = CurrentDb.OpenRecordset("база") Do While Not rst.EOF tmp = Nz(DLookup("имя", "подставить", "[кодТ] = " & rst("кодТ"))) If tmp <> "" Then rst.Edit rst("имя") = tmp rst.Update End If rst.MoveNext Loop End Sub
Gustav, я правильно понял Вашу корректировку? [vba]
Код
Sub upd() Dim rst As DAO.Recordset Set rst = CurrentDb.OpenRecordset("база") Do While Not rst.EOF rst.Edit NewName = DLookup("имя", "подставить", "[кодТ] = " & rst("кодТ")) If NewName <> "" Then rst("имя") = NewName End If rst.Update rst.MoveNext Loop End Sub
[/vba]
up: пока писал, вы успели добавить и код.
Gustav, я правильно понял Вашу корректировку? [vba]
Код
Sub upd() Dim rst As DAO.Recordset Set rst = CurrentDb.OpenRecordset("база") Do While Not rst.EOF rst.Edit NewName = DLookup("имя", "подставить", "[кодТ] = " & rst("кодТ")) If NewName <> "" Then rst("имя") = NewName End If rst.Update rst.MoveNext Loop End Sub
[/vba]
up: пока писал, вы успели добавить и код.DJ_Marker_MC
Почти. См. выше также я там добавил важное замечание про Nz. И если не собираемся обновлять запись, то и Edit/Update лишний раз делать не надо, поэтому их надо внутрь If
Почти. См. выше также я там добавил важное замечание про Nz. И если не собираемся обновлять запись, то и Edit/Update лишний раз делать не надо, поэтому их надо внутрь IfGustav
Gustav, уже заметил и понял что так будет быстрее, поскольку лишний раз не будет отрабатывать Edit/Update Но не совсем понял с Nz, у меня и без Nz смотрю проходит проверку отсутствующие строки тоесть когда [vba]
[/vba] показывает NULL, то NewName <> "" ровняется как и положено Ложь, а значит что NULL все же равен "" или я не правильно понял роль Nz она все же необходима?
Gustav, уже заметил и понял что так будет быстрее, поскольку лишний раз не будет отрабатывать Edit/Update Но не совсем понял с Nz, у меня и без Nz смотрю проходит проверку отсутствующие строки тоесть когда [vba]
[/vba] показывает NULL, то NewName <> "" ровняется как и положено Ложь, а значит что NULL все же равен "" или я не правильно понял роль Nz она все же необходима?DJ_Marker_MC
то NewName <> "" ровняется как и положено Ложь, а значит что NULL все же равен ""
Не совсем. Результатом выражений Null <> "" или Null = "" будет не Ложь, а Null в обоих случаях. И поскольку Null это НЕ Истина, то мы и не заходим в If. Т.е. в принципе нужное нам поведение соблюдается. Но для уверенности контроля я бы поставил Nz (как и делал в подобных случаях раньше, когда довольно много прогил на Акцесе).
то NewName <> "" ровняется как и положено Ложь, а значит что NULL все же равен ""
Не совсем. Результатом выражений Null <> "" или Null = "" будет не Ложь, а Null в обоих случаях. И поскольку Null это НЕ Истина, то мы и не заходим в If. Т.е. в принципе нужное нам поведение соблюдается. Но для уверенности контроля я бы поставил Nz (как и делал в подобных случаях раньше, когда довольно много прогил на Акцесе).Gustav
Отчитываюсь. Макрос Константина в файле весом 1.2Гб в котором содержится 1 864 670 строк и 28 столбцов провел замену по одному столбцу не больше не меньше РОВНО за 10 мин.
Большое спасибо за помощь.
Отчитываюсь. Макрос Константина в файле весом 1.2Гб в котором содержится 1 864 670 строк и 28 столбцов провел замену по одному столбцу не больше не меньше РОВНО за 10 мин.
Кстати! Хотел заостриться. С понятием "макрос" в Access надо аккуратнее. Дело в том, что в нём как объекты приложения есть и Модули, и Макросы. Модули - это VBA, а Макросы - это процедуры на специфическом встроенном языке команд. Ну, а мы конечно по традиции по-эксельному говорим о макросах, имея в виду процедуры VBA - и прекрасно понимаем друг друга! ))
Кстати! Хотел заостриться. С понятием "макрос" в Access надо аккуратнее. Дело в том, что в нём как объекты приложения есть и Модули, и Макросы. Модули - это VBA, а Макросы - это процедуры на специфическом встроенном языке команд. Ну, а мы конечно по традиции по-эксельному говорим о макросах, имея в виду процедуры VBA - и прекрасно понимаем друг друга! ))Gustav
Если же таблица "база" имеет размер 2 гига, то такой подход чреват долгим выполнением и большим отжором памяти запросом под свои нужды.
То в моем случае запрос вообще не выполнился поругавшись на недостаток оперативной памяти на всякий случай)):
но при небольших объемах я бы отдал предпочтение запросу, так как уверен будет намного быстрее макроса.
Но все равно не могу понять, неужели в акцесс нет реально простой возможности через какие нибудь связи подставить значения легко и быстро в нужный столбец? ((
Лена, Ваш запрос хорош но для маленьких файлов, как и писал выше Костя
Если же таблица "база" имеет размер 2 гига, то такой подход чреват долгим выполнением и большим отжором памяти запросом под свои нужды.
То в моем случае запрос вообще не выполнился поругавшись на недостаток оперативной памяти на всякий случай)):
но при небольших объемах я бы отдал предпочтение запросу, так как уверен будет намного быстрее макроса.
Но все равно не могу понять, неужели в акцесс нет реально простой возможности через какие нибудь связи подставить значения легко и быстро в нужный столбец? ((DJ_Marker_MC