Bramvia — Business Central Experts
Cómo convertir C/AL a AL paso a paso: txt2al, eventos, lo que no migra y el orden que evita rehacer trabajo
La guía técnica para pasar el código de Dynamics NAV a extensiones AL: exportar con la sintaxis nueva, ejecutar txt2al, convertir modificaciones del estándar en suscriptores de eventos, qué hacer con DotNet, ficheros y Codeunit 1, y el orden de trabajo que evita convertir código que ya no hace falta.
Respuesta corta: convertir C/AL a AL no es traducir código, es separar tres cosas: lo que ya existe en el estándar de Business Central (se elimina), lo que era una modificación del estándar (se reescribe como suscriptor de eventos) y lo que era funcionalidad propia (se convierte con txt2al y se limpia). El orden importa más que la herramienta: primero el inventario, después el triaje, y solo al final la conversión. Quien empieza ejecutando txt2al sobre todo el código convierte objetos que iban a borrarse y modificaciones que no compilarán nunca como extensión. Aquí está el proceso completo, con los comandos, los patrones de conversión más frecuentes y lo que no tiene equivalente en la nube.
0. Antes de tocar nada: el inventario
Exporta la lista de objetos de tu NAV (Object Designer → filtrar por Version List o por rango de IDs 50000-99999) y clasifica cada uno:
| Categoría | Qué es | Qué se hace |
|---|---|---|
| Estándar cubierto | Funcionalidad que Business Central trae hoy de serie (aprobaciones, dimensiones, lotes, Power BI, cierres) | Se elimina. No se convierte |
| Modificación del estándar | Código insertado en objetos base (tablas 18, 36, 37, codeunits 80, 90…) | Se reescribe como suscriptor de evento en una extensión |
| Objeto propio | Tablas, páginas, informes y codeunits en tu rango | Se convierte con txt2al y se revisa |
| Sin equivalente en SaaS | DotNet, acceso a ficheros locales, automation, Codeunit 1 | Se rediseña |
En un NAV con años, la primera categoría suele ser entre un tercio y la mitad del total. Ese es el trabajo que te ahorras si haces esto primero. Cómo se planifica la migración completa.
1. Exportar con la sintaxis nueva
Desde NAV 2015 en adelante, exporta los objetos con la sintaxis que txt2al entiende, usando finsql.exe desde la línea de comandos:
finsql.exe Command=ExportToNewSyntax, File=C:\export\objects.txt, Database="NAV_DB", ServerName=SQLSERVER, Filter="Version List=*MIEMPRESA*"
Filtercon tu marca de versión (MIEMPRESA,CUST, lo que usaseis) exporta solo objetos tocados. Si no marcasteis versiones, filtra por ID.- En NAV 2013 y anteriores no existe
ExportToNewSyntax: exporta en formato TXT normal y usa la opción--ignoreLegacySyntaxo un paso intermedio con una versión posterior de finsql. Es más trabajo; cuéntalo en el plan. - Exporta también los objetos estándar modificados en un archivo aparte. Los necesitas para ver el delta, no para convertirlos.
2. Separar el delta de las modificaciones del estándar
Para cada objeto base modificado, genera la diferencia contra el objeto original de la misma versión:
txt2al --source=C:\export\modified --target=C:\export\delta --baseline=C:\export\baseline --rename
El delta te muestra exactamente qué líneas añadisteis. Eso es lo que hay que reescribir como eventos; el resto del objeto no es tuyo y no se toca.
3. Convertir los objetos propios con txt2al
txt2al --source=C:\export\custom --target=C:\al\src --rename --extensionStartId=50100
--renamegenera nombres de archivo con la convención de AL.--extensionStartIdreasigna IDs si los originales colisionan con el rango de la extensión.- Instala la extensión AL Language en VS Code, crea el proyecto con
AL: Go!, descarga símbolos, y copia los.algenerados asrc/.
Lo que sale compila raramente a la primera. Lo que suele fallar, en orden de frecuencia:
Tipos y funciones que cambiaron de nombre. Text[250] → Text[250] está bien, pero BigText, Automation y DotNet no existen en SaaS. FORMAT, EVALUATE, STRSUBSTNO son iguales; COPYSTR, DELCHR también. CurrForm → CurrPage. TEXTCONST → variables Label.
Codeunit 1. Desapareció. Sus funciones viven ahora en codeunits de gestión: Codeunit 1 → "System Initialization", "Company Triggers", "Login Management", y los eventos correspondientes. Cualquier llamada a CODEUNIT.RUN(1, ...) hay que redirigirla.
Acceso a ficheros. File.Open, File.Create y rutas locales no funcionan en la nube. Se sustituyen por InStream/OutStream con TempBlob, DownloadFromStream para entregar al usuario y UploadIntoStream para recibir. Si el fichero iba a una carpeta de red, el destino ahora es Azure Blob, SharePoint o un correo — y es una decisión de diseño, no de sintaxis.
Informes. txt2al convierte el dataset; el layout RDLC se copia y suele necesitar ajustes de fuentes y márgenes. Los layouts en Word se rehacen o se sustituyen por los nuevos temas de informe de BC29, que evitan tocar cada layout.
4. Reescribir las modificaciones del estándar como eventos
Este es el trabajo de verdad. Un ejemplo típico: en NAV insertasteis en OnValidate del campo Sell-to Customer No. de la tabla 36 una validación propia. En AL es un suscriptor:
codeunit 50100 "BRV Sales Header Events"
{
[EventSubscriber(ObjectType::Table, Database::"Sales Header", 'OnAfterValidateEvent', 'Sell-to Customer No.', false, false)]
local procedure OnAfterValidateSellToCustomer(var Rec: Record "Sales Header"; var xRec: Record "Sales Header")
var
Customer: Record Customer;
begin
if not Customer.Get(Rec."Sell-to Customer No.") then
exit;
if Customer."BRV Bloqueado Comercial" then
Error('El cliente %1 está bloqueado por el departamento comercial.', Customer."No.");
end;
}
Y el campo nuevo que añadisteis a la tabla 18 es una extensión de tabla, no una copia de la tabla:
tableextension 50100 "BRV Customer Ext" extends Customer
{
fields
{
field(50100; "BRV Bloqueado Comercial"; Boolean) { Caption = 'Bloqueado comercial'; DataClassification = CustomerContent; }
}
}
Los eventos que usaréis el 90 % de las veces: OnAfterValidateEvent y OnBeforeValidateEvent en campos, OnAfterInsertEvent / OnAfterModifyEvent en tablas, y los eventos de negocio de las codeunits de registro (Sales-Post, Purch-Post): OnBeforePostSalesDoc, OnAfterPostSalesDoc, OnBeforePostLines. Busca el evento en el objeto base con Ctrl+Shift+P → AL: Find Event.
Si no existe un evento donde lo necesitas, la respuesta no es modificar el estándar (imposible en SaaS): es rediseñar el flujo alrededor del evento más cercano, o pedir el evento a Microsoft por GitHub — aceptan muchas peticiones y salen en la siguiente oleada.
5. Lo que no tiene equivalente y hay que rediseñar
- DotNet y Automation (COM, Excel Interop, componentes externos): no existen. Excel →
Excel Buffer; XML →XmlDocumentnativo de AL; correo →Emailmódulo estándar; llamadas externas →HttpClient. - Acceso SQL directo, ADO, consultas a otras bases de datos: se sustituye por APIs y OData. Por qué y cómo.
- Job Queue con ejecutables externos: la cola de trabajos existe, los ejecutables no. Lo que hacía el .exe pasa a una Azure Function o a Power Automate.
- Impresión directa a impresora: no hay servidor de impresión. Universal Print o descarga de PDF.
- Permisos por objeto en el código: los
permission setsse definen en AL y se publican con la extensión.
6. Compilar, probar, publicar
Ctrl+Shift+Bhasta cero errores. Las advertencias deAppSourceCopyCodeCopconviene resolverlas aunque no vayas a AppSource: son las que te avisan de lo que romperá en la próxima actualización.- Pruebas automatizadas en AL para lo que era crítico en NAV: registro de documentos, cálculos de precios, cierres. En BC29 se ejecutan desde línea de comandos y encajan en CI/CD.
- Sandbox con tus datos reales — no demo. Ejecuta el cierre de mes y el día de más pedidos.
- Publicar como extensión por tenant (
Extension Management → Upload) o, si va a AppSource, con el proceso de validación de Microsoft.
El orden que ahorra semanas
- Inventario y clasificación (2-4 días).
- Eliminar lo cubierto por el estándar (una decisión, no código).
- Convertir objetos propios con txt2al y hacerlos compilar.
- Reescribir las modificaciones como eventos, una por una, probando cada una.
- Rediseñar lo que no tiene equivalente — al final, cuando ya sabes cuánto queda.
Quien invierte este orden convierte código que iba a borrarse, y descubre los bloqueos de diseño cuando ya ha gastado el presupuesto.
En nuestros proyectos, el paso 1 lo hace la IA: lee todos los objetos, los agrupa por función y marca los que existen en el estándar. Lo que llevaba dos semanas de un consultor senior lleva dos días — y encuentra más solapamientos de los que encuentra una persona.
Preguntas frecuentes
¿Puedo convertir un NAV 2009 con txt2al? No directamente: no exporta en la sintaxis nueva. El camino habitual es un salto intermedio (importar en una versión más moderna solo para exportar) o conversión manual de los objetos propios, que en 2009 suelen ser menos y más simples.
¿Vale la pena convertir los informes o rehacerlos? Depende del layout. Los RDLC simples se convierten; los complejos suelen ser más rápidos de rehacer con los temas de informe de BC29, que además dejan de exigir un layout por documento.
¿Cuánto código sobrevive? En nuestra experiencia, un tercio se elimina, un tercio se convierte casi directo y un tercio se reescribe como eventos. El primer tercio es el que nadie te cuenta cuando te presupuestan "convertir todas las personalizaciones".
¿Y las tablas con datos? Se convierten a tablas AL con el mismo ID si es posible, y los datos migran con paquetes de configuración o por API. La estructura debe existir antes de migrar datos, por eso el código va primero.
¿Tienes un NAV con años de código y quieres saber cuánto sobrevive? Evaluación gratuita, sin compromiso: inventario de objetos y clasificación en cinco días laborables.