2016-05-03 3 views
-1

У меня есть лист Excel, который стал очень медленным. По какой-то причине, где бы я ни находился в документе, если я настрою Calculation на ручной и обновить текущий лист после любых изменений, он достаточно быстр и служит моей цели.Excel Автоматический расчет только на уровне листа

Это не очень удобно.

Я бы хотел, чтобы текущий лист (а не весь документ) обновлялся всякий раз, когда менялась ячейка. Это должно быть сделано на любом листе, в котором я включен. Как я могу это сделать?

EDIT: пусть будет ясно, что я не прошу подсказки о том, как сделать мою книгу быстрее, это была просто контекстная информация. Меня интересует только автообновление.

+0

Если вы не предоставите много, гораздо больше информации, мы можем только догадываться! Слишком много разных факторов, которые могут оказать влияние (автоматические ссылки, UDF, события на листах или изменениях, количество данных/листов/формул, неработающие ссылки в именованных диапазонах и т. Д.). Итак, если вы не обновите свой вопрос всеми возможными факторами, мы ничего не сможем сделать. Тем не менее, если вы обновляете свой вопрос со всеми возможными факторами воздействия, вы также можете проверить их и найти ошибку самостоятельно. – Ralph

+0

@ Ralph, может быть, я не был достаточно ясен, я отредактировал свой вопрос. Я работаю над медленностью моего файла, но это не проблема. Хорошим быстрым решением было бы иметь этот набор авторесурсов, но только на уровне листа, вот что я спрашиваю здесь. –

+1

Если вы хотите, чтобы Excel обновлял и вычислял все каждый раз, когда ячейка была изменена, вам просто нужно установить 'Application.Calculation = xlCalculationAutomatic', что эквивалентно входу в меню:' Формулы' -> 'Параметры расчета' - -> 'Автоматический'. Тем не менее, это значение по умолчанию для листов Excel в любом случае. В качестве альтернативы вы можете использовать событие «Worksheet_Change» и просто отбросить одну строку в этот подраздел 'ActiveSheet.Calculate'. – Ralph

ответ

1

Charles Williams имеет обширную информацию, техника и код при расчетах на своем сайте http://decisionmodels.com. Цитата из this page:

Другой метод использует свойство worksheet.enablecalculation. Когда это свойство изменилось, все формулы на листе отмечены как нерасчетные, поэтому для переключения свойства на false, а затем обратно на true для всех листов во всех открытых книгах приведет к вычислению следующего расчета.

> Dim oSht as worksheet Application.Calculation=xlCalculationManual 
> 
> for each oSht in Worksheets oSht.enablecalculation=false 
> osht.enablecalculation=true next osht 
> 
> Application.calculate 

Вы также можете использовать этот метод для одного листа, чтобы сделать полный лист Calculate.

Вы можете легко работать эту технику в случае Worsheet_Change, как это:

Private Sub Worksheet_Change(ByVal Target As Range) 

Application.Calculation = xlCalculationManual 

Me.EnableCalculation = False 
Me.EnableCalculation = True 
Me.Calculate 

End Sub 

Это будет делать полный расчет текущего листа только и оставить все остальные листы нерасчетливый.

+0

Спасибо @teylin, я мог бы заставить его работать благодаря вашему ответу, но я свел ее к Private Sub worksheet_change (ByVal Target As Range) Если Application.Calculation = xlCalculationManual Тогда Me.Calculate End Sub Я не уверен, что цель Me.EnableCalculation = False/Me.EnableCalculation = True здесь , вы можете уточнить? –

+1

Почему вы не читаете мое сообщение снова .... – teylyn

+0

Вы говорите, что «переключение свойства на false, а затем обратно на true для всех листов во всех открытых книгах приведет к тому, что следующий расчет будет полным вычислением». но, насколько я понимаю, application.calculate уже является полным вычислением, и аналогичным образом во второй части me.calculate мне кажется достаточно –

0

Я считаю, что событие Расчет может произойти в заявке, Worksheet или Range уровня (но не уровень Workbook.)

Если режим расчета установлен ручной режим, но требуется текущий рабочий лист (только) обновляется при введите что-то, вы можете добавить событие изменения листа (кладя код в соответствующем листе.)

Private Sub Worksheet_Change(ByVal ChangedRng As Range) 
    ChangedRng.Worksheet.Calculate 
End Sub 

Это будет пересчитывать только рабочий лист, а не остальные Workbook или любые другие книги.

0

Поскольку предоставленные ответы не полностью удовлетворяют меня, это мое собственное, заимствование из их благодарной помощи. Возможно, я пропустил какой-то нюанс от ответа Тейлина. Я с удовольствием отредактирую, если это будет актуально.

Невозможно обработать события изменений на уровне APPLICATION.

Таким образом, все изменения должны обрабатываться на уровне ЛИСТ.

Это может быть сделано путем копирования и вставки этот фрагмент кода в каждом листе объекта книги (и не забудьте скопировать и вставить его это всякий раз, когда вы добавляете новый лист):

Private Sub worksheet_change(ByVal Target As Range) 
    Me.Calculate 
End Sub 

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

Мы также можем не вводить петлю ада, если мы делаем массовое изменение на одном листе (скажем, через макрос, перетащить & drop или ctrl + H).

Для этого мы добавим новый лист под названием WS_refresh, где мы устанавливаем 3 значения:

  • в A2: Да/Нет, чтобы включить/не отключить нашу новую функцию
  • в A4: время последнего обновления
  • в A6: мин интервала, чтобы обновления, в секундах (я поставил его в 1)

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

Это то, что должно быть скопировано и вставлено в каждом объекте листа:

Private Sub worksheet_change(ByVal Target As Range) 
auto_refresh = ThisWorkbook.Worksheets("WS_refresh").Range("A2") 
If auto_refresh = "Yes" Then 
    last_refresh = ThisWorkbook.Worksheets("WS_refresh").Range("A4") 
    refresh_interval_sec = ThisWorkbook.Worksheets("WS_refresh").Range("A6") 
    refresh_interval_tv = TimeValue("0:00:" & refresh_interval_sec) 
    If Application.Calculation = xlCalculationManual And Now() > last_refresh + refresh_interval_tv Then 
     ThisWorkbook.Worksheets("WS_refresh").Range("A4") = Now() 
     Me.Calculate 
    End If 
End If 
End Sub 
Смежные вопросы