Updated 15 Aug 2026 Policy Tracker only 5 fixes + urgent diagnostic

Policy Tracker Fix Guide

One page, every confirmed fix kept in it, oldest first. Each entry has the exact control/property, the replacement formula, and a test to confirm it worked. Superseded by nothing — this page keeps growing instead of being replaced fix-by-fix.

Need to paste a whole screen instead of a small fix? That lives on a separate site: Policy Tracker — Screen YAML →

What This Page Is

This is the working fix log for the Policy Tracker canvas app (repo PhadeDev/policy-tracker). Reset to empty on 2026-08-13 — the previous entries (personal OneDrive link blocking, address-bar link save crash, generic-icon hint) had already been applied in Studio for weeks and were no longer needed as a reference.

Each fix below is a targeted property edit on the live app, applied by hand in Power Apps Studio. None of them require a full screen repaste unless stated otherwise.

Urgent - Newsletter Missing Item Diagnostic

NewsletterPack · temporary label · no data changes

Use this before changing the live formula again. The current NewsletterPack filter only includes records that match the target Thursday date, have final approval by XO/ACOS/DCOMD/D Commander, are not already published, and are not marked as requiring external consultation. Title and content do not affect inclusion. Stage 1 prints every SharePoint row matching the target Thursday date and shows exactly which gate is excluding it.

Stage 1 - Prove The SharePoint Rows Qualify

  1. Open NewsletterPack in Power Apps Studio.
  2. Add a temporary Label anywhere on the screen.
  3. Set the label's Text property to the formula below.
  4. Set AutoHeight to true, make it wide, and set the text size small enough to read the lines.
  5. Preview the screen. If the missing item is printed with include=false, the same line tells you which field is different. If the missing item is not printed at all, it is not matching the target Thursday date window.
Temporary debug label - Text v1 · 2026-08-13 12:35 BST
With(
    {_target: DateAdd(Today(), Mod(5 - Weekday(Today()) + 7, 7), "Days")},
    Concat(
        AddColumns(
            Filter(
                'Policy Proof Tracker',
                'Planned Publish Date' >= _target &&
                'Planned Publish Date' < DateAdd(_target, 1, "Days")
            ),
            DebugLine,
            Title &
            " | date=" & Text('Planned Publish Date', "dd mmm yyyy") &
            " | approval=" & Coalesce('Approved For Release By'.Value, "<blank>") &
            " | published=" & Text(Published) &
            " | external=" & Text('External consultation required') &
            " | include=" &
            Text(
                (
                    'Approved For Release By'.Value = "XO" ||
                    'Approved For Release By'.Value = "ACOS" ||
                    'Approved For Release By'.Value = "DCOMD" ||
                    'Approved For Release By'.Value = "D Commander"
                ) &&
                Published = false &&
                Coalesce('External consultation required', false) = false
            )
        ),
        DebugLine,
        Char(10)
    )
)
If the expected records print here, the raw SharePoint data is present. Continue to Stage 2 to check whether those same records are entering colNewsletterPack and the galleries.

Stage 2 - Check The Collection And Both Galleries

Keep the temporary label and replace its Text with this formula. This does not change data. It prints the row count for colNewsletterPack, the two gallery counts, and the titles currently inside the collection.

Temporary debug label - Text, stage 2 v1 · 2026-08-13 12:50 BST
Read it this way: if colNewsletterPack rows is still 1, the live NewsletterPack.OnVisible or btnRefresh_1.OnSelect formula is not building the same result as Stage 1. If colNewsletterPack rows is 3 but a gallery count is lower or the screen still shows one card, the bug is in gallery rendering/layout, not the SharePoint filter.

Stage 3 - Print The Current Pack Gates Per Record

If Stage 1 shows the three titles but Stage 2 shows colNewsletterPack rows = 1, use this label formula next. It prints the strict consultation check and the blank-safe consultation check for every record in the Thursday date window.

Temporary debug label - Text, stage 3 v1 · 2026-08-13 13:05 BST
With(
    {_target: DateAdd(Today(), Mod(5 - Weekday(Today()) + 7, 7), "Days")},
    Concat(
        AddColumns(
            Filter(
                'Policy Proof Tracker',
                'Planned Publish Date' >= _target &&
                'Planned Publish Date' < DateAdd(_target, 1, "Days")
            ),
            DebugLine,
            Text(ID) &
            " | " & Title &
            " | approval=" & Coalesce('Approved For Release By'.Value, "<blank>") &
            " | finalApprovalOK=" &
            Text(
                'Approved For Release By'.Value = "XO" ||
                'Approved For Release By'.Value = "ACOS" ||
                'Approved For Release By'.Value = "DCOMD" ||
                'Approved For Release By'.Value = "D Commander"
            ) &
            " | publishedOK=" & Text(Published = false) &
            " | consultationStrictOK=" & Text('External consultation required' = false) &
            " | consultationBlankSafeOK=" & Text(Coalesce('External consultation required', false) = false) &
            " | fixedPackRule=" &
            Text(
                (
                    'Approved For Release By'.Value = "XO" ||
                    'Approved For Release By'.Value = "ACOS" ||
                    'Approved For Release By'.Value = "DCOMD" ||
                    'Approved For Release By'.Value = "D Commander"
                ) &&
                Published = false &&
                Coalesce('External consultation required', false) = false
            )
        ),
        DebugLine,
        Char(10)
    )
)
If the missing records say consultationStrictOK=false but consultationBlankSafeOK=true, apply Fix 4. If consultationBlankSafeOK=false, the record is genuinely consultation-ticked and should stay out of the newsletter.
Confirmed result: the missing newsletter rows showed the old strict consultation check failing while finalApprovalOK=true and publishedOK=true. Apply Fix 4 below if those rows are not actually consultation-ticked.

Fix 1 - Publish Buttons No Longer Gated On External Consultation Flag

Main · property edit · no risk to formula syntax, changes real publish behaviour

Reported 2026-08-13: on a day with three items due, only one showed a per-item Publish button and Publish All read (1) instead of (3). It looked like an approval-based bug, but it wasn't — BossPublishBtn.Visible and PublishAllBtn never checked approval status at all. The actual gate was 'External consultation required' = false, present in four places (button visibility, the count shown in the button text, and both Filter() calls used when actually patching records). Two of the three items had that flag ticked. Decision: drop that condition everywhere so Publish/Publish All always show for boss users on unpublished, due items, regardless of the consultation flag.

Behaviour change, not just a bug fix: a boss can now publish an item that still needs external consultation. That's intentional, per instruction — flagging it here so it's not a surprise later.
  1. Open Main.
  2. In the Tree view, find BossPublishBtn (the per-item "⚡ Publish" button).
  3. Select Visible in the Properties dropdown, select all, and replace with this formula.
BossPublishBtn.Visible v1 · 2026-08-13 11:10 BST
!IsEmpty(Filter(colBossButtonUsers, Lower(Email) = Lower(User().Email))) &&
ThisItem.'Planned Publish Date' <= Today() &&
ThisItem.Published = false
  1. Find PublishAllBtn (the group-header "Publish All (n)" button).
  2. Select OnSelect in the Properties dropdown, select all, and replace with this formula.
PublishAllBtn.OnSelect v1 · 2026-08-13 11:10 BST
// PublishAllBtn.OnSelect
Set(varPublishGroupDate, ThisItem.PlannedDate);
Set(varPublishGroupCount, CountRows(Filter(ThisItem.GroupedItems, Published = false)));
Clear(colPublishFailures);
ForAll(
    Filter(ThisItem.GroupedItems, Published = false) As PubItem,
    IfError(
        Patch(
            'Policy Proof Tracker',
            LookUp('Policy Proof Tracker', ID = PubItem.ID),
            {
                Published: true,
                'Published Date': varPublishGroupDate
            }
        ); true,
        Collect(colPublishFailures, {ID: PubItem.ID}); true
    )
);
Set(varPublishFailCount, CountRows(colPublishFailures));
Refresh('Policy Proof Tracker');
RefreshActiveCache();
If(
    varPublishFailCount = 0,
    Notify(
        "Published all " & varPublishGroupCount & " items for " & Text(varPublishGroupDate, "d mmm yyyy"),
        NotificationType.Success
    ),
    Notify(
        varPublishFailCount & " of " & varPublishGroupCount & " items failed to publish for " & Text(varPublishGroupDate, "d mmm yyyy") & ". Please retry.",
        NotificationType.Error
    )
)
  1. Still on PublishAllBtn, select Text and replace with this formula.
PublishAllBtn.Text v1 · 2026-08-13 11:10 BST
"Publish All (" & CountRows(Filter(ThisItem.GroupedItems, Published = false)) & ")"
  1. Still on PublishAllBtn, select Visible and replace with this formula.
PublishAllBtn.Visible v1 · 2026-08-13 11:10 BST
!IsEmpty(Filter(colBossButtonUsers, Lower(Email) = Lower(User().Email))) &&
ThisItem.PlannedDate <= Today() &&
CountRows(Filter(ThisItem.GroupedItems, Published = false)) > 0
Test: on a day with several unpublished items due, including at least one flagged "External consultation required" — every item should now show its own Publish button, and Publish All's count should match the total number of unpublished items in that group, not just the ones without the consultation flag.

Fix 2 - Newsletter Pack Required Real Final Approval, Not Just Pillar Lead

NewsletterPack · property edit · changes which items appear in the pack

Reported 2026-08-13 alongside Fix 1: an item approved only by the Pillar Lead (not yet by ACOS or above) was still appearing in the newsletter pack. The Filter() that builds colNewsletterPack included 'Approved by Pillar Lead (Ready to Release)' = true as one of several OR'd conditions, so Pillar Lead approval alone was enough to qualify — even though a separate IsFinalApproved column (used only for the amber "pending" styling on the card) already correctly checked just the four senior sign-off values. Fix: removed the Pillar Lead OR branch from the qualifying filter, so an item only enters the pack once 'Approved For Release By' is XO, ACOS, DCOMD, or "D Commander" — DCOMD / D Commander is the Deputy Commander Cadets rank tier (Brigadier-equivalent), so that already covers "ACOS or above." There are two identical copies of this filter in the screen (initial load and the Refresh button) — both are given in full below.

  1. Open NewsletterPack.
  2. Select the screen itself (root node), then OnVisible in the Properties dropdown.
  3. Find the ClearCollect(colNewsletterPack, ...) block near the top and replace the whole formula with this.
NewsletterPack.OnVisible (top ClearCollect block) v1 · 2026-08-13 11:10 BST
Set(varNewsletterTargetDate, DateAdd(Today(), Mod(5 - Weekday(Today()) + 7, 7), "Days"));
Refresh('Policy Proof Tracker');
ClearCollect(
    colNewsletterPack,
    Sort(
        AddColumns(
            Filter(
                'Policy Proof Tracker',
                'Planned Publish Date' >= varNewsletterTargetDate &&
                'Planned Publish Date' < DateAdd(varNewsletterTargetDate, 1, "Days") &&
                (
                    'Approved For Release By'.Value = "XO" ||
                    'Approved For Release By'.Value = "ACOS" ||
                    'Approved For Release By'.Value = "DCOMD" ||
                    'Approved For Release By'.Value = "D Commander"
                ) &&
                Published = false &&
                'External consultation required' = false
            ),
            SortKey,
            If(
                'Top Item',
                -1000,
                Coalesce(LookUp(colChoiceColors, ChoiceValue = 'Document Type'.Value, SortOrder), 99)
            ),
            IsFinalApproved,
            Or(
                'Approved For Release By'.Value = "XO",
                'Approved For Release By'.Value = "ACOS",
                'Approved For Release By'.Value = "DCOMD",
                'Approved For Release By'.Value = "D Commander"
            ),
            PackTitle,
            Coalesce('Title for Newsletter', Title),
            PackAudience,
            Coalesce(Audience, ""),
            PackSummary,
            Coalesce('Item summary', "")
        ),
        SortKey,
        SortOrder.Ascending
    )
)
  1. Find btnRefresh_1 (the "Refresh" button on the same screen). It has an identical copy of the same formula.
  2. Select OnSelect in the Properties dropdown, select all, and replace with this formula.
btnRefresh_1.OnSelect v1 · 2026-08-13 11:10 BST
Set(varNewsletterTargetDate, DateAdd(Today(), Mod(5 - Weekday(Today()) + 7, 7), "Days"));
Refresh('Policy Proof Tracker');
ClearCollect(
    colNewsletterPack,
    Sort(
        AddColumns(
            Filter(
                'Policy Proof Tracker',
                'Planned Publish Date' >= varNewsletterTargetDate &&
                'Planned Publish Date' < DateAdd(varNewsletterTargetDate, 1, "Days") &&
                (
                    'Approved For Release By'.Value = "XO" ||
                    'Approved For Release By'.Value = "ACOS" ||
                    'Approved For Release By'.Value = "DCOMD" ||
                    'Approved For Release By'.Value = "D Commander"
                ) &&
                Published = false &&
                'External consultation required' = false
            ),
            SortKey,
            If(
                'Top Item',
                -1000,
                Coalesce(LookUp(colChoiceColors, ChoiceValue = 'Document Type'.Value, SortOrder), 99)
            ),
            IsFinalApproved,
            Or(
                'Approved For Release By'.Value = "XO",
                'Approved For Release By'.Value = "ACOS",
                'Approved For Release By'.Value = "DCOMD",
                'Approved For Release By'.Value = "D Commander"
            ),
            PackTitle,
            Coalesce('Title for Newsletter', Title),
            PackAudience,
            Coalesce(Audience, ""),
            PackSummary,
            Coalesce('Item summary', "")
        ),
        SortKey,
        SortOrder.Ascending
    )
)
Test: tick Pillar Lead approval only on an item due this week, leave "Approved For Release By" as "Not Yet Approved" — it should NOT appear in the newsletter pack. Set "Approved For Release By" to ACOS — it should now appear, regardless of the Pillar Lead tick.

Fix 3 - Deadline Warning Banner Flashing On Close

ViewItem · property edit · visual only, no data risk

Reported 2026-08-13: clicking Close on an item with a release date inside 10 days (not High Priority, not External Consultation) briefly flashed the amber "Release date is within 10 days" banner before navigating away. The first guide tried reordering Navigate() before the state resets, but that is not enough: Power Apps can still evaluate the old screen for a frame while statements after Navigate() run. Correct fix: add a close-in-progress guard, make the warning/top bar respect it, and set the guard on both close paths.

  1. Open ViewItem.
  2. Select the screen itself, then select OnVisible.
  3. Add this line near the top, immediately after the existing first Set(varLoadingLinks, ...) line.
ViewItem.OnVisible - add near top v2 · 2026-08-13 14:05 BST
Set(varClosingViewItem, false);
  1. Select conWarningBar1.
  2. Select Visible, select all, and replace with this formula.
conWarningBar1.Visible v2 · 2026-08-13 14:05 BST
!Coalesce(varClosingViewItem, false) &&
varSelectPolicy <> "Filled" &&
DateDiff(Today(), dpkPublishDate1.SelectedDate, "Days") >= 0 &&
DateDiff(Today(), dpkPublishDate1.SelectedDate, "Days") < 10 &&
!ckbHighPriority1.Value &&
!ckbExtConsult1.Value
  1. Select conTopBar1.
  2. Select Visible, select all, and replace with this formula.
conTopBar1.Visible v2 · 2026-08-13 14:05 BST
!(
    !Coalesce(varClosingViewItem, false) &&
    varSelectPolicy <> "Filled" &&
    DateDiff(Today(), dpkPublishDate1.SelectedDate, "Days") >= 0 &&
    DateDiff(Today(), dpkPublishDate1.SelectedDate, "Days") < 10 &&
    !ckbHighPriority1.Value &&
    !ckbExtConsult1.Value
)
  1. Select btnClose1 (the top-right Close button).
  2. Select OnSelect, select all, and replace with this formula.
btnClose1.OnSelect v2 · 2026-08-13 14:05 BST
If(
    varUnsavedChanges,
    UpdateContext({locDisplayDiscardPopUp: true}),
    Set(varClosingViewItem, true);
    If(varSourceScreen = "Historic", Navigate(Historic, ScreenTransition.Fade), Navigate(Main, ScreenTransition.Fade));
    Set(varSelectPolicy, "Empty");
    Set(varSelectedRelease, Blank());
    Set(varUnsavedChanges, false);
    Set(varShowLinkModal, false)
)
  1. Select btnModalAction1_2 in the Unsaved Changes modal (the button that confirms closing without saving).
  2. Select OnSelect, select all, and replace with this formula.
btnModalAction1_2.OnSelect v2 · 2026-08-13 14:05 BST
UpdateContext({locDisplayDiscardPopUp: false});
Set(varClosingViewItem, true);
Set(varSelectPolicy, "Empty");
Set(varSelectedRelease, Blank());
Set(varUnsavedChanges, false);
Set(varShowLinkModal, false);
If(varSourceScreen = "Historic", Navigate(Historic, ScreenTransition.Fade), Navigate(Main, ScreenTransition.Fade))
Test: open an item with a Planned Publish Date inside 10 days, not marked High Priority or External Consultation, then click Close without making changes. It should leave with no orange flash. Then make a small edit, click Close, confirm the unsaved-changes modal, and check that path also leaves with no flash.

Fix 4 - Newsletter Treats Blank Consultation As Unticked

NewsletterPack · property edit · changes which items appear in the pack

Confirmed by the urgent diagnostic on 2026-08-13: three records matched the Thursday date window, but colNewsletterPack only contained one. The two missing records had finalApprovalOK=true and publishedOK=true, but externalOK=false. The consultation gate must stay: consultation-ticked items should not appear in the newsletter. The safer fix is to keep that rule but make it blank-safe, because a SharePoint Yes/No field can come through as blank rather than explicit false. This uses Coalesce('External consultation required', false) = false, which includes blank/unticked records and still excludes real true.

Do not remove the consultation gate: this fix keeps consultation-ticked records out of the newsletter. It only prevents blank/unticked records being treated as if they failed the gate.
  1. Open NewsletterPack.
  2. Select the screen itself (root node), then select OnVisible in the Properties dropdown.
  3. Select all and replace with this full formula.
NewsletterPack.OnVisible v2 · 2026-08-13 13:32 BST
Set(varNewsletterTargetDate, DateAdd(Today(), Mod(5 - Weekday(Today()) + 7, 7), "Days"));
Refresh('Policy Proof Tracker');
ClearCollect(
    colNewsletterPack,
    Sort(
        AddColumns(
            Filter(
                'Policy Proof Tracker',
                'Planned Publish Date' >= varNewsletterTargetDate &&
                'Planned Publish Date' < DateAdd(varNewsletterTargetDate, 1, "Days") &&
                (
                    'Approved For Release By'.Value = "XO" ||
                    'Approved For Release By'.Value = "ACOS" ||
                    'Approved For Release By'.Value = "DCOMD" ||
                    'Approved For Release By'.Value = "D Commander"
                ) &&
                Published = false &&
                Coalesce('External consultation required', false) = false
            ),
            SortKey,
            If(
                'Top Item',
                -1000,
                Coalesce(LookUp(colChoiceColors, ChoiceValue = 'Document Type'.Value, SortOrder), 99)
            ),
            IsFinalApproved,
            Or(
                'Approved For Release By'.Value = "XO",
                'Approved For Release By'.Value = "ACOS",
                'Approved For Release By'.Value = "DCOMD",
                'Approved For Release By'.Value = "D Commander"
            ),
            PackTitle,
            Coalesce('Title for Newsletter', Title),
            PackAudience,
            Coalesce(Audience, ""),
            PackSummary,
            Coalesce('Item summary', "")
        ),
        SortKey,
        SortOrder.Ascending
    )
)
  1. Select btnRefresh_1 on the same screen.
  2. Select OnSelect, select all, and replace with this formula too.
btnRefresh_1.OnSelect v2 · 2026-08-13 13:32 BST
Set(varNewsletterTargetDate, DateAdd(Today(), Mod(5 - Weekday(Today()) + 7, 7), "Days"));
Refresh('Policy Proof Tracker');
ClearCollect(
    colNewsletterPack,
    Sort(
        AddColumns(
            Filter(
                'Policy Proof Tracker',
                'Planned Publish Date' >= varNewsletterTargetDate &&
                'Planned Publish Date' < DateAdd(varNewsletterTargetDate, 1, "Days") &&
                (
                    'Approved For Release By'.Value = "XO" ||
                    'Approved For Release By'.Value = "ACOS" ||
                    'Approved For Release By'.Value = "DCOMD" ||
                    'Approved For Release By'.Value = "D Commander"
                ) &&
                Published = false &&
                Coalesce('External consultation required', false) = false
            ),
            SortKey,
            If(
                'Top Item',
                -1000,
                Coalesce(LookUp(colChoiceColors, ChoiceValue = 'Document Type'.Value, SortOrder), 99)
            ),
            IsFinalApproved,
            Or(
                'Approved For Release By'.Value = "XO",
                'Approved For Release By'.Value = "ACOS",
                'Approved For Release By'.Value = "DCOMD",
                'Approved For Release By'.Value = "D Commander"
            ),
            PackTitle,
            Coalesce('Title for Newsletter', Title),
            PackAudience,
            Coalesce(Audience, ""),
            PackSummary,
            Coalesce('Item summary', "")
        ),
        SortKey,
        SortOrder.Ascending
    )
)
Test: click Refresh on NewsletterPack after pasting both formulas. If the two missing rows are blank/unticked consultation values, the temporary Stage 2 label should change to colNewsletterPack rows = 3. If they are genuinely ticked for consultation, they should still stay out of the newsletter.

Fix 5 - Thursday Batch 1/2 Email Drafting (New Feature)

NewsletterPack · new controls + property edit · adds two buttons, does not remove anything

Added 2026-08-15. Two new buttons in the "Email-ready format" panel, Thursday Batch 1 Email and Thursday Batch 2 Email, that build an HTML draft via the Office 365 Outlook connector's DraftEmail action — subject auto-dated, body has this week's newsletter items as a real bold bullet list plus a fixed footer (Previous Newsletters / About / recipient list, copied verbatim from the real sent email and never changing), and BCC pulled from the same BM Groups / BM Memberships SharePoint lists Branch Contact Groups already uses, filtered to whichever Thursday batch the button is for. One manual step remains inside each drafted email: paste this week's real release link over the placeholder text, and set the OFFICIAL sensitivity label before sending — MOD's Purview label can't be set by this connector.

This only ever creates a draft. Office365Outlook.DraftEmail is the connector's draft-creation action — nothing in this feature calls SendEmailV2 or SendDraftEmail. Clicking either button puts an unsent draft in the clicking user's own Outlook Drafts folder (the connector connection is per-user, confirmed live with two different mailboxes) and stops there. You still have to open it and press Send yourself.
Before pasting anything below: add BM Groups and BM Memberships as data sources in this app (Data pane → Add data → SharePoint → same site Branch Contact Groups uses), and confirm Office 365 Outlook is added as a data source too (each user needs their own connection/sign-in the first time they use the buttons — that's what makes the draft land in the right mailbox).
  1. Open NewsletterPack.
  2. Select the screen itself (root node), then OnVisible in the Properties dropdown.
  3. Select all and replace with this full formula — it's the existing formula with five new lines appended after the colNewsletterPack block.
NewsletterPack.OnVisible v3 · 2026-08-15
Set(varNewsletterTargetDate, DateAdd(Today(), Mod(5 - Weekday(Today()) + 7, 7), "Days"));
Refresh('Policy Proof Tracker');
ClearCollect(
    colNewsletterPack,
    Sort(
        AddColumns(
            Filter(
                'Policy Proof Tracker',
                'Planned Publish Date' >= varNewsletterTargetDate &&
                'Planned Publish Date' < DateAdd(varNewsletterTargetDate, 1, "Days") &&
                (
                    'Approved For Release By'.Value = "XO" ||
                    'Approved For Release By'.Value = "ACOS" ||
                    'Approved For Release By'.Value = "DCOMD" ||
                    'Approved For Release By'.Value = "D Commander"
                ) &&
                Published = false &&
                Coalesce('External consultation required', false) = false
            ),
            SortKey,
            If(
                'Top Item',
                -1000,
                Coalesce(LookUp(colChoiceColors, ChoiceValue = 'Document Type'.Value, SortOrder), 99)
            ),
            IsFinalApproved,
            Or(
                'Approved For Release By'.Value = "XO",
                'Approved For Release By'.Value = "ACOS",
                'Approved For Release By'.Value = "DCOMD",
                'Approved For Release By'.Value = "D Commander"
            ),
            PackTitle,
            Coalesce('Title for Newsletter', Title),
            PackAudience,
            Coalesce(Audience, ""),
            PackSummary,
            Coalesce('Item summary', "")
        ),
        SortKey,
        SortOrder.Ascending
    )
);
ClearCollect(colBatchGroups, AddColumns(Sort('BM Groups', SortOrder, SortOrder.Ascending), Ticked, false));
ClearCollect(colBatchMemberships, Filter('BM Memberships', false));
ForAll(colBatchGroups As grp, Collect(colBatchMemberships, Filter('BM Memberships', GroupName = grp.Title)));
Set(varNewsletterSubject, Text(Today(), "yyyymmdd") & " - Cadets Branch weekly policy updates");
Set(
    varNewsletterBodyLead,
    "Good afternoon all,<br><br>" &
    "Please find a link to this week's releases here - <a href=""PASTE-THIS-WEEKS-LINK-HERE"">PASTE THIS WEEK'S LINK TEXT HERE</a><br>" &
    "Below is a summary of this week's releases from Cadets Branch:<br><br>"
);
Set(
    varNewsletterBodyStatic,
    "<br><b>Previous Newsletters:</b><br>" &
    "All the previous weekly policy updates are available via the links below<br>" &
    "MODNet users: <a href=""https://modgovuk.sharepoint.com/teams/1598/SitePages/Weekly-Policy-Updates---Archive.aspx"">Weekly Policy Updates (sharepoint.com)</a><br>" &
    "Resource Centre users: Navigate to: Westminster " & Char(8594) & " Resource Centre " & Char(8594) & " Organisation " & Char(8594) & " Cadets Branch Weekly Policy Updates<br><br>" &
    "<b>About the Newsletter:</b><br>" &
    "This newsletter works on both MODNet and personal systems, and all policies included will also be uploaded on to both MODNet and the Resource Centre for routine accessing.<br>" &
    "Each week we will send out a version of this email, to the usual recipients, providing a link to the latest policy newsletter and a summary of what items have been included.<br>" &
    "This email has been sent to the groups listed below but please feel free to forward on as you deem necessary, emailed recipients:<br><br>" &
    "ACF CEOs (ex-HQ SE)<br>" &
    "JMC SO2's<br>" &
    "JMC OC CTT's<br>" &
    "---<br>" &
    "JMC Cadets Branch 0mailboxes<br>" &
    "JMC CTT 0mailboxes<br>" &
    "JMC Col Cadets (including Col Ashley Fulford)<br>" &
    "JMC RAL members<br>" &
    "JMC SCEOs<br>" &
    "Cadets Branch<br>" &
    "CTC Frimley<br>" &
    "CCAT<br>" &
    "CRFCA (Sam Plant and Simon Estick)<br>" &
    "ACCT UK (Murdo Urquhart and Richard Walton)<br>" &
    "CCRS (Shooting Manager - Daf Marston)<br>" &
    "CCF RAF &amp; RN leads"
)
  1. Select btnRefresh_1 on the same screen (it has its own separate copy of the same formula — same trap as Fix 2/Fix 4 above).
  2. Select OnSelect, select all, and replace with the exact same formula as above.
  1. Duplicate the existing btnCopyAll_1 button twice (select it, Ctrl+C, Ctrl+V twice) — this gives you the right base styling (Classic/Button, rounded corners, bold text) without retyping every colour property.
  2. Rename the two copies btnDraftBatch1_1 and btnDraftBatch2_1 (right-click → Rename, in the tree view).
  3. Position them in a new row under Copy All: Y = 56 for both, X = 20 for Batch 1, X = 32 + (Parent.Width - 52) / 2 for Batch 2, Width = (Parent.Width - 52) / 2 for both.
  4. Set Text to "Thursday Batch 1 Email" / "Thursday Batch 2 Email".
  5. Set BorderColor, Fill to RGBA(46, 110, 145, 1), HoverBorderColor/HoverFill/PressedBorderColor/PressedFill to RGBA(34, 88, 118, 1) — this is the same blue already used for Thursday Batch controls in Branch Contact Groups, kept consistent across both apps.
  6. Set each button's OnSelect to the matching formula below.
btnDraftBatch1_1.OnSelect v1 · 2026-08-15
Set(varBatch1Recipients, Distinct(Filter(colBatchMemberships As mem, CountRows(Filter(colBatchGroups As grp, Lower(Trim(grp.ThursdayBatch.Value)) = "batch 1" && Lower(Trim(grp.Title)) = Lower(Trim(mem.GroupName)))) > 0), Email));
Set(varBatch1Bcc, Concat(varBatch1Recipients, Value, "; "));
If(
    CountRows(colNewsletterPack) = 0,
    Notify("No newsletter items for this Thursday - nothing to draft.", NotificationType.Warning),
    CountRows(varBatch1Recipients) = 0,
    Notify("No recipients found for Thursday Batch 1.", NotificationType.Warning),
    Office365Outlook.DraftEmail(
        "",
        varNewsletterSubject,
        varNewsletterBodyLead & Concat(colNewsletterPack, Char(8226) & " <b>" & PackTitle & "</b><br>&nbsp;&nbsp;&nbsp;&nbsp;" & Char(9702) & " Intended audience: " & PackAudience & "<br><br>") & varNewsletterBodyStatic,
        {Bcc: varBatch1Bcc}
    );
    Notify("Thursday Batch 1 draft created - check Outlook Drafts.", NotificationType.Success)
)
btnDraftBatch2_1.OnSelect v1 · 2026-08-15
Set(varBatch2Recipients, Distinct(Filter(colBatchMemberships As mem, CountRows(Filter(colBatchGroups As grp, Lower(Trim(grp.ThursdayBatch.Value)) = "batch 2" && Lower(Trim(grp.Title)) = Lower(Trim(mem.GroupName)))) > 0), Email));
Set(varBatch2Bcc, Concat(varBatch2Recipients, Value, "; "));
If(
    CountRows(colNewsletterPack) = 0,
    Notify("No newsletter items for this Thursday - nothing to draft.", NotificationType.Warning),
    CountRows(varBatch2Recipients) = 0,
    Notify("No recipients found for Thursday Batch 2.", NotificationType.Warning),
    Office365Outlook.DraftEmail(
        "",
        varNewsletterSubject,
        varNewsletterBodyLead & Concat(colNewsletterPack, Char(8226) & " <b>" & PackTitle & "</b><br>&nbsp;&nbsp;&nbsp;&nbsp;" & Char(9702) & " Intended audience: " & PackAudience & "<br><br>") & varNewsletterBodyStatic,
        {Bcc: varBatch2Bcc}
    );
    Notify("Thursday Batch 2 draft created - check Outlook Drafts.", NotificationType.Success)
)
Test: click Thursday Batch 1 Email, check Outlook Drafts for a new draft with the right subject, a bold bullet per newsletter item, BCC populated from Batch 1's groups, and the placeholder link line intact. Repeat for Batch 2 and confirm the BCC list is different. Confirm nothing sends on its own either time.