SharePoint Connector Documentation
Index

Add the FactBox to Any Page

This page provides a ready-to-use template for adding the SharePoint Connector FactBox to any page in Business Central. The template uses background tasks so that SharePoint calls do not block the UI.

Based on the guide at hougaard.com.

Prerequisites

  1. A table mapping must exist for the source table of the page you are extending.
  2. Your extension must depend on the SharePoint Connector (see App Dependency).

App Dependency

In your extension's app.json, add a dependency on the SharePoint Connector:

{
  "dependencies": [
    {
      "id": "23ebd065-b289-4a68-85e3-b8410e360157",
      "name": "SharePoint Connector",
      "publisher": "hougaard.com",
      "version": "6.0.0.0"
    }
  ]
}

Page Extension Template

Copy the template below and replace the three placeholders:

Placeholder Replace with
<Object Number> Your page extension object number (e.g., 50100)
<Give it a Name> A descriptive name (e.g., "Job Card SharePoint")
<PageNameToBeExtended> The target page name (e.g., "Job Card")
pageextension <Object Number> "<Give it a Name>" extends <PageNameToBeExtended>
{
    layout
    {
        addfirst(factboxes)
        {
            part(SharePointPart_EFQ; "SharePoint Factbox EFQ")
            {
                ApplicationArea = All;
                Visible = SharePointActivated;
            }
        }
    }

    trigger OnAfterGetCurrRecord()
    var
        Mapping: Record "Table Mapping EFQ";
        SP: Codeunit "SharePoint EFQ";
        Ref: RecordRef;
        Parms: Dictionary of [Text, Text];
        EmptyData: Dictionary of [Text, Text];
    begin
        if SharePointActivated then
            if GuiAllowed then begin
                Ref.GetTable(Rec);
                SP.GetTableMapping(Mapping, Ref);
                Clear(Parms);
                Parms.Add('sitename', Mapping."Site Name");
                Parms.Add('basefolder', Mapping."Base Folder");
                Parms.Add('folder', CurrPage.SharePointPart_EFQ.Page.PrepareFill(Ref));
                if not CurrPage.EnqueueBackgroundTask(
                    PageTaskId,
                    Codeunit::"Factbox Background Task EFQ",
                    Parms,
                    30000,
                    PageBackgroundTaskErrorLevel::Warning)
                then begin
                    EmptyData.Add('data',
                        '{"error":{"code":"-2147024894, System.IO.FileNotFoundException",' +
                        '"message":{"lang":"en-US","value":"File Not Found."}}}');
                    CurrPage.SharePointPart_EFQ.Page.FinishFill(EmptyData);
                end;
            end;
    end;

    trigger OnPageBackgroundTaskCompleted(TaskId: Integer; Results: Dictionary of [Text, Text])
    begin
        if SharePointActivated then
            if TaskId = PageTaskId then
                CurrPage.SharePointPart_EFQ.Page.FinishFill(Results);
    end;

    trigger OnPageBackgroundTaskError(TaskId: Integer; ErrorCode: Text; ErrorText: Text;
        ErrorCallStack: Text; var IsHandled: Boolean)
    begin
        if SharePointActivated then
            if TaskId = PageTaskId then
                CurrPage.SharePointPart_EFQ.Page.FillError(ErrorText);
    end;

    trigger OnOpenPage()
    var
        TableMapping: Record "Table Mapping EFQ";
        Ref: RecordRef;
    begin
        Ref.GetTable(Rec);
        SharePointActivated := TableMapping.NeedsFactBox(Ref.Number());
    end;

    var
        SharePointActivated: Boolean;
        PageTaskId: Integer;
}

How It Works

OnOpenPage

Checks whether a table mapping exists for the page's source table. If no mapping is configured, the FactBox stays hidden and no SharePoint calls are made.

OnAfterGetCurrRecord

Each time the user selects a record, the trigger:

  1. Gets a RecordRef for the current record.
  2. Looks up the table mapping to find the SharePoint site and base folder.
  3. Calls PrepareFill on the FactBox to calculate the record's folder path.
  4. Enqueues a PageBackgroundTask with a 30-second timeout so the SharePoint call runs without blocking the UI.
  5. If the background task cannot be enqueued (e.g., maximum tasks reached), it sends an empty result to the FactBox to avoid a spinner that never completes.

OnPageBackgroundTaskCompleted

When the background task finishes, the results (file list from SharePoint) are passed to the FactBox via FinishFill.

OnPageBackgroundTaskError

If the background task fails, the error is displayed in the FactBox via FillError instead of raising a runtime error.

Example: Adding FactBox to the Job Card

pageextension 50100 "Job Card SharePoint" extends "Job Card"
{
    layout
    {
        addfirst(factboxes)
        {
            part(SharePointPart_EFQ; "SharePoint Factbox EFQ")
            {
                ApplicationArea = All;
                Visible = SharePointActivated;
            }
        }
    }

    trigger OnAfterGetCurrRecord()
    var
        Mapping: Record "Table Mapping EFQ";
        SP: Codeunit "SharePoint EFQ";
        Ref: RecordRef;
        Parms: Dictionary of [Text, Text];
        EmptyData: Dictionary of [Text, Text];
    begin
        if SharePointActivated then
            if GuiAllowed then begin
                Ref.GetTable(Rec);
                SP.GetTableMapping(Mapping, Ref);
                Clear(Parms);
                Parms.Add('sitename', Mapping."Site Name");
                Parms.Add('basefolder', Mapping."Base Folder");
                Parms.Add('folder', CurrPage.SharePointPart_EFQ.Page.PrepareFill(Ref));
                if not CurrPage.EnqueueBackgroundTask(
                    PageTaskId,
                    Codeunit::"Factbox Background Task EFQ",
                    Parms,
                    30000,
                    PageBackgroundTaskErrorLevel::Warning)
                then begin
                    EmptyData.Add('data',
                        '{"error":{"code":"-2147024894, System.IO.FileNotFoundException",' +
                        '"message":{"lang":"en-US","value":"File Not Found."}}}');
                    CurrPage.SharePointPart_EFQ.Page.FinishFill(EmptyData);
                end;
            end;
    end;

    trigger OnPageBackgroundTaskCompleted(TaskId: Integer; Results: Dictionary of [Text, Text])
    begin
        if SharePointActivated then
            if TaskId = PageTaskId then
                CurrPage.SharePointPart_EFQ.Page.FinishFill(Results);
    end;

    trigger OnPageBackgroundTaskError(TaskId: Integer; ErrorCode: Text; ErrorText: Text;
        ErrorCallStack: Text; var IsHandled: Boolean)
    begin
        if SharePointActivated then
            if TaskId = PageTaskId then
                CurrPage.SharePointPart_EFQ.Page.FillError(ErrorText);
    end;

    trigger OnOpenPage()
    var
        TableMapping: Record "Table Mapping EFQ";
        Ref: RecordRef;
    begin
        Ref.GetTable(Rec);
        SharePointActivated := TableMapping.NeedsFactBox(Ref.Number());
    end;

    var
        SharePointActivated: Boolean;
        PageTaskId: Integer;
}

Disabling the FactBox from Another Extension

Before the shared FactBox activates for a page, it raises the OnBeforeActivatingAnything event with the table number of the page's source table. Set FactboxDisabled to true to keep the FactBox hidden and skip all SharePoint calls for that table, without modifying the page extensions.

codeunit 50101 "Hide SP Factbox For Items"
{
    [EventSubscriber(ObjectType::Page, Page::"SharePoint Factbox EFQ", 'OnBeforeActivatingAnything', '', false, false)]
    local procedure HideForItems(GlobalTableNo: Integer; var FactboxDisabled: Boolean)
    begin
        if GlobalTableNo = Database::Item then
            FactboxDisabled := true;
    end;
}

Typical uses are hiding the FactBox for tables that are mapped but should not expose documents to a group of users, or switching it off during data migration.

Checklist

Before deploying your extension:

  • Table mapping exists for the target page's source table
  • App dependency added to app.json
  • Object number and name are unique
  • FactBox appears on the page
  • Files load when a record is selected
  • Upload and download work correctly
  • FactBox hides when no mapping is configured