Extending Excel Importer
We designed Excel Importer to be extensible so that our customers could handle new scenarios or create additional import types. This section provides information on how to extend Excel Importer, including the events that are available. Partners can use this information to extend Excel Importer.
To extend Excel Importer, you need to have a Premium plan.
Need help or additional events?
If you need some guidance extending Excel Importer or you want to request an additional event or helper to assist with your extension, please get in touch with us. Remember to tell us what outcome you want to achieve - you never know; we might want to add this feature to Excel Importer and save you the trouble.
Automating Files Imports
The app now includes an API that allows you to automate the process of importing files using the Excel Importer. You can read more about this here.
Adding a new Import Type
Example: Adding a new Import Type (Basic Example)
This example uses the Standard Cost Worksheet import type as an example, which does not have any special processing.
- Extend the enum "ImportType_EI_TSL" with your custom import type
enumextension 50000 "ImportType" extends ImportType_EI_TSL
{
value(50000; "Standard Cost Worksheet")
{
Caption = 'Standard Cost Worksheet';
}
}
- Create a codeunit similar to the one below:
codeunit 50000 "StdCostWorksheetMgt"
{
internal procedure ImportStandardCostWorksheet();
var
ExcelImportManagement: Codeunit "Excel Import Management_EI_TSL";
begin
ExcelImportManagement.Import(Enum::ImportType_EI_TSL::"Standard Cost Worksheet", Database::"Standard Cost Worksheet", false);
end;
}
- Create a page extension to add the Import action to your page and call your function
pageextension 50000 "StandardCostWrksheet" extends "Standard Cost Worksheet"
{
actions
{
addfirst("F&unctions")
{
action("ImportFromExcel")
{
ApplicationArea = All;
Caption = 'Import';
Ellipsis = true; Image = ImportExcel;
Promoted = true;
PromotedCategory = Process;
PromotedIsBig = true;
ToolTip = 'Allows you to import standard costs from Excel or text in a customisable layout.';
trigger OnAction()
var
StandardCostWrksheetImport: Codeunit StdCostWrksheetMgt;
begin
StandardCostWrksheetImport.ImportStandardCostWorksheet();
end;
}
}
}
}
Adding New Import Types or Changing Existing Imports
This section references events that are available to extend Excel Importer. It is not a complete list of the available events but includes events that get used frequently. You can use these events when you have more complex processing that must get handled. You can use these events when you create new import types or if you want to change the way existing import types work.
Events related to Import Template Configuration
Object - Event | Purpose |
---|---|
table "Exl. Mapping Template_EI_TSL" | Excel Mapping Template |
OnGetCustomTableID | Specifies the table associated with the import type. |
OnInsertCustomTemplateToBuffer | you can optionally subscribe to this event if you want to specify additional details about a custom import type |
OnCheckIfFieldFromCustomEntityCanBeEdited | Use this event if you want to protect certain fields from being updated by the import. Using this event will cause fields to be filtered out of lookups so they cannot be selected. |
OnBeforeGetRelatedFieldsAndSettingsForCustomEntity | Use this event to specify the available settings as well as any related tables that get updated by the import (e.g. Header/Line). Refer to the example below to see how to use this. |
OnBeforeGetRelatedFieldsAndSettings | Use this event to add additional settings to existing templates or if you want to implement different logic to handle related fields and settings for a template. |
OnBeforeGetCommaSeparatedDimensionFieldIDText | Use this event associate global/shortcut dimension fields with the dimension code. |
codeunit "SettingsHelper_EI_TSL" | Settings Helper |
HandleCustomSettingType | This event allows you to specify settings values for a custom setting type on an existing template. You can use the approach above to specify the allowed values. |
OnCustomLookupSettingValue | Use this event to specify the available setting values for the setting type in relation to a custom template. This is different to the HandleCustomSettingType event in that it only fires for a custom template. Here is an example on how to use this. |
Example - Adding related tables and settings
The example code comes from the sales and purchase document import (it has been changed slightly as build in imports do not use these events).
[EventSubscriber(ObjectType::Table, Database::"Exl. Mapping Template_EI_TSL", OnBeforeGetRelatedFieldsAndSettingsForCustomEntity, '', false, false)]
local procedure OnBeforeGetRelatedFieldsAndSettingsForCustomEntity(var ExcelImportManagement: Codeunit "Excel Import Management_EI_TSL"; var RelatedTableList: List of [Integer]; var RelatedFieldFilterList: List of [Text]; ImportType: Enum ImportType_EI_TSL)
begin
AddRelatedFieldsAndSettings(ExcelImportManagement, ImportType, RelatedTableList, RelatedFieldFilterList);
end;
/// <summary>
/// Adds the related tables and settings that are applicable for the import
/// </summary>
internal procedure AddRelatedFieldsAndSettings(var ExcelImportManagement: Codeunit "Excel Import Management_EI_TSL"; ImportType: Enum ImportType_EI_TSL; var RelatedTableList: List of [Integer]; var RelatedFieldFilterList: List of [Text]; var RelatedReferenceNo: Code[50]);
var
ItemTrackingMgt: Codeunit ItemTrackingMgt_EI_TSL;
NegativeDocumentTotalsTxt: Label 'Specify how to handle negative document totals - this does not apply to quotes and blanket orders', MaxLength = 100;
ReleaseDocsTxt: Label 'Release the documents or send them for approval after importing.', MaxLength = 100;
Prop_DocNoRuleTextLbl: Label 'Use the imported Document No. (if present) as the Posted Document No.', MaxLength = 100;
Prop_ReplaceDocNoTextLbl: Label 'Replace with the imported Document No. from the Number Series.', MaxLength = 100;
begin
// Add the setting types available for this import and provide some basic info including the default value and what the setting does
ExcelImportManagement.AddSettingToPropertyBuffer(SettingType::"Document No. as Posting No.", SettingValue::No, Prop_DocNoRuleTextLbl);
ExcelImportManagement.AddSettingToPropertyBuffer(SettingType::"Replace Document No.", SettingValue::No, Prop_ReplaceDocNoTextLbl);
ExcelImportManagement.AddSettingToPropertyBuffer(SettingType::"Negative Document Totals", SettingValue::"Do not Validate", NegativeDocumentTotalsTxt);
ExcelImportManagement.AddSettingToPropertyBuffer(SettingType::"Release Documents", SettingValue::No, ReleaseDocsTxt);
// tables
if ImportType = ImportType::Sales then
RelatedTableList.Add(Database::"Sales Header")
else
RelatedTableList.Add(Database::"Purchase Header");
RelatedFieldFilterList.Add(''); // you can optionally include a filter string if you only want to allow certain fields.
ItemTrackingMgt.AddTrackingSpecFields(ImportType, ExcelImportManagement, false, RelatedTableList, RelatedFieldFilterList);
end;
Example - Specifying Allowed Settings Values for a Setting Type on an existing template
This example shows you how to specify allowed values for a custom setting type on an existing template (e.g. Sales Document).
[EventSubscriber(ObjectType::Codeunit, Codeunit::SettingsHelper_EI_TSL, OnHandleCustomSettingType, '', false, false)]
local procedure OnHandleCustomSettingType(ImportType: Enum ImportType_EI_TSL; SettingType: Enum ImportSettingType_EI_TSL; var SettingsText: Text; var IsHandled: Boolean)
begin
SettingsText := GetSettingValuesAllowedForType(ImportType, SettingType);
IsHandled := true;
end;
/// <summary>
/// Creates a comma separated list of allowed setting values for the setting type.
/// </summary>
internal procedure GetSettingValuesAllowedForType(ImportType: Enum ImportType_EI_TSL; SettingType: Enum ImportSettingType_EI_TSL) SettingsText: Text
begin
case SettingType of
SettingType::"Post Documents Automatically":
begin
SettingsHelper.AddToSettingsText(SettingsText, SettingValue::No);
SettingsHelper.AddToSettingsText(SettingsText, SettingValue::Yes);
end;
end;
end;
Example - Specifying Allowed Settings Values for a Setting Type on a custom template
This example shows you how to specify allowed values for a custom setting type on a custom template you have created.
[EventSubscriber(ObjectType::Codeunit, Codeunit::SettingsHelper_EI_TSL, OnCustomLookupSettingValue, '', false, false)]
local procedure OnCustomLookupSettingValue(ImportType: Enum ImportType_EI_TSL; SettingType: Enum ImportSettingType_EI_TSL; var SettingsText: Text)
begin
SettingsText := GetSettingValuesAllowedForType(ImportType, SettingType);
end;
/// <summary>
/// Creates a comma separated list of allowed setting values for the setting type.
/// </summary>
internal procedure GetSettingValuesAllowedForType(ImportType: Enum ImportType_EI_TSL; SettingType: Enum ImportSettingType_EI_TSL) SettingsText: Text
begin
case SettingType of
SettingType::"Replace Document No.", SettingType::"Document No. as Posting No.",
SettingType::"Release Documents":
begin
SettingsHelper.AddToSettingsText(SettingsText, SettingValue::No);
SettingsHelper.AddToSettingsText(SettingsText, SettingValue::Yes);
end;
SettingType::"Negative Document Totals":
begin
SettingsHelper.AddToSettingsText(SettingsText, SettingValue::"Do not Validate");
SettingsHelper.AddToSettingsText(SettingsText, SettingValue::"Skip during Import");
SettingsHelper.AddToSettingsText(SettingsText, SettingValue::"Cancel Import");
SettingsHelper.AddToSettingsText(SettingsText, SettingValue::"Order/Invoice to Credit");
SettingsHelper.AddToSettingsText(SettingsText, SettingValue::"Order/Invoice to Return/Credit");
end;
else
SettingsHelper.SettingTypeNotValidForImportTypeError(ImportType, SettingType);
end;
end;
Example - Adding a text setting
It is possible to add a setting that is not an enum but a text value. Below is the example from the General Journal import. The Amount by Dimension setting will hold a dimension value.
internal procedure AddGeneralJournalRelatedFieldsAndSettings(var ExcelImportManagement: Codeunit "Excel Import Management_EI_TSL");
var
Prop_AmtByDimDescLbl: Label 'Specify this if there are multiple amount columns, each representing a different dimension.', MaxLength = 100;
Prop_ExcludeZeroDescLbl: Label 'Skip lines where the amount is zero', MaxLength = 100;
begin
ExcelImportManagement.AddSettingToPropertyBuffer(SettingType::"Exclude Zero Amounts", SettingValue::No, Prop_ExcludeZeroDescLbl);
ExcelImportManagement.AddSettingToPropertyBuffer(SettingType::"Amount by Dimension", SettingValue::"Text Value in Constant", Prop_AmtByDimDescLbl);
end;
- You can subscribe to
OnBeforeValidateSettingValuesForSettingType
to validate input while creating a template.
internal procedure ValidateDimensionForAmountByDimension(SettingTypeParam: Enum ImportSettingType_EI_TSL; SelectedValue: Text)
var
Dimension: Record Dimension;
begin
if (SelectedValue = '') or (SettingTypeParam <> SettingTypeParam::"Amount by Dimension") then
exit;
Dimension.Get(SelectedValue);
Dimension.TestField(Blocked, false);
end;
- You can access the value of the setting at runtime using the
GetConstantTextSettingFromStorage
procedure.
AmountDimensionCode := CopyStr(SettingsHelper.GetConstantTextSettingFromStorage(SettingType::"Amount by Dimension", '', false, false), 1, MaxStrLen(AmountDimensionCode));
if AmountDimensionCode = '' then
exit;
Example - Handling Global/Shortcut Dimensions
You use this event so that the Excel Importer will update the Global/Shortcut Dimension fields as expected.
[EventSubscriber(ObjectType::Table, Database::"Exl. Mapping Template_EI_TSL", 'OnBeforeGetCommaSeparatedDimensionFieldIDText', '', false, false)]
local procedure OnBeforeGetCommaSeparatedDimensionFieldIDText(ImportType: Enum ImportType_EI_TSL; var CommaSeparatedFieldIDText: Text; var IsHandled: Boolean);
var
ExlAccDimMapLine: Record ExlAccDimMapLine_EI_TSL;
begin
if ImportType <> ImportType::"Account/Dimension Mapping" then
exit;
CommaSeparatedFieldIDText := Format(ExlAccDimMapLine.FieldNo("Shortcut Dimension 1 Code")) + ',' + Format(ExlAccDimMapLine.FieldNo("Shortcut Dimension 2 Code"));
IsHandled := true;
end;
Events related to Import Processing
The events are shown in the order in which they fire.
OnBeforeImportExcelData
Use this event to perform custom logic after the Excel File is loaded but before the processing starts
OnBeforeCheckIfConcatenationIsRequired
This event allows you to skip concatenation in certain scenarios. For example, the General Journal Dimensioned Amount feature, when enabled on a template, disables concatenation for the Amount field.
OnAfterCopyExcelBufferToExlImpBuffer
This event is raised after the data from the current row is transferred into a temporary record, before any processing is done and before the app checks criteria for skipping the row. You can use this event if you want to perform special processing using a footer record. The event includes all buffers so you need to use the record type to determine which before to use. The LastImportedRecordRef will contain the values imported from a previous row as it has not been initialised as this stage.
OnBeforeCheckImportedValuesBeforeUpdate
Use this event if you want to do your validation before importing data. You will use this if you want to suppress some of the standard validation added by Excel Importer and add your own.
OnAfterCheckImportedValuesBeforeUpdate
Use this event to add additional validation before importing data.
OnBeforeExcludeExcelBufferRowFromImport
Use this event if you want to exclude an Excel row from the import. At this point Excel Importer has not transferred any values to fields
OnBeforeFindExistingRecord
This event fires before Excel Importer checks if there is an existing record. This is commonly used to manipulate the imported data - for example replacing an item reference with the actual item number. The StagingRecordRef parameter contains values that are mapped to fields.
OnBeforeSkipImportOfRecord
Use this event if you want to skip the import based on values on the line. The StagingRecordRef parameter contains values that are mapped to fields. This is before Excel Import has tried to find an existing record.
OnFindExistingRecord
This event is fired if Excel Importer finds an existing record with the Record ID as the record being imported.
OnInsertImportedData
This event fires before a record is inserted. At this stage no values will be transferred to the NewRecordRef unless the record exists already. You can use StagingRecordRef to get the mapped field values. You can also insert the record if it needs to exist before updating other field values.
OnBeforeApplyImportedData
This event fires before the import values are copied to the record.
OnAfterAssignFieldValue
This event gets fired after a value gets assigned to a field. You can use this event to perform special processing after updating a specific field during import.
OnBeforeModifyOrInsertImportedData
This event fires before the record is insert or modified. The dimension set is also not applied that this point. You can use this event to handle the insert or modify yourself or do some processing immediately before the insert/modify.
OnAfterApplyAndSaveData
This event fires after the dimension set is applied and the record has been insert/modified. You can use this event to handle processing that needs to happen after the record is updated.
OnPostImportData
This event fires after all records have been imported, but before the transaction has been committed. Use this event to handle post import processing that is directly connected to the import (e.g. releasing orders).
Sales and Purchase Document Events
Event | Purpose |
---|---|
Sales Documents | |
OnBeforeInsertSalesHeader | This event allows you to directly update any fields that need to be updated before the sales header is inserted. |
OnAfterInsertNewSalesHeaderBeforeModify | Allows you to implement custom logic directly after all fields are transferred to a sales header before it gets modified. |
OnAfterGetOrCreateSalesHeader_BeforeInsertLine | Allows you to implement custom logic after the sales header is created before the line is inserted. |
OnAfterInsertSalesLineBeforeUpdateFields | Allows you to implement custom logic after the sales line is inserted with the initial values but before the line gets updated with the rest of the imported values. |
Purchase Documents | |
OnBeforeInsertPurchaseHeader | This event allows you to directly update any fields that need to be updated before the purchase header is inserted. |
OnAfterInsertNewPurchaseHeaderBeforeModify | Allows you to implement custom logic directly after all fields are transferred to a purchase header before being modified. |
OnAfterGetOrCreatePurchaseHeader_BeforeInsertLine | Allows you to implement custom logic after the purchase header is created but before the line gets inserted. |
OnAfterInsertPurchaseLineBeforeUpdateFields | Allows you to implement custom logic after the purchase line is inserted with the initial values but before the line gets updated with the rest of the imported values. |
Common | These can be used for purchases and sales documents. |
OnBeforeAssignDocumentNo | Use this event to change how the document number gets assigned. If you assign a value to the NewDocNo parameter, the app will get that sales header. |
OnAfterFieldCannotBeEdited | The app has built-in rules to prevent certain fields from being updated directly. Use this event to restrict more fields. Fields that are restricted do not show in lookups |
OnBeforeFieldCannotBeEdited | Similar to the previous event, however, this event allows you to override the built-in rules |
OnAfterImportSalesOrPurchaseLine | Allows you to implement custom logic directly after all fields are transferred to a sales/purchase line and the line has been inserted. |
OnPostImportSalesPurchaseDocsBeforeDataRelease | This event fires after all the documents have been imported before the documents get released. This event allows you to process the imported documents before they get released or sent for approval. This event will fire even if the template is not configured to release the documents. The TempRecordRef parameter contains a record for every sales or purchase header created during the import. |
Physical Inventory Journal Events
Event | Purpose |
---|---|
OnClearPhysicalQuantityOnJournalBeforeUpdatePhysQty | You can use this event to handle specific logic required when resetting the physical quantity on the Physical Inventory Journal before importing the recording. |
Helper Functions
Function | Purpose |
---|---|
Excel Import Management | |
ProcessRelatedTableFields | Processes fields from a related table. The InputSeqFrom and InputSeqTo parameters allow you to specify a range of fields to process. If you specify zero for both, it does not apply a filter. If you specify a value for only one it is either a minimum or maximum. Refer to the example below. |
Example - ProcessRelatedTableFields
In this example, we show you how you can use the ProcessRelatedTableFields
function to process fields from the purchase header table, which is a related table on the purchase document import.
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Sales/Purch. Doc. Imp._EI_TSL", OnBeforeInsertPurchaseHeader, '', false, false)]
local procedure "OnBeforeInsertPurchaseHeader"(var PurchaseHeader: Record "Purchase Header"; var ExlImpFieldBuffer: Record "Exl. Imp Field Buffer_EI_TSL")
begin
UpdatePurchaseHeaderFieldsBeforeInsert(PurchaseHeader, ExlImpFieldBuffer);
end;
local procedure UpdatePurchaseHeaderFieldsBeforeInsert(var PurchaseHeader: Record "Purchase Header"; var ExlImpFieldBuffer: Record "Exl. Imp Field Buffer_EI_TSL")
var
RecordRef: RecordRef;
ExcelImportManagement: Codeunit "Excel Import Management_EI_TSL";
FromProcressingOrder: Integer;
ToProcressingOrder: Integer;
begin
// logic to determine which fields to apply before insert
//FromProcressingOrder :=
//ToProcressingOrder :=
RecordRef.GetTable(PurchaseHeader);
ExcelImportManagement.ProcessRelatedTableFields(RecordRef, ExlImpFieldBuffer, FromProcressingOrder, ToProcressingOrder);
RecordRef.SetTable(PurchaseHeader);
end;
Adding a New Import Type
Adding a new import type is very straightforward.
- Extend the "ImportType_EI_TSL" Enum to add your Import Type
- Subscribe to the OnGetCustomTableID
Custom Values
Events related to Custom Values
Custom values get used to map values required for processing when these values do not relate to a specific field.
Object | Event | Description |
---|---|---|
Table CustomValue_EI_TSL | OnAfterRefreshCustomValueActions Use this event to publish a new custom action. When you subscribe to this you can use the AddActionToNameValueBuffer function described below | |
Table CustomValue_EI_TSL | OnAfterCheckValueTypeSelectedForProcessingAction | |
Table CustomValue_EI_TSL | OnAfterGetDefaultValueType Allows you to specify the default value type for your custom processing action. | |
Table CustomValue_EI_TSL | OnBeforeCopyAccountDimensionValuesToSalesLine You can use this event to change how the information gets copied from the account dimension mapping. You can only make changes to the NewSalesLine parameter. | |
Table CustomValue_EI_TSL | OnAfterGetDefaultRoundingPrecision Allows you to specify the rounding precision on the custom value. Only use this if the default rounding precision will only work for you. | |
Table CustomValue_EI_TSL | OnBeforeCreateDefaultCustomValues You can use this event if you want to create default custom values. | |
Table CustomValue_EI_TSL | OnAfterGetDefaultRoundingPrecision You can use this event if you want to update a default custom value before it gets inserted. | |
Codeunit "Sales/Purch. Doc. Imp._EI_TSL" | OnBeforeAddNewSalesUsingValueAsAmount Allows you to add custom logic to the AddNewSalesPurchaseLineUsingValueAsAmount processing action for sales lines before the processing action gets executed. | |
Codeunit "Sales/Purch. Doc. Imp._EI_TSL" | OnBeforeAddNewPurchaseLineUsingValueAsAmount | As above, but applies to purchase documents |
Codeunit "Sales/Purch. Doc. Imp._EI_TSL" | OnAfterAddNewSalesUsingValueAsAmountBeforeInsertNewSalesLine | Allows you to add custom logic to the AddNewSalesPurchaseLineUsingValueAsAmount processing action for sales lines after the processing action gets executed. |
Codeunit "Sales/Purch. Doc. Imp._EI_TSL" | OnAfterAddNewPurchaseLineUsingValueAsAmountBeforeInsertNewPurchaseLine | As above, but applies to purchase documents. |
Codeunit "Sales/Purch. Doc. Imp._EI_TSL" | OnCustomSalesPurchaseValueProcessAction | Allows you to implement your own custom processing action. |
Codeunit "Sales/Purch. Doc. Imp._EI_TSL" | OnAfterSales_InitQuantitiesOnCopyLineForCustomValue | this event fires when the new sales line is copied from the existing purchase line. |
Codeunit "Sales/Purch. Doc. Imp._EI_TSL" | OnAfterPurch_InitQuantitiesOnCopyLineForCustomValue | this event fires when the new purchase line is copied from the existing purchase line. |
Helpers for Custom Values
Object | Function |
---|---|
Table CustomValue_EI_TSL | AddActionToNameValueBuffer |
Table CustomValue_EI_TSL | GetActionText Used to retrieve the caption or extended description for the given action. You can use this if you want to display a message to the user and provide a user friendly reference to the action. |
Table CustomValue_EI_TSL | CopyAccountDimensionValuesToSalesLine Use this function if you want your custom processing action to copy values from the account dimension mapping |
Example: Adding a new Processing Action
Publishing the Processing Action
The code snippet below shows you how to add a new processing action that you can select in the custom values list. The example adds a processing action that you can use on a sales import template.
var
ProcessingActionIDLbl: Label 'ProcessingActionCode_TSL', Locked = true, MaxLength = 250;
ProcessingActionCaptionTxt: Label 'Add a new sales line or purchase line if the value is not zero', MaxLength = 250;
ExtendedDescriptionTxt: Label 'Specify details about what this action does and how to use it.', MaxLength = 2048;
[EventSubscriber(ObjectType::Table, Database::CustomValue_EI_TSL, 'OnAfterRefreshCustomValueActions', '', false, false)]
local procedure OnAfterRefreshCustomValueActions(ImportType: Enum ImportType_EI_TSL; var TempNameValueBuffer: Record "Name/Value Buffer");
begin
case ImportType of
ImportType::Sales:
AddSalesProcessingActions(TempNameValueBuffer);
end;
end;
local procedure AddSalesProcessingActions(var TempNameValueBuffer: Record "Name/Value Buffer")
var
CustomValue: Record CustomValue_EI_TSL;
begin
CustomValue.AddActionToNameValueBuffer(
TempNameValueBuffer, ProcessingActionIDLbl, ProcessingActionCaptionTxt,
ExtendedDescriptionTxt);
end;
Implementing the Processing Action
Here is an example of how you can implement the processing logic on the sales import template.
var
ProcessingActionIDLbl: Label 'ProcessingActionCode_TSL', Locked = true, MaxLength = 250;
ProcessingActionCaptionTxt: Label 'Add a new sales line or purchase line if the value is not zero', MaxLength = 250;
ExtendedDescriptionTxt: Label 'Specify details about what this action does and how to use it.', MaxLength = 2048;
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Excel Import Management_EI_TSL", 'OnAfterApplyandSaveData', '', false, false)]
local procedure OnAfterApplyandSaveData(var RecRef: RecordRef; var ValuesImported: Record "Exl. Imp Field Buffer_EI_TSL"; var TableID: Integer; var PropertyBuf2: Record "Name/Value Buffer"; var RowNo: Integer; var FirstRowNo: Integer; var TmpDimSetEntry: Record "Dimension Set Entry"; ImportTypeAsEnum: Enum ImportType_EI_TSL);
begin
if ImportTypeAsEnum = ImportTypeAsEnum::Sales then
SalesOnAfterApplyandSaveData(RecRef, ValuesImported);
end;
local procedure SalesOnAfterApplyandSaveData(var RecordRef: RecordRef; var ExlImpFieldBuffer: Record "Exl. Imp Field Buffer_EI_TSL");
var
SalesLine: Record "Sales Line";
begin
RecordRef.SetTable(SalesLine);
ProcessSalesLineCustomValueActions(SalesLine, ExlImpFieldBuffer);
end;
local procedure ProcessSalesLineCustomValueActions(ImportedSalesLine: Record "Sales Line"; var ExlImpFieldBuffer: Record "Exl. Imp Field Buffer_EI_TSL")
var
TempCustValueExlImpFieldBuffer: Record "Exl. Imp Field Buffer_EI_TSL" temporary;
CustomValue: Record CustomValue_EI_TSL;
begin
TempCustValueExlImpFieldBuffer.FilterOnCustomValuesUsingImportedFields(ExlImpFieldBuffer);
if not TempCustValueExlImpFieldBuffer.FindSet() then
exit;
repeat
case CustomValue."Processing Action" of
ProcessingActionIDLbl:
HandleMyNewProcessingAction(ImportedSalesLine, TempCustValueExlImpFieldBuffer, CustomValue);
end;
until TempCustValueExlImpFieldBuffer.Next() = 0;
end;
local procedure HandleMyNewProcessingAction(ImportedSalesLine: Record "Sales Line"; ExlImpFieldBuffer: Record "Exl. Imp Field Buffer_EI_TSL"; var CustomValue: Record CustomValue_EI_TSL)
var
NewSalesLine: Record "Sales Line";
ExcelImportManagement: Codeunit "Excel Import Management_EI_TSL";
RecordRef: RecordRef;
FieldRef: FieldRef;
TotalLineAmountExcl: Decimal;
begin
if ExlImpFieldBuffer."Cell Value as Text" = '' then
exit;
// convert the text to an amount
RecordRef.Open(Database::"Sales Line");
// the next 4 lines get the decimal value. It uses the functions in Excel Importer because there are various transformations that can
// be done using the Excel Mapping. It is recommended you use this method instead of handling it yourself
FieldRef := RecordRef.Field(NewSalesLine.FieldNo("Unit Price")); // this can be any decimal field as we only want to get the decimal value
ExlImpFieldBuffer."Validate Field Method" := ExlImpFieldBuffer."Validate Field Method"::Never; // important - we just want the value
ExcelImportManagement.EvaluateFieldRef(FieldRef, ExlImpFieldBuffer);
TotalLineAmountExcl := FieldRef.Value();
if TotalLineAmountExcl = 0 then
exit;
NewSalesLine := ImportedSalesLine;
// do something like add a new line or make changes to the line that was imported
end;