2009-08-18 4 views
5

거의 모든 UDF를 사용하는 Excel 모델이 있습니다. 120 열, 400 행 이상이 있습니다. 계산은 수직적으로 그리고 나서 수평 적으로 행해진 다 - 먼저 컬럼 1에 대한 모든 계산이 끝난 다음 컬럼 1의 최종 출력은 컬럼 2의 입력이다. 각 컬럼에서 나는 약 6 또는 7 개의 UDF를 호출한다. 다른 UDF를 호출하십시오. UDF는 종종 h 열을 출력합니다.Excel 및 속도 문제 사용자 정의 함수

각 UDF에 대한 입력은 여러 변수, 일부 범위 변수 및 일부 복식입니다. 범위 변수는 내용에 액세스하기 전에 내부적으로 배열로 변환됩니다.

내 문제는 다음과 같습니다. UDF없이 Excel 모델을 만들 수 있으며 시뮬레이션을 실행하면 X 시간으로 모든 계산을 마칠 수 있습니다. UDF를 사용할 때 시뮬레이션 시간은 3X 시간 이상입니다. 명백한 질문에 답하기 위해 모델에 작은 변경 (예 : 다른 자산 유형 추가 (재무 모델))을하려는 경우 모델 재 작성 작업이 거의 하루가 걸리기 때문에 UDF를 사용해야합니다. 새로운 법적/재무 구조에 맞는 UDF가없는 경우 UDF를 사용하면 다른 재무 구조를 수용하는 데 약 20 분이 소요됩니다.)

어쨌든 화면 업데이트를 해제 했으므로 기능에 복사 및 붙여 넣기가 없습니다 , Variant 타입의 사용은 최소이고, 모든 데이터는 하나의 시트에 포함되어 있습니다. 나는 내용을 얻기 전에 모든 범위 타입 변수를 배열로 변환합니다.

VBA 코드/Excel 파일이 더 빨리 실행되도록하기 위해 더 빠른 컴퓨터 나 그와 비슷한 제품을 얻는 것 이외에 할 수있는 다른 방법은 무엇입니까? 더 많은 설명이 필요한 경우 알려 주시기 바랍니다.

감사합니다.

wks.EnableCalculation = False 

또는 또한

Application.Calculation = xlCalculationManual 

+0

여기에 기능을 게시 할 수 있습니까? 또는 단순화 된 버전으로 볼 수 있습니다. –

+0

와우, 나는 그렇게 빨리 반응을 얻을 것이라고 생각하지 않았다. 일주일 동안 어떤 일이 일어 났는지에 대한 간단한 버전을 게시 할 수 있는지 알 수 있습니다. 메시지 주셔서 감사합니다! –

+0

C에서 UDF를 코딩하고 XLL로 패키징하는 프로그래머 오버 헤드가 VBA UDF를 많이 호출하지 않아도 실행 오버 헤드를 절약 할 수있는 것처럼 보입니다. – jtolle

답변

1

제어 및 최소화 재 계산이 VBA와 통합 문서 사이의 교류를 최소화한다. 읽어야 셀하여 배열

MyArray = range("B2:B20000") 

보다는 세포 내로 한번에 셀 진영 쓰기 빠르다 (각 ...).

+0

아, 그래야했는데, 계산이 수동으로 설정되었습니다. 불행히도, 계산의 특성은 내가 입력으로 전체 범위를 미리 가져갈 수 없다는 것을 요구합니다. 그것은 func1 (A1 : A5)가 A6 : A10으로 출력하고, func2 (A6 : A10)가 A11 : A15 등으로 출력합니다. –

+0

또한 Range ("xxx")를 사용할 수 있습니다. 필요한 경우 계산하십시오. –

4

몇 가지 일반적인 팁.

  1. 병목 현상이 실제로 발생하는 곳에서 기능을 수행하고 해결하십시오. 엑셀의 use of timer에 대한이 질문을 참조하십시오. 저기에 VBA 프로파일 러가 있다고 확신합니다.하지만 아마도 그렇게 멀리 갈 필요는 없습니다. :

  2. 이 당신의 디자인에 대해 생각 (NB ... 첫 번째 데이터의 하나 개의 셀이 할) ... 데이터의 400x120 세포 하지 많은입니다. 고통 스러워야하는 시간이 필요합니다. (과거에 VLOOKUPS()의 1000 초 동안을 반환하기 위해 잠시 기다린 후 금이갔습니다. 어쨌든 UDF 스택을 사용하는 대신 간단한 서브 루틴이없는 이유는 for..each이고 범위를 통해 필요한 것은 수행합니다. 할 것. 48,000 개의 셀에 몇 초 또는 몇 분이 걸릴 수 있습니다. 그런 다음 서브 루틴을 사용자의 단추 또는 메뉴 항목과 연결할 수 있습니다.관심의 아웃

i는 각각의 모든 셀에 UDF를하는 것보다, 나를 위해 빠른 10 배를 일 옵션 2 얼핏을했고 활성 선택을 호출하기 위해 하위 DoMyUDF()를 사용하여, MYUDF()를 생성 . 당신이 계속해서 또 다시 같은 CALCS을 반복하는 경우에 특히. 당신이 당신의 UDF와 MyUDF()를 교체 할 경우

Option Explicit 



Function MyUDF(myVar As Variant) As Variant 
    MyUDF = myVar * 10 
End Function 

Sub DoMyUDF() 
    Dim r As Range 
    Dim c As Variant 

    Dim t As Single 
    t = Timer 


    If TypeName(Selection) <> "Range" Then 
    Exit Sub 
    End If 


    Set r = Selection.Cells 

    Application.DisplayStatusBar = True 

    For Each c In r 
    c.Value = MyUDF(c.Value) 

    Application.StatusBar = "DoMyUDF(): " & Format(Timer - t, "#0.0000ms") 
    Next 

    Debug.Print "DoMyUDF(): " & Format(Timer - t, "#0.0000ms") 

End Sub 

이 만 4.5 분을 절약 할 수 있습니다 ...하지만 당신이 만들 수있는 몇 가지 다른 경제가이 가능합니다.

+0

흥미 롭습니다. 나는 이것을 밖으로 시험 할 것이다. 문제는 120x400 셀의 데이터가 많지 않지만 30,000 개 이상의 시뮬레이션을 수행해야한다는 것입니다. 과거에는 UDF가없는 한 시간 안에이 작업을 수행 할 수 있었지만 지금은 3 시간 정도 걸립니다. 나는 당신의 제안을 시도하고 무슨 일이 일어나는 지 볼 것입니다. 한편, 응답 시간을내어 주셔서 감사합니다! –

+0

또한 워크 시트의 사용 범위에 변형 배열을로드 한 다음 해당 배열에 셀 값을 채우고 해당 변형 배열을 사용 범위 값으로 배치하여 작업을 조금 더 빠르게 만들 수 있습니다. 이것은 Excel이 각 개별 셀에 한 번에 하나씩 값을 입력하도록하는 것보다 훨씬 빠릅니다 ... –

2

Excel에서 UDF를 처리하는 방식에 속도 저하 버그가 있습니다. UDF가 계산 될 때마다 Excel은 VBE 제목 표시 줄을 새로 고칩니다 (깜박임). 다수의 UDF의 경우 이것은 매우 @립니다. 바이 패스는 수동 계산 모드에서 매우 간단합니다. Application.Calculate와 같은 것을 사용하여 VBA에서 계산을 시작하십시오 (OnKey를 사용하여 F9 등을 트래핑 할 수 있음).

자세한 내용은 http://www.decisionmodels.com/calcsecretsj.htm을 참조하십시오.

+0

+1 링크에 +1이 링크 소유자가됩니다! – jtolle

3

출력 셀당 한 번 호출되는 UDF를 루프의 셀 범위에서 작동 할 수있는 매크로로 바꾸는 것이 좋습니다.

UDF 설정/해제가 매우 느리며 각 UDF 호출은 다른 UDF와 공통적으로 작용합니다 (예 : 중복 입력에서 읽기)가 추가 작업이됩니다.

성능을 10-50x 향상시킬 수있었습니다. 한 달 전에 4000-30000 UDF 호출이 포함 된 스프레드 시트와 관련된 상황이 있었지만 몇 가지 이름이 지정된 범위에서 작동하는 단일 매크로로 바뀌 었습니다 .