Уважаемые гуру форума, помогите пожалуйста, решить возникшую проблему с формулой. Итак ситуация: для правильной работы формулы крайне желательно иметь возможность ограничить ее работу некой датой, т.е. для примера: для февраля формула должна считать, а для марта уже нет (можно, разумеется, просто удалить формулу, но это не комильфо). Делать я это решил, используя примечания в определенных ячейках. По задумке, если примечания в контрольной ячейке нет - формула считает, если же есть (примечание представляет собой дату закрытия договора), то формула должна проверить превышает ли контрольная дата на листе дату закрытия договора и, если нет - считать, в противном случае значение =0. Такая проверка (на непревышение даты) необходима, чтобы не отменились подсчеты более ранних периодов. для получения информации из примечания я использую функцию пользователя ,найлденную на просторах сети:
Код
Function Get_Text_from_Comment(rCell As Range)
Application.Volatile True
On Error Resume Next
Get_Text_from_Comment = rCell.Comment.Text
End Function
Все ОК, функция работает. Приступаю к конструированию 1 формулы: ЕСЛИ(ЕОШ(сравнение контрольной даты и примечания)) - при отсутствии примечания будет ИСТИНА формула СЧИТАЕТ в противном случае формула должна смотреть далее
2 формула: ЕСЛИ(ЕОШ(контрольная дата< примечания)) формула СЧИТАЕТ в противном случае = 0
Обе вышеописанные формулы считают правильно, в прилагаемом примере, можно проверить это в ячейках Y9 и Y10 листа "Расходы электроэнергии", но при попытке их объединить, вставив 2-ую формулу вместо "смотреть далее", возникает ошибка #ИМЯ? в значении для ЛЖИ (ячейка Y11 примера). Естественно, при попытке внедрения формулы в реальную формулу, тоже ничего не выходит (ячейка Y13 примера). Почему так происходит, формулы работающие правильно по отдельности, не работают будучи объединенными? И как это исправить? Заранее спасибо всем откликнувшимся.
P.S. Для ясности формула должна подсчитать результат за март для Арендатора 2 и НЕ ПОСЧИТАТЬ для Арендатора 3 (договор с которым закрыт), при этом результаты за февраль для обоих арендаторов должны считаться (проверять формулу и на тех ячейках)
Прошу прощения на некоторою назойливость , но все-таки попробую спросить еще раз. Форумчане, может кто-нибудь объяснить мне ситуацию с моими формулами, в чем там дело? В моей ошибке или принципиальной невозможности использовать пользовательскую функцию внутри формулы? Поймите, хотелось бы знать ответ прежде чем отказываться от задумки которая нравится. А может кто-нибудь сможет подсказать как иным методом (не текущей пользовательской функцией) извлечь информацию из примечания ячейки, каковую информацию можно было бы использовать в дальнейшем в ФОРМУЛАХ? (вот никогда бы не подумал несколько лет назад, что буду пенять на ограничения формул, а теперь вот думаю, что чисто в VBA было бы проще решить данный вопрос, спешу предупредить сразу, в данном случае ПРИХОДИТСЯ использовать формулы). Заранее спасибо
Доброе время суток. Давайте, я попробую ответить. По вашим же тестам udf-функция работает внутри формул рабочего листа. В чём проблема? Вы используете как аргумент udf-функции ссылку на объект Range (ссылка на ячейку). Могу только предположить, что когда вы формируете ссылку формулами рабочего листа в некоторых случаях Excel формирует ссылку на ячейку, а в других только значение этой ячейки. Может быть и что-то другое. Но, в этом случае VBA не считает, что аргумент - это объект Range. Попробуйте для исследования попробовать такой вариант, когда при ошибке функция вернёт текст ошибки.
Код
Function Get_Text_from_Comment(rCell As Range)
Application.Volatile True
On Error GoTo errHandle
Get_Text_from_Comment = rCell.Comment.Text
Exit Function
errHandle:
Get_Text_from_Comment = Err.Description
End Function
Я не формулист, поэтому не могу подсказать, как обернуть её формулами с учётом тех формул, формирующих аргумент для этой функции, чтобы это было близко к полевым испытаниям. Такое же поведение можно получить, когда создаём имя, но для него формируем не ссылку на диапазон, а некоторый набор формул, возвращающих динамический диапазон по условиям. В этом случае движок Access SQL не считает такое имя именем таблицы (хотя по прямой ссылке на диапазон всё работает). С другой стороны, в элементе управления ListBox формы такое имя прекрасно работает.
Как вариант, предлагаю переделать функцию, чтобы она принимала аргументом текстовую строку. Тогда формулой АДРЕС вы формируете текстовую ссылку на требуемую ячейку, а уже в функции получаете по этому адресу ссылку на ячейку. Для активной книги, например
Код
=Get_Text_from_Comment(АДРЕС(2;3;1;1;"Лист1"))
Код функции будет
Код
Function Get_Text_from_Comment(rCell As String)
Application.Volatile True
On Error GoTo errHandle
Get_Text_from_Comment = Application.Range(rCell).Comment.Text
Exit Function
errHandle:
Get_Text_from_Comment = Err.Description
End Function
Андрей, а Вы не могли ли скачать прилагаемый пример, просмотреть мои формулы и указать на причину ошибки? Ситуация-то выглядит больно странно 2 достаточно простые формулы ЕСЛИ работают правильно порознь и НЕ работают будучи объединенными. Если не трудно, просмотрите мой файл-пример, а я пока проверю Ваш совет
Проверил, могу сказать следующее. Изначально, когда использовал udf в качестве результата она выдавала правильный ответ (текст комментария нужной ячейки), а Ваша измененная udf (в которой (rCell As String)), выдает теперь Method 'Range' of object '_Application' failed. Может эта информация поможет в решении проблемы?
Хочу пояснить. Ошибка о которой я писал немного необычна, если так можно сказать. Смотрите: использую формулу в которой пытаюсь объединить 2 работающие:
в результате ответ в ячейке = 0 (хотя должен быть иным, для этого арендатора формула должна считать), захожу в формулу, в аргументе "Значение_если_ложь" 1 формулы ЕСЛИ стоит #ИМЯ? хотя повторюсь в ячейке не сообщение об ошибке, а 0
OlegO написал: Method 'Range' of object '_Application' failed.
Скорее всего не правильно сформирован полный адрес ячейки. Вариант. Для того чтобы тестировать непосредственно вашу проблему - нужно быть формулистом. Я, увы, не он. Я исхожу из рассуждений, бывших несколько лет назад, когда исследовалось как ведёт себя функция, если ей передаётся диапазон. Если ссылка на диапазон в открытой книге, то аргументом будет Range, а для закрытой - двумерный массив
книга открытая, соседние листы. Парадокс именно в том, что и udf выдает правильный результат, и индекс, которым ищется ячейка с комментарием, все считает правильно, и ЕСЛИ, используя найденные данные считает правильно, а при объединении 2 функций ЕСЛИ вылезает затык, да еще странный какой-то (подробнее в моем предыдущем посту)
Андрей, может я совсем к вечеру отупел, но Ваш вариант udf из последнего поста совсем не хочет считать, =Get_Text_from_Comment(АДРЕС(4;4;;;"Справочник")) выдает ЗНАЧ, хотя именно в ячейке D4 листа Справочник и находится ячейка с комментарием. Очень жаль что Вы не формулист . Ау, формулисты форума, отзовитесь, возможно эта задача как раз для Вас
Если кому-то покажется интересным, покажу решение которое придумал: сначала проверяем все ячейки диапазона с формулами, определяя нужно ли для конкретной ячейки расчеты или уже нет (вешаем код на активацию листа):
Код
Range(Cells(2, [Data_resulting_e].Column), Cells(Cells(Rows.Count, [Objects_e].Column).End(xlUp).Row, Application.Match("-", Rows(1), 0) - 1)).ClearComments 'снятие комментариев
x = Range(Cells(2, [Data_resulting_e].Column), Cells(Cells(Rows.Count, [Objects_e].Column).End(xlUp).Row, Application.Match("-", Rows(1), 0) - 1)).Value 'данные в массив
For j = 1 To Application.Match("-", Rows(1), 0) - Application.Match("+", Rows(1), 0) - 1
For i = 1 To UBound(x)
Set note = Application.Index(Sheets("Справочник").Range("D2:D101"), Application.Match(Cells(i + 2, 4), Sheets("Справочник").Range("M2:M101"), 0))
If Len(Cells(i + 2, 4).Value) > 0 Then 'если есть объект из списка арендаторов
If Not note.Comment Is Nothing Then
If x(1, j) > CDate(note.Comment.Text) Then
Sheets("Расходы электроэнергии").Cells(i+2, j + [Data_resulting_e].Column - 1).AddComment
Sheets("Расходы электроэнергии").Cells(i+2, j + [Data_resulting_e].Column - 1).Comment.Text Text:="Договор закрыт"
End If
End If
End If
Next i
Next j
затем используем UDF, только помещая ее "выше" формул расчетов: ЕСЛИ(Get_Text_from_Comment("нужная ячейка"))=0, т.е. ситуация, когда комментария в ячейке нет считать формулы иначе =0 По крайней мере пока, такая конструкция работает, сейчас проверяю на рабочем файле.