Extend DocXTender to Customize SharePoint Folder Names in DocXtender

Skip to main content

Extend DocXTender to Customize SharePoint Folder Names in DocXtender

You are here:

A Business Central extension can customize DocXtender’s SharePoint folder names programmatically when using “Non-Interactive” configuration for SharePoint.  This article describing this customization process will not work for interactive drag and drop.

Refer to this guide on configuring non-interactive mode: How to Configure Non-Interactive Mode in DocXTender

This article includes example code to include the customer or vendor name as an example of how the folder path can be altered, adjust as needed to suit your use case.

For example, a purchase order folder could change from:

DocXtender/Purchase Header/PO10482/

to:

DocXtender/Purchase Header/PO10482 - Fabrikam Supplies/

Requirements

Configure SharePoint storage and Non-Interactive Integration on DocXtender Setup, including the required Client ID and secret.

The example below only applies to uploads using Non-Interactive Integration. It does not change folder names for interactive SharePoint uploads.

Example extension

The following subscriber changes the document subfolder for Sales Header and Purchase Header records. It uses Sell-to Customer Name for sales documents and Buy-from Vendor Name for purchase documents.

Possible integration events could be:

  • OnBeforeHandleNonInteractiveUploadV3
  • or OnAfterGetFilePath

The following example code uses the OnAfterGetFilePath approach.



codeunit 50100 "Custom DocXtender Folders Approach A"
{
    InherentPermissions = X;
    // Do not implement both  OnBeforeHandleNonInteractiveUploadV3 and OnAfterGetFilePath, choose one of the examples
    [EventSubscriber(ObjectType::Codeunit,
        Codeunit::"IWX DocXtender Sharepoint Intg",
        'OnAfterGetFilePath', '', true, true)]
    local procedure HandleOnAfterGetFilePath(
        var ptxtFileName: Text;
        var pvCurrentRec: Variant;
        var rtxtFilePath: Text)
    var
        SalesHeader: Record "Sales Header";
        PurchaseHeader: Record "Purchase Header";
        DataTypeManagement: Codeunit "Data Type Management";
        SourceRecord: RecordRef;
        DocumentNo: Text;
        PartyName: Text;
        ExpectedSuffix: Text;
    begin
        if not DataTypeManagement.GetRecordRef(
            pvCurrentRec, SourceRecord)
        then
            exit;

        case SourceRecord.Number of
            Database::"Sales Header":
                begin
                    SourceRecord.SetTable(SalesHeader);
                    DocumentNo := SalesHeader."No.";
                    PartyName := SalesHeader."Sell-to Customer Name";
                end;
            Database::"Purchase Header":
                begin
                    SourceRecord.SetTable(PurchaseHeader);
                    DocumentNo := PurchaseHeader."No.";
                    PartyName := PurchaseHeader."Buy-from Vendor Name";
                end;
            else
                exit;
        end;

        // Remove characters unsuitable for a folder name.
        PartyName := DelChr(PartyName, '=', '"*:<>?\/#|');
        PartyName := DelChr(PartyName, '<>', ' .');

        if (DocumentNo = '') or (PartyName = '') then
            exit;

        ExpectedSuffix := DocumentNo + '/' + ptxtFileName;
        if not rtxtFilePath.EndsWith(ExpectedSuffix) then
            exit;

        // Preserve the base folder, table folder, and file name.
        rtxtFilePath :=
            CopyStr(rtxtFilePath, 1,
                StrLen(rtxtFilePath) - StrLen(ExpectedSuffix)) +
            DocumentNo + ' - ' + PartyName + '/' + ptxtFileName;
    end;
}

An alternative integration event could be with OnBeforeHandleNonInteractiveUploadV3.



codeunit 50101 "Custom DocXtender Upload Path Alternate Approach"
{
    // This is a different event to change the folder path.
    // Do not implement both  OnBeforeHandleNonInteractiveUploadV3 and OnAfterGetFilePath, choose one of the examples
    InherentPermissions = X;
    [EventSubscriber(ObjectType::Codeunit,
        Codeunit::"IWX DocXtender Sharepoint Intg",
        'OnBeforeHandleNonInteractiveUploadV3', '', true, true)]
    local procedure HandleOnBeforeHandleNonInteractiveUploadV3(
        var ptxtFullFileName: Text;
        var ptxtB64FileContent: Text;
        var pvRecToAttachLink: Variant;
        var ptxtFilePath: Text;
        var rbSuccess: Boolean;
        var pbHandled: Boolean)
    var
        SalesHeader: Record "Sales Header";
        PurchaseHeader: Record "Purchase Header";
        DataTypeManagement: Codeunit "Data Type Management";
        SharePointIntegration: Codeunit "IWX DocXtender Sharepoint Intg";
        SourceRecord: RecordRef;
        DocumentNo: Text;
        PartyName: Text;
        DefaultPath: Text;
        ExpectedSuffix: Text;
    begin
        // Respect paths already supplied by another subscriber.
        if pbHandled or (ptxtFilePath <> '') then
            exit;

        if not DataTypeManagement.GetRecordRef(
            pvRecToAttachLink, SourceRecord)
        then
            exit;

        case SourceRecord.Number of
            Database::"Sales Header":
                begin
                    SourceRecord.SetTable(SalesHeader);
                    DocumentNo := SalesHeader."No.";
                    PartyName := SalesHeader."Sell-to Customer Name";
                end;
            Database::"Purchase Header":
                begin
                    SourceRecord.SetTable(PurchaseHeader);
                    DocumentNo := PurchaseHeader."No.";
                    PartyName := PurchaseHeader."Buy-from Vendor Name";
                end;
            else
                exit;
        end;

        // Remove characters unsuitable for a folder name.
        PartyName := DelChr(PartyName, '=', '"*:<>?\/#|');
        PartyName := DelChr(PartyName, '<>', ' .');

        if (DocumentNo = '') or (PartyName = '') then
            exit;

        DefaultPath := SharePointIntegration.GetFilePath(
            ptxtFullFileName, pvRecToAttachLink);
        ExpectedSuffix := DocumentNo + '/' + ptxtFullFileName;

        if not DefaultPath.EndsWith(ExpectedSuffix) then
            exit;

        // Preserve the base folder, table folder, and file name.
        ptxtFilePath :=
            CopyStr(DefaultPath, 1,
                StrLen(DefaultPath) - StrLen(ExpectedSuffix)) +
            DocumentNo + ' - ' + PartyName + '/' + ptxtFullFileName;

        // Leave pbHandled and rbSuccess unchanged.
        // DocXtender performs the upload and determines success.
    end;
}

For purchase order PO10482, with Buy-from Vendor Name set to Fabrikam Supplies, the resulting folder is:

DocXtender/Purchase Header/PO10482 - Fabrikam Supplies/

Limitations

  • This example will not work with interactive drag and drop.  You must use non-interactive configuration for this example.
  • These are two different examples to accomplish the goal, do not implement them both, choose one or the other depending on your integration scenario.
    • OnAfterGetFilePath will occur after DocXtender already determines it’s built-in path, giving you an opportunity to inspect and alter it.
    • OnBeforeHandleNonInteractiveUploadV3 will occur before DocXtender determines the file path.
  • This example covers Sales Header and Purchase Header records. Posted documents use different tables and require additional handling.
  • Existing folders and files are not renamed or moved.
  • Changing the customer or vendor name on the document changes the destination for subsequent uploads and may create another folder.
  • Test the extension in a sandbox before deployment, including names containing special characters and long folder paths.
Was this article helpful?
0 out Of 5 Stars
5 Stars 0%
4 Stars 0%
3 Stars 0%
2 Stars 0%
1 Stars 0%
5
How can we improve this article?
Please submit the reason for your vote so that we can improve the article.
Need help?

Leave A Comment

Table of Contents
Go to Top