2016-09-23 4 views
0

Кажется, что Application.Volatile и ActiveSheet.Calculate - это не то, что я думал, что это так, мне нужна помощь в создании функции, которая правильно пересчитывается при изменении соответствующих данных. Вот что я собираюсь прямо сейчас:Неустойчивая пользовательская функция не пересчитывается, как ожидалось (VBA/Excel)

Public Function Availability(EmpName As Range) 
Application.Volatile (True) 
ColLetter = Cletter(EmpName.Column) 
Set NameRange1 = Range("$" & ColLetter & "$1:$" & ColLetter & "$" & (Application.ActiveCell.Row - 1)) 
Set SumRange1 = Range(Cletter(Application.ActiveCell.Column) & "1:" & Cletter(Application.ActiveCell.Column) & (Application.ActiveCell.Row - 1)) 
Sum1 = Application.SumIfs(SumRange1, NameRange1, EmpName) 
Availability = Sum1 
End Function 

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

CLetter - это еще одна небольшая функция, которая превращает колонку № в букву, потому что я слишком ленив, чтобы вызвать R1C1 и найти ее более читаемой.

Но всякий раз, когда я вношу изменения в диапазоны критериев или сумм, вместо пересчета для учета изменений в идентификаторах или числах, кажется, забывает, что затронутая строка существует (даже если я только что изменил ее на MATCH критерии) или просто выбросите ошибку #VALUE. Это легко устранить, щелкнув по функции «= Доступность (A #)» и нажав кнопку ввода, но я бы не хотел писать дополнительный макрос, чтобы обновить все эти ячейки, когда они будут по всей электронной таблице. Toggling Волатильность помог немного, но не решить проблему, а также не добавляя некоторые вариации на следующем событии изменения листа:

Private Sub Worksheet_Change(ByVal Target As Range) 
ActiveSheet.Calculate 
End Sub 

Наверняка есть какой-нибудь способ, чтобы получить функцию, чтобы обновить себя всякий раз, когда любая клетка изменяется , а не только своими.

+0

Проблема заключается в том, что вы ссылаетесь на активную ячейку. Если вы меняете данные, активная ячейка является той, которая только что изменилась, а не той, в которой находится формула. –

+0

«Энергоэффективная функция должна быть пересчитана всякий раз, когда расчет происходит в любых ячейках на листе». - если ячейки, которые вы меняете, не ссылаются на * any * формулу, тогда никакие вычисления не вызваны редактированием. Вы можете попробовать добавить «фиктивную» формулу, которая ссылается на ячейки, которые вы меняете, - этого должно быть достаточно, чтобы вызвать перерасчет. –

+0

Dangit, вы правы, Скотт, я считал, что это может быть проблемой, но не может найти способ, который не содержит аргументов, чтобы найти строку и столбец, в котором он должен быть (не вводить вручную , Я имею в виду). Любая идея, как я всегда мог ссылаться на эту ячейку внутри функции? Возможно, что-то с косвенным? – basaltanglia

ответ

0

Поскольку расчет был уже автоматическим, и цель заключалась не в том, чтобы добавить больше аргументов, которые нужно определить (т. Е. Чтобы все было автоматическим, кроме критерия для sumif), единственное необходимое изменение заключалось в том, что Application.ActiveCell в Appplication.ThisCell , Application.Caller также может работать, но этот способ казался более определенным. Спасибо за помощь Тим и Скотт!

1

Сначала убедитесь, что в ваших настройках установлены автоматические параметры. Если ваши расчеты установлены на автоматическое, это будет меняться каждый раз, когда данные, к которым он относится, будут изменены.

Вторая часть проблемы заключается в том, что вы ссылаетесь на активную ячейку. Если вы измените данные, активная ячейка будет той, которая только что изменилась, а не той, в которой находится формула. Используйте Application.Caller, который ссылается на ячейку, из которой вызывается функция.

Третье использование Cells вместо вызова другой функции, чтобы найти букву столбца. Ячейки позволяют ссылаться на числа.

Public Function Availability(EmpName As Range) 
Application.Volatile 

Set NameRange1 = Range(Cells(1, EmpName.Column), Cells(Application.Caller.Row - 1, EmpName.Column)) 
Set SumRange1 = Range(Cells(1, Application.Caller.Column), Cells(Application.Caller.Row - 1, Application.Caller.Column)) 
Sum1 = Application.SumIfs(SumRange1, NameRange1, EmpName) 
Availability = Sum1 
End Function 
1

ИМХО это ошибка использовать Application.Volatile как бинт для игнорирования перерасчета в Excel правило проведения
- почему бы не сделать это правильно и пройти все диапазоны, что UDF должна ОДС в качестве параметров?
Тогда вам не понадобится приложение volatile и т. Д., И ваша книга и UDF будут вычислять гораздо более чисто.

+0

Потому что я проектирую это для людей, которые не очень хорошо разбираются, и поэтому чем меньше аргументов, они должны пройти лучше. Им нужна функция, которая вычисляет общее количество часов работы человека в данном столбце, не зная, как долго будет этот столбец (и он будет часто переупорядочен), поэтому единственным аргументом, который я хочу, чтобы они были выбраны, является имя человека. Длина столбца должна быть автоматической. – basaltanglia

+0

Итак, передайте столбец как целый столбец и пересекайтесь с используемым диапазоном. –

+0

Не будет ли причиной ошибки самооценки? Моя полная версия использует идентификаторы столбцов в сочетании с Application.ThisCell.Row - 1 и Application.ThisCell.Row + 1 для вычисления диапазонов, не может заставить ее пытаться добавить или вычесть себя. – basaltanglia

Смежные вопросы