Custom Report Grouping

  • Thread starter Thread starter CARRIE
  • Start date Start date
C

CARRIE

I have created a database in Access 2003 and am trying to group by months but
the months set up in the database are based on a tradional month. We use
4,4,5 accounting months. How can I create a group to based on dates I set up?
 
I have created a database in Access 2003 and am trying to group by months but
the months set up in the database are based on a tradional month. We use
4,4,5 accounting months. How can I create a group to based on dates I set up?

I'd suggest setting up a table with the dates of your accounting months. One
way might be to use Excel to create a table with one record per day for the
next twenty years or so (still a very small table), with fields for the
calendar date, your fiscal year, and your fiscal month. You can then join this
table to a query containing a date field to retrieve the accounting year and
month.
 
Carrie,
I'm not sure what you mean by 4,4,5 accounting months?
Some data examples please...
------
A shot in the dark...
Perhaps you mean the first 4 months of the year should be in
accounting Group1, the next 4 months in Group2, etc..?
(But 4,4,5 add up to 13??)

A calculated column in your query design grid, like this...
(all on one line, and assuming your date field is [DOC])

AcctGrp : IIF(Month(DOC) >=1 and Month(DOC) <=4,"Group1",
IIF(Month(DOC)>=5 and Month(DOC) <=9,"Group2",
IIF(Month(DOC)>=10 and Month(DOC) <=13,"Group3","")))

AcctGrp on the report can be used to group your dates into
accounting periods.
Even though I don't understand the 4,4,5, this "date grouping" method
might be what you're looking for.
--
hth
Al Campagna
Microsoft Access MVP 2006-2009
http://home.comcast.net/~cccsolutions/index.html

"Find a job that you love... and you'll never work a day in your life."
 
With a bit of cutting and pasting the code transalates into a VBA function as
follows:

Nice, Ken. I'll make a copy of this in case it should ever come up.

Might there be a performance benefit to hybridizing your code with my table
suggestion - e.g. running your code in a loop to build a ten or twenty year
translation table, which could be indexed appropriately and joined in queries?
 
The easiest way to handle this is to use a table to specify the start and end
of the accounting months or

Table
AccountingMonths
YearNumber
MonthNumber
MonthStartDate
MonthEndDate

Then you can use a non-equi join (join where the on clause is not using the
equals operator). This type of join cannot be built in the query design view.

SELECT AccountingMonths.MonthNumber, AccountingMonths.YearNumber
, Sum(SomeTable.Amount)
FROM SomeTable INNER JOIN AccountingMonths
ON SomeTable.SomeDate >=AccountingMonths.MonthStartDate
AND SomeTable.SomeDate <=AccountingMonths.MonthEndDate
GROUP BY AccountingMonths.MonthNumber, AccountingMonths.YearNumber

Another method is to build a table -tblCalendar with every date that you will
need and any additional columns.
tblCalendar
TheDate
AccountingYear
AccountingMonth
AccountingWeek


John Spencer
Access MVP 2002-2005, 2007-2010
The Hilltop Institute
University of Maryland Baltimore County
 
Bruce,
Thanks for that clarification...
Thanks
Al Campagna

BruceM via AccessMonster.com said:
I think 4,4,5 refers to a month being either four or five weeks. At 13
weeks
per quarter (4,4,5, 5.4.4, etc.) there are 52 weeks in a year. I don't
know
the rules, but I think that's the general idea. The terminology is
clearly
not as widely understood as the OP assumed.

Al said:
Carrie,
I'm not sure what you mean by 4,4,5 accounting months?
Some data examples please...
------
A shot in the dark...
Perhaps you mean the first 4 months of the year should be in
accounting Group1, the next 4 months in Group2, etc..?
(But 4,4,5 add up to 13??)

A calculated column in your query design grid, like this...
(all on one line, and assuming your date field is [DOC])

AcctGrp : IIF(Month(DOC) >=1 and Month(DOC) <=4,"Group1",
IIF(Month(DOC)>=5 and Month(DOC) <=9,"Group2",
IIF(Month(DOC)>=10 and Month(DOC) <=13,"Group3","")))

AcctGrp on the report can be used to group your dates into
accounting periods.
Even though I don't understand the 4,4,5, this "date grouping" method
might be what you're looking for.
I have created a database in Access 2003 and am trying to group by months
but
the months set up in the database are based on a tradional month. We
use
4,4,5 accounting months. How can I create a group to based on dates I
set
up?
 
The following link:

http://www.tek-tips.com/faqs.cfm?fid=1960

includes code for Crystal Reports for returning the accounting month based on
'4-4-5' accounting periods. Its basis is:

1. The accounting year always starts on the first day of the month of the
first month in the fiscal year
2. The Accounting Year always ends on the last day of the month in the last
month of the fiscal year

Each quarter in the year is comprised of Accounting Months as follows:

3. Four weeks in the first month of the quarter, unless the first day of the
fiscal year falls on the last day of the fiscal week - in this case the first
fiscal month is comprised of four weeks plus 1 day
4. Four weeks in the second month of the quarter
5. Five weeks in the third month of the quarter, except for the last fiscal
month since the last accounting month runs all the way to the end of the
fiscal year, regardless of the number of weeks

With a bit of cutting and pasting the code transalates into a VBA function as
follows:

Public Function OpMonth(varDate)
...

A join table like John suggested seems to be the easiest way to
implement the business logic here, but perhaps some have queries that
would make adding another join unreasonably complicated. For them,
maybe:

'Begin Module Code
Public Function GetOperatingMonth455(intFiscalYearStartMonthNum As
Integer, vbLastDayOfFiscalWeek As Integer, dtTestDate As Date) As Date
Dim dtFYStart As Date
Dim dtFYEnd As Date
Dim dtFirstLastDayOfFiscalWeek As Date
Dim dtEndOfFirstFiscalWeek As Date
Dim dtFMEnd(12) As Date
Dim I As Integer

dtFYStart = DateSerial(Year(dtTestDate) - Abs(Month(dtTestDate) <
intFiscalYearStartMonthNum), intFiscalYearStartMonthNum, 1)
dtFYEnd = DateAdd("d", -1, DateAdd("yyyy", 1, dtFYStart))
dtFMEnd(12) = dtFYEnd
dtFirstLastDayOfFiscalWeek = NthXDate(1, vbLastDayOfFiscalWeek,
dtFYStart)
dtEndOfFirstFiscalWeek = DateAdd("d", Abs(dtFYStart =
dtFirstLastDayOfFiscalWeek), dtFirstLastDayOfFiscalWeek)
dtFMEnd(1) = DateAdd("ww", 3, dtEndOfFirstFiscalWeek)
For I = 2 To 11
dtFMEnd(I) = DateAdd("ww", 4 + Abs(I / 3 = I \ 3), dtFMEnd(I - 1))
Next I
For I = 1 To 12
If DateDiff("d", dtTestDate, dtFMEnd(I)) >= 0 Then
GetOperatingMonth455 = DateSerial(Year(dtFYStart), I, 1)
Exit Function
End If
Next I
End Function

Public Function NthXDate(n As Integer, d As Integer, dtD As Date) As
Date
NthXDate = DateSerial(Year(dtD), Month(dtD), (7 - WeekDay(DateSerial
(Year(dtD), Month(dtD), 1)) + d) Mod 7 + 1 + (n - 1) * 7)
End Function
'End Module Code

Sample calls:

GetOperatingMonth455(1, vbSaturday, #1/26/2002#) => 1/1/2002

GetOperatingMonth455(1, vbSaturday, #1/27/2002#) => 2/1/2002

Oops, the varTestDate you used is obviously better than inputting a
Date in case a field used for the test date contains a Null value (an
exercise for the reader). Here 2/1/2002 actually means that the
operating month is the second one of FY2002, so anyone can format the
output as desired by relying on the Variant output type to handle
returning a string or a Null value. The GetOperatingMonth455()
function above seems simpler than having all that Case logic shown in
the link and should handle any starting fiscal month and fiscal end of
week day (someone please let me know if it doesn't).

Note: I only tested the function for a few dates. It seems to behave
in accordance with what I believe the general rules are implying. It
was a fun little exercise.

James A. Fortune
(e-mail address removed)

Disclaimer: Any programming examples shown are for illustration
purposes only, without warranty either expressed or implied. This
includes, but is not limited to, the implied warranties of
merchantability or fitness for a particular purpose. This post assumes
that you are familiar with the programming language that is being
demonstrated and with the tools that are used to create and to debug
procedures. I might explain the functionality of a particular
procedure, but I am under no obligation to modify these examples to
provide added functionality or to construct procedures to meet your
specific requirements. Any code samples posted contain no known
hidden material defects. However, anyone who uses any code sample
posted does so with the understanding that they are responsible for
any testing of any illustrative code sample for any particular use.
Furthermore, anyone using an illustrative code sample I provide or
code derived from it does so at their own risk.
 
Thanks for all the suggestions... It's way over my head so I am going to
pass it on to our IT and see if it makes sense.
 
Shouldn't it be GetOperatingMonth445?

Please give me more context. Did I use an incorrect function name
somewhere?
It’s certainly neater code than the Crystal Reports solution off the Tek-Tips
site, but I think I'd go for a return value in YYYY-MM format (truncatingthe
ISO 8601 date format) as a string, e.g.

GetOperatingMonth455 = Format(DateSerial(Year(dtFYStart), I, 1), "yyyy-mm")

or:

GetOperatingMonth455 = Year(dtFYStart) & "-" & Format(I, "00")

That's a good suggestion and it's easy to implement.
More to the point though, when I call both theirs and yours in a query ona
'calendar' table with dates from 2005 to 2025 I get discrepancies (198 rows
in total, 66 per year) between the return values in 2005, 2011 and 2022. As
far as I can see the basis for them both is the same. Am I missing something?

Thanks for testing the function. Comparing the two functions for a
range of date values was an excellent idea. I'll try to look at it
today to determine why the results for the two functions are different
for those years.

James A. Fortune
(e-mail address removed)
 
Please give me more context. Did I use an incorrect function name
somewhere?

I see now. I had 455. Yes, it should be 445 so that the name
corresponds to what is being done by the program. Doh!

James A. Fortune
(e-mail address removed)
 
It’s certainly neater code than the Crystal Reports solution off the Tek-Tips
site, but I think I'd go for a return value in YYYY-MM format (truncatingthe
ISO 8601 date format) as a string, e.g.

GetOperatingMonth455 = Format(DateSerial(Year(dtFYStart), I, 1), "yyyy-mm")

or:

GetOperatingMonth455 = Year(dtFYStart) & "-" & Format(I, "00")

More to the point though, when I call both theirs and yours in a query ona
'calendar' table with dates from 2005 to 2025 I get discrepancies (198 rows
in total, 66 per year) between the return values in 2005, 2011 and 2022. As
far as I can see the basis for them both is the same. Am I missing something?

I took the "plus one day" too literally :-). The "plus one day" was
referring to the New Year's Day Saturday itself. I replaced "d" with
"ww" on the offending line so that it adds a week for the special
case. Also, I incorporated your suggestions for formatting and for
allowing a Null value as input. Here is the revised function:

'Begin Module Code
Public Function GetOperatingMonth445(intFiscalYearStartMonthNum As
Integer, vbLastDayOfFiscalWeek As Integer, varTestDate As Variant) As
Variant
Dim dtFYStart As Date
Dim dtFYEnd As Date
Dim dtFirstLastDayOfFiscalWeek As Date
Dim dtEndOfFirstFiscalWeek As Date
Dim dtFMEnd(12) As Date
Dim I As Integer

GetOperatingMonth445 = Null
If IsNull(varTestDate) Then Exit Function
dtFYStart = DateSerial(Year(varTestDate) - Abs(Month(varTestDate) <
intFiscalYearStartMonthNum), intFiscalYearStartMonthNum, 1)
dtFYEnd = DateAdd("d", -1, DateAdd("yyyy", 1, dtFYStart))
dtFMEnd(12) = dtFYEnd
dtFirstLastDayOfFiscalWeek = NthXDate(1, vbLastDayOfFiscalWeek,
dtFYStart)
dtEndOfFirstFiscalWeek = DateAdd("ww", Abs(dtFYStart =
dtFirstLastDayOfFiscalWeek), dtFirstLastDayOfFiscalWeek)
dtFMEnd(1) = DateAdd("ww", 3, dtEndOfFirstFiscalWeek)
For I = 2 To 11
dtFMEnd(I) = DateAdd("ww", 4 + Abs(I / 3 = I \ 3), dtFMEnd(I - 1))
Next I
For I = 1 To 12
If DateDiff("d", varTestDate, dtFMEnd(I)) >= 0 Then
GetOperatingMonth445 = Year(dtFYStart) & "-" & Format(I, "00")
Exit Function
End If
Next I
End Function

Public Function NthXDate(n As Integer, d As Integer, dtD As Date) As
Date
NthXDate = DateSerial(Year(dtD), Month(dtD), (7 - WeekDay(DateSerial
(Year(dtD), Month(dtD), 1)) + d) Mod 7 + 1 + (n - 1) * 7)
End Function
'End Module Code

Please let me know if that causes the two functions to coincide for
the years where January 1 falls on a Saturday. Also, I'd like to
remind everyone that SQL doesn't know about vbSaturday, so it should
be replaced by a 7 in any queries. Having less "moving parts" was a
plus for debugging.

James A. Fortune
(e-mail address removed)
 
Back
Top