Профессиональные приемы работы в Microsoft Excel

Обмен опытом => Microsoft Excel => Тема начата: 0mega от 02.12.2017, 18:45

Название: Написать на VBA аналог формулы с несколькими условиями
Отправлено: 0mega от 02.12.2017, 18:45
Всем доброго времени суток

как в IF прописать формулу с несколькими условиями

пример
Sub Test()
Dim r As Byte
Dim c As Byte
For r = 4  To 9
For c = 4 To 31
If Cells(r, c) условие под звездочкой
Next c
Next r

End Sub

уcловие для IF
если произведение строка*деньнедели кратное 8; тогда столбец+день(сегодня())+строка() и ячейку закрасить желтым; иначе строка()*столбец()
Название: Re: VBA . IF под формулой
Отправлено: boa от 02.12.2017, 19:46
Почитайте Хэлп (https://msdn.microsoft.com/en-us/library/ee440532(v=office.12).aspx)
Но в общем, сложная схема Ифа така:


Sub Test2()
    If условие_1 = Критерий_1 Then
        MsgBox "Критерий_1"
        If условие_1_1 = Критерий_1_1 Then
            MsgBox "Критерий_1_1"
        ElseIf условие_1_2 = Критерий_1_2 Then
            MsgBox "Критерий_1_2"
        Else
            MsgBox "Критерий_1 выполняется не полностью"
        End If
    ElseIf условие_2 = Критерий_2 Then
        MsgBox "Критерий2_"
    Else
        MsgBox "Критерии не выполняются"
    End If
End Sub
Название: Re: VBA . IF под формулой
Отправлено: 0mega от 02.12.2017, 21:09

boa , здравствуйте

Цитата: boa от 02.12.2017, 19:46
Почитайте Хэлп (https://msdn.microsoft.com/en-us/library/ee440532(v=office.12).aspx)
пока  изучал макросы методом тыка,  я еще что-то понимал...
После прочтения помощи оказалось что я все делал неправильно. а по правильному у меня ничего не получается ...


спасибо за оперативный ответ и подробное описание
Но на данном уровне моих знаний это все равно что первокласснику дать "Капитал" читать ...

Записал макрос макрокодером
получилось так

Range("D4").Select
    ActiveCell.FormulaR1C1 = _
        "=IF(ROW()*WEEKDAY(TODAY(),2)/8=INT(ROW()*WEEKDAY(TODAY(),2)/8),COLUMN()+DAY(TODAY()+ROW()),ROW()*(COLUMN()))"


попытка загнать все это в ячейку
IF Cells (r, c) = IF(ROW()*WEEKDAY(TODAY(),2)/8=INT(ROW()*WEEKDAY(TODAY(),2)/8),COLUMN()+DAY(TODAY()+ROW()),ROW()*(COLUMN()))
Машина отказывается  работать с этой белебердой !
Не могли бы вы написать конкретный код под мои требования





Название: Re: VBA . IF под формулой
Отправлено: vikttur от 02.12.2017, 21:31
Забудьте о ЕСЛИ и объясните ЗАДАЧУ, а не выбранный способ решения.
И предложите название темы, отражающее суть задачи.
Название: Re: VBA . IF под формулой
Отправлено: 0mega от 03.12.2017, 02:20
vikttur, здравствуйте
Цитата: vikttur от 02.12.2017, 21:31
и объясните ЗАДАЧУ
Если опускать все тонкости, то конечная цель: научиться работать в среде VBA
А то что написано в стартовом топике - это не задача, а "предисловие"

Цитироватьа не выбранный способ решения.
Если у Вас лично или на форуме имеется список в котором отмечаются решенные/нерешенные вопросы, тогда эту задачу можно отмечать птичкой, потому что решение этой задачи имеется .
Я его предоставил вместе с вопросом (см.файл)
Но это решение на формулах и условном форматировании.
Мне бы хотелось получить такой же ответ но через макросы.
Я допускаю что Вы и/или другие форумчане можете предложить не один и не два макроса с правильным и красивым решением.
Но мое серое вещество не сможет воспринять ту информацию ввиду отсутствия знаний.
Поэтому мне не надо "КРАСИВЫЙ" ответ. Мне надо "ПОНЯТНОЕ" решение
На сегодняшний день IF- это мой спасательный круг
Если по каким-то причинам ответ не может быть предоставлен в том виде в каком я хочу - тогда могу убрать часть условий
ЦитироватьИ предложите название темы, отражающее суть задачи
Это самый сложный (для меня) пункт Вашего поста
Может быть так?
Как записать IF, при условии что ИСТИНА и ЛОЖЬ задаются математическим решением и при этом ответ тоже должен исходить из формулы
Название: Re: VBA . IF под формулой
Отправлено: vikttur от 03.12.2017, 11:28
Название темы заменил.

Цитироватьможете предложить не один и не два макроса с правильным и красивым решением.
Вам дали в руку карту с отмеченным маршрутом. Задание: достичь конечной точки, оптимизировав маршрут. Но главное условие - от указанной нитки не отклоняться.
Так и здесь. Прошу улучшить, но от формулы шаг влево, шаг вправо - расстрел :)

ЦитироватьНа сегодняшний день IF- это мой спасательный круг
Код получается более структурирован и читабелен, если вместо многих условных операторов применяется *Select Case/End Select*. Часто каскад If можно заменить поиском или циклами.

Цитироватьрешение этой задачи имеется
Отлично. Для решения конкретной задачи (не об операторах и формулах) создайте новую тему, опишите ЗАДАЧУ так, как будто Excel Вы и в глаза не видели.
Название: Re: Написать на VBA аналог формулы с несколькими условиями
Отправлено: boa от 03.12.2017, 13:38
Для вызова с листа в ячейке напишите формулу "=condition()"

Option Explicit

Sub test()
Dim r&: r = 3
Dim c&: c = 3
    If Cells(r, c) = condition(r, c) Then MsgBox "Получилось"
End Sub

Function condition(Optional iRow&, Optional iCol&)
'"=IF(ROW()*WEEKDAY(TODAY(),2)/8=INT(ROW()*WEEKDAY(TODAY(),2)/8),COLUMN()+DAY(TODAY()+ROW()),ROW()*(COLUMN()))"

Dim MyDate As Date: MyDate = Date
' если функцию планируете вызывать не с листа, то функции надо передавать значения iCol и iRow
' Caller является объектом Range, т.е ссылкой на ячейку, из которой вызвана функция пользователя
    If iCol = 0 Then iCol = Application.Caller.Column
    If iRow = 0 Then iRow = Application.Caller.Row
   
    If iRow * Weekday(MyDate, vbMonday) / 8 = Int(iRow * Weekday(MyDate, vbMonday) / 8) Then
        condition = iCol + Day(MyDate + iRow)
    Else
        condition = iCol * iRow
    End If
End Function
Название: Re: Написать на VBA аналог формулы с несколькими условиями
Отправлено: _Boroda_ от 03.12.2017, 14:05
0mega, добрый день!
Давненько не встречались! Вижу, Вы уже к макросам подобрались и не пишете свое "sub - no". Поздравляю.
По поводу
Цитата: 0mega от 02.12.2017, 21:09
Range("D4").Select
    ActiveCell.FormulaR1C1 = _
        "=IF(ROW()*WEEKDAY(TODAY(),2)/8=INT(ROW()*WEEKDAY(TODAY(),2)/8),COLUMN()+DAY(TODAY()+ROW()),ROW()*(COLUMN()))"


попытка загнать все это в ячейку
IF Cells (r, c) = IF(ROW()*WEEKDAY(TODAY(),2)/8=INT(ROW()*WEEKDAY(TODAY(),2)/8),COLUMN()+DAY(TODAY()+ROW()),ROW()*(COLUMN()))
- Вы просто неверно загоняете. Нужно именно так, как Вам рекодер написал. Вот так
Cells (r, c).FormulaR1C1 = _
        "=IF(ROW()*WEEKDAY(TODAY(),2)/8=INT(ROW()*WEEKDAY(TODAY(),2)/8),COLUMN()+DAY(TODAY()+ROW()),ROW()*(COLUMN()))"


Абсолютно согласен с Виктором в части оптимизации. Но и с Вами тоже согласен - помню свои муки в начальной стадии изучения VBA и прекрасно понимаю Ваше желание сделать не так, как нужно, а так, как понятнее.
Думаю, что этот код затруднений у Вас не вызовет, тем более, что я комментарии туда написал
Sub Test()
    Application.ScreenUpdating = 0 'Отключаем обновление экрана
    d_ = Weekday(Date, 2) 'день недели https://msdn.microsoft.com/ru-ru/VBA/Language-Reference-VBA/articles/weekday-function
    den_ = Day(Date) 'сегодняшний день
    For r_ = 4 To 31 'цикл по строкам
        If r_ * d_ Mod 8 = 0 Then 'если остаток от деления = 0
        'https://msdn.microsoft.com/ru-ru/vba/language-reference-vba/articles/mod-operator
            '2 строки ниже пишем ДО цикла по столбцам, они одинаковы для любого столбца строки r_
            n_ = den_ + r_ 'день + строка
            Cells(r_, 4).Resize(1, 6).Interior.Color = 65535 'красим 6 ячеек вправо от ячейки строка r_, столбец 4
            For c_ = 4 To 9 'цикл по столбцам
               Cells(r_, c_) = c_ + n_ 'каждая ячейка равна столбец + n_
            Next c_ 'конец цикла по столбцам
        Else 'если остаток от деления НЕ = 0
            For c_ = 4 To 9 'цикл по столбцам
               Cells(r_, c_) = c_ * r_ 'каждая ячейка равна столбец * строку
            Next c_ 'конец цикла по столбцам
        End If 'конец условия if
    Next r_ 'конец цикла по строкам
    Application.ScreenUpdating = 1 'Включаем обновление экрана
End Sub
Название: Re: Написать на VBA аналог формулы с несколькими условиями
Отправлено: boa от 03.12.2017, 14:42
Кстати, повторяющиеся формулы, да бы исключить ошибки, лучше создавать в Менеджере имен(Ctrl+F3) и потом в ячейку вставлять только имя созданной формулы
Название: Re: Написать на VBA аналог формулы с несколькими условиями
Отправлено: 0mega от 03.12.2017, 20:44



boa , спасибо за иллюстрацию
скорее всего будут вопросы и я их задам, но _Вoroda_  предоставил более понятный (для меня ) ответ
Название: Re: Написать на VBA аналог формулы с несколькими условиями
Отправлено: 0mega от 03.12.2017, 21:53
_Boroda_ , здравствовать

Цитата: _Boroda_ от 03.12.2017, 14:05
0mega, добрый день!
Давненько не встречались! Вижу, Вы уже к макросам подобрались и не пишете свое "sub - no". Поздравляю.


Немного "тесновато "мне стало среди формул...

Александр, что значит нижнее подчеркивание справа от переменной (d_ ,  r_ ,  c_ ... ) ?
Название: Re: Написать на VBA аналог формулы с несколькими условиями
Отправлено: _Boroda_ от 03.12.2017, 22:33
Ничего. Я так делаю просто для того, чтобы гарантированно не обозвать переменную тем именем, которое уже есть внутри VBA - их же там туча немереная и все запомнить я ну никак не могу (да и зачем)
Название: Re: Написать на VBA аналог формулы с несколькими условиями
Отправлено: Hugo121 от 08.12.2017, 15:37
Привет подводным лодкам! :)
Часто проще и удобнее вместо If-Then использовать select case условие, в частности

select case true
case Cells(r, c) = произведение строка*деньнедели кратное 8
тогда столбец+день(сегодня())+строка() и ячейку закрасить желтым
case какое-то другое выполняющееся условие
тут действие при другом выполняющемся условии
case else ' когда никакие условия не выполнились
строка()*столбец()
end select


При первом совпавшем условии дальнейшие проверки не производятся!
Название: Re: VBA . IF под формулой
Отправлено: boa от 08.12.2017, 19:21
Цитата: Hugo121 от 08.12.2017, 15:37
Часто проще и удобнее вместо If-Then использовать select case условие, в частности

Об этом уже писал vikttur в данной теме... :-\

Цитата: vikttur от 03.12.2017, 11:28
Код получается более структурирован и читабелен, если вместо многих условных операторов применяется *Select Case/End Select*. Часто каскад If можно заменить поиском или циклами.

З.Ы. Если б все рисовали одинаково, то мир бы не увидел шедевров
Название: Re: Написать на VBA аналог формулы с несколькими условиями
Отправлено: Hugo121 от 08.12.2017, 20:48
Про select case true многие не знают, и в шпаргалках редко упоминается.
Название: Re: Написать на VBA аналог формулы с несколькими условиями
Отправлено: 0mega от 10.12.2017, 17:10


Цитата: Hugo121 от 08.12.2017, 15:37
Привет подводным лодкам! :)
Игорь , здравствуйте
хех ...  максимум 2 , но большая вероятность что Вы единственный,  кто знает о подводных лодках.
Остальные, очевидно , предполагагают что  два однополчанина вспоминают службу на форуме excel  ?!

Цитата: Hugo121 от 08.12.2017, 15:37

Часто проще и удобнее вместо If-Then использовать select case условие, в частности

При первом совпавшем условии дальнейшие проверки не производятся!

сейчас для меня это очень сложно .
Поскольку живого преподавателя рядом нет, то  единственная "палочка-выручалочка" - это маросы вытягивать из формул.
тем не менее, спасибо за подсказку .
Ковырнул изюм ...
Но только неизвесно когда этот я буду печь свои булочки с Вашим изюмом