Presently i have a vba which i am using as an add-in in excel to call some UDF. the functions take in parameters such as a range of numbers, and some attributes about these numbers and constants.
e.g. ROR(some_range_of_numbers,weekly)
the second parameter has the following options. it could be either Daily or weekly or monthly or quarterly or annual. if its daily i use 365, if its weekly i use 52, if its monthly i use 12 if its Qtrly then i use 4 and Annual i use 1 as one of the components of the formula in the UDF.
now, my question is when the user wants to use the function, i want to force the user to input daily or weekly etc. i remember something about using types or parameters in VB. But am lost here. Any help will be greatly appreciated.
Thanks
Try below function:
Function ROR(rng As Range, interval As String)
Dim intervalNum As Integer
select Case LCase(interval)
Case "daily":
intervalNum = 365
Case "weekly":
intervalNum = 52
Case "monthly":
intervalNum = 12
Case "quarterly":
intervalNum = 4
Case "annual":
intervalNum = 1
End Select
Debug.Print intervalNum
End Function
Updated code after comments :
Enum interval
daily = 365
weekly = 52
monthly = 12
quarterly = 4
annual = 1
End Enum
Function ROR(rng As Integer, val As interval)
End Function
Also you can use type wherein you will get it as dropdownlist.
Type interval
daily As Integer
weekly As Integer
monthly As Integer
quarterly As Integer
annual As Integer
End Type
Related
I am in need of your assistance with my visual basic code. I need to display the double depreciation of a product. Each year the product will lose value. I need to display the year and the value it lost in that particular year using Visual Basic
I have the Interface the code but when I run the code I get incorrect output.
For example:
Product cost is R 5000
Useful Life is 5 Years
when I apply the formula to the problem the answer should be:
1 should be 2000
2 should be 1200
3 should be 720
4 should be 432
5 should be 259.20
With my code I do get year 1 correct but years 2 - 5 have the same answer as year 1.
I have used a for loop to do the calculations but it seems to be stuck at year 1.
Any assistance will be appreciated as I am completely new to programming.
Calculating the Depreciation
Sub Calculations()
For yr As Integer = 1 To Life
If yr <= Life Then
Depreciation = (2 / Life) * Cost
lstBalances.Items.Add(yr & " " & Depreciation)
End If
Next
End Sub
You're not adjusting the cost for the next calculation. Also your line If yr <= Life Then is redundant. The scope of the loop is already defined in the For/Next context and yr will always be less than or equal to Life.
Sub Calculations()
For yr As Integer = 1 To Life
Depreciation = (2 / Life) * Cost
lstBalances.Items.Add(yr & " " & Depreciation)
Cost = Cost - Depreciation
Next
End Sub
I made a custom function in Excel VBA:
Option Explicit
Function Units(budgetYear As Integer, birthday As Date, serviceStart As Date, serviceEnd As Date, isMarried As Boolean, isServingAbroad As Boolean) As Double
' in this function all dates are converted to the first day of the date's month to make calculations easier
Dim units As Double: units = 0
' service end date cannot be earlier than service start
If serviceEnd < serviceStart Then
Units = units
Exit Function
End If
Dim firstMonthOfYear As Date: firstMonthOfYear = DateSerial(budgetYear, 1, 1)
Dim lastMonthOfYear As Date: lastMonthOfYear = DateSerial(budgetYear, 12, 1)
Dim newServiceStart As Date: newServiceStart = FirstOfTheMonth(serviceStart)
Dim newServiceEnd As Date: newServiceEnd = FirstOfTheMonth(serviceEnd)
Dim eighteenthBirthday As Date: eighteenthBirthday = DateSerial(year(birthday) + 18, Month(birthday), 1)
Dim thisYearServiceStart As Date: thisYearServiceStart = WorksheetFunction.Max(newServiceStart, firstMonthOfYear)
Dim thisYearServiceEnd As Date: thisYearServiceEnd = WorksheetFunction.Min(newServiceEnd, lastMonthOfYear)
Dim serviceMonthsThisYear As Integer: serviceMonthsThisYear = (Month(thisYearServiceEnd) - Month(thisYearServiceStart)) + 1
' unit multipliers
Dim serviceTypeMultiplier As Integer: serviceTypeMultiplier = 1
If isServingAbroad Then serviceTypeMultiplier = 2
' service must fall in the budget year supplied
If newServiceStart > lastMonthOfYear Or newServiceEnd < firstMonthOfYear Then
Units = units
Exit Function
End If
If isMarried Then
units = serviceMonthsThisYear
ElseIf eighteenthBirthday < thisYearServiceStart Then
' this person is already eighteen in the supplied year
units = serviceMonthsThisYear * 0.5
ElseIf eighteenthBirthday > thisYearServiceEnd Then
' this person is under eighteen in the supplied year
units = serviceMonthsThisYear * 0.25
Else
' this person turns eighteen during the supplied year
Dim underEighteenMonths As Integer: underEighteenMonths = (Month(eighteenthBirthday) - Month(thisYearServiceStart))
Dim overEighteenMonths As Integer: overEighteenMonths = serviceMonthsThisYear - underEighteenMonths
units = (underEighteenMonths * 0.25) + (overEighteenMonths * 0.5)
End If
' multiply units by servingAbroad multiplier
units = units * serviceTypeMultiplier
Units = units
End Function
Private Function FirstOfTheMonth(dateToConvert As Date) As Date
FirstOfTheMonth = DateSerial(year(dateToConvert), Month(dateToConvert), 1)
End Function
I have a lookup table (named Table1):
I want to run the function above on each of the rows that match a certain criteria in the lookup table via an array formula.
I've tried this:
=SUM(IF(Table1[Payee]="Bill",Units(G1,"1/2/2003",Table1[Start],Table1[End],Table1[Status],Table1[Location])))
This just gives me #VALUE.
I want it to do like the SUM function. If I had another column in the lookup table called value, I could do this:
=SUM(IF(Table1[Payee]="Bill",Table1[value]))
And it would sum the value column just for the rows that match the criteria ("Bill").
How can I get the same to work with my custom function? I would prefer not to have to modify the custom function. The array formula should run the custom function for each row that matches the criteria. Am I misunderstanding how array functions work in Excel?
Edit:
Just in case it makes a difference, I'm using the latest version of Excel from Office 365 on a Mac.
Edit 2:
Added the full code from the function. Basically the function takes the months served in the budgetYear and applies a weight to them. Months under eighteen get 0.25 weight, months eighteen or older get 0.5 weight, and married gets 1 weight. If isServingAbroad is TRUE, the result gets multiplied by 2.
I have a data set which includes dates.
I need to split this out by week number for reporting purposes.
What I have so far is:
startDate variable containing 03/01/2015 (populated from data in spreadsheet)
startDay = Day(startDate)
startMonth = Month(startDate)
startYear = Year(startDate)
startWeek = Application.WorksheetFunction.WeekNum(DateSerial(startYear, startMonth, startDay))
which gives me week 1 in startWeek
However I know need to know how far into week 1 the date is.
So for this example, as the date is the 3rd of January, it includes 3 days of week 1
Meaning the reporting I'm putting together will only report on 3 days (as opposed to the full week)
The only way I've figured to do this so far is to calculate which day of the year the date is and the use a MOD calculation (basically divide by 7 and the remainder is how far into the week it is)
dayNumber = DateDiff("d", DateSerial(startYear, 1, 1), DateSerial(startYear, startMonth, startDay)) + 1
dayOfWeek = dayNumber Mod 7
This does work, but I was wondering if there was a nicer solution than this.
You could use a loop to determine how many days before startDate the week number changed:
Public Sub FindDaysInWeekNo()
Dim startDate As Date
startDate = DateSerial(2015, 1, 3)
Dim startWeek As Integer
startWeek = Application.WorksheetFunction.WeekNum(startDate)
Dim i As Integer
Do While startWeek = Application.WorksheetFunction.WeekNum(DateAdd("d", -i, startDate))
i = i + 1
Loop
Debug.Print i '= 3rd day in this week number
End Sub
The following table shows my comparison to the other suggested formulas and why I think that (refered to =WEEKNUM) my calculation is correct.
Note that if you assume 1st to 7th January will be week 1 (days 1 to 7) you cannot use the WeekNum function because this will give you a different result (see table above and note that the first week has only 6 days according to the WeekNum function). Also you cannot name this week number (as what everybody calls week number is defined as https://en.wikipedia.org/wiki/Week#Week_numbering).
Instead you will need to use …
Public Function AlternativeWeekNum(startDate As Date) As Integer
AlternativeWeekNum = WorksheetFunction.Days(startDate, DateSerial(Year(startDate), 1, 1)) \ 7 + 1 'note that this no normal division but a integer division and uses a backslash instead
End Function
to calculate the week number your alternative way, and …
Public Function AlternativeWeekNumDay(startDate As Date) As Integer
AlternativeWeekNumDay = WorksheetFunction.Days(startDate, DateSerial(Year(startDate), 1, 1)) Mod 7 + 1
End Function
to calculate the day in the alternative week.
You can use the Weekday() function for this:
=WEEKDAY(B4;2)
The second parameter mentions how you want your days to be counted (starting from Sunday or Monday, counting starting from 0 or from 1, ...).
dayOfWeek = (8 + Weekday(startDate) - Weekday(DateSerial(startYear, 1, 1))) mod 7
Just take the positive mod 7 of the difference between the current Day-Of-Week and the Day-Of-Week for the 1st January of whatever the year is
7000
10008.54
13665.45
18110.44
23513.35
30080.62
38063.19
47766.04
59559.92
73895.45
91320.39
112500.50
In the above list, 7000 is stationary. From 10,008.54 to downwards, I have the following formula pulled down with $N$27 containing 1500 (does not change)
=((((M27*1.05)*1.05)*1.05)*1.05)+$N$27
This essentially calculates 7000 compounded 4 times monthly with 1500 added at the end of period. In excel I was able to come up with this
=FV(P32,P29,-N27)+(P31*POWER((1+P32),P29))
P32 = .05
P29 = 48
N27 = 1500
First FV calculates the FV of 1500 end of 48 periods with interest rate of 5%
The second part simplifies the table above. However the results differ by huge margin.
Question being: How else can I show my list above in short simple formula. I want the beginning of the month value compounded 4 times/weekly the following month + a payment added at the end of the month for up to 1 year.
Any leads and your time is appreciated.
I will put this out there. This is a UDF that will do what you want. I realize that you did not ask for a vba answer but just in case you are open to one:
Function FVSPECIAL(rate As Double, nper As Double, PV As Double, PMT As Double, PMTEvry As Double)
Dim i As Integer
Dim otpt As Double
otpt = PV
For i = 1 To CInt(nper / PMTEvry) - 1
otpt = otpt * (1 + rate) ^ (PMTEvry) + PMT
Next i
FVSPECIAL = otpt
End Function
Add a module to the workbook and paste this into it.
Then call the function. To call it you would, using the cells from the question
=FVSPECIAL(P32,P29,M27,N27,4)
It basically is FVSPECIAL(Rate,Nper,PV,PMT, # of NPer per payment)
I have a date with this format : 14w01 (year : 2014 week number : 1)
I want to convert this date in month like this : 14m01
Is there a function which converts a week number in a month number ?
Maybe something like this (in vba, not in formula) :
Format(weekNumber, "mm")
Thank you
It depends on how the weeks are defined. One way is to say that the first day of week#1 of a year is 1 January of that year. For this definition, a typical UDF is:
Public Function MonthFromDt(s As String) As Integer
Dim yr As Integer, wk As Integer, d As Date
ary = Split(s, "w")
yr = CInt(ary(0)) + 2000
wk = ary(1)
MonthFromDt = Month(DateSerial(yr, 1, 1) + 7 * (wk - 1))
End Function
There are other definitions of week number.
The DateFormat function is quiet comfortable, however the DateValue function, which parses a date, won't probably support your week format.
I suggest a trick with DateAdd, as DateAdd can handle weeks.
First split your date in year and week number:
Dim parts
parts = Split("2014w33", "w")
Dim year
Dim week
year = CInt(parts(0))
week = CInt(parts(1))
Then, add both to a "zero-date" to add up to the final date. Note that if you give "0" as year for DateAdd, VBA compiler interprets 2000.
dim DateResult
DateResult = dateAdd("yyyy", (year - 2000), DateValue("Jan 1, 0"))
Debug.Print dateResult
DateResult = dateAdd("ww", week, dateResult)
Debug.Print dateResult
Then show the result reformatted:
Debug.Print Format(DateResult, "yyyy\mm")
This prints on my side:
01.01.2014
20.08.2014
2014m08
August 2014, there is week 33 if I look up in the calendar. Seems correct.
I found a way to do it without VBA (and only using Formulas). This assumes A1 contains the "14w01" format
=LEFT(A1,2)&"m"&TEXT(MONTH(DATE(20&LEFT(A1,2),1,1)+(RIGHT(A1,2)*7)),"00")
Heres a breakdown of what the code does..
LEFT(A1,2) returns "14" (year)
MONTH(DATE(20&LEFT(A1,2),1,1)+(RIGHT(A1,2)*7)) converts the week # to the month # and it takes in the year 20&LEFT(A1,2) as well as week # RIGHT(A1,2)
TEXT(...,"00") pads the month # with a 0 if necessary (i.e. 3 becomes 03)
Then we just combine everything together to get "14m01"