簡體   English   中英

從vba中的sub調用函數

[英]Call a function from sub in vba

我編寫了此函數,該函數應該從選定的范圍內獲取用戶定義的單元格,並將其值與用戶定義的數字相加或相乘。 輸出應為具有一個已更改單元格的數組。

我能夠編譯它; 但是,我不能這樣稱呼。

我試圖復制這個這個,但是失敗了。

Function Macro1(cellref As Range, row_number As Long, column_number As Long, x As Double, method As Integer) As Variant
'Number, which will be added or multiplied by chosen cell value in an array
'One for multiplication, two for addition
  If method = 1 Then
    Cells(row_number, column_number) = Cells(row_number, column_number) * x
  ElseIf method = 2 Then 
    Cells(row_number, column_number) = Cells(row_number, column_number) + x
  End If
  Result = Macro1
End Function

Sub try()
  Macro1(Range("A1:AX3").Select, 2, 2, 0.5, 1) = Result
End Sub

運行此代碼時,出現錯誤消息“運行時錯誤424,所需對象”。 Macro1(Range("A1:AX3").Select, 2, 2, 0.5, 1) = Result突出顯示為紅色

然后我嘗試

Function Macro1(cellref As Range, row_number As Long, column_number As Long, x As Double, method As Integer) As Variant
'Number, which will be added or multiplied by chosen cell value in an array
'One for multiplication, two for addition
  If method = 1 Then
    Cells(row_number, column_number) = Cells(row_number, column_number) * x
  ElseIf method = 2 Then 
    Cells(row_number, column_number) = Cells(row_number, column_number) + x
  End If
  Result = Macro1
End Function

Sub try()
  Macro1(Worksheets("Macro1").Range("A1:AX3"), 2, 2, 0.5, 1)
End Sub

但是我收到“類型不匹配錯誤13”消息。 Sub try()行以黃色突出顯示,其下面的行為紅色

我看到幾個問題:

,行

Result = Macro1

Macro1是對Macro1的遞歸調用。 Macro1正在嘗試自我調用。

因為Macro1需要參數(第一個參數是ObjectRangeObject )),並且沒有提供對象參數,所以會出現錯誤。 實際上,您沒有在此調用中提供任何必需的參數。


,代碼:

<functionName> = value

是倒退。 該行嘗試將Macro1 (賦值運算符=左側的<functionName> )設置為Result的值。 這是不可能的(至少在VBA中沒有)。 我相信您想要的是:

result = Macro1(Worksheets("Macro1").Range("A1:AX3"), 2, 2, 0.5, 1)

將執行Macro1使用指定的參數,然后將返回的值( Variant如你定義它)的Variant變量(因為你沒有Dim配有它) result


第三 ,您已經將Macro1聲明為Function ,但是沒有必要-它返回值,而是將其設置為已傳遞的Range的單元格。 最好將其更改為Sub ,因為這是它正在做的工作。 我認為您可能已經打算讓它在Result = Macro1行中返回一個值,但是如上所述,它不會這樣做。 VBA通過將要返回的值分配給Function名稱來工作,而不是像某些其他語言那樣使用return函數。 如果確實有想要返回的某種結果,則可以使用以下代碼為其分配:

Macro1 = <the value to be returned>

但是,我不確定您從Function實際返回的內容是什么,因為它可以在一個Range而不是單個Cell


第四 ,我不確定您為什么要接受整個Range作為Macro1的參數,然后在其中指定單個Cell 傳遞...Range("A1:AX3")然后指定我想column 2Row 2的那個范圍是太多的認知努力挑選出你是什么細胞后。 為什么不僅僅傳遞...Range("B2")並完成它呢? 好處是

1) Macro1直接與所需的單元格一起使用,並且僅與所需的單元格一起使用

2)呼叫者僅指定所需的單元格和所需的單元格

3)從參數列表中消除其他不必要的參數。


第五,您的Macro1收到一個Range參數以供處理,但從未引用它。 您接受cellref As Range ,但是在代碼體中,您正在使用Cells()並且從未引用過cellref 有兩個問題:

1)您有一個未指定的Cells() ,它將自動引用ActiveSheet ,無論您的意圖與否。

2)您根本不使用調用Macro1時傳遞的內容(它可以在Worksheet Workbook 任何 Worksheet上)。

通過指定Worksheets("Macro1").Range("A1:AX3")以便VBA 確切知道要在哪個單元格上,您在 Macro1的調用中非常具體。 但是,如果您恰巧在調用時正在查看Sheet2 ,則Macro1將與Worksheets("Sheet2").Range("B2")因為此時Activesheet = Worksheets("Sheet2")而不是Worksheets("Macro1")


第六,您不對輸入值做任何檢查。 如果傳遞的單元格中的值恰好是red而不是17.256會發生什么。 red * 2的值是多少? 為什么,這是Runtime error #13. Type mismatch Runtime error #13. Type mismatch 您需要某種形式的健全性檢查或錯誤處理,以確保您使用的是數字數據。


最后,我將通過執行前的健全性檢查來建議這樣的事情:

Function Macro1(cellref As Range, x As Double, method As Long) As Variant
'Number, which will be added or multiplied by chosen cell value in an array
'One for multiplication, two for addition

  Dim Result As Double

  If Not IsNumeric(cellref.Value) Then
    MsgBox ("The cell does not contain a numeric value")
    Exit Function
  End If

  If method = 1 Then
    Result = cellref.Value * x
  ElseIf method = 2 Then
    Result = cellref.Value + x
  End If
  Macro1 = Result

End Function

Sub try()
  With Worksheets("Sheet1")
    .Range("B2") = Macro1(.Range("B2"), 0.5, 1)
  End With
End Sub

或者,您可以進行錯誤處理並按以下方式進行操作:

Option Explicit

Function Macro1(cellref As Range, x As Double, method As Long) As Variant
'Number, which will be added or multiplied by chosen cell value in an array
'One for multiplication, two for addition

  On Error GoTo ErrorHandler

  Dim Result As Double

  If method = 1 Then
    Result = cellref.Value * x
  ElseIf method = 2 Then
    Result = cellref.Value + x
  End If

CleanExit:
  Macro1 = Result

ErrorHandler:
  MsgBox ("The cell does not contain a numeric value")
  Result = vbNull
  Resume CleanExit

End Function

Sub try()
  With Worksheets("Sheet1")
    .Range("B2") = Macro1(.Range("B2"), 0.5, 1)
  End With
End Sub

請注意, Option Explicit的包含要求您在使用它們之前聲明所有變量( Dim )。 這將有助於消除其他可能的錯誤,因為您會錯誤地將Variable1拼寫為Varaible1而VBA“有幫助”地為您創建了一個全新的變量,從而創建了一個很難發現的錯誤。


根據其他一些評論,我認為您正在嘗試為范圍內的許多單元格調用此方法。 在這種情況下,您可以向Try()過程添加一些簡單的循環,以遍歷所有需要應用的單元格。 如果不是,並且您正試圖基於該范圍內的其他值將其應用於“ Range的一個單元格,則需要修改它的某些部分以執行后續操作。 我希望這篇文章中有足夠的信息供您了解如何做到這一點。 如果沒有,那么一旦您完全理解了更改此單元格的過程后,可能會提出一個很大的后續問題。


附帶說明一下,有一個很棒的OSS VBE附加軟件,名為Rubberduck ,可幫助您發現和修復許多此類錯誤。 我是該工具的忠實擁護者,每天都會使用它,我也為該項目做出了貢獻。

首先,不需要不需要的cellref參數。

就像@nacorid和@Jnevill所說的那樣,結果= Macro1不執行任何操作,代碼只是跳過了它。 如果要返回函數,則為Macro1 = result。 但是,您不分配任何結果,因此它仍然不會做任何事情。 您還需要在sub try()創建一個分配以捕獲返回值。

我不確定您期望的輸出是一個具有一個已更改單元格的數組,您正在更改一個單元格,但它不是一個數組,您只是在此行直接更改其值: Cells(row_number, column_number) = Cells(row_number, column_number) * x

編輯:這是您加載陣列,修改並將其粘貼到其他位置的方式。

您將需要添加一些錯誤處理,以免類型不匹配。

您可能還希望使用pasterange的偏移量使其更具動態性。

sub macro1()
    Dim rngarr() As Variant
    Dim divisor As Double
    Dim targetcol As Long
    Dim targetrow As Long
    Dim pasterange As Range

    rngarr = Range("A1:AX3").Value
    'Remember that your array starts at index 1
    'A range that starts at row 2 will still have an index 1
    targetcol = 2
    targetrow = 2

    divisor = 0.5

    rngarr(targetrow, targetcol) = rngarr(targetrow, targetcol) * divisor

    Set pasterange = Range("A5:AX7")

    pasterange = rngarr
end sub

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM