Страницы: 1 2 3 След.
RSS
Select Case Target.Address
 
Прошу совета, как укоротить Case:  
 Select Case Target.Address 'выбор в Range("K27:L34")  
 Case "$K$27", "$K$27", "$K$28", "$K$29", "$K$30", "$K$31", "$K$32", "$K$33", "$K$34", _  
 "$L$27", "$L$28", "$L$29", "$L$30", "$L$31", "$L$32", "$L$33", "$L$34"  
  Здраствуйте  
 Case Else  
  Досвидания  
 End Select
 
Так не устроит?  
 
Private Sub Worksheet_Change(ByVal Target As Range)  
 If Target.Count > 1 Or Intersect(Target, Range("K27:L34")) Is Nothing Then  
   MsgBox "Bye!"  
 Else  
   MsgBox "Hi!"  
 End If  
End Sub
 
нужно отслеживать очень много адресов. If не желателен.  
Можно получить Строку, Столбец ячейки и их проверять в Case, но это не очень красиво.
 
Из кода 1-го сообщения многое непонятно.  
Нужна более четкая формулировка, иначе возникают варианты:  
 
1. Target должна быть одной ячейкой  
 
Private Sub Worksheet_Change(ByVal Target As Range)  
 Dim i&  
 i = Target.Count  
 Select Case Target.Count & Target.Address(0, 0)  
   Case "1K27" To "1K34", "1L27" To "1L34"  
     MsgBox "Hi!"  
   Case Else  
     MsgBox "Bye!"  
 End Select  
End Sub  
 
2. Target должна включать хотя бы одну ячейку внутри заданного диапазона K27:L34, остальные могут быть снаружи  
 
Private Sub Worksheet_Change(ByVal Target As Range)  
 Select Case Target.Address(0, 0)  
   Case "K27" To "K34", "L27" To "L34"  
     MsgBox "Hi!"  
   Case Else  
     MsgBox "Bye!"  
 End Select  
End Sub  
 
 
3. Target может включать несколько ячеек, но все должны быть внутри заданного диапазона K27:L34  
 
Private Sub Worksheet_Change(ByVal Target As Range)  
 Select Case Target.Address(0, 0) & "я"  
   Case "K27я" To "K34я", "L27я" To "L34я"  
     MsgBox "Hi!"  
   Case Else  
     MsgBox "Bye!"  
 End Select  
End Sub
 
{quote}{login=ZVI}{date=22.03.2011 06:34}{thema=}{post}1. Target должна быть одной ячейкой  
 
Private Sub Worksheet_Change(ByVal Target As Range)  
 Dim i&  
 i = Target.Count  
 ...  
{/post}{/quote}  
Это лишнее:  
Dim i&  
i = Target.Count
 
1-й вариант правильнее так, чтобы не срабатывало еще, например, на K270  
 
Private Sub Worksheet_Change(ByVal Target As Range)  
 Select Case Target.Count & Target.Address(0, 0) & "я"  
   Case "1K27я" To "1K34я", "1L27я" To "1L34я"  
     MsgBox "Hi!"  
   Case Else  
     MsgBox "Bye!"  
 End Select  
End Sub
 
1-й и 2-й варианты не работают
 
Можно конкретизировать, какой именно нужен?
 
в Case должна быть проверка принадлежности активной ячейки диапазону K27:L34
 
работает. Спасибо!
 
Приложил 1-й и 3-й вариант
 
оба работают. огорчает, что необходимо цеплять префикс к адресу, и хвост.:(
 
if target.count>1 then exit sub  
select case target.row+(target.column-1)*999  
case 10027 to 10034,11027 to 11034 : msgbox "hi"  
caseelse: msgbox "by"  
endselect
Живи и дай жить..
 
только    
 
elect case target.row+(target.column-1)*1000
Живи и дай жить..
 
{quote}{login=слэн}{date=22.03.2011 10:17}{thema=}{post}только  
elect case target.row+(target.column-1)*1000{/post}{/quote}  
 
красиво. спасибо.
 
{quote}{login=k61}{date=22.03.2011 07:29}{thema=нужен:}{post}в Case должна быть проверка принадлежности активной ячейки диапазону K27:L34{/post}{/quote}  
 
в таком случае и Case не нужен:  
 
if intersect(...) then ... else ... end if
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
точнее:  
 
if not intersect(target, range("K27:L34")) is nothing then  
здравствуйте  
else  
до свидания  
end if
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
{quote}{login=k61}{date=22.03.2011 06:08}{thema=дело в том, что}{post}дело в том, что нужно отслеживать очень много адресов. If не желателен.  
Можно получить Строку, Столбец ячейки и их проверять в Case, но это не очень красиво.{/post}{/quote}
 
{quote}{login=k61}{date=22.03.2011 10:32}{thema=Re: слэн}{post}красиво. спасибо.{/post}{/quote}  
Красиво, только я уже отмечал, что в таком случае будет много других ячеек вне диапазона, которые выдадут такие же суммы, т.е. будут ложные срабатывания кода.  
 
По-моему, лучше делать на базе традиционого подхода:  
 
Private Sub Worksheet_Change(ByVal Target As Range)  
   
 If Target.Count > 1 Then Exit Sub  
   
 Const MyRanges = "A1:B2,A3:B3,C1:D3"  
 Dim a, i&, j&, x  
   
 a = Split(MyRanges, ",")  
   
 For Each x In a  
   i = i + 1  
   If Not Intersect(Target, Range(x)) Is Nothing Then j = i: Exit For  
 Next  
   
 Select Case j  
   
 Case 1: MsgBox a(j - 1)  
 Case 2: MsgBox a(j - 1)  
 Case 3: MsgBox a(j - 1)  
   
 End Select  
 
End Sub
 
Упростил немного код:  
 
Private Sub Worksheet_Change(ByVal Target As Range)  
   
 If Target.Count > 1 Then Exit Sub  
   
 Const MyRanges$ = "A1:B2,A3:B3,C1:D3"  
 Dim a, i&, x  
   
 a = Split(MyRanges, ",")  
   
 For i = 0 To UBound(a)  
   If Not Intersect(Target, Range(a(i))) Is Nothing Then Exit For  
 Next  
   
 Select Case i  
   
 Case 0: MsgBox a(i)  
 Case 1: MsgBox a(i)  
 Case 2: MsgBox a(i)  
   
 End Select  
 
End Sub
 
извините, ZVI, Вы не разобрались - повторений быть не может. это аналог индексации двумерного массива, соответствующего части листа - в данном случае ограниченного тысячью строк(можно больше)
Живи и дай жить..
 
Ложных срабатываний не обнаружено.  
Не ожидал, что для записи в условии Case - адреса области, будут такие сложности.  
Век живи, век учись.  
Пока остановился на варианте ZVI, но как говорят одесские грузчики "таким багажом не разбрасываются! (вариант Слэна)"  
 
Ещё раз всем спасибо.
 
ну, в крайнем случае, поставить еще одну проверку:  
 
if target.row>1000 then exit sub
Живи и дай жить..
 
{quote}{login=слэн}{date=22.03.2011 01:48}{thema=}{post}ну, в крайнем случае, поставить еще одну проверку:{/post}{/quote}  
либо отодвинуть неприятный момент:  
Select case target.row+(target.column-1)*10000  
Case 100027 ......
 
ну да, если речь идет об интерактивных действиях, то чаще бывает, что диапазон изначально ограничивается одной страницей..  
 
1000 я привел как раз чтобы подчеркнуть абстрактность этого числа..
Живи и дай жить..
 
{quote}{login=внимательный}{date=22.03.2011 01:20}{thema=Re: ikki дело в том, что}{post}{quote}{login=k61}{date=22.03.2011 06:08}{thema=дело в том, что}{post}дело в том, что нужно отслеживать очень много адресов. If не желателен.  
Можно получить Строку, Столбец ячейки и их проверять в Case, но это не очень красиво.{/post}{/quote}{/post}{/quote}  
 
то, что кто-то из нас не понял другого, это да.  
вы для КАЖДОГО из "много адресов" хотите выполнять оператор Case?  
а я вам предлагаю вместо ОДНОГО оператора Case использовать ОДИН оператор if. то есть сколько там по вашему алгоритму будет Case'ов, вместо этого будет столько же if'ов.  
просто КАЖДЫЙ из этих if'ов будет работать (имхо!, не проверял) быстрее.
 
это был я.  
вообще, тогда хотелось бы узнать реальную задачу, а не "упростить Case"  
а так - что спросили, на то и ответили, т.е. упростили Case и заменили на If
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
если в каждом if будет стоять intersect, то быстрее уж точно не будет..
Живи и дай жить..
 
{quote}{login=слэн}{date=22.03.2011 03:32}{thema=}{post}если в каждом if будет стоять intersect, то быстрее уж точно не будет..{/post}{/quote}  
 
да, Вы правы. протестировал. проигрыш почти в 1,9 раза.
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
Public Sub test_case()  
 Dim r As Range, c As Range, x As Range, i As Long  
 Set r = ActiveSheet.Range("K27:L34")  
 Set c = ActiveSheet.Range("A1:AZ50000")  
 t = Now  
 i = 0  
 For Each x In c.Cells  
   Select Case x.Address  
     Case "$K$27", "$K$27", "$K$28", "$K$29", "$K$30", "$K$31", _  
       "$K$32", "$K$33", "$K$34", "$L$27", "$L$28", "$L$29", _  
       "$L$30", "$L$31", "$L$32", "$L$33", "$L$34"  
       i = i + 1  
   End Select  
 Next  
 MsgBox Format(Now - t, "ttttt")  
End Sub  
 
время работы - 26...27 сек.  
 
 
Public Sub test_intersect()  
 Dim r As Range, c As Range, x As Range, i As Long  
 Set r = ActiveSheet.Range("K27:L34")  
 Set c = ActiveSheet.Range("A1:AZ50000")  
 t = Now  
 i = 0  
 For Each x In c.Cells  
   If Not Intersect(x, r) Is Nothing Then i = i + 1  
 Next  
 MsgBox Format(Now - t, "ttttt")  
End Sub  
 
время работы - 45...46 сек.  
 
 
Public Sub test_if_and()  
 Dim r As Range, c As Range, x As Range, i As Long  
 Set r = ActiveSheet.Range("K27:L34")  
 Set c = ActiveSheet.Range("A1:AZ50000")  
 t = Now  
 i = 0  
 For Each x In c.Cells  
   If x.Row <= 34 And x.Row >= 27 And (x.Column = 11 Or x.Column = 12) Then i = i + 1  
 Next  
 MsgBox Format(Now - t, "ttttt")  
End Sub  
 
время работы - 15...16 сек.  
 
 
пс. машинка на работе слабенькая - Celeron 2.8, RAM 256 Mb. Ex-2003.
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
Страницы: 1 2 3 След.
Читают тему
Наверх