SharePoint Connector Documentation
Index

Published Events Reference

This page lists every integration event the SharePoint Connector publishes. For each event it covers the signature, when the event is raised, and what a subscriber can change. Use these events to customize folder names, file names, uploads, the FactBox, auto-upload on posting, e-signing and incoming documents. You don't need to modify the connector to do any of this.

All events are declared as [IntegrationEvent(false, false)]. Subscribe to them from your own extension after adding the SharePoint Connector as a dependency (see Programming Examples).

Before You Subscribe

Subscriber Syntax

Point the subscriber at the object that publishes the event. The object type matters: most events are on codeunits, but the FactBox events are on a page, one event is on a table, and one is on a report.

codeunit 50110 "My SharePoint Subscribers"
{
    // Codeunit publisher
    [EventSubscriber(ObjectType::Codeunit, Codeunit::"SharePoint EFQ", 'OnBeforeUploadEx', '', false, false)]
    local procedure MyOnBeforeUploadEx(var Mapping: Record "Table Mapping EFQ"; var Folder: Text; var FileName: Text; var Overwrite: Boolean)
    begin
    end;

    // Page publisher
    [EventSubscriber(ObjectType::Page, Page::"SharePoint Factbox EFQ", 'OnBeforeDownloadDocument', '', false, false)]
    local procedure MyOnBeforeDownloadDocument(var Mapping: Record "Table Mapping EFQ"; var CurrentFolder: Text; var Rec: Record "SharePoint File EFQ" temporary; var GlobalRef: RecordRef; var Handled: Boolean)
    begin
    end;

    // Table publisher
    [EventSubscriber(ObjectType::Table, Database::"Table Mapping EFQ", 'OnBeforeFiguringOutIfAFactBoxIsNeeded', '', false, false)]
    local procedure MyOnBeforeFiguringOutIfAFactBoxIsNeeded(TableNo: Integer; var SkipFactBox: Boolean)
    begin
    end;
}

Publishing Objects

Object Type ID Area
SharePoint EFQ Codeunit 70319500 Core API: upload, delete, folders, table mapping, naming, document generation
SharePoint Factbox EFQ Page 70319502 The shared SharePoint FactBox and its actions
Table Mapping EFQ Table 70319504 Whether a page shows the FactBox
SharePoint Related Docs EFQ Page 70319521 Related SharePoint Documents FactBox on journals
Related Documents Mgt EFQ Codeunit 70319503 Finding related documents for a journal line
Auto-Upload Sales EFQ Codeunit 70319476 Auto-upload after posting sales documents
Auto-Upload Purchase EFQ Codeunit 70319478 Auto-upload after posting purchase documents
Background Report Handling EFQ Codeunit 70319477 Rendering and uploading the posted document
Send to DocuSign EFQ Codeunit 70319480 DocuSign signed-document retrieval
Send to Adobe EFQ Codeunit 70319481 Adobe Sign signed-document retrieval
Incoming Doc. Management EFQ Codeunit 70319484 Placing incoming documents in SharePoint
EMail Match EFQ, Pattern Match EFQ, FileName Pattern Match EFQ, FileName with key EFQ, Create Document Criteria EFQ Codeunit 70319485, 70319486, 70319487, 70319491, 70319492 Incoming document match criteria
Transfer Attachments EFQ Report 70319478 Moving BC document attachments to SharePoint

Where Your Subscriber Runs

Many of these events do not fire in an interactive session, so do not call Message, Confirm, Page.RunModal or other UI from a subscriber without checking GuiAllowed() first.

Scenario Session
FactBox actions, drag-and-drop, the Related Documents FactBox The user's client session
Auto-upload OnSettingUp... events The posting session, inside OnAfterFinalizePosting of Sales-Post / Purch.-Post
Background Report Handling EFQ events A separate background session started with StartSession. They run in the posting session only when Debug Mode is on or Auto-Upload Process is set to Foreground. Single-instance state and manually bound subscribers from the posting session are not available
Incoming document import The user session (Incoming Documents list), a job queue entry (Job Queue Processing), or a web service call (the Incoming Documents API page)
Folder resolution, upload, sanitizing Any of the above. These run wherever the connector resolves a folder or uploads a file

Parameters Passed by Value

A parameter without var is a copy. Changing it in your subscriber has no effect on the connector. This applies in particular to the Doc record in both OnAfterGetSignedDocument events, to MatchTxt in the incoming-document match events, and to all parameters of OnAfterUpload, OnAfterRenameMappedFolder, OnAfterDocumentPlaced and OnAfterUploadingAttachment. Treat those events as notifications.

What Handled Does

Handled does not mean the same thing everywhere. In the FactBox it simply stops the action. In SharePoint EFQ it also decides what the procedure returns to its caller:

Event When Handled is true
OnBeforeDeleteFile (codeunit) DeleteFile / RecycleFile exit and return false
OnBeforeDeleteFolder DeleteFolder exits and returns false
OnBeforeCreateFolderEx CreateFolderEx and the non-RecordRef CreateFolder overloads return true; the RecordRef CreateFolder overloads return false
OnBeforeSanitizeName / OnBeforeSanitizeNameNoDot Your value of Name is returned unchanged
OnBeforeMappingFolderForRecord Your value of Folder is returned; see Folder Resolution
All FactBox OnBefore... events The action exits without doing anything else

SharePoint EFQ (Codeunit 70319500)

Uploading Files

local procedure OnBeforeUpload(var Folder: Text; var FileName: Text)
local procedure OnBeforeUploadEx(var Mapping: Record "Table Mapping EFQ"; var Folder: Text; var FileName: Text; var Overwrite: Boolean)
local procedure OnAfterUpload(Folder: Text; FileName: Text; Result: Text)
Event Raised You can
OnBeforeUpload At the start of every UploadFile call, whichever overload is used Change the target folder and file name
OnBeforeUploadEx Immediately after OnBeforeUpload Change folder, file name and Overwrite, and read or change the mapping (site)
OnAfterUpload Once, after SharePoint confirms the upload and returns the stored file length React to the upload. Result is SharePoint's raw JSON response
  • Every upload goes through UploadFile: FactBox uploads, drag-and-drop, photos, auto-upload, generated documents, incoming documents, e-signed documents and Transfer Attachments. These events therefore see all uploads.
  • Mapping in OnBeforeUploadEx is empty when the caller used an UploadFile overload that takes no mapping.
  • The file name has usually been sanitized by the caller already. If you change it, keep it valid for SharePoint (call SanitizeNameNoDot yourself if needed).
  • OnAfterUpload is not raised when the upload fails.

Deleting Files and Folders

local procedure OnBeforeDeleteFile(var F: Record "SharePoint File EFQ"; var Handled: Boolean)
local procedure OnBeforeDeleteFolder(var Folder: Text; var Handled: Boolean)
Event Raised You can
OnBeforeDeleteFile Before DeleteFile and RecycleFile send the request to SharePoint Block or replace the delete. Handled = true makes the call return false
OnBeforeDeleteFolder Before DeleteFolder sends the request Block or replace the delete. Handled = true makes the call return false

The FactBox raises its own OnBeforeDeleteFile event before calling the codeunit. See SharePoint Factbox EFQ.

Creating Folders

local procedure OnBeforeCreateFolderEx(var Mapping: Record "Table Mapping EFQ"; var ParentFolder: Text; var FolderName: Text; var Handled: Boolean)
local procedure OnAfterCreateSubFolder(var Mapping: Record "Table Mapping EFQ"; GlobalTableNo: Integer; CurrentFolder: Text; SubFolders: Record "Auto-Create subfolder EFQ")
Event Raised You can
OnBeforeCreateFolderEx Before any folder is created, from CreateFolder (all overloads) and CreateFolderEx Change the parent folder and folder name, or skip creation with Handled
OnAfterCreateSubFolder After each auto-create subfolder is created by CreateSubfolders React to subfolder creation. CurrentFolder is the record's folder (the parent), not the new subfolder
  • CreateFolderEx splits the complete path at the last / before raising the event. CreateFolderEx with CreateParentIfFailed = true can raise the event again for each parent it has to create.
  • For subfolders that come from an alternative mapping, OnAfterCreateSubFolder passes the SubFolders record left over from the standard subfolder loop. It does not describe the alternative subfolder, so don't rely on its field values in that case.

Table Mapping

local procedure OnBeforeGetTableMapping(var TM: Record "Table Mapping EFQ"; var Ref: RecordRef)
local procedure OnAfterFoundTableMapping(var TM: Record "Table Mapping EFQ"; var Ref: RecordRef)
Event Raised You can
OnBeforeGetTableMapping In GetTableMapping(TM, Ref), after the table mapping was read, before alternative mappings are applied Adjust the mapping for this record. Alternative mappings that match can still overwrite fields you set
OnAfterFoundTableMapping At the end of GetTableMapping(TM, Ref), after alternative mappings Make the final adjustment to site, base folder, folder name, caption fields or parent fields for this record
  • Neither event fires when no table mapping exists for the table, and neither fires from the GetTableMapping(TM, TableNo) overload that takes an integer.
  • TM is an in-memory copy for this call. Don't Modify it unless you really want to change the stored setup.

Folder Resolution

These events fire while GetFolderForRecord(Ref, CreateIfNotFound) works out the SharePoint folder for a record. The FactBox, auto-upload, document generation, incoming documents and your own code all rely on this procedure. The order is:

  1. The table mapping is read (see above). If the caption field is empty or the record has no SystemId, the procedure returns '' and no events fire.
  2. For the Name (Number) and Inherited Dynamic methods, an existing folder pin (SharePoint Folder Mapping EFQ) is returned directly. No folder events fire.
  3. OnBeforeMappingFolderForRecord is raised.
  4. For child tables, the parent record is filtered, then OnOverrideParentRecordFilters is raised before the parent is looked up.
  5. The folder name is built from the caption fields and OnBeforeFormattingFolderName is raised.
  6. If CreateIfNotFound is true, the folder is created, the pin is stored, and OnAfterCreateFolderForRecord is raised.
  7. OnAfterFoundFolderForRef is raised and its Folder value is returned.
local procedure OnBeforeMappingFolderForRecord(var Ref: RecordRef; var CreateIfNotFound: Boolean; var TableMapping: Record "Table Mapping EFQ"; var Folder: Text; var Handled: Boolean)
local procedure OnOverrideParentRecordFilters(var ParentRec: RecordRef; var Ref: RecordRef; var TableMapping: Record "Table Mapping EFQ")
local procedure OnBeforeFormattingFolderName(var FolderFormatting: Text; var NameTxt: Text; var NumberTxt: Text; var Mapping: Record "Table Mapping EFQ"; var Ref: RecordRef)
local procedure OnAfterCreateFolderForRecord(var TableMapping: Record "Table Mapping EFQ"; SharePointFolder: Text[500]; var RecRef: RecordRef; ParentRecRef: RecordRef)
local procedure OnAfterFoundFolderForRef(var Ref: RecordRef; var Folder: Text)
local procedure OnOverrideTableMapping(var Ref: RecordRef; var TableMapping: Record "Table Mapping EFQ")
local procedure OnOverrideFoundFolderName(var Folder: Text; Ref: RecordRef; TableMapping: Record "Table Mapping EFQ"; ParentRec: RecordRef)
Event You can
OnBeforeMappingFolderForRecord Supply the complete folder path yourself (Folder + Handled = true), or change CreateIfNotFound / the mapping before the connector builds the path
OnOverrideParentRecordFilters Change the filters on ParentRec that the connector set from Parent Ref. Field No. 1-3, for example to find the parent through a different field
OnBeforeFormattingFolderName Change the folder name format. FolderFormatting is '%1 (%2)' when a number field is mapped and has a value, otherwise '%1'. %1 is NameTxt, %2 is NumberTxt, and both are already sanitized. The result is the record's own folder name, not the full path
OnAfterCreateFolderForRecord React to the record's folder being created (for example, create extra folders, set permissions, or log it). ParentRecRef is not open when the table has no parent
OnAfterFoundFolderForRef Change the folder that is returned to the caller
OnOverrideTableMapping Adjust the mapping in the fallback path (see note)
OnOverrideFoundFolderName Change the folder in the fallback path (see note)

Notes:

  • Handled in OnBeforeMappingFolderForRecord: your Folder is returned as-is. The connector does not create it on SharePoint, and OnAfterCreateFolderForRecord and OnAfterFoundFolderForRef are not raised. For the Name (Number) method, your folder is also stored as the record's folder pin, even when CreateIfNotFound is false. After that, step 2 returns it and no events fire for that record again.
  • OnAfterCreateFolderForRecord frequency: for Name (Number) and Inherited Dynamic this fires the first time the folder is created, because later calls return the pin. For the other methods it fires on every GetFolderForRecord(Ref, true) call, whether or not the folder already existed.
  • OnAfterFoundFolderForRef is skipped when a pinned folder is returned (step 2) or when OnBeforeMappingFolderForRecord is handled. Don't use it as a guaranteed "every lookup" hook.
  • Fallback path: OnOverrideTableMapping and OnOverrideFoundFolderName are raised only by an internal fallback. It runs when a child table's parent record cannot be found and the folder has to be built from partial information. They don't fire in normal lookups.
  • OnBeforeFormattingFolderName is also raised by the public GetFolderStringForRec and GetFolderStringForRecEx procedures.

Name Sanitizing

local procedure OnBeforeSanitizeName(var Name: Text; var Handled: Boolean)
local procedure OnBeforeSanitizeNameNoDot(var Name: Text; var Handled: Boolean)
Event Raised You can
OnBeforeSanitizeName Before SanitizeName applies the Name Sanitizing setting. The connector uses it for folder names, and in Strict mode it also replaces dots Replace the sanitizing rules. Set Handled = true and your Name is returned
OnBeforeSanitizeNameNoDot Before SanitizeNameNoDot. The connector uses it for file names, and it keeps the dot before the extension Same as above

If you set Handled without cleaning the name yourself, characters that SharePoint rejects reach the REST call and the operation fails. A complete override example is in Programming Examples.

Document Generation

local procedure OnAfterGenerateDocumentSetFileName(var NewFileName: Text; var TableMapping: Record "Table Mapping EFQ"; var Template: Record "Document Template EFQ"; var GlobalRef: RecordRef; var OverrideName: Text; var Overwrite: Boolean)
local procedure OnAfterGenerateDocumentSetFileName2(var NewFileName: Text; var TableMapping: Record "Table Mapping EFQ"; var Template: Record "Document Template RL EFQ"; var GlobalRef: RecordRef; var OverrideName: Text; var Overwrite: Boolean)
Event Raised
OnAfterGenerateDocumentSetFileName In GenerateDocument (Custom Report Layout templates)
OnAfterGenerateDocumentSetFileName2 In GenerateDocumentRL (Report Layout templates)

Both events fire after the report has been rendered and NewFileName has been built from the template description. The description is used as a format string: %1 = name, %2 = number, %3 = current date/time, %4 = user ID. The following have not been applied yet:

  • The Add Name to Document Name and Add Identification to Doc Name suffixes (you can switch these off on Template).
  • The template's optional subfolder.
  • The file extension, which is always appended afterwards. Don't add one yourself.

Overwrite controls whether an existing file with the same name is replaced. OverrideName has already been applied to the template description by the time the event fires, so changing it has no effect. Change NewFileName instead.

Renaming Mapped Folders

local procedure OnAfterRenameMappedFolder(Mapping: Record "Table Mapping EFQ"; OldFolder: Text; NewFolder: Text; UpdatedMappingCount: Integer)

Raised by RenameMappedFolder. In the UI this is the Rename mapped folder action on the Change SharePoint mapping page, which opens from Folder Mapping in the FactBox. It fires after the folder was renamed on SharePoint and every folder pin pointing to OldFolder or one of its subfolders was updated. UpdatedMappingCount is the number of pins changed. It is not raised when the rename fails or the name did not change. Use it to update references to the folder path that your own extension stores.

SharePoint Factbox EFQ (Page 70319502)

This is the single FactBox part shared by every page that shows SharePoint documents, including the pages you add it to yourself. The events therefore fire for every host page. Filter on GlobalRef.Number() when you only want one table.

Action Events

Each event is raised when the user starts the action, before the connector does anything. Setting Handled (or Abort) to true cancels the connector's own handling.

local procedure OnBeforeOpenSharePointFile2(var Rec: Record "SharePoint File EFQ" temporary; var Handled: Boolean)
local procedure OnBeforeUploadDocument(var CurrentFolder: Text; var GlobalRef: RecordRef; var Handled: Boolean)
local procedure OnBeforeDownloadDocument(var Mapping: Record "Table Mapping EFQ"; var CurrentFolder: Text; var Rec: Record "SharePoint File EFQ" temporary; var GlobalRef: RecordRef; var Handled: Boolean)
local procedure OnBeforeCopyFile(var CurrentFolder: Text; var Rec: Record "SharePoint File EFQ" temporary; var GlobalRef: RecordRef; var Handled: Boolean)
local procedure OnBeforeGenerateDocument(var CurrentFolder: Text; var GlobalRef: RecordRef; var Handled: Boolean)
local procedure OnBeforeOpeningTemplateList(TableNo: Integer; var Ref: RecordRef; var TemplateRecForFiltering: Record "Document Template EFQ")
local procedure OnBeforeUploadPhoto(var CurrentFolder: Text; var GlobalRef: RecordRef; var Handled: Boolean)
local procedure OnBeforeConvertToPDF(var CurrentFolder: Text; var Rec: Record "SharePoint File EFQ" temporary; var GlobalRef: RecordRef; var Handled: Boolean)
local procedure OnBeforeViewOnSharePoint(var CurrentFolder: Text; var GlobalRef: RecordRef; var Handled: Boolean)
local procedure OnBeforeOpeningeSignDialogue(var Rec: Record "SharePoint File EFQ" temporary; var Mapping: Record "Table Mapping EFQ"; var GlobalRef: RecordRef; var CurrentFolder: Text; var Abort: Boolean)
local procedure OnBeforeShareFile(var CurrentFolder: Text; var Rec: Record "SharePoint File EFQ" temporary; var GlobalRef: RecordRef; var Handled: Boolean)
local procedure OnBeforeCreateSubFolders(var CurrentFolder: Text; var GlobalRef: RecordRef; var Handled: Boolean)
local procedure OnBeforeOpeningFolderMapping(var CurrentFolder: Text; var GlobalRef: RecordRef; var Handled: Boolean)
local procedure OnBeforeCheckout(var CurrentFolder: Text; var Rec: Record "SharePoint File EFQ" temporary; var GlobalRef: RecordRef; var Handled: Boolean)
local procedure OnBeforeCheckin(var CurrentFolder: Text; var Rec: Record "SharePoint File EFQ" temporary; var GlobalRef: RecordRef; var Handled: Boolean)
local procedure OnBeforeDeleteFile(var Rec: Record "SharePoint File EFQ" temporary; var CurrentFolder: Text; var GlobalRef: RecordRef; var Handled: Boolean)
Event User action Notes
OnBeforeOpenSharePointFile2 Clicking a file name Files only; clicking a folder navigates into it without raising the event
OnBeforeUploadDocument Upload Document and drag-and-drop Raised once per dropped file. The file name is not passed
OnBeforeDownloadDocument Download Document Mapping is still empty when the event fires
OnBeforeCopyFile Copy File Raised before the destination picker opens
OnBeforeGenerateDocument Generate Document Raised before the template list opens, in both template modes
OnBeforeOpeningTemplateList Generate Document Custom Report Layout mode only. Add filters to TemplateRecForFiltering to limit which templates are offered. It already has a filter on TableNo. There is no Handled
OnBeforeUploadPhoto Take Photo Raised before the camera opens
OnBeforeConvertToPDF Convert Word to PDF Raised before the .docx check
OnBeforeViewOnSharePoint Browse on SharePoint Raised before the "create folder?" prompt
OnBeforeOpeningeSignDialogue e-Signing Uses Abort instead of Handled. Mapping is empty when the event fires
OnBeforeShareFile Share File
OnBeforeCreateSubFolders Create subfolders Raised before the confirmation
OnBeforeOpeningFolderMapping Folder Mapping
OnBeforeCheckout / OnBeforeCheckin Check out file / Check in file Raised before the confirmation
OnBeforeDeleteFile Deleting a row in the FactBox With Handled = true the row stays in the list and nothing is deleted. Otherwise the file goes to the SharePoint recycle bin through RecycleFile, which also raises the codeunit's OnBeforeDeleteFile

CurrentFolder is the folder currently shown in the FactBox. It can be a subfolder the user navigated into, or empty if the record has no folder yet. GlobalRef is the record of the host page. Print PDF has no event.

Content and Activation Events

local procedure OnBeforePopulatingFactBoxWithContent(var Mapping: Record "Table Mapping EFQ"; var CurrentFolder: Text; var GlobalRef: RecordRef; var FolderHistory: List of [Text]; var FactboxRec: Record "SharePoint File EFQ" temporary)
local procedure OnBeforeActivatingAnything(GlobalTableNo: Integer; var FactboxDisabled: Boolean)
Event Raised You can
OnBeforePopulatingFactBoxWithContent Before file rows are added to the FactBox. This happens after a record change (when the background task completes) and on refresh or folder navigation Add your own rows to FactboxRec, or change CurrentFolder on refresh. Earlier rows have been cleared, except the .. row shown inside a subfolder
OnBeforeActivatingAnything In the FactBox's OnInit trigger Set FactboxDisabled = true to switch off the FactBox's own OnOpenPage (sign-in and license check, e-signing setup), its per-row handling and deleting

Notes:

  • After a record change, the SharePoint listing has already been fetched by the background task when OnBeforePopulatingFactBoxWithContent fires. Changing CurrentFolder or Mapping at that point does not change which folder was listed. On refresh and navigation, the listing is fetched after the event, so changing CurrentFolder there does take effect.
  • OnBeforeActivatingAnything fires before the host page has passed its record to the FactBox, so GlobalTableNo is always 0 when your subscriber runs. You can't use it to disable the FactBox for a single table.
  • FactboxDisabled does not hide the FactBox. The host page still calls PrepareFill and runs the background listing, so files are still shown. To hide the FactBox and stop the SharePoint calls, use OnBeforeFiguringOutIfAFactBoxIsNeeded below.

Table Mapping EFQ (Table 70319504)

local procedure OnBeforeFiguringOutIfAFactBoxIsNeeded(TableNo: Integer; var SkipFactBox: Boolean)

Raised by NeedsFactBox(TableNo). Every built-in FactBox page extension calls it from OnOpenPage, and so should yours (see Add the FactBox to Any Page). The Related SharePoint Documents FactBox calls it too. Set SkipFactBox = true and NeedsFactBox returns false: the page hides the FactBox and makes no SharePoint calls. The event fires before the license and mapping checks, so it is the cheapest way to switch the FactBox off per table.

// Page "SharePoint Related Docs EFQ" (70319521)
local procedure OnBeforeOpenRelatedDocument(var Rec: Record "Related Document EFQ" temporary; var Handled: Boolean)

// Codeunit "Related Documents Mgt EFQ" (70319503)
local procedure OnAfterFindAppliedEntries(GenJnlLine: Record "Gen. Journal Line"; var Buffer: Record "Related Document EFQ" temporary)
Event Raised You can
OnBeforeOpenRelatedDocument When the user opens a row in the Related SharePoint Documents FactBox on a journal Open the document your own way. It fires for every row type (Entry, Folder, File, Info)
OnAfterFindAppliedEntries After the connector has collected the customer, vendor or employee ledger entries (and their SharePoint files) related to the journal line Add, remove or change rows in Buffer, for example to show documents from your own tables

Auto-Upload on Posting

Setting Up the Background Upload

// Codeunit "Auto-Upload Sales EFQ" (70319476)
local procedure OnSettingUpInvoiceBackgroundPrint(var SalesInvoiceHeader: Record "Sales Invoice Header"; var SessionParm: Record "Background Report EFQ")
local procedure OnSettingUpCreditMemoBackgroundPrint(var SalesCrMemoHeader: Record "Sales Cr.Memo Header"; var SessionParm: Record "Background Report EFQ")
local procedure OnSettingUpShipmentBackgroundPrint2(var SalesShipmentHeader: Record "Sales Shipment Header"; var SessionParm: Record "Background Report EFQ")

// Codeunit "Auto-Upload Purchase EFQ" (70319478)
local procedure OnSettingUpInvoiceBackgroundPrint2(var PurchInvHeader: Record "Purch. Inv. Header"; var SessionParm: Record "Background Report EFQ")
local procedure OnSettingUpCreditMemoBackgroundPrint2(var PurchCrMemoHdr: Record "Purch. Cr. Memo Hdr."; var SessionParm: Record "Background Report EFQ")

These events fire in the posting session after a sales or purchase document is posted (not in preview). The relevant Auto-Upload setting must be enabled for them to fire. SessionParm has already been filled with FileName (<No.>.pdf), Account Type, No. (bill-to customer or pay-to vendor), ReportUsage, DataTable and DocNo. It is then handed to Background Report Handling EFQ. Change SessionParm to use another report usage, file name or source document. Keep subscribers light: they run inside the posting routine.

Rendering and Uploading

// Codeunit "Background Report Handling EFQ" (70319477)
local procedure OnBeforeRunningAutoUpload(var Parameters: Record "Background Report EFQ"; var Handled: Boolean)
local procedure OnBeforeRunReport(var Reports: Record "Report Selections"; var UploadFileName: Text; var Folder: Text; var Mapping: Record "Table Mapping EFQ")
local procedure OnAfterRunReport(var Mapping: Record "Table Mapping EFQ"; var Folder: Text; var UploadFileName: Text; var DataRef: RecordRef; var Reports: Record "Report Selections"; var B: Codeunit "Temp Blob")
Event Raised You can
OnBeforeRunningAutoUpload At the start of the upload, before the posted document is looked up Take over the whole upload (Handled = true) or change the parameters
OnBeforeRunReport For each report selection with the document's usage, before the report is saved as PDF Change the file name (default: report caption + file name, already sanitized) or the target folder. If an auto-upload subfolder is configured, it is already part of the folder
OnAfterRunReport After each report has been uploaded and its metadata columns filled Use the rendered PDF in B, for example to e-mail it, store it elsewhere or upload a copy

These events run in the background session described under Where Your Subscriber Runs. In a foreground run, a failed upload shows a message and processing continues, so OnAfterRunReport can fire even though the upload failed. In a background session, a failed upload raises an error and the event is not reached.

E-Signing

// Codeunit "Send to DocuSign EFQ" (70319480)
local procedure OnAfterGetSignedDocument(Doc: Record "SharePoint File Details EFQ")

// Codeunit "Send to Adobe EFQ" (70319481)
local procedure OnAfterGetSignedDocument(Doc: Record "SharePoint File Details EFQ")

Raised when a completed document is retrieved from the e-Signature Overview. At that point the signed PDF has been downloaded from DocuSign or Adobe Sign, uploaded next to the original, and its metadata columns filled. Doc has Signed Document Downloaded, Signed Date and Signed Document Name set, and its SourceTable and SourceId identify the BC record. Doc is passed by value, so use the event to trigger follow-up work, not to change Doc. With DocuSign the record has already been saved when the event fires. With Adobe Sign it is saved right after the event.

Incoming Documents

Match Criteria

Each match criteria codeunit publishes its own pair of events. Subscribe to every codeunit whose criteria you want to follow.

// Codeunits "EMail Match EFQ" (70319485), "Pattern Match EFQ" (70319486), "FileName Pattern Match EFQ" (70319487),
// "FileName with key EFQ" (70319491), "Create Document Criteria EFQ" (70319492)
local procedure OnBeforeMatchCheckInTable(var Doc: Record "Incoming Document EFQ"; var CriRec: Record "Incoming Match Criteria EFQ"; MatchTxt: Text)
local procedure OnAfterMatchCheckInTable(var Doc: Record "Incoming Document EFQ"; var CriRec: Record "Incoming Match Criteria EFQ"; MatchTxt: Text)
Event Raised
OnBeforeMatchCheckInTable For each candidate value found in the document (e-mail address, regex match or file name part), before the connector searches the criteria's table for it
OnAfterMatchCheckInTable When a record was found and Doc has been updated with the matched table, record, subfolder and search match
  • MatchTxt is passed by value; changing it does not change what is searched for.
  • FileName with key EFQ raises OnBeforeMatchCheckInTable with an empty MatchTxt, after the primary key values from the file name have been set on the search record.
  • OnAfterMatchCheckInTable is raised only for the first match; the codeunit then stops.

Placing the Document

// Codeunit "Incoming Doc. Management EFQ" (70319484)
local procedure OnAfterDocumentPlaced(Doc: Record "Incoming Document EFQ"; Folder: Text; Ref: RecordRef)

Raised after an incoming document has been uploaded to the folder of the matched record Ref, marked as imported, committed, and its metadata filled. It fires before the OCR JSON file is uploaded and before the source file is removed. Import can run from the Incoming Documents list, the job queue or the Incoming Documents API.

Transfer Attachments (Report 70319478)

local procedure OnAfterUploadingAttachment(Ref: RecordRef; Mapping: Record "Table Mapping EFQ"; Folder: Text; DocumentAttachment: Record "Document Attachment"; SanitizeName: Text)

Raised after each BC document attachment has been uploaded to SharePoint and its metadata filled. SanitizeName is the file name used on SharePoint. A typical use is deleting or flagging the original Document Attachment once it has been moved.

Obsolete and Inactive Events

These events are still published so existing subscribers keep compiling, but new code should not use them:

Event Publisher Status Use instead
OnBeforeCreateFolder SharePoint EFQ Obsolete. Still raised, but its parameters are not var, so it cannot change anything OnBeforeCreateFolderEx
OnBeforeOpenSharePointFile SharePoint Factbox EFQ Obsolete, never raised OnBeforeOpenSharePointFile2
OnSettingUpShipmentBackgroundPrint Auto-Upload Sales EFQ Never raised OnSettingUpShipmentBackgroundPrint2
OnSettingUpInvoiceBackgroundPrint Auto-Upload Purchase EFQ Obsolete, never raised OnSettingUpInvoiceBackgroundPrint2
OnSettingUpCreditMemoBackgroundPrint Auto-Upload Purchase EFQ Obsolete, never raised OnSettingUpCreditMemoBackgroundPrint2

The sales invoice and credit memo events keep their original names (without 2) and are active.

Examples

Custom Folder Name Format

Name customer folders C10000 - Adatum Corporation instead of Adatum Corporation (C10000):

[EventSubscriber(ObjectType::Codeunit, Codeunit::"SharePoint EFQ", 'OnBeforeFormattingFolderName', '', false, false)]
local procedure CustomerFolderFormat(var FolderFormatting: Text; var NameTxt: Text; var NumberTxt: Text; var Mapping: Record "Table Mapping EFQ"; var Ref: RecordRef)
begin
    if Ref.Number() <> Database::Customer then
        exit;
    if NumberTxt <> '' then
        FolderFormatting := '%2 - %1';
end;

This only affects folders that have not been created yet. Existing folders stay where they are, because Name (Number) mappings are pinned.

Prefix Auto-Uploaded Invoices

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Background Report Handling EFQ", 'OnBeforeRunReport', '', false, false)]
local procedure PrefixInvoiceFileName(var Reports: Record "Report Selections"; var UploadFileName: Text; var Folder: Text; var Mapping: Record "Table Mapping EFQ")
begin
    if Reports.Usage = Reports.Usage::"S.Invoice" then
        UploadFileName := Format(Today(), 0, '<Year4>-<Month,2>-<Day,2>') + ' ' + UploadFileName;
end;

This subscriber usually runs in a background session, so it must not show UI.

Hide the FactBox on Item Pages

[EventSubscriber(ObjectType::Table, Database::"Table Mapping EFQ", 'OnBeforeFiguringOutIfAFactBoxIsNeeded', '', false, false)]
local procedure HideForItems(TableNo: Integer; var SkipFactBox: Boolean)
begin
    if TableNo = Database::Item then
        SkipFactBox := true;
end;

Prevent Deleting Files from the FactBox

[EventSubscriber(ObjectType::Page, Page::"SharePoint Factbox EFQ", 'OnBeforeDeleteFile', '', false, false)]
local procedure BlockDeleteOnPostedInvoices(var Rec: Record "SharePoint File EFQ" temporary; var CurrentFolder: Text; var GlobalRef: RecordRef; var Handled: Boolean)
var
    DeleteNotAllowedErr: Label 'Files attached to posted invoices cannot be deleted.';
begin
    if GlobalRef.Number() = Database::"Sales Invoice Header" then
        Error(DeleteNotAllowedErr);
end;

Raising an error shows the reason to the user. Setting Handled := true instead cancels the delete silently.

Tips and Best Practices

  • Filter early. Events such as OnBeforeUpload, OnAfterFoundTableMapping and the FactBox events fire for every table, so exit at once when Ref/GlobalRef is not the table you care about.
  • Keep subscribers fast. Folder-resolution and table-mapping events can fire several times for one user action.
  • Never assume a UI session. Check GuiAllowed() before any Message, Confirm or page.
  • If you change a file or folder name, make sure the result is still valid for SharePoint.
  • If you use Handled, check its value first, because another extension may already have handled the event.