Why does my function tell me that I have a Type Mismatch? - function

I'm trying to get the following function to work:
Private Function FirstOfMonth(MonthsAgo As Integer) As Date
FirstOfMonth = DateSerial(Year(Now()), Month(Now() - MonthsAgo), 1)
End Function
I'm passing in a value as follows:
FirstOfMonth(4)
The aim of the function is to return the date for the first of the month a number of 'MonthsAgo'.
However, whenever I run it it tells me that I have a Type Mismatch.
I'm new to programming, so if there's anyone that can point me in the right direction as to where I'm going wrong, I'd be very grateful. It's slowing me down solving a fairly simple problem.

I think what you meant to be doing was:
' Note the brackets change around 'Month(Now()) - MonthsAgo'
FirstOfMonth = DateSerial(Year(Now()), Month(Now()) - MonthsAgo, 1)
However, even this won't work. Consider the case where the month is January (1). In that scenario you will end up with a Date of 2012/-3/1 which is obviously complete nonsense!
You will instead need to use the DateAdd function:
DateAdd("m", 4, Now())
So your entire function looks like
Private Function FirstOfMonth(MonthsAgo As Integer) As Date
Dim newDate
newDate = DateAdd("m", 0 - MonthsAgo , Now())
FirstOfMonth = DateSerial(Year(newDate), Month(newDate), 1)
End Function

You must pass FirstOfMonth(4) into a "Date" variable

Related

Expression.Error: A cyclic reference was encountered during evaluation. - using custom function NetWorkDays in Power Query

I have created a custom function from a blank query to calculate the number of days excluding holidays and the weekends, the function is below
Query1 = (StartDate as date, EndDate as date) as number =>
let
DateList = List.Dates(StartDate, Number.From(EndDate - StartDate) , #duration(1, 0, 0, 0)),
RemoveWeekends = List.Select(DateList, each Date.DayOfWeek(_, Day.Monday) < 5),
RemoveHolidays = List.RemoveItems(RemoveWeekends, Holidays),
CountDays = List.Count(RemoveHolidays)
in
CountDays,
Custom1 = Query1
in
Custom1
Everything is working in the file on my computer, but the issue is when anyone else from my team is trying to use the file with queries there. We are getting error <Expression.Error: A cyclic reference was encountered during evaluation.>
I've tried to trace steps and find out when the error is occurring and it's always pointing at the custom function.
Please help me, I need to fix it asap so my team can use this.
Function screen
Calendar before function
Calendar after function
I was using this youtube guide to create function: https://www.youtube.com/watch?v=e2ic432NvhY
try changing your function to
(StartDate as date, EndDate as date) as number =>
let DateList = List.Dates(StartDate, Number.From(EndDate - StartDate) , #duration(1, 0, 0, 0)),
RemoveWeekends = List.Select(DateList, each Date.DayOfWeek(_, Day.Monday) < 5),
RemoveHolidays = List.RemoveItems(RemoveWeekends, Holidays),
CountDays = List.Count(RemoveHolidays)
in CountDays
then, assuming Holidays is a query with some list of dates like
= {#date(2022,6,15),#date(2022,1,18)}
then
= Table.AddColumn(#"Changed Type", "Custom", each NetWorkDays([StartDate],[EndDate]))
works fine
Thanks everyone for such quick answers.
My issue was that first I've created custom function based on list of holidays and calendar and then i've used it in calendar as well. When I removed custom function from the calendar query, leaving only starting date of the week, ending date and week number it started to work again.

% Variance change in Matrix SSRS

Hi I am trying to include Variance in my SSRS matrix for Percentages on a month by month basis.
This is what I want to achieve:
the expression I am trying to use which I have got from a forum is as follows:
=ReportItems!Textbox15.Value - Code.GetPreviousValue(ReportItems!Textbox15.Value)
And this references custom code again from the same forum as follows:
Private previousValue As Integer = 0
Public Function GetPreviousValue(ByVal runningValue) As Integer
Dim temp As Integer = previousValue
previousValue = runningValue
Return temp
End Function
My issue is this does not work for the variance between April and May for example giving me results that are incorrect.
To be clear April% and May% figures are correct but the variances do not appear as in my example. When I check them they are incorrect.
If I alter the (variance) query so instead of taking the query that calculates the % I just calculate variance between the numerator of April% and numerator of May%, variances are correct.
I think the issue is that percentages don't go through the custom code portion correctly. Could this be due to the fact that this works according to INT?
I appreciate this may be as clear as mud... Struggling a bit to explain my problem. Thanks
Yes the integer makes the problem, because you have values with dots (97.3, 91.8, etc...). When these values get converted to integer, they lose the right decimal places. Just replace the datatype in your function like this:
Private previousValue As Double = 0
Public Function GetPreviousValue(ByVal runningValue) As Double
Dim temp As Double = previousValue
previousValue = runningValue
Return temp
End Function

Global Date Variable Works Only for Entered Values

I'm currently working on what should be a relatively simple database, which is very close to being at its end, until I hit the inevitable problem.
I'm using Global Variables and a Form to collect parameters to pass into the Criteria portion of a Query, which works just fine for the first two, which are basic strings and integers.
Then comes the dates, which work, so long as you chose a date from the DatePicker that is entered into the query.
For example, if the query field holds 6/1/2014, 6/3/2014, and 6/8/2014, and the date 6/5/2014 is picked, the form will crash and go blank, though if you pick 6/8/2014, it'll go on as it should.
I had tried a variety of different forms of the code, but in the most basic form I simple have:
Between Get_Global('GBL_Start_Date_ID') AND Get_Global('GBL_End_Date_ID')
I'm not sure if I should be limiting the DatePicker based on the values entered in the query, or if there's a more robust way of going about this, or maybe I just completely missed a simple checkbox.
EDIT
My code for the Global Variables looks like this:
Option Compare Database
Global GBL_Start_Date_ID As Date
Global GBL_End_Date_ID As Date
Global GBL_Customer_ID As Long
Global GBL_Engineer_ID As Long
Public Function Init_Globals()
GBL_Start_Date_ID = #6/1/2014#
GBL_End_Date_ID = #6/30/2014#
GBL_Customer_ID = 1
GBL_Engineer_ID = 1
End Function
Public Function Get_Global(gbl_parm)
Select Case gbl_parm
Case "GBL_Customer_ID"
Get_Global = GBL_Customer_ID
Case "GBL_Engineer_ID"
Get_Global = GBL_Engineer_ID
Case "GBL_Start_Date_ID"
Get_Global = GBL_Start_Date_ID
Case "GBL_End_Date_ID"
Get_Global = GBL_End_Date_ID
End Select
End Function
And I just add a simple line to the AfterUpdate event of the ComboBoxes and TextBoxes to assign the variable:
GBL_Engineer_ID = Me.EngineerSelection
Thanks in advance,
Aaron
You can do two things. Fix the query as it is written or make it much more robust.
To fix it as written
Between "#" & Get_Global('GBL_Start_Date_ID') & "#" AND "#" & Get_Global('GBL_End_Date_ID') & "#"
OR
change your Get_Global function
Public Function Get_Global(gbl_parm)
Select Case gbl_parm
Case "GBL_Customer_ID"
Get_Global = GBL_Customer_ID
Case "GBL_Engineer_ID"
Get_Global = GBL_Engineer_ID
Case "GBL_Start_Date_ID"
Get_Global = "#" & GBL_Start_Date_ID & "#"
Case "GBL_End_Date_ID"
Get_Global = "#" & GBL_End_Date_ID & "#"
End Select
End Function
You are correctly specifying that the values of GBL_Start_Date_ID and GBL_End_Date_ID are dates by using #s when you create them however when you use them in your query they appear without them. You can prove to yourself this is what is happening by typing ?#1/1/2014# into the immediate window. The date is printed as 1/1/2014 which when used in your query, makes Between 6/1/2014 AND 6/30/2014 which is a syntax error.
To make things all that much better you need to parameterize this part of your query. Change this
Between Get_Global('GBL_Start_Date_ID') AND Get_Global('GBL_End_Date_ID')
to this
Between pStartDate AND pEndDate
Before you call your query you need to do your usual checks: are either of these null? is pStartDate < pEndDate?
By performing these checks and parameterizing this you ensure that you never end up with a query like this. Calling your query means you need to need to populate the parameters with DAO or ADO.
Between AND

get specific value from parameter

I have a multi-valued parameter TimeMonthOfYear(from cube) that contains January Februrary...December.
I want to set a default value showing current month using MonthName(Month(Today)) (I tried it and it didn't work) when running report...
If I do this [Time].[Month Of Year].&[October] it works! October is selected in dropdown after previous dropdown (Year) was selected.
I don't want to do it the "hard coded" way...I have tried
[Time].[Month Of Year].&[MonthName(Month(Today))] and
="[Time].[Month Of Year].&["&MonthName(Month(Today))&"]" without luck
Any help is very much appreciated!
Yup :) Well it's now working with may be a not so nice solution but will work for now with the help of vb code. in standard value I have ="[Time].[Month Of Year].&[" + Code.SetMonth() + "]" and custom code Function SetMonth() As String Dim x as STRING x =CStr(MonthName(Month(Today))) 'CStr not needed I think If x = "januari" Then x = "January" ElseIf x = "februari" Then x = "February" ... End If Return(x) End Function That is giving me the current month after selecting value in year drop-down :)

Inherited database has leap year code that compiler doesn't like

In my job, I have inherited an Access 97 database. This database is very unstable and I need to remedy that in one way or another. I have been trying to go through and debug the current version so that I can migrate it to 2007. I have run across some code that the compiler doesn't like and not sure how to fix it...here is the code:
Function DaysInMonth(ByVal D As Date) As Long
' Requires a date argument because February can change
' if it's a leap year.
Select Case Month(D)
Case 2
If LeapYear(Year(D)) Then
DaysInMonth = 29
Else
DaysInMonth = 28
End If
Case 4, 6, 9, 11
DaysInMonth = 30
Case 1, 3, 5, 7, 8, 10, 12
DaysInMonth = 31
End Select
End Function
I get a compile error: Sub or Function not defined and it highlights the first "LeapYear".
Any help at all would be greatly appreciated! Thanks!
LeapYear is another function or procedure that appears not be present in your modules or has been made Private. LeapYear isn't a VBA function. There must have been a function that takes a year Year(D) and returns TRUE or FALSE if it's a leapyear. either insert one or set the existing one to Public
Edit:You could use IsLeapYear but change to 'LeapYear' and call using IsLeapYear(D)
The code in question is idiotic -- it was clearly written by somebody who didn't have a clue about VBA dates, which already know everything that is needed without needed to encode this crap into a CASE SELECT.
This expression will get you the number of days in a month:
Day(DateAdd("m", 1, DateValue(Month(Date()) & "/1/" & Year(Date()))) - 1)
What this does is get the first of the current month, adds a month to it (for the first of the next month), and then subtracts 1 from it. Since the integer part of the VBA date type is the day part, that will get you the last day of the current month. Then you take the result and pull the day out with the Day() function.
Coding that up as a function:
Function DaysInMonth(ByVal dteDate As Date) As Integer
Dim dteFirstOfMonth As Date
Dim dteLastOfMonth As Date
dteFirstOfMonth = DateValue(Month(dteDate) & "/1/" & Year(dteDate))
dteLastOfMonth = DateAdd("m", 1, dteFirstOfMonth) - 1
DaysInMonth = Day(dteLastOfMonth)
End Function
You could also code this up using the fact that the DateSerial() function treats the zeroth day as the last of the previous month:
Function DaysInMonth(ByVal dteDate As Date) As Integer
Dim dteOneMonthFromDate As Date
Dim dteLastOfThisMonth As Date
dteOneMonthFromDate = DateAdd("m", 1, dteDate)
dteLastOfThisMonth = DateSerial(Year(dteOneMonthFromDate), Month(dteOneMonthFromDate), 0)
DaysInMonth = Day(dteLastOfThisMonth)
End Function
But that doesn't make it any shorter...
None of this requires figuring out leap year rules -- those are built into the VBA date type.
And, of course, the function should not return a Long, but an Integer, since the maximum value it can ever return is 31.
LeapYear may not be your only issue.
In Access '97, go to the VBA editor and click "Tools/References":
Look in the references of your '97 project and see what DLLs are listed.
A screen will appear that shows you the ActiveX DLLs that can be used for the project. The ones that are checked are the ones currently used:
Odds are there is a DLL there that needs to be referenced in your new 2007 database.