BC Blueprint - Data Exchange Definition
Un análisis funcional y técnico en profundidad sobre el framework
de intercambio de datos que Business Central esconde detrás de una
página de configuración: cómo separa formato, ejecución y mapeo; qué
tablas, codeunits y XMLports participan; cómo procesa CSV, fixed-width,
XML y estructuras personalizadas; qué ocurre durante una importación o
exportación; y dónde esperan las trampas detrás de la aparentemente
inocente página Data Exchange Definition.
Nota de versión: los nombres e identificadores de objetos, campos, procedimientos públicos y eventos de este artículo se contrastaron originalmente con Microsoft Base Application 27.5.46862.47988 y se han revisado contra la documentación pública actual de Microsoft disponible el 31 de agosto de 2026. Los textos funcionales están en español, pero los objetos, campos, valores de configuración y referencias de AL conservan su nombre original en inglés. Comprueba siempre los símbolos de la versión exacta contra la que compila tu extensión: una definición puede ser configuración, pero los objetos Integer que contiene siguen teniendo una relación muy física con el runtime.
La funcionalidad que todo el mundo ha visto y casi nadie quiere tocar
Business Central tiene la costumbre de esconder maquinaria industrial detrás de páginas que parecen tan amenazantes como una hoja de Excel ligeramente enfadada.
Data Exchange Definitions es un ejemplo perfecto.
A primera vista, parece una página de configuración en la que alguien selecciona CSV, elige un separador, mapea unas cuantas columnas y vuelve a casa antes de que el edificio empiece a arder. Sin embargo, debajo de esa página existe un pipeline de integración completo capaz de:
- Obtener archivos o streams desde diferentes orígenes.
- Interpretar texto delimitado, texto de ancho fijo, XML y formatos personalizados.
- Persistir los valores interpretados en un buffer de ejecución normalizado.
- Representar relaciones padre-hijo en documentos jerárquicos.
- Transformar valores antes de mapearlos.
- Mapear valores externos mediante
RecordRefyFieldRef. - Utilizar registros intermedios en lugar de atacar directamente las tablas de producción.
- Exportar documentos delimitados, de ancho fijo y XML.
- Inyectar lógica personalizada antes, durante y después del mapeo.
Microsoft utiliza este framework en escenarios como extractos bancarios, exportaciones de pagos, documentos electrónicos, tipos de cambio, nóminas, Intrastat y otras integraciones localizadas. La documentación oficial lo presenta como una capa configurable para intercambiar documentos empresariales y archivos de datos cuyos formatos varían según el proveedor, la autoridad o el país. Esa es la descripción educada. La descripción menos educada es que se trata de un pequeño motor ETL configurable que vive dentro del ERP y finge que no lo es. Consulta About the Data Exchange Framework y Set up data exchange definitions.
Dentro de la serie BC Blueprint, este módulo ocupa un
lugar distinto a Posting Groups y Dimensions:
aquellos explican cómo Business Central decide y clasifica el registro;
Data Exchange Definition explica cómo un dato externo
consigue cruzar la frontera del ERP sin que cada proveedor obligue a
escribir un importador completamente nuevo. Después de cruzarla, posting
groups, dimensions, validaciones y reglas empresariales siguen esperando
al otro lado. El framework traduce; no concede ciudadanía
automática.
Este artículo explica qué hace realmente el framework, qué objetos AL participan y dónde guardan sus papeles los dragones.
Primero, el modelo mental
Una Data Exchange Definition no es una sola cosa. Son tres contratos que trabajan juntos:
- El contrato de formato describe el archivo externo: tipo, codificación, líneas, columnas, longitudes, rutas, separadores y culturas.
- El contrato de mapeo conecta esos elementos externos con tablas y campos de Business Central.
- El contrato de ejecución selecciona los codeunits y XMLports que obtienen, leen, validan, mapean, escriben y entregan los datos.
Durante la ejecución se crea una entrada Data Exch.
independiente para cada intercambio. La definición es la receta;
Data Exch. es la desafortunada cena de esta noche.
Data Exch. conserva la ejecución.La idea arquitectónica más importante es la frontera entre
Data Exch. Field y la tabla final. Cuando entiendes esa
frontera, todo el framework deja de parecer magia negra y empieza a
parecer magia negra organizada.
Mapa de objetos
Todos los objetos principales se encuentran en el namespace
System.IO en Base Application 27.5.
Tablas de configuración y ejecución
| ID | Objeto AL | Propósito |
|---|---|---|
| 1222 | table "Data Exch. Def" |
Cabecera de la definición reutilizable de formato y ejecución. |
| 1227 | table "Data Exch. Line Def" |
Describe tipos de línea lógicos o nodos jerárquicos. |
| 1223 | table "Data Exch. Column Def" |
Describe columnas, elementos XML, atributos, constantes, formatos, longitudes y rutas. |
| 1224 | table "Data Exch. Mapping" |
Conecta una definición de línea con una tabla y con codeunits de premapeo, mapeo y posmapeo. |
| 1225 | table "Data Exch. Field Mapping" |
Conecta una columna con un campo y almacena transformación, prioridad, sobrescritura, valor predeterminado, opcionalidad y multiplicador. |
| 1265 | table "Data Exch. Field Mapping Buf." |
Buffer utilizado por la configuración del mapeo genérico y las sugerencias de campos. |
| 1238 | table "Data Exch. Field Grouping" |
Define los campos de agrupación utilizados por el mapeo genérico de exportación. |
| 1233 | table "Data Exch. Table Filter" |
Almacena vistas adicionales de tablas de origen utilizadas en exportaciones con varias partes. |
| 1239 | table "Data Exch. FlowField Gr. Buff." |
Soporte temporal para agregar FlowFields en exportaciones agrupadas. |
| 1220 | table "Data Exch." |
Una ejecución del intercambio, incluyendo nombre y BLOB del archivo, código de definición, filtros, documento entrante y registro relacionado. |
| 1221 | table "Data Exch. Field" |
Valores normalizados interpretados o generados, identificados por intercambio, línea, columna y nodo. |
| 1214 | table "Intermediate Data Import" |
Estructura genérica de staging que almacena tabla destino, campo destino, relación entre registros y valor. |
| 1237 | table "Transformation Rule" |
Transformaciones reutilizables y encadenables. |
La documentación pública de objetos confirma las tablas centrales de
configuración y sus campos actuales: Data Exch. Def,
Data Exch. Mapping,
Data Exch. Field Mapping
y Data Exch..
Objetos de procesamiento que merece la pena conocer por su nombre
| ID | Objeto AL | Función |
|---|---|---|
| 1201 | codeunit "Process Data Exch." |
Mapeador genérico de campos de importación y conversor de tipos. |
| 1203 | codeunit "Import XML File to Data Exch." |
Interpreta rutas XML y nodos padre-hijo configurados en
Data Exch. Field. |
| 1214 | codeunit "Map DataExch To Intermediate" |
Convierte campos normalizados en
Intermediate Data Import. |
| 1241 | codeunit "Fixed File Import" |
Divide líneas de ancho fijo según las longitudes configuradas en las columnas. |
| 1413 | codeunit "Read Data Exch. from Stream" |
Obtiene el contenido del archivo mediante un suscriptor de eventos. |
| 1240 | codeunit "Read Data Exch. from File" |
Utiliza el selector de archivos del cliente y coloca el archivo seleccionado en el BLOB del intercambio. |
| 1220 | xmlport "Data Exch. Import - CSV" |
Lee texto delimitado y escribe valores en
Data Exch. Field. |
| 1268 | codeunit "Export Launcher" |
Inicia una exportación genérica desde un registro de origen o
RecordRef. |
| 1269 | codeunit "Export Mapping" |
Lee registros de origen y genera líneas de
Data Exch. Field para exportación. |
| 1283 | codeunit "Export Generic XML" |
Construye XML a partir de rutas de columnas y campos de intercambio generados. |
| 1230 | xmlport "Export Generic CSV" |
Escribe campos secuenciales del intercambio como texto delimitado. |
| 1231 | xmlport "Export Generic Fixed Width" |
Escribe campos secuenciales del intercambio sin delimitadores. |
| 1225 | xmlport "Imp / Exp Data Exch Def & Map" |
Mueve definiciones y mapeos entre entornos. |
Las páginas que más suelen encontrar los desarrolladores son
Data Exch Def List (1211), Data Exch Def Card
(1210), Data Exch Line Def Card (1212) y
Data Exch Mapping Card (1214).
La lista parece grande porque el framework separa deliberadamente lo que se configura de lo que ocurre en cada ejecución. Esa separación es el motivo por el que una definición puede reutilizarse miles de veces sin convertirse ella misma en un log de archivos importados.
Data Exch. Def:
la cabecera y el armario de conexiones
table 1222 "Data Exch. Def" contiene los campos
generales del formato:
CodeyNameidentifican la definición reutilizable.Typeutiliza el enum extensibleData Exchange Definition Type.File TypeadmiteXml,Variable Text,Fixed TextyJson.File Encodingadmite codificaciones MS-DOS, UTF-8, UTF-16 y Windows.Column Separator,Custom Column SeparatoryLine Separatorcontrolan la interpretación del texto.Header Lines,Header TagyFooter Tagcontrolan qué líneas no deben convertirse en datos.
Los tipos estándar de definición son
Bank Statement Import, Payment Export,
Payroll Import, Generic Import,
Positive Pay Export y Generic Export. El enum
es extensible, aunque añadir un valor nuevo solamente pone nombre al
escenario. No invoca un procesador desde el vacío. Aún tienes que
conectar el pipeline. Consulta Data Exchange Definition Type.
La definición también contiene campos Integer que apuntan a cinco codeunits, además de un XMLport de lectura y escritura:
| Campo | Responsabilidad práctica |
|---|---|
Ext. Data Handling Codeunit |
Introduce datos en el BLOB del intercambio durante una importación, o los entrega externamente durante una exportación. |
Reading/Writing Codeunit |
Interpreta contenido importado o escribe contenido generado. Durante la importación tiene prioridad sobre el XMLport cuando su valor no es cero. |
Reading/Writing XMLport |
Lector o escritor estándar cuando lo invoca el pipeline correspondiente. |
Validation Codeunit |
Hook de validación utilizado por los lanzadores estándar de
exportación. No se invoca automáticamente mediante
Data Exch. Def.ProcessDataExchange() durante una
importación genérica. |
Data Handling Codeunit |
Preparación específica del escenario. Durante
ProcessDataExchange() se ejecuta antes del bucle de
mapeo. |
User Feedback Codeunit |
Limpieza final o información al usuario cuando la ruta de exportación lo invoca. |
Aquí existe un detalle peligroso pero importante: estos campos son
simples identificadores Integer de objetos. La tabla puede confirmar que
el objeto seleccionado es un codeunit, pero no puede imponer el contrato
TableNo del codeunit.
Un launcher puede ejecutar un hook con un registro
Data Exch., otro puede hacerlo con
Data Exch. Mapping y una exportación especializada de pagos
puede pasar una línea de diario. Una combinación incorrecta compila
estupendamente porque la configuración son datos, y después falla en
ejecución con toda la elegancia de un piano cayendo por unas
escaleras.
Trata el codeunit seleccionado y el registro que recibe como un único contrato inseparable.
Data Exch. Line Def:
una línea a veces es una línea y a veces un subárbol XML
Para archivos delimitados y de ancho fijo, una definición de línea suele describir la línea de detalle repetitiva. Sus campos principales son:
Column Count, relevante sobre todo para texto delimitado y para preparar columnas durante la exportación.Line Type:Detail,HeaderoFooter.Data Line Tag, utilizado para reconocer una línea de texto fijo o seleccionar un nodo XML.Namespace, utilizado para validar el namespace XML en los lectores compatibles.Parent Code, que crea una jerarquía entre definiciones de línea.
Para un CSV sencillo, una sola línea DETAIL suele ser
suficiente.
En XML, la definición de línea se parece más al límite de un
registro. Una definición padre puede representar una factura y una
definición hija sus líneas. El Data Line Tag configurado
identifica el nodo repetitivo, mientras que Parent Code
indica al framework qué registros lógicos pertenecen debajo de otro
registro.
No confundas Header Lines de Data Exch. Def
con una definición de línea cuyo Line Type sea
Header. El primero indica a un lector de texto cuántas
filas físicas debe omitir. El segundo describe un tipo lógico de
registro que puede participar en código especializado de importación o
exportación. La misma palabra, dos criaturas distintas, porque la paz
nunca fue una opción.
Data Exch. Column Def:
describir datos externos antes de que tengan hogar
table 1223 "Data Exch. Column Def" describe un elemento
externo. Para CSV, normalmente significa una columna posicional. Para
XML, significa un elemento o atributo seleccionado mediante una
ruta.
Los campos principales son:
Column No.: identificador estable utilizado por los mapeos de campos.Data Type:Text,Date,Decimal,DateTimeoBoolean.Data FormatyData Formatting Culture: instrucciones de lectura o salida.Length: obligatorio para texto de ancho fijo y útil para validar exportaciones.Path: información de ruta XML o JSON.Constant: valor configurado, especialmente útil durante la exportación.Negative-Sign Identifier: identifica un valor de signo independiente, por ejemploDpara débito.Text Padding Required,Pad CharacteryJustification: control de salida de ancho fijo.Use Node Name as Value: almacena el nombre del elemento en lugar de su texto interno en los lectores compatibles.Blank Zero: exporta el cero como vacío.Export If Not Blank: evita generar un elemento XML vacío.
El formato y la cultura no son decorativos
Si una fecha externa es 20260822, configura su formato
como yyyyMMdd. Si un decimal es 1.234,56,
utiliza una cultura que entienda esa notación. No dependas del idioma
del service tier, del usuario actual, de la fase lunar o del formato que
funcionó por casualidad en la máquina del desarrollador.
Durante el mapeo directo de una importación,
Process Data Exch. utiliza
Type Helper.Evaluate para campos Date y Decimal, pasando
Data Format y Data Formatting Culture de la
columna. Un valor incorrecto produce un error que identifica el archivo,
la definición, la línea, la columna, el tipo esperado y el valor real.
Es bastante mejor que importar silenciosamente 1,234 como
uno coma doscientos treinta y cuatro o como mil doscientos treinta y
cuatro y dejar que Finanzas descubra después la sorpresa.
La capa de
ejecución: Data Exch. y Data Exch. Field
Cada ejecución comienza con table 1220 "Data Exch.".
Almacena:
- El número de entrada.
- El nombre del archivo y el BLOB con su contenido.
- Los códigos de la definición y de la definición de línea actual.
- Los filtros serializados de la tabla de origen para exportación.
- Un vínculo con el documento entrante.
- Un valor genérico
Related Record.
Cuando se elimina el registro, también se eliminan sus líneas
relacionadas de Data Exch. Field. Ambas tablas tienen
ReplicateData = false, lo cual tiene sentido porque los
buffers de ejecución de una integración no necesitan irse de vacaciones
a todas las réplicas de la empresa.
table 1221 "Data Exch. Field" es el almacén normalizado
de valores. Su clave agrupada es:
Data Exch. No., Line No., Column No., Node ID
Cada registro contiene el valor sin procesar, además de:
Data Exch. Line Def Code.Node IDyParent Node IDpara la jerarquía.Value BLOBpara valores que superan los 250 caracteres del campoValue.
Esta tabla es la superficie de depuración más útil del framework. Si un resultado mapeado es incorrecto, hazte tres preguntas en este orden:
- ¿Llegó el archivo de origen a
Data Exch."File Content"? - ¿Creó el lector las líneas esperadas de
Data Exch. Field? - ¿Convirtieron correctamente esas líneas la transformación y el mapeo?
No depures el Sales Header final durante tres horas cuando la columna 5 nunca salió del lector CSV. He visto esa película. El final contiene sobre todo palabrotas.
El pipeline de importación, órgano por órgano
1. Crear u obtener la
entrada Data Exch.
Puedes introducir un InStream existente en la entrada de
ejecución mediante Data Exch.InsertRec(). Si el BLOB sigue
vacío, Data Exch.ImportFileContent() ejecuta el
Ext. Data Handling Codeunit configurado, que debe rellenar
el nombre y el BLOB del archivo.
Read Data Exch. from File (1240) es un origen
interactivo estándar. Read Data Exch. from Stream (1413)
publica un evento que un suscriptor puede gestionar para devolver un
Temp Blob, algo útil cuando el origen es una API, un
servicio documental u otra extensión.
2. Leer el archivo en
Data Exch. Field
Data Exch.ImportToDataExch(DataExchDef) abre el BLOB del
archivo como InStream.
Su regla de selección es sencilla y extremadamente importante:
if DataExchDef."Reading/Writing Codeunit" > 0 then
Codeunit.Run(DataExchDef."Reading/Writing Codeunit", DataExch)
else
XmlPort.Import(DataExchDef."Reading/Writing XMLport", Source, DataExch);
Si hay un codeunit de lectura configurado, el XMLport no se ejecuta. Configurar ambos no crea un equipo de lucha libre. Crea un lector activo y un identificador de objeto decorativo.
Los lectores estándar incluyen:
Data Exch. Import - CSV(1220) para texto delimitado.Fixed File Import(1241) para texto posicional.Import XML File to Data Exch.(1203) para jerarquías XML configuradas.
El XMLport CSV aplica dinámicamente el separador de campos, la
codificación y el separador de líneas de la definición. Omite las
cabeceras y pies configurados, numera solamente las filas de datos
importadas e inserta un registro Data Exch. Field por cada
valor no vacío.
Esa última frase importa: una celda CSV vacía no crea una línea de campo. Durante el mapeo directo, un mapeo obligatorio falla entonces con un error de valor ausente, mientras que uno opcional puede continuar.
3. Ejecutar el tratamiento de datos de la definición
Data Exch. Def.ProcessDataExchange() ejecuta primero
Data Handling Codeunit, si está configurado.
Este hook suele confundirse con el codeunit final de registro. En
realidad, no es necesariamente el final de nada. Se ejecuta antes del
bucle de mapeo de la definición. Un uso estándar es
Map DataExch To Intermediate (1214), que convierte los
campos normalizados del intercambio en la tabla intermedia genérica.
4. Ejecutar los codeunits de mapeo
Para cada definición de línea de nivel superior, la definición
localiza sus registros Data Exch. Mapping y ejecuta:
Pre-Mapping Codeunit.Mapping Codeunit.Post-Mapping Codeunit.
ProcessDataExchange() solamente enumera directamente las
definiciones de línea de nivel superior. Un codeunit de mapeo jerárquico
debe gestionar por sí mismo las definiciones hijas.
Map DataExch To Intermediate lo hace de forma
recursiva.
Este orden permite que cada escenario prepare el contexto, realice un mapeo genérico o personalizado y finalice el procesamiento empresarial. También nos proporciona cuerda suficiente para tejer una integración preciosa o ahorcar todo el pipeline de documentos de compra. La documentación sigue siendo importante.
Mapeo directo con
Process Data Exch.
codeunit 1201 "Process Data Exch."
contiene el mapeador estándar de importación directa.
Su procedimiento ProcessColumnMapping() recibe:
- El registro de ejecución
Data Exch.. - Un
Data Exch. Line Def. - Un
RecordRefque sirve como plantilla de la tabla destino.
Para cada línea importada, duplica la plantilla, asigna los identificadores del intercambio y de la línea cuando están configurados, mapea los campos, los valida e inserta un registro.
Lo que realmente admite
SetField()
El switch estándar gestiona estos tipos de campos destino:
- Text.
- Code.
- Date.
- Decimal.
- Option.
- BLOB.
Otros tipos de destino alcanzan el error de tipo de datos no
compatible, salvo que un suscriptor de eventos gestione la conversión.
Conviene fijarse en esto porque
Data Exch. Column Def."Data Type" también ofrece DateTime y
Boolean. El tipo de la columna externa y los tipos de campo admitidos
como destino directo no comparten exactamente la misma lista de
capacidades.
Para tipos de destino más amplios, validaciones complejas o creación de documentos, utiliza un modelo de staging o intermedio y controla explícitamente la conversión final.
Comportamiento de la validación y la inserción
Después de asignar cada FieldRef destino, el mapeador
llama a FieldRef.Validate(). Por tanto, se ejecutan los
triggers de validación del campo.
El registro final se inserta con RecRef.Insert() sin
solicitar la ejecución de los triggers de tabla. En el comportamiento
estándar de AL, esto significa que el trigger OnInsert de
la tabla no se ejecuta. La distinción es crítica:
- Se ejecuta la lógica
OnValidatede los campos. - La lógica
OnInsertde la tabla no se ejecuta de forma predeterminada.
Por eso, mapear directamente a una tabla empresarial compleja es arriesgado incluso antes de hablar de numeración, dimensiones, grupos contables, relaciones entre documentos o la colonia salvaje de suposiciones que vive dentro de los triggers de tabla estándar.
Mapea a una tabla de staging diseñada para ese propósito salvo que tengas una razón excelente para no hacerlo.
Suposiciones sobre la clave primaria
El mapeador genérico examina la clave primaria de la tabla destino y espera que su último campo sea Integer. Utiliza ese campo para generar valores basados en el número de línea importado y en el desplazamiento existente de la clave.
En tablas personalizadas, diseña la clave del staging de acuerdo con
esta condición. Configura también los dos campos ocultos de
Data Exch. Mapping:
Data Exch. No. Field ID.Data Exch. Line Field ID.
El fallback cuando falta el campo de línea está programado
específicamente para Bank Acc. Reconciliation Line y
Gen. Journal Line. Tu tabla de staging personalizada no es
secretamente una de ellas, por mucho que se identifique como un
diario.
Varios mapeos, sobrescritura y prioridad
Varias columnas externas pueden mapearse al mismo campo Text o Code de destino.
- Con
Overwrite Value = false, los valores se combinan con un espacio hasta llenar el campo destino. - Con
Overwrite Value = true, el mapeo procesado más tarde sustituye el valor actual.
Si algún mapeo tiene un valor Priority distinto de cero,
los mapeos se procesan por Priority descendente. Utilízalo cuando un
valor mapeado dependa de que otro campo ya haya sido validado o cuando
importe el orden de sobrescritura.
Multiplicador decimal y campos de signo independientes
Multiplier se aplica después de interpretar un decimal.
Resulta útil para invertir el signo, porcentajes, unidades monetarias
menores o proveedores que han inventado una nueva y emocionante manera
de representar el dinero.
Negative-Sign Identifier admite formatos en los que el
importe y el indicador de débito o crédito se encuentran en columnas
distintas. Mapea la columna de signo al mismo campo Decimal destino y
configura el identificador, por ejemplo D. El mapeador
recuerda el campo destino y cambia su signo después de ejecutar todos
los mapeos de la línea.
La ruta intermedia: más segura, flexible y con un poco más de papeleo
Map DataExch To Intermediate (1214) escribe en table 1214 "Intermediate Data Import".
En lugar de crear inmediatamente registros destino, almacena una línea por cada campo de destino:
Data Exch. No..Table IDde destino.Record No.lógico.Field IDde destino.- Valor Text o BLOB.
Parent Record No..Validate Only.
Esta estructura puede representar un Purchase Header con varias Purchase Lines sin crear ninguna de las dos tablas durante la lectura. Después, un procesador específico del escenario agrupa las líneas, construye registros reales, los valida, gestiona los valores predeterminados y decide qué hacer cuando las reglas de negocio se rebelan.
El flujo estándar de documentos entrantes utiliza este patrón. El
código de mapeo genérico conserva las relaciones padre-hijo del XML
mediante Record No. y Parent Record No., y
después el código especializado crea el documento de compra.
El campo
Optional cambia de significado
En un mapeo directo de campos, Optional significa que la
ausencia de un valor interpretado no provoca un error.
Cuando Use as Intermediate Table está habilitado, la
página presenta ese mismo campo físico como Validate Only.
El mapeador intermedio lo copia en
Intermediate Data Import."Validate Only" y el procesador
posterior decide no asignar ese valor como un campo destino normal.
El mismo Boolean. Un disfraz semántico diferente. No lo configures por memoria muscular.
La limpieza es responsabilidad tuya
Eliminar un registro Data Exch. elimina sus líneas
Data Exch. Field. No elimina automáticamente todas las
líneas Intermediate Data Import pertenecientes al
intercambio.
Los procesadores de escenarios estándar eliminan explícitamente sus registros intermedios. Los procesadores personalizados deberían hacer lo mismo después de completar correctamente el proceso, o conservarlos deliberadamente mediante una estrategia de retención documentada. De lo contrario, tu tabla de integración temporal se convierte lentamente en un yacimiento arqueológico.
Sales Header”. Una tabla de staging propia sigue siendo la opción prudente para estructuras planas.XML: donde las definiciones de línea se convierten en un árbol
El lector XML Import XML File to Data Exch. comienza con
las definiciones de línea cuyo Parent Code está vacío.
Selecciona nodos mediante el Data Line Tag de cada
definición y después procesa recursivamente las definiciones hijas.
Para cada registro XML lógico escribe una línea especial
Data Exch. Field con Column No. = -1. Esta
línea ancla la definición incluso cuando no se ha extraído ninguna
columna normal. Los nodos interpretados reciben valores
Node ID generados y los registros hijos almacenan un
Parent Node ID.
Esa relación permite posteriormente que el mapeador intermedio conecte un registro de cabecera con sus hijos.
Rutas y namespaces
Los valores Path de las columnas seleccionan elementos o
atributos relativos al Data Line Tag de la línea.
El lector utiliza un administrador de namespaces XML. Si un segmento XPath no tiene prefijo, el helper estándar puede reescribirlo para buscar por nombre local. Esto facilita el consumo de archivos imperfectos de proveedores, pero también puede ocultar ambigüedades cuando dos vocabularios usan el mismo nombre local de elemento.
En integraciones controladas por un esquema formal:
- Mantén explícitos los prefijos de namespace cuando tengan significado.
- Configura
Namespacecuando sea necesario validar el namespace raíz. - Prueba documentos con nodos opcionales, nodos repetidos, atributos y varios prefijos de namespace.
- No asumas que el XML de ejemplo del proveedor representa todo el caos disponible en producción.
La acción Get File Structure puede sugerir definiciones de columna para XML y JSON, y los esquemas XML también pueden ayudar a inicializar una definición. Trata las rutas generadas como un punto de partida, no como tablas sagradas descubiertas en una montaña.
Una nota sobre JSON
La tabla de definición incluye Json y la aplicación
contiene objetos para descubrir estructuras JSON. Eso no significa que
todas las versiones y escenarios dispongan de un lector JSON de
ejecución completo y listo para usar, equivalente a los lectores
estándar de CSV o XML.
Comprueba el Reading/Writing Codeunit configurado en tu
versión destino. Para importaciones JSON personalizadas, un lector
dedicado que interprete JsonObject y escriba registros
Data Exch. Field suele ser el enfoque más limpio. El
framework ejecutará encantado las etapas posteriores de transformación y
mapeo cuando existan las líneas normalizadas.
Transformation Rules: blanqueo de datos civilizado
table 1237 "Transformation Rule" almacena
transformaciones de texto reutilizables. Un mapeo selecciona una regla
mediante
Data Exch. Field Mapping."Transformation Rule".
Base Application 27.5 proporciona, entre otros, los siguientes tipos de transformación:
- Uppercase, Lowercase, Title Case y Trim.
- Substring.
- Sustitución de texto y sustitución mediante expresiones regulares.
- Remove non-alphanumeric characters.
- Formato de Date, DateTime y decimales.
- Coincidencia mediante expresiones regulares.
- Field Lookup.
- Round.
- Extract From Date.
- Unix timestamp.
- Custom.
La superficie completa del registro y sus métodos públicos de
creación están documentados en Transformation Rule.
Las reglas pueden encadenarse
Next Transformation Rule apunta a otra regla.
TransformText() aplica la regla actual y envía
recursivamente el resultado a la siguiente.
Esto permite crear pipelines como:
Trim -> Remove non-alphanumeric -> Uppercase
Mantén las cadenas cortas y sin ciclos. La llamada recursiva estándar
no proporciona un detector de ciclos amable.
RULE-A -> RULE-B -> RULE-A no es arquitectura de
integración. Es un diminuto uróboros devorando el service tier.
Extender el enum de transformación cuando la configuración deja de ser suficiente
enum 1237 "Transformation Rule Type" es extensible e
implementa interface "Transformation Rule". Por tanto, un
tipo personalizado puede conectarse a la página estándar de
transformaciones y al pipeline de mapeo.
using System.IO;
enumextension 50100 "Generic Transform. Type" extends "Transformation Rule Type"
{
value(50100; "Normalize External Ref.")
{
Caption = 'Normalize External Reference';
Implementation = "Transformation Rule" = "External Ref. Normalizer";
}
}
codeunit 50100 "External Ref. Normalizer" implements "Transformation Rule"
{
procedure TransformText(
TransformationRule: Record "Transformation Rule";
OldValue: Text;
var NewValue: Text)
begin
NewValue := DelChr(UpperCase(OldValue), '=', ' ');
end;
procedure IsDataFormatUpdateAllowed(): Boolean
begin
exit(false);
end;
procedure CheckMandatoryFieldsInTransformationRule(
TransformationRule: Record "Transformation Rule")
begin
end;
procedure ValidateTransformationRuleField(
FieldNo: Integer;
var TransformationRule: Record "Transformation Rule";
var xTransformationRule: Record "Transformation Rule"): Boolean
begin
exit(false);
end;
procedure GetVisibleGroups(
TransformationRule: Record "Transformation Rule";
var VisibleGroups: List of [Enum "Transformation Rule Group"])
begin
end;
}
Utiliza una transformación personalizada para una normalización pura de valor a valor. Si la lógica necesita varios registros, contexto de configuración, llamadas externas o el estado de un documento empresarial, pertenece a un codeunit de mapeo o procesamiento.
Ejemplo práctico en AL: importar líneas de venta externas
Imagina que una tienda web, un punto de venta o una aplicación comercial externa entrega este archivo UTF-8 separado por punto y coma:
ExternalDocumentNo;PostingDate;CustomerNo;ItemNo;Quantity;UnitPrice;Currency
WEB-10001;2026-08-20;10000;1896-S;2;245.50;EUR
WEB-10002;2026-08-21;20000;1900-S;1;199.95;eur
El objetivo es interpretar y normalizar el archivo en una tabla de
staging. Más adelante, un procesador independiente agrupará líneas por
documento externo y creará Sales Header y
Sales Line mediante la lógica empresarial apropiada. El
lector no debería crear directamente una Sales Invoice: todavía faltan
customers, items, unidades, prices, dimensions, posting groups,
duplicados y todas las formas creativas en que una venta puede negarse a
existir.
1. Crear una tabla de staging diseñada para el mapeador genérico
using System.IO;
table 50110 "External Sales Staging"
{
Caption = 'External Sales Staging';
DataClassification = CustomerContent;
fields
{
field(1; "Entry No."; Integer)
{
Caption = 'Entry No.';
}
field(2; "Data Exch. Entry No."; Integer)
{
Caption = 'Data Exch. Entry No.';
TableRelation = "Data Exch."."Entry No.";
}
field(3; "Data Exch. Line No."; Integer)
{
Caption = 'Data Exch. Line No.';
}
field(10; "External Document No."; Code[50])
{
Caption = 'External Document No.';
}
field(20; "Posting Date"; Date)
{
Caption = 'Posting Date';
}
field(30; "Customer No."; Code[20])
{
Caption = 'Customer No.';
}
field(40; "Item No."; Code[20])
{
Caption = 'Item No.';
}
field(50; Quantity; Decimal)
{
Caption = 'Quantity';
}
field(60; "Unit Price"; Decimal)
{
Caption = 'Unit Price';
}
field(70; "Currency Code"; Code[10])
{
Caption = 'Currency Code';
}
field(80; Processed; Boolean)
{
Caption = 'Processed';
}
field(90; "Error Message"; Text[2048])
{
Caption = 'Error Message';
}
}
keys
{
key(PK; "Entry No.")
{
Clustered = true;
}
key(ExchangeLine; "Data Exch. Entry No.", "Data Exch. Line No.")
{
}
}
}
El último campo de la clave primaria es Integer, lo que satisface la suposición del mapeador genérico sobre la clave. La tabla también almacena el intercambio de ejecución y la línea de origen, haciendo trazable cada línea del staging.
2. Crear el codeunit de mapeo
using System.IO;
codeunit 50111 "External Sales Exch. Mapper"
{
TableNo = "Data Exch.";
trigger OnRun()
var
DataExchLineDef: Record "Data Exch. Line Def";
ExternalSalesStaging: Record "External Sales Staging";
ProcessDataExch: Codeunit "Process Data Exch.";
StagingRecordRef: RecordRef;
begin
DataExchLineDef.Get(
Rec."Data Exch. Def Code",
Rec."Data Exch. Line Def Code");
StagingRecordRef.GetTable(ExternalSalesStaging);
ProcessDataExch.ProcessColumnMapping(
Rec,
DataExchLineDef,
StagingRecordRef);
end;
}
Este codeunit no interpreta el CSV. Comienza después de que el lector
haya rellenado Data Exch. Field. Su trabajo consiste en
seleccionar la tabla destino y permitir que el mapeador estándar aplique
los mapeos de campos configurados.
3. Configurar la definición
Los valores relevantes de la definición son:
| Configuración | Valor |
|---|---|
| Code | GEN-SALES |
| Type | Generic Import |
| File Type | Variable Text |
| File Encoding | UTF-8 |
| Column Separator | Semicolon |
| Header Lines | 1 |
| Reading/Writing XMLport | Data Exch. Import - CSV (1220) |
| Line Definition | DETAIL, type Detail, column count
7 |
Crea estas definiciones de columna:
| Columna | Nombre | Tipo de datos | Formato | Cultura |
|---|---|---|---|---|
| 1 | External Document No. | Text | ||
| 2 | Posting Date | Date | yyyy-MM-dd |
en-US |
| 3 | Customer No. | Text | ||
| 4 | Item No. | Text | ||
| 5 | Quantity | Decimal | en-US |
|
| 6 | Unit Price | Decimal | en-US |
|
| 7 | Currency | Text |
Crea un Data Exch. Mapping para la tabla
External Sales Staging:
Mapping Codeunit=External Sales Exch. Mapper.Data Exch. No. Field ID=External Sales Staging."Data Exch. Entry No.".Data Exch. Line Field ID=External Sales Staging."Data Exch. Line No.".
Después, mapea las siete columnas con los siete campos de staging.
Aplica TRIM donde corresponda, una regla de mayúsculas a
Currency Code y Normalize External Ref. solo si eliminar
espacios forma parte realmente del contrato externo. No normalices un
dato solo porque una vez te miró de manera extraña.
Las definiciones pueden crearse manualmente, importarse con XMLport 1225 o instalarse desde AL. El siguiente fragmento muestra las referencias de objetos utilizadas al inicializar la cabecera y el mapeo:
using System.IO;
local procedure CreateExternalSalesDefinition()
var
DataExchDef: Record "Data Exch. Def";
begin
if DataExchDef.Get('GEN-SALES') then
exit;
DataExchDef.Init();
DataExchDef.Code := 'GEN-SALES';
DataExchDef.Name := 'Generic External Sales Import';
DataExchDef.Type := DataExchDef.Type::"Generic Import";
DataExchDef."File Type" := DataExchDef."File Type"::"Variable Text";
DataExchDef."File Encoding" := DataExchDef."File Encoding"::"UTF-8";
DataExchDef."Column Separator" := DataExchDef."Column Separator"::Semicolon;
DataExchDef."Header Lines" := 1;
DataExchDef."Reading/Writing XMLport" := XmlPort::"Data Exch. Import - CSV";
DataExchDef.Insert(true);
end;
local procedure CreateExternalSalesMapping()
var
DataExchMapping: Record "Data Exch. Mapping";
ExternalSalesStaging: Record "External Sales Staging";
begin
DataExchMapping.Init();
DataExchMapping."Data Exch. Def Code" := 'GEN-SALES';
DataExchMapping."Data Exch. Line Def Code" := 'DETAIL';
DataExchMapping."Table ID" := Database::"External Sales Staging";
DataExchMapping.Name := 'External sales to staging';
DataExchMapping."Mapping Codeunit" := Codeunit::"External Sales Exch. Mapper";
DataExchMapping."Data Exch. No. Field ID" :=
ExternalSalesStaging.FieldNo("Data Exch. Entry No.");
DataExchMapping."Data Exch. Line Field ID" :=
ExternalSalesStaging.FieldNo("Data Exch. Line No.");
DataExchMapping.Insert(true);
end;
En código de configuración para producción, haz que toda la operación sea idempotente, inserta las definiciones de líneas y columnas, crea todos los mapeos de campos, actualiza las versiones modificadas y nunca elimines una definición que el cliente haya personalizado sin una estrategia explícita de actualización.
La definición exportada contiene identificadores de tablas, campos y objetos de procesamiento. Al moverla a otro tenant o versión, instala primero las extensiones necesarias y valida todos los objetos referenciados después de la importación. Basado en configuración no significa libre de dependencias. Solo significa que las dependencias llevan bigotes falsos.
4. Crear un importador basado en streams
using System.IO;
codeunit 50112 "External Sales Import"
{
procedure Import(FileName: Text[250]; var Source: InStream): Integer
var
DataExch: Record "Data Exch.";
DataExchDef: Record "Data Exch. Def";
ImportFailedErr: Label 'The external sales file could not be imported.';
begin
DataExchDef.Get('GEN-SALES');
DataExch.InsertRec(FileName, Source, DataExchDef.Code);
if not DataExch.ImportToDataExch(DataExchDef) then
Error(ImportFailedErr);
DataExchDef.ProcessDataExchange(DataExch);
exit(DataExch."Entry No.");
end;
}
La secuencia de llamadas es la esencia de una importación personalizada:
InsertRec -> ImportToDataExch -> ProcessDataExchange
No es necesario ningún diálogo de selección de archivos. El llamador puede proporcionar un stream procedente de una carga, una respuesta de API, un adjunto, un adaptador de Azure Storage o una integración programada.
5. Mantener separado el procesamiento empresarial
Después de importar, procesa los registros
External Sales Staging por
Data Exch. Entry No. y External Document No..
Valida allí duplicados, customers, items, currencies, posting dates,
quantities, prices, dimensions y posting groups antes de crear el sales
document.
Esta separación proporciona:
- Interpretación técnica repetible.
- Datos originales y de staging trazables.
- Errores empresariales vinculados a una línea de origen específica.
- Reintentos controlados.
- Un lugar donde revisar los datos antes de crear registros operativos.
También evita que un CSV malformado se convierta en una Sales Invoice creada a medias y con una crisis existencial.
Pipeline de exportación: las flechas apuntan al otro lado, pero los buffers permanecen
La ruta genérica de exportación comienza con
Export Launcher (1268). El llamador proporciona un Record,
RecordId o RecordRef. El launcher almacena la vista del
origen en Data Exch."Table Filters", ejecuta la preparación
y validación configuradas y después llama a
Data Exch.ExportFromDataExch().
Export Mapping (1269) abre la tabla de origen, aplica la
vista almacenada, selecciona opcionalmente el Key Index
configurado y escribe los valores de salida formateados en
Data Exch. Field.
El código estándar de gestión de exportación de pagos realiza gran parte de la conversión a nivel de campo:
- Calcula FlowFields cuando es necesario.
- Aplica las comprobaciones de campos obligatorios.
- Convierte al tipo de destino de la columna.
- Aplica el multiplicador.
- Formatea valores.
- Ejecuta reglas de transformación.
- Rellena valores de ancho fijo.
- Comprueba las longitudes configuradas.
Después, el escritor serializa esos campos.
Los campos secuenciales son obligatorios para los escritores genéricos de texto
Export Generic CSV y
Export Generic Fixed Width esperan que los números de línea
y columna sean secuenciales. Una columna ausente produce un error en
lugar de desplazar silenciosamente todo hacia la izquierda y crear un
archivo que parece válido hasta que el banco lo rechaza un viernes a las
16:59.
La agrupación es una operación de exportación
Export Mapping consume
Data Exch. Field Grouping. Cuando existen campos de
agrupación, el mapeador construye un conjunto temporal agrupado del
origen. Los campos numéricos mapeados que no forman parte de la clave se
acumulan, incluidos los valores FlowField compatibles mediante un buffer
temporal de agrupación.
Utiliza la agrupación cuando la autoridad externa necesite una línea resumida por combinación de campos en lugar de una línea por cada registro de Business Central.
Exportación XML
Export Generic XML crea elementos a partir de las rutas
configuradas, admite namespaces y determinados patrones de atributos, y
puede omitir elementos vacíos mediante
Export If Not Blank.
Su compatibilidad con XPath es deliberadamente más limitada que un lenguaje general de transformación XML. Cuando un documento exige estructuras condicionales complejas, varios namespaces no relacionados, firmas u ordenación específica del esquema, un escritor XML dedicado puede resultar más claro que obligar a la configuración genérica a bailar danza interpretativa.
Qué queda guardado y qué significa para la trazabilidad
El framework distribuye la evidencia entre varias capas:
| Capa | Objeto principal | Qué conserva | Pregunta que responde |
|---|---|---|---|
| Configuración | Data Exch. Def y tablas hijas |
Formato, componentes y mapeos | ¿Cómo debía interpretarse? |
| Ejecución | Data Exch. |
Archivo, nombre, definición y contexto relacionado | ¿Qué intercambio se ejecutó? |
| Parsing | Data Exch. Field |
Valores por línea, columna y nodo | ¿Qué entendió el lector? |
| Staging | Tabla propia o Intermediate Data Import |
Datos convertidos hacia una estructura destino | ¿Qué preparó el mapper? |
| Negocio | Documento o ledger creado | Resultado validado por el proceso | ¿Qué aceptó finalmente Business Central? |
La configuración puede cambiar después de una importación. Eso significa que conservar únicamente el código de la definición no demuestra por sí solo qué versión exacta del mapeo produjo un documento histórico. Para integraciones reguladas o auditables, añade una estrategia de versionado: versión funcional en la definición o en tu setup, hash del archivo, fecha, estado, usuario o job, y relación con los registros creados.
Data Exch. y Data Exch. Field no sustituyen
a un log funcional. Son buffers de ejecución y diagnóstico. Decide
cuánto tiempo se conservan, quién puede ver el contenido y si contienen
datos personales, bancarios o confidenciales.
ReplicateData = false evita su replicación estándar, pero
no convierte un BLOB lleno de datos bancarios en decoración inocua.
La transacción y el reintento
El framework no define por sí solo una semántica universal de reintentos. Si una línea de negocio falla después de crear otras, el resultado depende de los límites de transacción del procesador que hayas escrito. Una integración robusta decide explícitamente entre:
- Todo o nada: un error revierte el lote completo.
- Por registro: cada registro lógico se confirma o rechaza de forma independiente.
- Staging primero: la importación técnica termina; el procesamiento empresarial marca estados y permite reintentar solo lo pendiente.
La tercera opción suele ser la más operable para lotes de terceros.
También requiere idempotencia: un External ID o una clave
equivalente debe impedir que pulsar “reprocesar” cree el mismo documento
dos veces. El botón no debería funcionar como una fotocopiadora
contable.
Impacto funcional: mucho más que importar un CSV
El Data Exchange Framework influye en varias áreas de Business Central porque actúa como frontera entre un contrato externo y objetos empresariales internos.
Banca y conciliación
Los bank statement imports convierten líneas bancarias en estructuras
que después participan en reconciliation y matching. Un separador
decimal incorrecto no es solo un error de formato: altera importes,
signos y capacidad de conciliación. Un
Negative-Sign Identifier mal configurado puede transformar
cobros en pagos con una serenidad escalofriante.
Payment exports
Las exportaciones de pagos deben cumplir formato, longitud, orden, agrupación y campos obligatorios exigidos por el banco. Aquí el framework no solo serializa: prepara datos, valida y entrega el fichero. El resultado puede ser técnicamente XML y aun así ser rechazado por el banco por una regla que vive tres capas por encima del XML.
Incoming Documents y documentos electrónicos
La ruta intermedia permite representar header y lines antes de construir purchase documents o general journal lines. Es el lugar donde se reconcilian códigos externos con vendors, items, units of measure, VAT setup, dimensions y posting groups. El framework transporta valores; el procesador empresarial debe crear documentos mediante las validaciones correctas.
Currency exchange rates
La configuración puede importar valores de servicios externos y mapearlos al proceso de actualización. La cultura, el formato de fecha y la unidad —por uno, por cien, directa o inversa— son parte del contrato. Un decimal perfectamente parseado puede seguir siendo económicamente incorrecto si representa la escala equivocada.
Localizaciones e Intrastat
Las localizaciones utilizan el framework para formatos que dependen de país, autoridad y versión. Esto demuestra su mayor virtud: mover parte del cambio desde código a configuración. También demuestra su coste: una actualización puede modificar definiciones, objetos y expectativas de formato. La configuración local no debe tratarse como una reliquia que nadie compara después de una actualización.
En todos estos escenarios, Data Exchange Definition es
modular porque separa adquisición, parsing, transformación, mapeo,
validación y entrega. El impacto de un error depende del módulo en el
que se introduce. Por eso la depuración debe recorrer el pipeline en
orden y no empezar por la tabla final como quien busca unas llaves
debajo de la farola porque allí hay más luz.
Puntos de extensibilidad que son realmente útiles
El framework expone integration events en la mayoría de sus fronteras importantes.
En Process Data Exch.
Entre los eventos útiles se incluyen:
OnBeforeFormatFieldValuepara gestionar un tipo de destino no compatible o una conversión personalizada.OnSetFieldOnBeforeGetTransformedValuepara modificar el contexto del origen o del mapeo.OnSetFieldOnBeforeFieldRefValidatepara sustituir el comportamiento estándar de validación.OnProcessColumnMappingOnBeforeRecRefInsertpara controlar la inserción final.OnBeforeProcessAllLinesColumnMappingpara sustituir el mapeo de un escenario.OnAfterProcessColumnMappingpara posprocesamiento.
En los lectores
- La importación CSV permite que los suscriptores sustituyan mensajes de error relacionados con la cabecera.
- La importación de archivos fijos expone la línea antes del bucle estándar de longitudes.
- La importación XML expone el XML interno y externo antes de insertar una columna.
- La adquisición mediante stream publica un evento que devuelve el
contenido del archivo mediante
Temp Blob.
En las reglas de transformación
El enum extensible junto con la interfaz
Transformation Rule es la ruta recomendada para crear un
tipo personalizado de transformación reutilizable.
Elige el punto de extensión más pequeño que resuelva el problema.
Sustituir un mapeo completo porque un proveedor envía Y y
N para un Boolean es técnicamente posible, pero también lo
es demoler una cocina porque hay una cuchara sucia.
Modos de fallo y sus causas
“The value is missing”
El lector no creó una línea Data Exch. Field para ese
intercambio, línea y columna. Las causas habituales son una celda CSV
vacía, un separador incorrecto, una configuración errónea de la
cabecera, un código de definición de línea equivocado o un archivo con
menos columnas de las esperadas.
Inspecciona Data Exch. Field antes de tocar la tabla
destino.
“Incorrect format or type”
El valor llegó al mapeador, pero Type Helper.Evaluate no
pudo convertirlo utilizando el formato y la cultura de la columna.
Comprueba el valor original real, incluidos espacios, separadores
decimales y texto de zona horaria.
“Data type not supported”
El mapeador directo alcanzó un campo de destino fuera de su conjunto
estándar compatible. Utiliza OnBeforeFormatFieldValue, un
codeunit de mapeo personalizado o la ruta intermedia.
El codeunit de mapeo falla inmediatamente
Comprueba su TableNo frente al registro que pasa el
pipeline que lo invoca. Los identificadores de objeto almacenados en
configuración no son contratos de ejecución fuertemente tipados.
Los valores XML aparecen debajo del padre incorrecto
Comprueba Parent Code, Data Line Tag, las
rutas relativas de las columnas, el Node ID generado y
Parent Node ID. Los errores padre-hijo normalmente se crean
durante la lectura, no durante la creación final del documento.
La importación creó registros pero omitió la lógica de inicialización
Recuerda que el mapeador directo estándar valida los campos, pero
inserta el RecordRef destino sin ejecutar el trigger
OnInsert de la tabla.
La misma definición funciona manualmente pero falla en una job queue
Los codeunits interactivos de origen pueden abrir un diálogo de
archivos o una ventana de progreso. El procesamiento programado necesita
una adquisición basada en streams y código que respete
GuiAllowed.
Estrategia de pruebas
Una Data Exchange Definition debe probarse como configuración más código. Probar únicamente el mapeador personalizado no es suficiente, porque un separador o cultura incorrectos pueden destruir los datos antes de que el mapeador se despierte.
Como mínimo, cubre:
- Un archivo válido con varias líneas.
- Valores opcionales y obligatorios vacíos.
- Demasiadas o muy pocas columnas.
- Formatos de fecha y decimal no válidos.
- Separadores decimales específicos de una cultura.
- Variaciones en cabeceras y pies.
- Texto más largo que el campo destino.
- Cadenas de transformaciones.
- Identificadores de origen duplicados.
- Rollback cuando falla una línea.
- XML sin nodos opcionales.
- XML con hijos repetidos y prefijos de namespace.
Utiliza Temp Blob para crear streams en memoria durante
las pruebas. Llama al mismo importador que utiliza el código de
producción y valida después ambas capas:
- Líneas
Data Exch. Fieldinterpretadas. - Registros finales de staging o intermedios.
Esto permite saber si el fallo pertenece a la adquisición, lectura, transformación, mapeo o procesamiento empresarial. Cinco capas, cinco sospechosos, una sala de interrogatorios.
Guía de diseño y operación
Utiliza Data Exchange Definitions cuando
- El formato de archivo de un partner se presta a la configuración.
- Los administradores pueden necesitar ajustar mapeos sin publicar una extensión.
- Necesitas valores interpretados y trazables.
- Varios formatos similares de proveedores comparten una arquitectura de procesamiento.
- Trabajas con CSV, ancho fijo o XML de complejidad moderada.
- Los formatos de exportación necesitan ordenación, formato, agrupación o constantes configurables.
Prefiere una lectura dedicada en AL cuando
- El payload es un contrato JSON profundamente condicional.
- La integración es API-first y el esquema JSON ya está modelado limpiamente en AL.
- El documento necesita firmas, cifrado, streaming a gran escala o una validación de esquema compleja.
- Todos los campos están controlados por código y la configuración no aporta valor empresarial real.
- El framework genérico necesitaría más eventos personalizados para sustituir comportamiento que comportamiento estándar.
La elección no es configuración buena, código malo. La cuestión es si convertir el contrato de formato en datos aporta una ventaja. Si la página de configuración se convierte en la representación críptica de un programa, escribe el programa.
Migración, despliegue y gobierno
Una definición completa contiene referencias a tablas, fields,
codeunits, XMLports y transformation rules. Exportarla con
Imp / Exp Data Exch Def & Map (XMLport 1225) mueve la
configuración, pero no instala los objetos que esa configuración espera
encontrar.
Orden de despliegue
- Publica primero las extensiones con tablas, enums, interfaces y codeunits requeridos.
- Ejecuta los datos de setup mediante install/upgrade codeunits o importa la definición.
- Verifica que los object IDs y field IDs existen en el entorno destino.
- Revisa separadores, encoding, formatos y culturas.
- Ejecuta un fichero de prueba conocido.
- Compara
Data Exch. Field, staging y resultado empresarial. - Activa job queues o endpoints solamente después de esa reconciliación.
No uses una renumeración de fields alegremente en una tabla de
staging que ya participa en field mappings. La configuración guarda
Field ID, no el nombre ni el sentimiento que te produce.
Cambiar el ID rompe el contrato aunque el caption siga pareciendo
correcto.
Setup como código, pero sin borrar al cliente
Crear definiciones desde AL hace el despliegue repetible. El install codeunit puede insertar una versión inicial y el upgrade codeunit aplicar cambios conocidos. El reto es distinguir configuración gestionada por la extensión de ajustes que el cliente tiene derecho a modificar.
Un patrón razonable conserva:
Setup Versionen una tabla propia.- Procedimientos idempotentes de creación y actualización.
- Cambios por versión, no un
DeleteAll()seguido de optimismo. - Validación de dependencias antes de modificar.
- Un export de respaldo antes de cambios grandes.
- Documentación de qué campos son personalizables.
Si cada actualización reconstruye toda la definición, el sistema es repetible para el desarrollador y sorprendente para el cliente. La automatización también puede destruir configuración con una eficiencia admirable.
Seguridad y privacidad
Los archivos pueden contener IBAN, importes, nombres, direcciones,
documentos fiscales o información de empleados. Aplica permisos mínimos
sobre las páginas de configuración, Data Exch., staging y
acciones de reintento. No escribas payloads completos en telemetry o
error messages. Para diagnóstico, registra identificadores, tamaños,
tiempos, definición, etapa y resultado; enmascara los valores
sensibles.
Observabilidad
Para procesos programados, mide al menos:
- definición y versión;
- origen y nombre lógico del archivo;
- bytes y líneas/nodos leídos;
- filas de
Data Exch. Fieldcreadas; - registros de staging válidos, rechazados y procesados;
- duración por etapa;
- mensaje y etapa de error;
- relación con documentos creados.
Esto convierte “la importación no funciona” en “el lector terminó, produjo 4.812 fields, 37 registros llegaron a staging y el registro 19 falló por Currency Code”. Una frase permite trabajar. La otra convoca una sesión de espiritismo con el debugger.
Checklist antes de producción
Contrato externo
Configuración
Arquitectura
Operación
Reflexiones finales
Data Exchange Definitions es una de las piezas más capaces y menos celebradas de Business Central. Separa el conocimiento del formato externo del procesamiento empresarial, proporciona una capa persistente de normalización y expone hooks suficientes para soportar integraciones serias.
También tiene edad suficiente para contener patrones de varias generaciones de arquitectura de Business Central: campos Option junto a enums extensibles, identificadores de objetos almacenados como Integer, XMLports al lado de codeunits de lectura, lógica XML basada en DotNet junto a tipos XML modernos de AL y campos de configuración cuyo significado cambia según la ruta seleccionada.
Eso no es una razón para evitar el framework. Es una razón para entenderlo antes de introducir identificadores de objetos al azar en la configuración y esperar que el ERP respete nuestra confianza.
El patrón seguro es sencillo:
Acquire -> Parse -> Inspect -> Transform -> Stage -> Validate -> Process -> Clean up
Utiliza Data Exch. Field como frontera observable.
Prefiere staging o Intermediate Data Import para registros
empresariales complejos. Mantén documentados los contratos de los
codeunits. Prueba explícitamente formatos y culturas. Exporta la
definición junto con sus mapeos. Y nunca construyas una cadena circular
de transformaciones salvo que el objetivo sea enseñar recursividad a un
servidor mediante el sufrimiento.
La regla que conecta todo el módulo es esta:
Una
Data Exchange Definitionno importa ni exporta por sí sola. Define contratos.Data Exch.instancia el intercambio, el reader convierte bytes enData Exch. Field, las transformaciones normalizan, el mapping proyecta y un procesador empresarial decide qué merece entrar realmente en Business Central.
Este es el Data Exchange Framework: configurable, potente, ligeramente embrujado y algo que merece absolutamente la pena conocer.
Ese es el blueprint.
Referencias oficiales
- About the Data Exchange Framework
- Set up data exchange definitions
Data Exch. DeftableData Exch.tableData Exch. Field MappingtableData Exch. Import - CSVXMLportImport XML File to Data Exch.codeunitFixed File ImportcodeunitProcess Data Exch.codeunitMap DataExch To IntermediatecodeunitIntermediate Data ImporttableTransformation RuletableExport LaunchercodeunitSystem.IOnamespace