2017-02-18 56 views
0

我有這樣的VBA練成costum式:Excel的VBA costum式太慢

'=ConcatenateRangeIfs(A1;Sheet2!C:C;B1;Sheet2!D:D;Sheet2!G:G;". ") 
Function ConcatenateRangeIfs(_ 
    ByVal match_val1 As String, _ 
    ByVal match_range1 As Range, _ 
    ByVal match_val2 As String, _ 
    ByVal match_range2 As Range, _ 
    ByVal concatenate_range As Range, _ 
    Optional ByVal separator As String _ 
) As String 

'disable uncessary processing to improve performance 
Application.Calculation = xlCalculationManual 
Application.ScreenUpdating = False 
Application.DisplayStatusBar = False 
Application.EnableEvents = False 
ActiveSheet.DisplayPageBreaks = False 

Dim concatedString As String 
Dim toConcatenateCellValue As String 
Dim toConcatenateCellRow As Long 

For Each toConcatenateCell In concatenate_range.SpecialCells(xlConstants, 23) 
    toConcatenateCellValue = toConcatenateCell.Value 
    If Not IsEmpty(toConcatenateCellValue) Then 
     toConcatenateCellRow = toConcatenateCell.Row 
     If match_val1 = match_range1.Cells(toConcatenateCellRow, 1).Value Then 
      If match_val2 = match_range2.Cells(toConcatenateCellRow, 1).Value Then 
       concatedString = concatedString & (separator & toConcatenateCellValue) 
      End If 
     End If 
    End If 
Next toConcatenateCell 

If Len(concatedString) <> 0 Then 
    concatedString = Right$(concatedString, (Len(concatedString) - Len(separator))) 
End If 

'enable disabled processing 
ConcatenateRangeIfs = concatedString 
Application.Calculation = xlCalculationAutomatic 
Application.ScreenUpdating = True 
Application.DisplayStatusBar = True 
Application.EnableEvents = True 
ActiveSheet.DisplayPageBreaks = True 

End Function 

的Sheet 2中例如: enter image description here

的Sheet 1中示例,其中公式是在列d:d細胞: enter image description here

不明白爲什麼,但每次更改公式中使用的任何值時,它會花費太長的時間和凍結excel。 我試過禁用不必要的excel東西,並使用本地可訪問性來訪問對象屬性,但並沒有多大改變...

任何消音來提高性能?

+0

第一件事,我可以發現:'toConcatenateCellValue = toConcatenateCell.Value'不這樣做分配,當你沒有一個匹配。實際上,你根本不需要這個臨時變量,它是在所有單元格上執行的無用副本,包括那些不匹配的單元格! –

+1

一個'String'永遠不能是'Empty',所以'不是IsEmpty(toConcatenateCellValue)'總是會成爲'True'。 – YowE3K

回答

3

這應該是更快:

Option Explicit 
'=ConcatenateRangeIfs(A1;Sheet2!C:C;B1;Sheet2!D:D;Sheet2!G:G;". ") 
Function ConcatenateRangeIfs(_ 
     ByVal match_val1 As String, _ 
     ByRef match_range1 As Variant, _ 
     ByVal match_val2 As String, _ 
     ByRef match_range2 As Variant, _ 
     ByRef concatenate_range As Variant, _ 
     Optional ByVal separator As String _ 
     ) As String 

    Dim concatedString As String 
    Dim toConcatenateCellValue As String 
    Dim j As Long 

    ' get data into variant arrays 
5 If TypeOf match_range1 Is Range Then 
     Set match_range1 = Intersect(match_range1.Parent.UsedRange, match_range1) 
     match_range1 = match_range1.Value2 
    End If 
    If TypeOf match_range2 Is Range Then 
     Set match_range2 = Intersect(match_range2.Parent.UsedRange, match_range2) 
     match_range2 = match_range2.Value2 
    End If 
    If TypeOf concatenate_range Is Range Then 
     Set concatenate_range = Intersect(concatenate_range.Parent.UsedRange, concatenate_range) 
     concatenate_range = concatenate_range.Value2 
    End If 
    ' 
    ' assumes all arrays are equal length - no error checking 
    ' 
    For j = 1 To UBound(match_range1) 
     If Not IsEmpty(concatenate_range(j, 1)) Then 
      If match_val1 = match_range1(j, 1) Then 
       If match_val2 = match_range2(j, 1) Then 
        concatedString = concatedString & (separator & concatenate_range(j, 1)) 
       End If 
      End If 
     End If 
    Next j 

    If Len(concatedString) <> 0 Then 
     concatedString = Right$(concatedString, (Len(concatedString) - Len(separator))) 
    End If 
ConcatenateRangeIfs = concatedString 

End Function 
+0

確實...... –