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

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.

Related

How do I query for the last 30 days of data in Power Query using JSON?

I would like to request the last 30 days of CrewHu Import data from today's date in this query. At the moment it is just set to get everything greater than the 25th September 2022 but I want to change this to be a dynamic value. Has anyone else had this problem / knows of a workaround?
let
Source = Json.Document(Web.Contents("https://api.crewhu.com/api" & "/v1/survey?query={""_updated_at"":{""$gte"":""2022-09-25T00:00:00.000Z""}}", [Headers=[X_CREWHU_APITOKEN="xxxxxxxxxxx"]])),
I've tried:
OneMonthAgo = Text.Replace(Text.Start (Text.From(Date.AddDays(DateTime.LocalNow(),-30)),10),"/","-") & "T00:00:00.000Z",
And calling this as a variable but because the string does not come with quotation marks it gives a syntax error when the variable is called in the 'Source = ' line.
Well, first you want
= Date.ToText(Date.From(Date.AddDays(DateTime.LocalNow(),-30)), [Format="yyyy-MM-dd"])& "T00:00:00.000Z"
since that returns 2022-09-28T00:00:00.000Z while yours returns 9-28-2022 T00:00:00.000Z which does not seem to be the original format
then try out this, which I cant test
let variable = Date.ToText(Date.From(Date.AddDays(DateTime.LocalNow(),-30)), [Format="yyyy-MM-dd"])& "T00:00:00.000Z",
Source = Json.Document(Web.Contents("https://api.crewhu.com/api" & "/v1/survey?query={""_updated_at"":{""$gte"":"""&variable&"""}}", [Headers=[X_CREWHU_APITOKEN="xxxxxxxxxxx"]]))
in Source

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.

Code combination in microsoft access (yyxxxx format)

I'm struggeling with a part of code that I want to implement in Microsoft Access.
The required code is used for project asignments.
The code format contains the last 2 numbers of the year + 4 digits which add up until a new year, then the last 2 numbers of the year add up with 1 and the 4 digits start at 1 again.
For example:
2019:
190001 = first task;
190002 = second task;
etc...
2020:
200001 = first task;
200002 = second task;
etc...
Could anybody help me out how to code this in Microsoft Access, preferably by VBA?
This way I can asign the code to a "submit" button to avoid similar numbers.
Thanks!
Formatting your code given an integer could be achieved in several ways, here is one possible method:
Function ProjectCode(ByVal n As Long) As Long
ProjectCode = CLng(Format(Date, "yy") & Format(n, "0000"))
End Function
?ProjectCode(1)
200001
?ProjectCode(2)
200002
?ProjectCode(100)
200100
You probably need to assign the next task id to a project.
So, look up the latest id in use and add 1 to obtain the next task id:
NextTaskId = (Year(Date()) \ 100) * 10000 + Nz(DMax("TaskId", "ProjectTable", "TaskId \ 10000 = Year(Date()) \ 100"), 0) Mod 10000 + 1
Nz ensures that a task id also can be assigned the very first task of a year.

Legend changing when report is deployed or exported

I have a 100% Stacked Bar chart. Students are banded based on their attendance,and the report simply tracks changes in the band populations as a percentage of the total student population. In Report Builder, this works totally fine (except in that it highlights our rubbish attendance of course...)
The problem arises when:
The report is exported from Report Builder to PDF/Word/Excel/whatever
The report is deployed to an SSRS server and run through the browser
You change to a subsequent page of the report, and then change back to the page with the graph.
In all case although the actual chart remains unchanged, the Legend loses its mind a little bit and shows the top three items as 100%:
I can't think of any reason that that should happen...the report was particularly finicky to make as a result of the underlying data structure (which regrettably is based on a Report Model, meaning I can't tweak it with SQL) and I had to use custom vb code in the end to get it to do what I wanted, but I can't see why any of that should change its behaviour either on the server or when exported.
So my question is; why does this happen, and how do I stop it happening?
EDIT: By Request:
The dataset inherently returns data in the format below. There's a row per learner ID per "Week Start Date".
The custom code I am using is pasted below (inept I know - no laughing!):
Private attendance_table As New System.Collections.Hashtable()
Private last_added_table As New System.Collections.Hashtable()
Public Function band_calc(ByVal attendance As Double) As String
REM Define the bands that I want to track
If attendance = 1 Then
Return "A"
ElseIf attendance >= 0.975 Then
Return "B"
ElseIf attendance >= 0.95 Then
Return "C"
ElseIf attendance >= 0.925 Then
Return "D"
ElseIf attendance >= 0.90 Then
Return "E"
ElseIf attendance >= 0.85 Then
Return "F"
ElseIf attendance >= 0.8 Then
Return "G"
Else
Return "X"
End If
End Function
Public Function get_attendance_band(ByVal week_start_date as String, ByVal learnerID As Integer, ByVal possibles As Integer, ByVal presents As Integer) As String
If attendance_table Is Nothing Then
Dim attendance_table As New System.Collections.Hashtable()
End If
If last_added_table Is Nothing Then
Dim last_added_table As New System.Collections.Hashtable()
End If
REM check if attendance_table has the Learner already
If attendance_table.ContainsKey(learnerID) Then
REM check if we've already added this week's data in
If attendance_table(learnerID).ContainsKey(week_start_date) Then
REM just return the band_calc for those data
Return band_calc(attendance_table(learnerID)(week_start_date)(1) / attendance_table(learnerID)(week_start_date)(0))
Else
REM Add in this week to the hashtable. Add this weeks data to the last weeks data
attendance_table(learnerID).Add(week_start_date, New Object() { possibles + attendance_table(learnerID)(last_added_table(learnerID))(0), presents + attendance_table(learnerID)(last_added_table(learnerID))(1)})
REM record that this is now the last date updated for this learner
last_added_table(learnerID) = week_start_date
REM show the band!
Return band_calc(attendance_table(learnerID)(week_start_date)(1) / attendance_table(learnerID)(week_start_date)(0))
End If
Else
attendance_table.Add(learnerID, New System.Collections.Hashtable())
attendance_table(learnerID).Add(week_start_date, New Object() {possibles, presents})
last_added_table.Add(learnerID, week_start_date)
Return band_calc(attendance_table(learnerID)(week_start_date)(1) / attendance_table(learnerID)(week_start_date)(0))
End If
End Function
For the series properties; The sort, group and label (which defines the Legend obviously) are all set to this:

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

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