Designing and Generating Reports Issues

You’re right that the code wasn’t working because it was inside the header div. When you use the helper function, it usually inserts the necessary div tags for you. If you switch to HTML view, you should see those divs appear automatically.

For example, when you insert it like this:

After inserting and switching to HTML view, the div is generated like this:

Regarding the date issue, the reason the dates are showing a day early is due to time zone differences when using the JavaScript Date object. The easiest fix is to use substring to extract the date portion, which avoids the time zone problem. By doing that, you get the correct date without it shifting by a day.

Let me know if this clears things up!

Thank you for your help on this Vin.

As a programmer, I can’t believe there is no reliable way to use a Date object without having a time zone problem. I will continue to research this, but in the meantime, I will switch to sub-stringing the supplied date for now.

Regarding the reporting issues:
Some of this I may have caused myself by manually moving the helper codes in the template viewer, and not doing it the proper way in the HTML viewer. I notice that sometimes the HTML can be broken by this process.

I’ve been working on this one report for months, before changes were made in Five to make group-by and headers work better with each other.

It’s still not entirely clear how to do this on my own, when creating a new report. Unless new documentation has been created for the new Five version, I can’t find instructions on how to build a grouped report with headers. Since there are many reports yet to be designed, and most will require some grouping, I need to be able to reliably create a report and apply grouping and headers without spending weeks (or longer!) going back and forth on the forum.

Can you please advise if there is any documentation available for the new version, which I’m using in the beta / development environment? That would be really appreciated.

And thanks again for all of your help!

Can you please suggest a way to print a date in a color based on whether the date is past-due or not?

The Roster report’s data source contains a field called ValidTo. This indicates the end of the fiscal year, which is June 30th. of each year.

Most members are paid through June 30th, 2025. As of today, they would be considered current. There are some members who are paid through June 30th, 2024 and they would be considered past due.

My template contains the following html code:

<td style="width: 10%;">
    <div style="color: {{#if DuesPastDue}}blue{{else}}black{{/if}};">{{ConvertDateToUS ValidTo}}</div>
</td>

Here is a function that I use to return whether they are past due or not. It is supposed to return true or false.

function DuesPastDue() {
    isPastDue = five.now() > five.field.ValidTo;
    return isPastDue;
}

I was expecting that if the member is past due (today > ValidTo field value), then the date would appear on the report in blue. This is not working. Can you please advise what I did wrong? Thanks…
FDF is up on OneDrive.

Using the Date object, you can avoid time zone issues by leveraging UTC methods. Here’s an approach you can try:

function ConvertDateToUS(dateStr) {
    const dateOnly = dateStr.split('T')[0]; // Extract only the date part (ignore time if present)
    const date = new Date(dateOnly); // Parse the date

    // Check for invalid date
    if (isNaN(date.getTime())) {
        return 'Invalid Date';
    }

    const month = date.getUTCMonth() + 1; // Use UTC methods to avoid time zone issues
    const day = date.getUTCDate();
    const year = date.getUTCFullYear();

    return `${month}/${day}/${year}`;
}

Regarding the documentation, it’s continuously being updated. In the meantime, please use the forum for anything you can’t find.

Hi @RMittelman,

The unexpected results are likely due to the function not receiving the date parameter for each row. You can try the solution below:

function isDuesPastDue(dueDate) {
    return five.now() > dueDate;
}

Changes made:

  • Add dueDate as a parameter to ensure the function evaluates each row correctly.
  • Renamed the function to isDuesPastDue to follow Boolean naming conventions.
  • Removed the isPastDue variable and returned the comparison result directly for simplicity.

In the template, you can call it like this:

<div style="color: {{#if (isDuesPastDue ValidTo)}}blue{{else}}black{{/if}};">

Hope this helps.

Thanks for the help on converting date. The ConvertDateToUS could use some work, but it is unclear how it differentiates a date parameter from a string parameter. Currently I’m sending it a date parameter (the Paid field from my data records) and it seems to reliably work without error. I will play with your suggestions on this.

Regarding IsDuesPastDue, this now works perfectly.
I want to extend this to the Paid field, which is the date the member paid their study-group fees. This is a somewhat more complex calculation:
Our fiscal year starts 1-July of each year. Around June we start asking members to pay study group fees. If a new member joins in April, we allow them to pay for the current year and we also credit them for the following fiscal year. So if they pay 1-April-2024, they get credit for 23-24 fiscal year (the year they join) and also for the new 24-25 fiscal year.

So if the current date is in July 2025 or later, they are considered current if they paid 1-April 2024 or later. If they paid 1-March 2024, then they would be considered past due in July or later of 2025. Because we “give” them 3 free months if they are new members.

I’ve probably confused you with all of this detail. I will try to simplify with some examples.

1:
It is now between January and June 2025.
They are current if their pay date is April 2024 or later (we allow extra 3-months)
They are past due if their pay date is before April 2024.

2:
It is now July-2025 or later.
They are current if their pay date is April 2025 or later.
They are past due if their pay date is before April 2025

So I need to figure a way, knowing the start of the fiscal year is July, to calculate when they are current and when they are past due.

I’m not sure if you should help me because this is a Five question, or I should be able to figure it out on my own because this is a general programming question.

Any thoughts on this? Thanks so much.

Hi,

I’m not sure if I understand your question correctly, but based on what you’ve described, this JavaScript function may help handle the fiscal year logic and the grace period for new members.

function checkMembershipStatus(paymentDateStr) {
    const paymentDate = new Date(paymentDateStr);
    const currentDate = new Date();
    const currentYear = currentDate.getFullYear();
    const currentMonth = currentDate.getMonth() + 1;

    let cutoffDate;

    if (currentMonth >= 7) {
        // July or later: cutoff is April 1st of the current year
        cutoffDate = new Date(currentYear, 3, 1);
    } else {
        // Jan to June: cutoff is April 1st of the previous year
        cutoffDate = new Date(currentYear - 1, 3, 1);
    }

    return paymentDate >= cutoffDate ? "Current" : "Past Due";
}

Call this in the template, and it will return Current or Past Due:

{{checkMembershipStatus Paid}}

Explanation:

  • January to June: Members are current if they paid on or after April 1st of the previous year.
    Example: In May 2025, a payment from April 1, 2024 is considered current. A payment from March 31, 2024 is past due.
  • July to December: Members are current if they paid on or after April 1st of the current year.
    Example: In August 2025, a payment from April 1, 2025 is considered current. A payment from March 31, 2025 is past due.

I hope this helps!

Thanks for the suggestion.

In my Access app, I save the date of the current fiscal year start in a variable, then test if the date paid is < that saved date - 3 months. This works perfectly.

So here is what I did:

At login time, I save a variable for fiscal year start date.

    // save fiscal year start date
    let fyStartMo = 7;
    let yr = today.getFullYear();
    let mo = today.getMonth() + 1;
    if (mo < fyStartMo) {
        yr -= 1;
    }
    five.setVariable("FyStartDate", new Date(yr, fyStartMo - 1, 1));
    
    return five.success(result);
}

In my report, I have a function to test the Paid date.

function IsSGFeePastDue(feePaidDate) {
    let fyStartDate = five.variable.FyStartDate;
    let fyStartYear = fyStartDate.getFullYear();
    let fyStartMonth = fyStartDate.getMonth();
    fyStartMonth -= 3; // subtract 3 months for prior year grace period
    
    // fix if fiscal year start date was very early in the year
    if(fyStartMonth < 0) {
        fyStartYear -= 1 ;
        fyStartMonth += 12;
    }
    let validDate = new Date(fyStartYear, fyStartMonth, 1);
    return feePaidDate < validDate;
}

Then I have a calculated value in one of my table cells, to test the code.

{{IsSGFeePastDue Paid}}

However, when I run the report, I get the following error:

Unlike your earlier example, I’m supplying date variables rather than string variables.

If I use

{{five.variable.FyStartDate}}

on the template instead of

{{IsSGFeePastDue Paid}}}

Then it works fine, showing that my variable was properly set.

Can you identify what I may have done wrong?
LATEST FDF IS ON ONEDRIVE.

Hi @RMittelman,

You can use new Date(variable) to ensure it’s a proper Date object before using it.

let fyStartDate = new Date(five.variable.FyStartDate); // Ensure five.variable is a Date object

or

let fyStartDate = new Date(feePaidDate); // Ensure parameter is a Date object

new Date(variable) can handle both Date objects and strings

How new Date(variable) Works:

  1. If variable is already a Date object, it remains unchanged.
  2. If variable is a string, it attempts to parse it into a Date.
  3. If variable is a number (timestamp), it treats it as milliseconds since 1970-01-01.

This helps avoid errors when working with dates stored as strings or passed as parameters.

Thanks for the help on dates. Forcing the date to be a date variable (even if it already was one) seems to help a lot.

I appreciate your help Vin. The report is almost perfect. I do have 2 follow-up questions.

1:
Why, when rendering my report, do I see the default text “Group By Footer” + the group name after every group but the last? It seems that particular footer doesn’t appear if the data has ended.

2:
It’s taken a long time to arrive at my finished report, which includes Group By AND page headers for each group-by entity. This only works correctly because you folks updated the code and walked me through the entire process of creating the header which would appear on each page. It is totally unclear to me how I would do it from scratch for the next report.

On a blank report template, do I first insert the group-by functionality using the helper function, THEN place my cursor inside the group header area THEN insert a header using the helper function? Since all of this new functionality probably hasn’t made it into the documentation yet, could you possibly give a step-by-step list of actions to get me to that point? Once I have that working, I can probably design the specifics of the new report on my own.

Thanks…

In addition to the 2 questions above, can you advise when I will be able to insert a logo on my report?

Without a logo in the template, I get the proper number of pages on my report, based on the parameters supplied at run-time.

WITH a logo on my report, it never generates the report. Instead, it keeps counting up the pages in the progress message, until I cancel the report action.

Hi Vin,

Is it possible to address this topic sooner rather than later? I need all questions answered, but especially #2 above. I don’t feel comfortable designing a new report without knowing these steps.

Some reports will use group-by just like my Roster report, and some will just be detail reports, such as a member list. I need to know where to put the page header codes in both cases, and also where to put the page footer code if I need to have a footer. Thanks…

The reason you see the default “Group By Footer” text along with the group name after every group (except the last one) is likely because the footer is tied to the group and only renders when there’s another group following it. If the data ends, there’s no next group, so the footer doesn’t appear. To ensure it displays consistently, you might need to check if there’s an option to always render the footer or explicitly add a separate summary/footer section.

The issue was caused by using <div> instead of <table> for the header and structural inconsistencies in the table setup. The following changes resolved it:

  1. Replaced <div> with <table> for proper formatting and alignment.
  2. Ensured correct table nesting by adding <tr> and <td> tags before the second table.
  3. Used rowspan="5" to allow the logo to span multiple rows.
  4. Removed extra <td> elements in the header table to prevent unintended extra columns.

With these adjustments, the logo displays correctly, and the report generates as expected. I have uploaded a file named ‘ReportTemplateCode.txt’ for your reference.

You can refer to the Five documentation for reports here: Five Reports Documentation. Let me know if you need any further details!

Thanks so much for your help Vin. This is much closer, but there are some questions:

I didn’t like the logo jammed up into the top corner of the blue area, so I changed the code to add a small margin around the logo:

                        <table style="width: 100%; background-color: rgb(207, 226, 243); border-collapse: collapse;">
                            <tbody>
                                <tr style="width: 100%">
                                    <td rowspan="5">
                                        <div style="margin: 5px;">{{five.variable.logo}}</div><br>
                                    </td>
                                </tr>

So it looks like this:

I didn’t like the big area at the bottom, and it looks like I may only need 4 rows for my header, so I did this to the last row of the table:

                                <!-- removed last row, and changed rowspan of logo to 4
                                <tr>
                                    <!--<td style="width: 18%; text-align: left;"><br></td> -- >
                                    <td style="width: 64%; text-align: center; font-size: 14px;"><br></td>
                                    <td style="width: 18%; text-align: right;"><br></td>
                                </tr> -->

Now the picture is a bit better:


You can see the logo is a bit smaller, and the blue area is not so tall.

Still, it looks like the blue area is still a bit to large, as there is empty blue below the last line of the header. I tried changing the outer table’s height from 10mm to 8mm, but that didn’t help. Also changed the last table row’s height to 3mm, but that didn’t help either.

Can you suggest a better way to make the header area not be any taller than I need? THANKS!

Sorry to throw a monkey wrench into the gears, but since I changed my html code to match yours, the report isn’t correct anymore. I tried printing 4 different study groups by using the GenerateReports screen and choosing the first 4 study groups.

The body of the report is correct, each study group including the proper members. However, the headers are only showing data from the first study group. Meaning the blue area AND the VP/Registrar area just below the blue, but still part of the header are only showing information from one study group.

FDF from this morning is on OneDrive. Thanks…
ALSO, StudyGroupRoster.pdf is on OneDrive, showing the issue.