私は4枚持っている:VBAユーザー定義関数#VALUEエラー
投資を
sample row-1: ABC, INV_ID1 sample row-2: ABC, INV_ID2 sample row-3: XYZ, INV_ID3 sample row-4: XYZ, INV_ID4
RETURNS-ABC
sample row: date1, status_INV_ID_1, returns_INV_ID_1, status_INV_ID_2, returns_INV_ID_2, totalABC=returns_INV_ID_1+returns_INV_ID_2
RETURNS-XYZ
sample row: date1, status_INV_ID_3, returns_INV_ID_3, status_INV_ID_4, returns_INV_ID_4, totalXYZ=returns_INV_ID_3+returns_INV_ID_4
戻りシートの数は将来的に増加させることができると私が所有者(ABC/XYZ等)に基づいてフィルタリングを提供しようとするので、私は
all_totals = totalABC + totalXYZ
したい
sample row: date1, all_totals
を合計、私はパラメータとしてdate1を持つ "TOTALS"シートのall_totals列から呼び出される以下のvba関数を書いています。これは機能しませんし、私の推測では、これは "User Defined Function"の制限に起因する可能性があります。
しかし、以下でわかるように、私は他のセル値を変更しておらず、関数が呼び出されているセルだけを変更しています。誰かがこれを修正する方法に関する提案があるのかどうか疑問に思うだけですか?
'========
'Returns the current month total due for ALL
'Data is pulled from individual owner sheets
Function getCurrentMonthTotalDue(theDate As Date) As Integer
' theDate - MANDATORY: Month for which data is needed
' RETURNS_PER_OWNER_INSTALLMENT_DATE_LIST - is a named range of all installment dates in the "RETURNS-XXX" sheets
' RETURNS_PER_OWNER_TOTAL_DUE_THIS_MONTH_LIST - is a named range of totals in the "RETURNS-XXX" sheets
Dim uniqueOwnerList as Variant
Dim returnsPerOwnerDateRange, returnsPerOwnerTotalDueRange as Range
Dim i,j as integer
Dim totalDue as Integer
totalDue = 0
uniqueOwnerList = getUniqueOwnerList
for i = LBound(uniqueOwnerList, 1) To UBound(uniqueOwnerList, 1)
'Construct the ranges to refer
returnsPerOwnerDateRange = Sheets(RETURNS_PER_OWNER_SHEET_PREFIX & uniqueOwnerList(i)).Range(RETURNS_PER_OWNER_INSTALLMENT_DATE_LIST)
returnsPerOwnerTotalDueRange = Sheets(RETURNS_PER_OWNER_SHEET_PREFIX & uniqueOwnerList(i)).Range(RETURNS_PER_OWNER_TOTAL_DUE_THIS_MONTH_LIST) '=====> CONTROL HITS THIS BREAKPOINT
for j = 1 to returnsPerOwnerDateRange.Count '=====> BUT DOES NOT HIT THIS ONE AND NO ERROR IS SHOWN
if (returnsPerOwnerDateRange(j).value = theDate) then
totalDue = totalDue + returnsPerOwnerTotalDueRange(j)
end if
next j
next i
'Return value
getCurrentMonthTotalDue = totalDue
End Function
EDIT:より多くのコンテキストを提供するために、完全なコードを含む:
Option Explicit
'GLOBALS
'--------
'Header names
Public Const COMMITTED_INVESTMENTS_OWNER_LIST = "COMMITTED_INVESTMENTS_OWNER_LIST"
Public Const COMMITTED_INVESTMENTS_TICKET_LIST = "COMMITTED_INVESTMENTS_TICKET_LIST"
Public Const COMMITTED_INVESTMENTS_ID_LIST = "COMMITTED_INVESTMENTS_ID_LIST"
Public Const COMMITTED_INVESTMENTS_SHEET_PREFIX = "INVESTMENTS"
Public Const RETURNS_PER_OWNER_SHEET_PREFIX = "RETURNS-"
Public Const RETURNS_PER_OWNER_TOTAL_DUE_THIS_MONTH_LIST = "RETURNS_PER_OWNER_TOTAL_DUE_THIS_MONTH_LIST"
Public Const RETURNS_PER_OWNER_INSTALLMENT_DATE_LIST = "RETURNS_PER_OWNER_INSTALLMENT_DATE_LIST"
Public Const RETURNS_PER_OWNER_INSTALLMENT_DATE_COLUMN_ID = 1
Public Const RETURNS_PER_OWNER_FIRST_INVESTMENT_ID_COLUMN_ID = 2
'UTILITY
'-------
'========
'Returns column number in the range containing the given header string
'Input range is assumed to be a single row range
Function getColumnNumber(theRange as Range, theColumnHeader as String)
' theRange - MANDATORY: The range in which search is to be made
' theColumnHeader - MANDATORY: The string to be searched
Dim myRow As Range
Dim myCell As Range
Dim myColumn as long
myColumn = -1
for each myRow in theRange.rows
for each myCell in myRow.Cells
myColumn = myColumn + 1
if myCell.Value = theColumnHeader then
getColumnNumber = myColumn
return
end if
next myCell
next myRow
getColumnNumber = -1
End Function
'FUNCTIONALITY
'-------------
'========
'Returns a list of unique entries from a given range
Function getUniqueListFromRange(theSourceRange as Range)
'Code courtesy Jean-François [email protected]
Dim varIn As Variant
Dim varUnique As Variant
Dim iInRow As Long
Dim iUnique As Long
Dim nUnique As Long
Dim isUnique As Boolean
varIn = theSourceRange
ReDim varUnique(1 To UBound(varIn, 1) * UBound(varIn, 2))
nUnique = 0
For iInRow = LBound(varIn, 1) To UBound(varIn, 1)
isUnique = True
For iUnique = 1 To nUnique
If varIn(iInRow, 1) = varUnique(iUnique) Then
isUnique = False
Exit For
End If
Next iUnique
If isUnique = True Then
nUnique = nUnique + 1
varUnique(nUnique) = varIn(iInRow, 1)
End If
Next iInRow
'// varUnique now contains only the unique values.
'// Trim off the empty elements:
ReDim Preserve varUnique(1 To nUnique)
getUniqueListFromRange = varUnique
End Function
'========
Function getUniqueOwnerList()
Dim myRange As Range
Set myRange = Sheets("INVESTMENTS").Range("COMMITTED_INVESTMENTS_OWNER_LIST")
getUniqueOwnerList = getUniqueListFromRange(myRange)
End Function
'========
Function getUniqueTicketList()
Dim myRange As Range
Set myRange = Sheets("INVESTMENTS").Range("COMMITTED_INVESTMENTS_TICKET_LIST")
getUniqueTicketList = getUniqueListFromRange(myRange)
End Function
'========
Function getUniqueInvestmentIDList()
Dim myRange As Range
Set myRange = Sheets("INVESTMENTS").Range("COMMITTED_INVESTMENTS_ID_LIST")
getUniqueInvestmentIDList = getUniqueListFromRange(myRange)
End Function
'========
Function isItemPresentinList(theItem as String, theList as Variant) as Boolean
Dim i as long
isItemPresentinList = False
for i=LBound(theList, 1) To UBound(theList, 1)
if (theList(i) = theItem) then
isItemPresentinList = True
return
end if
next i
End Function
'========
Function getColumnID(theColumnHeader as String, theHeaderRange as Range) as long
Dim columnIndex as long
Dim myCell as Range
columnIndex = 0
getColumnID = 0
for each myCell in theHeaderRange
columnIndex = columnIndex + 1
if myCell.Value = theColumnHeader then
getColumnID = columnIndex
return
end if
next myCell
End Function
'========
Function getInvestmentIDIndex(theInvestmentID as String) as long
Dim theIndex as long
theIndex = 0
'If provided SVR-1, will return 1
theIndex = Instr(theInvestmentID,"-")
if theIndex = 0 then
theIndex = -1
else
theIndex = theIndex + 1
end if
getInvestmentIDIndex = theIndex
End Function
'========
Function getAllInvestmentIDForOwner (theOwner as String) as Variant
Dim i as long
Dim j as long
Dim theInvestmentOwnerRange as Range
Dim theInvestmentIDRange as Range
Dim theInvestmentList as Variant
j = 0
ReDim theInvestmentList(1 To UBound(theInvestmentIDRange, 1) * UBound(theInvestmentIDRange, 2))
Set theInvestmentOwnerRange = Sheets(COMMITTED_INVESTMENTS_SHEET_PREFIX).Range("COMMITTED_INVESTMENTS_OWNER_LIST")
Set theInvestmentIDRange = Sheets(COMMITTED_INVESTMENTS_SHEET_PREFIX).Range("COMMITTED_INVESTMENTS_ID_LIST")
for i = LBound(theInvestmentOwnerRange, 1) To UBound(theInvestmentOwnerRange, 1)
if (theInvestmentOwnerRange(i) = theOwner) then
j = j + 1
theInvestmentList(j) = theInvestmentIDRange(i)
end if
next i
ReDim Preserve theInvestmentList(1 to j)
getAllInvestmentIDForOwner = theInvestmentList
End Function
'========
Function getAllInvestmentIDForTicket (theTicketID as String) as Variant
Dim i as long
Dim j as long
Dim theInvestmentOwnerRange as Range
Dim theInvestmentTicketRange as Range
Dim theInvestmentList as Variant
j = 0
ReDim theInvestmentList(1 To UBound(theInvestmentIDRange, 1) * UBound(theInvestmentIDRange, 2))
Set theInvestmentOwnerRange = Sheets(COMMITTED_INVESTMENTS_SHEET_PREFIX).Range("COMMITTED_INVESTMENTS_OWNER_LIST")
Set theInvestmentTicketRange = Sheets(COMMITTED_INVESTMENTS_SHEET_PREFIX).Range("COMMITTED_INVESTMENTS_TICKET_LIST")
for i = LBound(theInvestmentTicketRange, 1) To UBound(theInvestmentTicketRange, 1)
if (theInvestmentTicketRange(i) = theTicketID) then
j = j + 1
theInvestmentList(j) = theInvestmentIDRange(i)
end if
next i
ReDim Preserve theInvestmentList(1 to j)
getAllInvestmentIDForTicket = theInvestmentList
End Function
'========
Function getTicketForInvestmentID (theInvestmentID as String) as String
Dim i as long
Dim j as long
Dim theInvestmentIDRange as Range
Dim theInvestmentTicketRange as Range
Set theInvestmentIDRange = Sheets(COMMITTED_INVESTMENTS_SHEET_PREFIX).Range("COMMITTED_INVESTMENTS_ID_LIST")
Set theInvestmentTicketRange = Sheets(COMMITTED_INVESTMENTS_SHEET_PREFIX).Range("COMMITTED_INVESTMENTS_TICKET_LIST")
for i = LBound(theInvestmentIDRange, 1) To UBound(theInvestmentIDRange, 1)
if (theInvestmentIDRange(i) = theInvestmentID) then
getTicketForInvestmentID = theInvestmentTicketRange(i)
return
end if
next i
getTicketForInvestmentID = ""
End Function
'========
'Returns the current month total due for ALL
'Data is pulled from individual owner sheets
Function getCurrentMonthTotalDue(theDate As Date)
' theDate - MANDATORY: Month for which data is needed
Dim uniqueOwnerList as Variant
Dim returnsPerOwnerDateRange as Range
Dim returnsPerOwnerTotalDueRange as Range
Dim i as long
Dim j as long
Dim totalDue as long
totalDue = 0
uniqueOwnerList = getUniqueOwnerList
for i = LBound(uniqueOwnerList, 1) To UBound(uniqueOwnerList, 1)
'Construct the ranges to refer
Set returnsPerOwnerDateRange = Sheets(RETURNS_PER_OWNER_SHEET_PREFIX & uniqueOwnerList(i)).Range("RETURNS_PER_OWNER_INSTALLMENT_DATE_LIST")
Set returnsPerOwnerTotalDueRange = Sheets(RETURNS_PER_OWNER_SHEET_PREFIX & uniqueOwnerList(i)).Range("RETURNS_PER_OWNER_TOTAL_DUE_THIS_MONTH_LIST")
for j = 1 to returnsPerOwnerDateRange.CountLarge
if (returnsPerOwnerDateRange(j).value = theDate) then
totalDue = totalDue + returnsPerOwnerTotalDueRange(j)
end if
next j
next i
'Return value
getCurrentMonthTotalDue = totalDue
End Function
'========
'Returns the current month due for the specified parameters
'Data is pulled from individual owner sheets with name matching the template 'RETURNS-XXX'
Function getCurrentMonthDue(theDateRow As long, theOwnerList As Variant, theTicketList As Variant, theInvestmentList As Variant)
' theDateRow - MANDATORY: RowID of Month for which data is needed
' theOwnerList - MANDATORY: List of Owner names for which data is needed
' theTicketList - MANDATORY: List of Ticket IDs for which data is needed
' theInvestmentList - MANDATORY: List of Investment IDs for which data is needed
Dim uniqueOwnerList as Variant
Dim allInvestmentsList as Variant
Dim returnsPerOwnerDataRange as Range
Dim i as long
Dim j as long
Dim theColumnID as long
theColumnID = 0
uniqueOwnerList = getUniqueOwnerList
'FIRST: Loop through all owners mentioned in the filter value
for i = LBound(theOwnerList, 1) To UBound(theOwnerList, 1)
'SECOND: Loop through all investments for the specific owner from the filter values provided
allInvestmentsList = getAllInvestmentIDForOwner(CStr(theOwnerList(i)))
for j = LBound(allInvestmentsList, 1) To UBound(allInvestmentsList, 1)
'THIRD: Check if the ticketID and investmentID match the filter values provided
if isItemPresentinList(getTicketForInvestmentID(Cstr(allInvestmentsList(j))),theTicketList) AND isItemPresentinList(CStr(allInvestmentsList(j)),theInvestmentList) then
'Construct the ranges to refer
Set returnsPerOwnerDataRange = Sheets(RETURNS_PER_OWNER_SHEET_PREFIX & theOwnerList(i)).Range("RETURNS_PER_OWNER_DATA_RANGE")
'return the correct due amount
theColumnID = RETURNS_PER_OWNER_FIRST_INVESTMENT_ID_COLUMN_ID*getInvestmentIDIndex(CStr(theInvestmentList(j)))
getCurrentMonthDue = returnsPerOwnerDataRange (theDateRow)(theColumnID)
return
end if
next j
next i
'Return value
getCurrentMonthDue = 0
End Function
'========
Function getFilteredList(theShape as Shape)
Dim i As Long
Dim selectedCount As Long
Dim filteredList As Variant
selectedCount = 0
With theShape
ReDim filteredList(1 To .ListCount)
For i = 1 To .ListCount
If .Selected(i) Then
selectedCount = selectedCount + 1
filteredList(selectedCount) = .List(i)
End If
Next i
' Trim off the empty elements:
ReDim Preserve filteredList(1 To selectedCount)
End With
getFilteredList = filteredList
end function
'========
Function getOwnerFilteredList
getOwnerFilteredList = getFilteredList(Sheets("CONSOLIDATED SUMMARY").ListBoxes("List Box 8"))
End function
'========
Function getTicketFilteredList
getTicketFilteredList = getFilteredList(Sheets("CONSOLIDATED SUMMARY").ListBoxes("List Box 9"))
End function
'========
Function getInvestmentIDFilteredList
getInvestmentIDFilteredList = getFilteredList(Sheets("CONSOLIDATED SUMMARY").ListBoxes("List Box 10"))
End function
をコードが不完全である:あなたの実装から ' getUniqueOwnerList() 'は範囲を返さなければならず、そのセルは有効な行番号(文字列、ネガティブ、0、または空のセル)を含まなければなりません。しかし、より多くの問題があります:モジュールの上部にある 'Option Explicit'を使って基本的な問題を解消し、Integerのすべてのインスタンスを見つけ、** Longに置き換えてください**。すべての変数を適切に定義してください: 'Dim i、j as integer'という行は、iをVariant、jをIntegerとして定義します。必要なものがDim i As Long、j as Longとなります。 'returnsPerOwnerDateRange'と同じです。 –
上記を完了したら、範囲に割り当てるときに 'Set'キーワードを使用してください:' returnsPerOwnerTotalDueRange = Sheets(RETURNS_PER_OWNER ...) 'はSet returnsPerOwnerTotalDueRange = Sheets(RETURNS_PER_OWNER ...)'になり、 'returnsPerOwnerDateRangeを置き換えてください。 Count'を 'returnsPerOwnerDateRange.CountLarge'で –
Thxに変更しました。 getUniqueOwnerList()は問題にはならなかったので(関数が値を返していて、ループに入っていたので)、私は含めませんでした。実行制御が「設定範囲」を超えない理由を説明することはできません。 (PS:あなたのコメントを上記の質問の最後に組み込んだコードを含む) –