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. MappinginOnBeforeUploadExis empty when the caller used anUploadFileoverload 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
SanitizeNameNoDotyourself if needed). OnAfterUploadis 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 |
CreateFolderExsplits the complete path at the last/before raising the event.CreateFolderExwithCreateParentIfFailed = truecan raise the event again for each parent it has to create.- For subfolders that come from an alternative mapping,
OnAfterCreateSubFolderpasses theSubFoldersrecord 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. TMis an in-memory copy for this call. Don'tModifyit 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:
- 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. - For the Name (Number) and Inherited Dynamic methods, an existing folder pin (
SharePoint Folder Mapping EFQ) is returned directly. No folder events fire. OnBeforeMappingFolderForRecordis raised.- For child tables, the parent record is filtered, then
OnOverrideParentRecordFiltersis raised before the parent is looked up. - The folder name is built from the caption fields and
OnBeforeFormattingFolderNameis raised. - If
CreateIfNotFoundis true, the folder is created, the pin is stored, andOnAfterCreateFolderForRecordis raised. OnAfterFoundFolderForRefis raised and itsFoldervalue 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: yourFolderis returned as-is. The connector does not create it on SharePoint, andOnAfterCreateFolderForRecordandOnAfterFoundFolderForRefare not raised. For the Name (Number) method, your folder is also stored as the record's folder pin, even whenCreateIfNotFoundis false. After that, step 2 returns it and no events fire for that record again. OnAfterCreateFolderForRecordfrequency: 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 everyGetFolderForRecord(Ref, true)call, whether or not the folder already existed.OnAfterFoundFolderForRefis skipped when a pinned folder is returned (step 2) or whenOnBeforeMappingFolderForRecordis handled. Don't use it as a guaranteed "every lookup" hook.- Fallback path:
OnOverrideTableMappingandOnOverrideFoundFolderNameare 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. OnBeforeFormattingFolderNameis also raised by the publicGetFolderStringForRecandGetFolderStringForRecExprocedures.
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
OnBeforePopulatingFactBoxWithContentfires. ChangingCurrentFolderorMappingat that point does not change which folder was listed. On refresh and navigation, the listing is fetched after the event, so changingCurrentFolderthere does take effect. OnBeforeActivatingAnythingfires before the host page has passed its record to the FactBox, soGlobalTableNois always 0 when your subscriber runs. You can't use it to disable the FactBox for a single table.FactboxDisableddoes not hide the FactBox. The host page still callsPrepareFilland runs the background listing, so files are still shown. To hide the FactBox and stop the SharePoint calls, useOnBeforeFiguringOutIfAFactBoxIsNeededbelow.
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.
Related SharePoint Documents
// 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 |
MatchTxtis passed by value; changing it does not change what is searched for.FileName with key EFQraisesOnBeforeMatchCheckInTablewith an emptyMatchTxt, after the primary key values from the file name have been set on the search record.OnAfterMatchCheckInTableis 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,OnAfterFoundTableMappingand the FactBox events fire for every table, so exit at once whenRef/GlobalRefis 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 anyMessage,Confirmor 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.