2016-09-27 21 views
2

我想讓用戶更容易使用Excel表格而不必隨時修改繁重的表達式需要改變。我將函數的結果動態地放入單元格中。我得到的一切運作如何,除了:我用戶定義的VBA函數正在更新所有使用它的單元格,但我也不想要它

如果我去另一張表,並使用公式,它會返回正確的結果;但是,當返回到已經使用的另一張表單時,該表單將顯示最新的重新發送結果,而不再是其自己的傳遞變量實例。這些表單也與儀表板表格綁定,因此我需要確保如果計算一張表單,則不會篡改其他表單。我不知道該怎麼說這個問題,所以如果有我沒有使用的命名法,或者過去是否回答了這個問題,請告訴我,我會將其解決。

'------------------- 
'getScore 
' This function is called from a cell and is passed an intager. 
' The integer represents the section that it is being called from. 
' There is also the sheet title that is passed thrugh to the range. 
'------------------- 

Function getScore(section As Integer, sheetTitle As String) 
Application.Volatile 

Dim rngSt As Integer 
Dim rngEnd As Integer 

rngSt = getRange(section, sheetTitle, 1) 'Gets start range for formula 
rngEnd = getRange(section, sheetTitle, 2) 'Gets end range for formula 


Dim Formula As String 'Broken into seperate concatinated lines for readablility 
'-(COUNTBLANK(H" & rngSt & ":H" & rngEnd & "))," 
' This section uses nested if statements to acrue the score through each level. 

Formula = "=IF(SUM(D" & rngSt & ":D" & rngEnd & ")= nonBlank(D" & rngSt & ":D" & rngEnd & ")," 
Formula = Formula & "IF(SUM(F" & rngSt & ":F" & rngEnd & ")= nonBlank(F" & rngSt & ":F" & rngEnd & ")," 
Formula = Formula & "IF(SUM(H" & rngSt & ":H" & rngEnd & ")= nonBlank(H" & rngSt & ":H" & rngEnd & ")," 
Formula = Formula & "IF(SUM(J" & rngSt & ":J" & rngEnd & ")= nonBlank(J" & rngSt & ":J" & rngEnd & ")," 
Formula = Formula & "IF(SUM(L" & rngSt & ":L" & rngEnd & ")= nonBlank(L" & rngSt & ":L" & rngEnd & "),5,4),3),2),1), 0)" 

getScore = Eval(Formula) 'Evaluates formula and returns a score of 0-5. 

End Function 

這裏是getRange溫控功能

Function getRange(section As Integer, sheetName As String, rangePoint As Integer) 
    Application.Volatile 

    Dim FindRow As Range 

    Dim ws As Worksheet 
    Dim wb As Workbook 

    Set wb = ActiveWorkbook 

    If section = 1 Then 

     If rangePoint = 1 Then 
      With wb.Sheets(sheetName) 
       Set FindRow = .Range("C9:C9") 
      End With 
      getRange = FindRow.Row 
     End If 

    If rangePoint = 2 Then 
     With wb.Sheets(sheetName) 
      Set FindRow = .Range("C:C").Find(What:="rngEnd", LookIn:=xlValues) 
     End With 
     getRange = FindRow.Row - 1 
    End If 
    End IF 

    End Function 

這裏是我的評估和演示機能的研究

Function Eval(Ref As String) 
     Application.Volatile 
    Eval = Evaluate(Ref) 
    End Function 

非空溫控功能

Function nonBlank(r As Range) As Long 'Counts and returns the number of non blank cells found in given range. 
    Application.Volatile 
    nonBlank = r.Cells.Count - WorksheetFunction.CountBlank(r) 
    End Function 
+2

由於這是一個用戶定義函數(UDF),您不必使用'Formula'。您的所有邏輯都可以簡單地放在VBA中,以確定結果傳遞給單元格。 – PeterT

+0

這是因爲我有這個問題的公式方法嗎? –

+0

你可以發佈getRange函數嗎? –

回答

1

在你的情況,該函數返回你確切說出它。您的UDF沒有任何地方的工作表規範。第二張紙計算後,第一張紙上看到的是函數的返回值,因爲它是在第二張紙上計算的。這有點令人困惑,所以讓我試着另闢蹊徑。

  • 您與UDF在Sheet1中輸入公式
  • UDF計算工作表Sheet1上,與工作表Sheet1範圍
  • 您導航到Sheet2並重新計算UDF進入有
  • UDF計算在Sheet2上,與Sheet2的範圍
  • 同時在Sheet1上,UDF也使用Sheet2範圍計算(這個是您獲得相同結果的原因)

由於您在更改工作表時沒有發生計算,所以仍然可以正確計算結果。

底線(TL; DR):您的UDF寫得不好

爲了幫助解答您的問題,請按照Scott的要求發佈您的getRange函數,以及如何調用UDF的示例。 編輯:我看到你發佈了getRange函數,但它不完整。我想你可能錯過了一個End If語句。另外,你的getScore函數不會編譯,因爲你有一個額外的「>」字符。不確定它在那裏做什麼。

Formula = "=IF(SUM('" & sheetTitle & "'D" & rngSt & ":D" & rngEnd & ")= nonBlank('" & sheetTitle & "'D" & rngSt & ":D" & rngEnd & ")," 
Formula = Formula & "IF(SUM('" & sheetTitle & "'F" & rngSt & ":F" & rngEnd & ")= nonBlank('" & sheetTitle & "'F" & rngSt & ":F" & rngEnd & ")," 
Formula = Formula & "IF(SUM('" & sheetTitle & "'H" & rngSt & ":H" & rngEnd & ")= nonBlank('" & sheetTitle & "'H" & rngSt & ":H" & rngEnd & ")," 
Formula = Formula & "IF(SUM('" & sheetTitle & "'J" & rngSt & ":J" & rngEnd & ")= nonBlank('" & sheetTitle & "'J" & rngSt & ":J" & rngEnd & ")," 
Formula = Formula & "IF(SUM('" & sheetTitle & "'L" & rngSt & ":L" & rngEnd & ")= nonBlank('" & sheetTitle & "'L" & rngSt & ":L" & rngEnd & "),5,4),3),2),1), 0)" 

請注意,這是快速修復。我不會這樣寫一個UDF。但是如果我們深入研究,我們將需要更多的細節。

編輯:如果我明白你需要什麼,這是一個更短的版本,應該可以解決你遇到的問題...

Function Score(_ 
    ByVal Section As Long, _ 
    ByVal Anchor As Range _ 
    ) As Long 

    Dim CheckRange As Range 

    Application.Volatile True 
    Set CheckRange = Anchor.Parent.Range("C9", Anchor.Parent.Cells(Anchor.Parent.Rows.Count, "C").End(xlUp)) 

    Score = Abs(CLng(WorksheetFunction.CountA(CheckRange.Offset(0, 1)) = CheckRange.Cells.Count) + _ 
       CLng(WorksheetFunction.CountA(CheckRange.Offset(0, 3)) = CheckRange.Cells.Count) + _ 
       CLng(WorksheetFunction.CountA(CheckRange.Offset(0, 5)) = CheckRange.Cells.Count) + _ 
       CLng(WorksheetFunction.CountA(CheckRange.Offset(0, 7)) = CheckRange.Cells.Count) + _ 
       CLng(WorksheetFunction.CountA(CheckRange.Offset(0, 9)) = CheckRange.Cells.Count)) 

End Function 

然後,您可以從任何像這樣的小區調用這些.. 。

=Score(1,A1) 
=Score(1,Sheet2!A1) 
=Score(1,'Some other sheet'!A1) 

我甚至不確定'Section'變量的用途。這裏沒有太多解釋。

謝謝,Zack Barresse

+0

我在上面的一個編輯中發佈了它。老實說,我仍然在學習,我認爲,因爲我在函數中指定了工作表,它會保持它傳遞過去的工作表的上下文 –

+1

這是一個很好的想法,但是傳遞給評估的範圍不會獲取工作表名稱,所以它假定活動工作表,這是關鍵,也沒有定義「非空白」是什麼,我將編輯解決方案以包含需要發生的事情, –

+0

啊,對,nonBlank計算有信息的細胞 –

相關問題