Estado actual (2025+): SAC soporta bloques
try/catchen versiones recientes del Analytics Designer. Sin embargo, el soporte no ha existido siempre y en versiones antiguas los scripts crasheaban silenciosamente sin posibilidad de capturar errores.La guia introductoria de este repositorio menciona "sin try/catch" como limitacion. Esto era cierto en versiones iniciales. A partir de ~2023-2024, SAP anadio soporte para try/catch, pero con limitaciones.
try {
var ds = Table_1.getDataSource();
var data = ds.getData({"Account": "Revenue", "Region": "EMEA"});
Application.showMessage(ApplicationMessageType.Info, "Valor: " + data.rawValue);
} catch (e) {
Application.showMessage(
ApplicationMessageType.Error,
"Error al obtener datos: " + e.message
);
}- No todas las excepciones son capturables. Errores de infraestructura (timeout, conexion perdida) no se capturan.
- Los errores de compilacion (sintaxis) no se capturan en runtime.
- Algunos metodos de la API fallan silenciosamente devolviendo
undefinedofalseen lugar de lanzar excepciones. - La propiedad
e.messagepuede contener mensajes genericos poco utiles.
// En vez de depender solo de try/catch, valida antes de operar
var ds = Table_1.getDataSource();
if (ds === undefined) {
Application.showMessage(ApplicationMessageType.Error, "DataSource no disponible");
return;
}
var planning = Table_1.getPlanning();
if (planning === undefined) {
Application.showMessage(ApplicationMessageType.Error, "Planning no disponible");
return;
}
var selections = Table_1.getSelections();
if (selections.length === 0) {
Application.showMessage(ApplicationMessageType.Warning, "No hay seleccion");
return;
}
// Solo ahora operar con seguridad
var success = planning.setUserInput(selections[0], "100");console.log() funciona en SAC y es la herramienta principal de depuracion junto con Application.showMessage().
- Ejecuta la aplicacion en modo View o Preview
- Abre las Developer Tools del navegador:
F12oCtrl+Shift+J - Ve a la pestana Console
- Los mensajes de
console.log()aparecen ahi
// Depuracion con console.log
var ds = Table_1.getDataSource();
var members = ds.getMembers("Region");
console.log("Numero de miembros Region: " + members.length.toString());
for (var i = 0; i < members.length; i++) {
console.log("Miembro " + i.toString() + ": " + members[i].id + " - " + members[i].description);
}Importante:
console.log()no es API oficial de SAC. Es una funcionalidad del navegador que SAC no bloquea. No aparece en la documentacion oficial de SAP, pero funciona y la comunidad lo usa extensivamente para debugging.
console.log() |
Application.showMessage() |
|
|---|---|---|
| Visible al usuario final | No (solo Developer Tools) | Si (toast en pantalla) |
| Volumen de datos | Ilimitado | Un mensaje a la vez |
| Tipos de datos | Cualquiera | Solo strings |
| Documentado por SAP | No | Si |
| Uso recomendado | Desarrollo/debugging | Feedback al usuario + debugging basico |
Puedes activar el modo debug anadiendo &debug=true a la URL de la aplicacion:
https://<HOST>/sap/fpa/ui/app.html?tenant=<TENANT>#;mode=present;view_id=appBuilding;appId=<APP_ID>&debug=true
- Comentarios en codigo generado: Los comentarios de tus scripts se preservan en el JavaScript transformado, facilitando encontrar tu codigo en DevTools.
- Breakpoints funcionales: Puedes poner breakpoints en tus scripts desde el editor.
- Mejor trazabilidad: Los errores en consola incluyen mas contexto.
- Abre el script en el editor de SAC (design time)
- Haz click en el numero de linea a la izquierda
- Aparece un marcador azul indicando el breakpoint
- Ejecuta la aplicacion: el script se pausa en ese punto
Puedes insertar debugger; directamente en tu codigo:
// El script se pausara aqui si DevTools esta abierto
var ds = Table_1.getDataSource();
debugger;
var data = ds.getData({"Account": "Revenue"});
// Desde DevTools puedes inspeccionar 'ds' y 'data'Requisito: Las Developer Tools del navegador deben estar abiertas ANTES de que se ejecute la linea
debugger;. Si no estan abiertas, la sentencia se ignora.
- Abre DevTools (
F12) - Ve a la pestana Sources
- En el arbol de archivos, busca la entrada que empieza con
sandbox.worker.main - Dentro, busca AnalyticApplication > nombre de tu aplicacion
- Ahi encontraras todos los scripts que se han ejecutado
// ERROR: si getDataSource() devuelve undefined
var value = Table_1.getDataSource().getData({"Account": "Revenue"});
// SOLUCION: validar cada paso
var ds = Table_1.getDataSource();
if (ds !== undefined) {
var data = ds.getData({"Account": "Revenue"});
if (data !== undefined) {
// usar data.rawValue
}
}Ocurre cuando llamas un metodo que no existe en el tipo de widget. Ejemplo: llamar getPlanning() en un Chart.
// Verificar disponibilidad del metodo
// No hay un typeof check fiable, pero puedes verificar el tipo de widget
// La mejor practica es conocer que metodos tiene cada widgetLos scripts tienen un limite de ejecucion de aproximadamente 30 segundos. Si un bucle procesa muchos elementos o hace muchas llamadas API, puede exceder este limite.
// PROBLEMA: bucle sobre miles de miembros
var members = ds.getMembers("CostCenter");
for (var i = 0; i < members.length; i++) {
// Si CostCenter tiene 5000 miembros, esto puede exceder timeout
ds.setDimensionFilter("CostCenter", members[i].id);
// ... procesamiento ...
}
// SOLUCION: limitar el procesamiento o usar Data Actions para logica masiva// Si el miembro no existe en la dimension, no da error pero el filtro no se aplica
ds.setDimensionFilter("Region", "REGION_QUE_NO_EXISTE");
// No hay error, pero la tabla puede quedar vacia// getResultSet devuelve los datos tal como estan filtrados en la tabla
// Si hay filtros activos, solo devuelve los datos visibles
var rs = ds.getResultSet();
// rs puede estar vacio si los filtros excluyen todo// En un ScriptObject (ScriptObject_ErrorHandler)
function safeExecute(description) {
// Registrar en consola para debugging
console.log("[INFO] Ejecutando: " + description);
}
function logError(operation, errorMsg) {
console.log("[ERROR] " + operation + ": " + errorMsg);
Application.showMessage(
ApplicationMessageType.Error,
"Error en " + operation + ": " + errorMsg
);
}
function logWarning(operation, msg) {
console.log("[WARN] " + operation + ": " + msg);
Application.showMessage(
ApplicationMessageType.Warning,
msg
);
}// Uso desde cualquier evento
ScriptObject_ErrorHandler.safeExecute("Aplicar filtro Region");
var ds = Table_1.getDataSource();
if (ds === undefined) {
ScriptObject_ErrorHandler.logError("Filtro Region", "DataSource no disponible");
return;
}
var sel = Dropdown_Region.getSelectedKey();
if (sel === "" || sel === undefined) {
ScriptObject_ErrorHandler.logWarning("Filtro Region", "No hay region seleccionada");
return;
}
ds.setDimensionFilter("Region", sel);Los errores de Data Actions son especialmente dificiles de depurar porque se ejecutan en el backend:
// Ejecutar Data Action y verificar resultado
var result = DataAction_Calculate.execute();
// El resultado tiene una propiedad status
if (result.status === "OK") {
Application.showMessage(ApplicationMessageType.Success, "Data Action completada");
} else {
Application.showMessage(
ApplicationMessageType.Error,
"Data Action fallo con status: " + result.status
);
}Nota: El objeto
DataActionExecutionResponsedevuelto porexecute()contiene el campostatus. Los valores posibles no estan completamente documentados, pero incluyen "OK" para ejecucion exitosa.
- Primero: Usa
Application.showMessage()para verificar valores intermedios rapidamente - Segundo: Anade
console.log()para datos volumosos o inspecciones detalladas - Tercero: Activa debug mode (
&debug=true) y usa breakpoints para stepping - Cuarto: Usa
debugger;en puntos especificos donde necesites inspeccionar variables - Siempre: Valida
undefinedantes de acceder a propiedades o metodos de objetos
-
console.log en produccion: No olvides quitar o comentar los
console.log()antes de publicar. No causan errores pero ensucian la consola. -
Breakpoints no funcionan: Si los breakpoints no se activan, verifica que
debug=trueesta en la URL y que DevTools esta abierto. -
showMessage se acumula: Si pones showMessage dentro de un bucle, los mensajes se acumulan y solo se ve el ultimo. Usa console.log para bucles.
-
Error oculto por try/catch: Un catch vacio oculta errores. Siempre loggea algo en el catch.
-
Scripts en widgets invisibles: Si un widget es invisible y su script se ejecuta, puede fallar silenciosamente si depende de widgets que aun no se han renderizado.