Regular Reporting Dilemma

Parariddle

Registered User.
Local time
Today, 17:17
Joined
Jan 28, 2009
Messages
34
Hi All

I am trying to create a database that will allow us to record and monitor all our regular reports.

The main functionality required is

- Recording when a report is delivered
- Reporting on if the report was late etc
- Being able to look into the future to plan work loads by looking at a list of reports due on a certain day.

My problem lies with the different frequency of reports. At present I am using sticky back plaster, access and excel to report on reports due and I have a form and input table to record what reports have been completed but I am now at a point of how best to marry the 2 together.

I would appreciate any advice you can offer and would really like to achieve this myself with some pointers in the right direction !

Thanks in advance !
 
in access?

whereever you provide the ability to run a report, store the details in an audit trail
 
My problem lies with the different frequency of reports.

How do you determine when the reports are due now? A little more information might be helpful.

You can easily set a due date for reports, which makes it easy to determine if they are overdue.

From your comments I suspect however that the reports may be recurring, such as being required on a weekly or monthly basis. This can be achieved in a number of ways, such as using a combobox with the RowSourceType set to a Value List and the RowSource such as "Daily";"Weekly";"Monthly"...

One possible option is to create a table to store the main report infomation (tblReports) and then a second table storing each instance of a report call tblReportInstances. tblReportInstances contains the due date, status and actual delivery date of a specific instance. The due date would be calculated when a record is added to tblReports and is based on the combobox frequency.

If using this approach, you will need to set an end date for each main report, so that when creating the ReportInstances, you don't go on for eternity - possibly set this to the end of the year.

One benefit of this is that you can easily report on when reports need to be completed in the future which sould satisy your requirement:
Being able to look into the future to plan work loads by looking at a list of reports due on a certain day.
 
Hi Camerpn

The reports are due on a cycle from a start date. So I presume I would have to put a start and end date in for all reports in that year as you said. When someone completes a report I would like that stored in the db with a new due date added to the report information.

Thanks
 
do you mean you want to track which users are producing which reports?

or do you mean that you just want to control the reporting cycle so that all reports are produced on time

these are possibly similar but not necessarily identical projects
 
Hi Gemma

What my manager wants to see are reports that are due on a certain day.

I would like to see if there is a way of doing this using a start date and frequency rather than input every single report due for the year
 
i would store all your reports in a table, together with some fields to identify the frequency, and timing of the report (and maybe a last run field, but thats harder)

you can use the frequency fields to calculate the due date for the next report etc, and bring a list up for any day, by a sutiable query

just a simple function

pass in the frequency indicator for the report, and the day of month due, and the function should return true for a report due to be prepared today. No more than a handful of code lines i would think


however if you then wish to update this table to reflect the fact that the report HAS been run, this is rather more complex.
 
Hi Husky Thanks again !

Could you perhaps point me in the right direction with an example.

I have a frequency column and day of the week column i,e, monday reports etc.
 
what frequency settings do you have?

eg daily? weekly? monthly? 4-weekly? quarterly?
the weekday will not be appropriate for all of these

ie daily will be every day
weekly once per week on set day
monthly, maybe once per month on a given date? or first Monday? or last day?
etc

so can you clarify these possibilities first
 
All of those frequencies are possible Gemma but the main are Daily, Weekly and Monthly.

Thanks
 
right

you need a function called eg

nextreportdate(basedate as date, frequency as long, normalday as long) as date

this is trying to calculate the next date based on ,.,,,

basedate - the date you are checking (maybe today)
frequency - it depends how you store this - i assume a long value, but it may be a text.
irrespective, you need a case statement here, so that
- if its daily, you do one thing,
- if its weekly, you do another thing,
- if its monthly, you do something else,
etc

normalday, now depending on the above, this will mean something different
- if its weekly, it will be a value in the range 1 to 7 (mon - sun)
based on that, and the date you are checking you can now evaluate when the next report is due. You were storing monday as text - its better to store numbers, here I think - the easiest way is storing numbers corresponding to vbconstants, as vb has constants vbmonday thru vbsunday - then there is no confusion

- if its monthly, it will probably be a value in the range 1 to 31
based on that, and the date you are checking you can now evaluate when the next report is due, although this may take you into next month

- if its quarterly, it will probably also be a value in the range 1 to 31
- but now you need some more info, because its Feb, but you may not need this report in Feb. so you need some more info to identify how the quarter is constructed

- if you have 4-wekely periods, you need a way of mapping the date to the appropriate week no, so again, you need some more info


so you need to think about precisley how you work out when the next report is due and then access can replicate this with your algorithm
 
Let me toss some thoughts into the mix. I see two ways to approach this. The idea of computing items ahead of time and making entries for them is one way. But for day-to-day scheduling, you might consider a more dynamic method that doesn't store as much. This doesn't address your load projections, but hey, I'm just offering thoughts.

I have a similar problem in a non-Access environment, but the concepts apply anyway.

Our site does all sorts of reports on various frequencies. Our task scheduler is on a system where neither Windows Task Scheduler nor UNIX CRON were available. (It's called OpenVMS.) So our scheduler has a set of tasks and their frequencies are defined kind of like this:

Report A is run weekly on Tuesdays at 0900.

Report B is run monthly on the first monday of the month at 1200

Report C is run daily at 1500

Report D is run on Tuesday through Saturday (but not Sunday or Monday)

Multiply those entries to bring the total to several hundred tasks.

So then we have a task that drives the whole mess. It wakes up every 15 minutes. It first determines what time it is. Then it determines when it last ran. Then it reads the list of scheduled items and does, in essence, a "Between Last Run and This Run" type of comparison. The results of the comparison are "Not due" or "Due Now" or "Overdue"

What that scan does is it marks each entry with its schedule status. Things that are due or overdue are scheduled UNLESS the overdue item is marked with "Only at Exact Time." (In which case we missed the window of opportunity and have to wait for the next one.)

The most important part of this is the ability to run a test that says "Due this cycle" or "Not due this cycle." If necessary, followed by a test of the last scheduler run that says, "Overdue in this cycle."

So the trick is that you need scheduling data that shows you when something is due based on the current time. You also need the ability to supply something for the current time that isn't really the current time if you are doing load projections.

Anyway, that's the overview of how we approach multiple variable event frequencies.
 
I like the idea of not having to store each instance of a report being run, but I have never discovered a way that can do that and still let you forecast future workload and also track if the actual report was completed on time.

In the past I have had similar scheduling systems, for Tasks or Staff Rosters, and I have always finished up having to store the instances in a second table.

In Parariddle's case I would create the main table, a second table to store the scheduled instances for each report and a lookup table for freqeuncy.

Code:
tblReports (ReportID, ReportName, FrequencyID, StartDate, EndDate)
 
tblReportInstances (InstanceID, ReportID, DueDate, ActualDate)
 
tblReportFrequency(FrequencyID, Interval, IntervalType, Description)

When creating a brand new report record, I would use a function, similar to the one Gemma suggested, that would use the Frequency field to insert records into tblReportInstances. Some rough code would be:

Code:
Private Sub cmdGenerate_Click()
    Dim dteCurrrentDate As Date
 
    'store the startdate in a local variable
    dteCurrrentDate = Me.txtStartDate
 
    'loop through while dteCurrrentDate is less than the end date
    While dteCurrrentDate < Me.txtEndDate
 
        'insert the a new record into tblReportInstances
        strSQL = "INSERT INTO tblReportInstances (ReportID, DueDate) VALUES (" & Me.txtReportID & ",#" & dteCurrrentDate & "#) "
        CurrentDb.Execute (strSQL)
 
        'Frequency combo Columns are FrequencyID, Interval, IntervalType, Description
        'Interval (a number) IntervalType (a string) are used in the DateAdd function
        dteCurrrentDate = DateAdd(Me.cboFrequencyID.Column(2), Me.cboFrequencyID.Column(1), dteCurrrentDate)
    Wend
End Sub

I'd love to hear a better way as there is a fair coding overhead to allow users to change the frequency of existing reports and there is always the issue that you need an end date otherwise the generation will go on until you fill the computers HDD (not a good idea).
 
Hi Guys

Thanks both for you help. What you are saying sounds spot on but please could you elaborate a little as I am fairly new and what do you define as interval type ?

Also how does that VBA tie in with people recording what they do.


The 2 main functions are to allow staff too record there workloads and For managers to see what reports are due on a certain (could be tomorrow or in 2 months) to better plan any new reports etc or use of staff time.

Thanks again for your patience and help !!
 
Last edited:
I'm going to suggest a "divide and conquer" type of thing.

First, your "schedule" table MIGHT look like this (and it resembles OUR schedule table though from a different environment):

tblSchedItem
SIID - Prime Key (PK), autonumber is probably adequate
SchInterval = text, one character = m for monthly, d for daily, h for hourly, y for yearly, w for weekly, etc.
SchMonth = for yearly items, month in which it runs else 0
SchDay = for monthly & yearly items, day of month on which it runs else 0 and for weekly items, day of WEEK on which it runs or -1 (have to use -1 for this because 0 = Sunday in Access.)
SchHour = for yearly, monthly, weekly, and hourly items - hour of day at which it runs, 00 is midnight, set to -1 if not hourly.
SchMinute = for all of the above, minute of the hour at which it runs, 00 means top of the hour, and this can be -1 in only one case. The value of this field has to be an integer multiple of the scheduler base frequency. For us, every 15 minutes, so the values are 00, 15, 30, and 45. Plus the -1 value meaning "every cycle" But then, we have some itty-bitty jobs that actually DO run that often, for security scan purposes and some other things we do.
SchItem - a reference to the actual item to be executed.

If you run a weekly report 3 times a week on Mon, Wed, Fri then you have three entries for that report, once for each day of the week. In this scheme, no harm exists in repeating an entry if the corresponding report runs that often as well.

OK, mind-set issue: What is "due" to your business? What is "overdue" to your business?

Now, a single query does not get you what you want no matter what you want - unless there is a UNION query involved. This might also be a "VBA" situation in which you have a little subroutine that scans your schedule recordset and sets a flag for any record that is due at a given scan cycle. The key is that a schedule is not tested by a time, but by a pair of times - previous run and current run.

OK, how would you use it? Well, for starters, before ANY scan of the schedule, reset all Y/N flags you were using to track "Due" or "Overdue" or "Projected as due" or whatever.

First, for scheduling, you need to know the last time you ran the scheduler (which should be a DMAX() of the "ran the scheduler" history table). Then take that time and the current time. For each record, set a Y/N type "due" flag based on looking at the current time. Set an "overdue" Y/N flag based on looking at the last time you ran the scheduler and the current time. Alternative: Each entry in the schedule table should ALSO have a date/time of most recent run, which allows you to determine via VBA-type logic whether the item ran on schedule or not. The trick is that for the given schedule frequency, at least for us, an item isn't overdue unless it should have been run twice in the given interval.

For workload projections, have another Y/N flag called "projected due" (or something like that) where you give it two arbitrary times and have it set or clear the projection flag if the item would be due on that date. Then count the projected due flags.

The idea we use in our BASIC language algorithm is we start a test of the schedule by iterating the run cycles between the last run date and the current run date. For a given record, because the disk I/O is more expensive, we loop through the possible dates. When we are done, we have a count of the number of times that the individual record should be scheduled in the interval.

Answers could be 0, 1, or many. Zero is easy. Not due. Skip it.

One is fairly easy - though we have lately added a wrinkle: If the count is one but the cycle that triggered the count wasn't the current time, set the OVERDUE flag as well as the DUE flag.

A return value of MANY is very easy. No matter what it was, it is overdue at least once. Maybe more than once.

The key for us is that little jewel that iterates through the date range incrimented by the scheduler's run-time interval, in essence a DO WHILE (step-time < current-time) loop. Then for each step we flag whether it was due or not. It isn't that hard to write. The only nasty part is that you need different SELECT/CASE statements for the different intervals of yearly, monthly, weekly, daily, or other intervals.

I'd write it for you but the trick is, I don't know your business rules and I'm kind of busy at the moment preparing for a business trip. But this should give you an overview of what is going on.

By the way, we added another little wrinkle to this. We break out the various parts of the date inside the iteration so we know the current month, weekday, day of month, hour of day, minute of hour etc. But we ALSO know from a little test whether a given day is the last day of the month. (If today is the last day of the month, tomorrow is the first day of another month, so it has a DatePart of 1 for the day number). So for our monthly items, we define an impossible day number to represent "last day of month." For non-monthly items, we use 0, so for last-day items we use -1.

In summary, your schedule becomes a run of the interval tester to see what is due in the current interval. Your projected load on day X becomes a run of the interval tested to see what is due in the future interval. Your "overdue" is a wrinkle within the tester that makes a special mark when an entry should have run - but did not run - during a given interval, or when the count of expected runs is > 1.
 
Last edited:
Wow Doc thank you so very much for this and for your time !

I will try this Monday at work and let you know how it goes !
 
Also how does that VBA tie in with people recording what they do.


The 2 main functions are to allow staff too record there workloads and For managers to see what reports are due on a certain (could be tomorrow or in 2 months) to better plan any new reports etc or use of staff time.

The VBA simply creates the records in tblReportInstances. Each record represents a future report that needs to be created.

You could add a whole bunch of fields to tblReportInstances that help manage these reports. For example, you would add a field to identify the staff member assigned to generate the report, maybe a field to store the current status, such as 'In Progress', 'On Hold', 'Awaiting Information from Client'. Also it might be a good idea to add a general notes field, so staff can enter comments regarding that particular instance of the report - for example if they are awaiting some more details before running the report.

It's a fairly easy step then to create queries based on date ranges and staff names so your managers and staff can see what is due in the next month or whatever timeframe makes sense for you.

You can also add some user friendly screens based on these queries, where staff would click through to see the details of each report and make any changes.
 
Hi Cameron

Thanks for all your help I really appreciate it. You have helped a lot in lifting some of the fog.

My question lies in the VBA code you provided previousley and where to use it. Are you referring to adding it too a button or on report open ? Ideally I would like the manager to open the report and have a msg box appear.

Sorry for taking up your time but I have the idea but its how to action it.

Thanks !
 
The previous code could exist behind a button. That button is located on the form were you enter the details of each report (that is the main report, not each instance). You would set values for frequency, start/end dates, report type, staff member responsible for report and any other details you need.

When this is completed, you press the Generate button to create the instances of this report between the start and end dates.

I have used a similar technique with a client recently who provided scheduled (weekly) services. After they are created, each instance can be rescheduled in cases where it falls on a non-work day, such as a bank/public holiday. I have also used an employee field from the main record as the default value for each instance, but then this can be changed should a different staff member need to be assigned to a particular instance.
 
Thank you so much cameron for your help I have tried to overload your reputation ha ha

This is all working smoothly now so thank you !!!
 

Users who are viewing this thread

Back
Top Bottom