Запрет на выход из ячейки на время проверки ее содержимого

Автор verdim, 17.07.2012, 15:27

« назад - далее »

verdim

Добрый день !!!
Мне для определения дальнейшей логики действий надо проверить информацию, введенную пользователем.
Для этой цели хотелось бы заблокировать выход из ячейки до завершения проверки.
Я пробовал и Change и SelectionChange: все они у меня дают адрес текущей (следующей после щелчка) ячейки.
Например, курсор был в ячеке А1. После щелчка он переходит в А2. И обе эти команды (Change, SelectionChange) дают один и тот же результат, - адрес А2 с небольшим различием: столбец 2 строка 1; $A$2.
Как мне сделать так, чтобы при вводе ошибочных данных курсор продолжал оставаться в А1 и переходил в А2 при верных данных.
Спасибо.

Prist

Во многих событийных процедурах есть передаваемый параметр. В указанных ВАми тоже - Target. Если будете проверять именно Target, то будем Вам счастье:
Private Sub Worksheet_Change(ByVal Target As Range)
   MsgBox Target.Address
End Sub
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
www.excel-vba.ru
Просто СПАСИБО [+оказать+]
Считаешь СПАСИБО мало? Яндекс.Деньги: 41001332272872; WM: R298726502453

verdim

Спасибо. Более-менее понятно. Не совсем ясно как сделать так, чтобы, в одном случае не выходить, а вдругом, - выйти из ячейки ...
К примеру:
if (a=b) <выход>
else <остаться в ячейке>
Весь вопрос был в этом.

Шпец Докапыч

Если пользователя просто держать в ячейке, то он сможет менять в ней информацию, бесконечно дёргая проверку. Вот пример не очень удачного варианта:
Private Sub Worksheet_Change(ByVal Target As Range)
  If Target.Address = "$A$1" Then
    Target.Select
    Application.EnableCancelKey = 0
    For i = 50000 To 1 Step -1 'заглушка, вместо проверки
      Application.StatusBar = "Ждите... " & i
      DoEvents
    Next
    Application.EnableCancelKey = 1
    Application.StatusBar = "Готово"
  End If
End Sub

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
  If Application.StatusBar Like "Ждите*" Then [A1].Select
End Sub


Лучше, во время проверки, ставить защиту на лист (запретив выделение заблокированных ячеек), а целевую ячейку изобразить выделенной с помощью форматирования рамки.

Ещё вариант: отобразить пользователю UserForm, проверку подвесить на UserForm_Activate + прописать запрет на закрытие формы.
Знания недостаточно, необходимо применение. Желания недостаточно, необходимо действие. (с) Брюс Ли

Prist

Наверное, что-то навроде того подойдет:
Private Sub Worksheet_Change(ByVal Target As Range)
    if (Target.Value <> b) Then
         with application
             .enableevents = 0
             .Undo
             .enableevents = 1
         end with
    end if
End Sub

Иными словами, если значение, введенное в ячейку, не соответствует тому, которое мы хотим там видеть - оно будет удалено и курсор останется в целевой ячейке.
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
www.excel-vba.ru
Просто СПАСИБО [+оказать+]
Считаешь СПАСИБО мало? Яндекс.Деньги: 41001332272872; WM: R298726502453

verdim

Чувствую, перестал излагать по-русски свои мысли ... Возраст, знаете ли ..., лечиться надо ...
А тяжесть в моих мозгах вот от чего.
Ячейки, которые сравниваются, находятся в одном столбце, но в разных строках. Причем, интервал между строками с дублями может быть произвольный (надеюсь, что дублей не больше одного).
У меня на листе есть столбец сообщений, в котором нормально отражаются все дубли, сколько бы их ни было.
Но ... Для того, чтобы поймать все дубли, приходится делать (по-крайней мере, мне) несколько проходов, сравнивая каждую следующую ячейку с ячейками, начиная с позиции на единицу больше. Топорно, - чувствую. Вот и задумал этот способ.
Я все делаю в SelectionChange. Т.е., только после выхода из ячейки проверяю на дубли. И тут опять загвоздка: Tatget.Select у меня отрабатывает только в Change. Эффект страшно понравился ... И опять затык: войти-то я в покинутую ячейку не могу, чтобы исправить, - выкидывает Select.
Чтобы Вас по-меньше истязать, решил, что проще послать исходники.
Это исключит разговор глухого с немым.

IKor

Вдруг пригодится когда-нибудь...
Поиск дублированной информации в столбце при помощи дополнительного столбца (или условного форматирования)
=СЧЁТЕСЛИ($A$1:A1;A1)>1

посмотрите прилагаемый пример...

P.S. возможно, условное_форматирование позволит упростить вашу VBA программу - за счет поиска предварительно выделенных цветом дубликатов...

verdim

Спасибо, конечно.
Может быть я что-то недопонял в Вашем примере ... Но этот пример, скорее, наверное, для администратора базы, а не для пользователя.
Как я понимаю, формулу надо дублировать по-мере добавления новой строки ... Причем вручную.
У меня это сделано несколько по другому: если Вы смотрели исходники, там присутствуют имена полей.
Дело в том, что берется интервал ячеек и именуется, а уже относительно этого имени выполняются все проверки.
Именованный интервал изменяет как-раз администратор если видит, что число заполненных строк приближается к критическому числу.
Можно, конечно, "вытягивать" формулу, но с именованным диапазоном, мне кажется, как-то проще. Тем более с ним могут работать несколько процедур. И проверка на дубли у меня идет только внутри интервала ... Чувствую, надо как-то по другому ...

IKor

В том случае, если существуют заранее созданные именованные диапазоны, то добавить только для них поиск дубликатов можно точно также. Даже необязательно привязываться к конкретным именам... При добавлении новых строк в них придется просто скопировать форматы, уже содержащие нужное условное_форматирование (или же убедится, что форматирование уже скопировалось). Ничего более сложного, чем расширение именованного списка.
Цитата: verdim от 20.07.2012, 14:17
Дело в том, что берется интервал ячеек и именуется, а уже относительно этого имени выполняются все проверки.
Именованный интервал изменяет как-раз администратор если видит, что число заполненных строк приближается к критическому числу.
Если соблюдать нехитрые правила копирования форматов, то ваши именованные диапазоны просто получат динамически изменяемый видимый атрибут - например, цвет шрифта. Я думаю, что этот атрибут можно будет проверять в коде VBA и действовать соответственно. Не хотите его использовать в логике программы - используйте только для визуализации результата. Не нужно и этого - просто игнорируйте :)

На всякий случай поясню принцип работы функции =СЧЁТЕСЛИ($A$1:A1;A1)>1
Она предназначена для подсчета количества значений ячейки А1 в диапазоне А1:А1 и сравнения результата с единицей.
Очевидно, что при вычислении этой функции будет проверяться неравенство 1>1, что неверно - поэтому функция вернет значение ЛОЖЬ и условное_форматирование выполняться не будет.
Когда мы копируем эту формулу в ячейку (в условное_форматирование ячейки) А2, то в соответствии с правилами Excel она принимает вид =СЧЁТЕСЛИ($A$1:A2;A2)>1 => начало диапазона $A$1 фиксируется знаками $. При выполнении этого сравнения, если значения ячеек А1 и А2 совпадают, то будет проверяться условие 2>1, что верно - поэтому функция вернет ИСТИНА и к ячейке А2 будет применено условное_форматирование.
Дальнейшее копирование форматов "вниз" приведет к постепенному расширению проверяемого диапазона и поиску дублей последующих значений.

Надо сказать, что выделение всех повторяющихся ячеек, а не именно дублей можно осуществить при помощи, чуть более наглядной формулы:  =СЧЁТЕСЛИ(имена;A1)>1 - которая сразу проверяет весь массив и выделяет все повторы, включая первое вхождение.

verdim

Спасибо.
Меня теперь смущают два момента:
1. если не знаешь отличие "$a$1" от "a1", то за Excel лучше не браться;
2. вызывает вопрос: намного ли быстрее выделять дубли ячеек, а затем проходить по "раскраске", используя, как я себе представляю, не     
   многим отличающийся способ от моего.
Ведь в этот диапазон могут попасть, во-первых несколько дублей одного и того же значения, которые, уйдя за экран, никак не насторожат торопливого оператора. А во-вторых, если есть дубли разных значений, то выделение собьет с толку программу, т.к. выделение будет одного цвета.
На мой взгляд, более симпатичный способ не выпускать пользователя из ячейки при попытке ввода первого же дубля.
Тогда не должна, вроде бы, потребоваться раскраска.
Вопрос: возможно ли скорректировать с минимальными затратами мои исходники и как Вы рекомендуете это сделать используя политику "не пущать при дубле" или требуется коренная переделка ???
Спасибо.

verdim

Цитата: Prist от 17.07.2012, 22:22
Наверное, что-то навроде того подойдет:
Private Sub Worksheet_Change(ByVal Target As Range)
    if (Target.Value <> b) Then
         with application
             .enableevents = 0
             .Undo
             .enableevents = 1
         end with
    end if
End Sub

Иными словами, если значение, введенное в ячейку, не соответствует тому, которое мы хотим там видеть - оно будет удалено и курсор останется в целевой ячейке.
Спасибо.
Подошло, но частично. Курсор взбесился:
он скакнул в ячейку с дублем, стер дубль и вернулся обратно ...
Возврат обратно совсем не нужен ...
Уже в полшаге до решения ... Как теперь "привязать" курсор ??? Что будет играть роль нарколога ???
Надеюсь, это будет Вашей последней подсказкой.
Спасибо.