Ir al contenido

Capítulo 13: Tu primer script EPLAN

Parte II: Introducción a EPLAN API - Sección 3: Primeros pasos con EPLAN - Nivel: Intermedio


Al finalizar este capítulo serás capaz de:

  • Entender el atributo [Start] y su importancia
  • Abrir proyectos EPLAN programáticamente
  • Leer propiedades de proyectos (nombre, descripción, configuración)
  • Usar SelectionSet para obtener proyecto actual
  • Mostrar mensajes con BaseException
  • Validar existencia de proyectos antes de procesarlos
  • Crear tu primer script funcional completo que resuelve un problema real
  • Manejar errores específicos de EPLAN API

Antes de comenzar este capítulo debes:

  • ✅ Haber completado el Capítulo 12
  • ✅ Entender la arquitectura de EPLAN API
  • ✅ Conocer namespaces principales
  • ✅ Tener EPLAN Electric P8 instalado
  • ✅ Tener al menos un proyecto EPLAN de prueba

Validador Inteligente de Proyectos EPLAN

Al final de este capítulo habrás construido un script completo que:

  • Valida que un proyecto esté abierto
  • Lee todas las propiedades importantes del proyecto
  • Verifica la configuración básica
  • Cuenta páginas, funciones y dispositivos
  • Detecta posibles problemas
  • Genera un reporte profesional de validación
  • Maneja todos los errores posibles

Tiempo estimado: 70-80 minutos


El atributo [Start] marca el punto de entrada de tu script. Es donde EPLAN comienza a ejecutar tu código.

Analogía: Como la función main() en C/C++ o public static void Main() en C# de consola.

using Eplan.EplApi.ApplicationFramework;
public class MiPrimerScript
{
[Start]
public void Ejecutar()
{
// Tu código comienza aquí
}
}

Reglas importantes:

  • ✅ Debe ser un método public
  • ✅ Puede llamarse como quieras (Ejecutar, Run, Main, etc.)
  • ✅ Solo puede haber un método [Start] por archivo
  • ✅ El método puede tener parámetros opcionales
  • ✅ No tiene que devolver nada (puede ser void)
[Start]
public void NombreDelMetodo()
{
// Código del script
}

Variantes válidas:

// 1. Sin parámetros (más común)
[Start]
public void Ejecutar()
{
}
// 2. Con parámetros opcionales
[Start]
public void Ejecutar(string parametro = "")
{
}
// 3. Nombre en inglés
[Start]
public void Execute()
{
}
// 4. Nombre descriptivo
[Start]
public void ValidarProyecto()
{
}
// ❌ ERROR - EPLAN no sabe dónde empezar
public class MiScript
{
public void Metodo1() { }
public void Metodo2() { }
// ¿Cuál ejecutar?
}
// ✓ CORRECTO
public class MiScript
{
[Start] // ← EPLAN ejecuta esto
public void Ejecutar()
{
Metodo1();
Metodo2();
}
public void Metodo1() { }
public void Metodo2() { }
}

MiScript.cs
//
// Descripción: Descripción breve
// Autor: Tu nombre
// Fecha: 2025
//
using System;
using Eplan.EplApi.Base;
using Eplan.EplApi.ApplicationFramework;
public class MiScript
{
[Start]
public void Ejecutar()
{
try
{
// Tu código aquí
new BaseException("Script ejecutado correctamente",
MessageLevel.Message).FixMessage();
}
catch (Exception ex)
{
new BaseException("Error: " + ex.Message,
MessageLevel.Error).FixMessage();
}
}
}
MiScript.cs
//
// Descripción: [Descripción detallada]
// Autor: [Tu nombre]
// Fecha: [Fecha]
// Versión: 1.0
//
// Uso:
// 1. Abrir proyecto en EPLAN
// 2. Ejecutar: Utilidades > Scripts > MiScript
// 3. [Instrucciones específicas]
//
// Requisitos:
// - EPLAN Electric P8 2023+
// - Proyecto abierto
//
using System;
using System.Collections.Generic;
using Eplan.EplApi.Base;
using Eplan.EplApi.ApplicationFramework;
using Eplan.EplApi.DataModel;
public class MiScript
{
[Start]
public void Ejecutar()
{
try
{
// ====================================
// 1. VALIDACIONES INICIALES
// ====================================
if (!ValidarPrecondiciones())
{
return; // Salir si no se cumplen requisitos
}
// ====================================
// 2. LÓGICA PRINCIPAL
// ====================================
ProcesarProyecto();
// ====================================
// 3. MENSAJE DE ÉXITO
// ====================================
new BaseException("Proceso completado correctamente",
MessageLevel.Message).FixMessage();
}
catch (Exception ex)
{
// ====================================
// 4. MANEJO DE ERRORES
// ====================================
string mensajeError = string.Format(
"Error en el script:\n\n{0}\n\n{1}",
ex.Message, ex.StackTrace);
new BaseException(mensajeError,
MessageLevel.Error).FixMessage();
}
}
private bool ValidarPrecondiciones()
{
// Validaciones aquí
return true;
}
private void ProcesarProyecto()
{
// Lógica principal aquí
}
}

using Eplan.EplApi.ApplicationFramework;
using Eplan.EplApi.DataModel;
[Start]
public void Ejecutar()
{
// Crear SelectionSet
SelectionSet seleccion = new SelectionSet();
seleccion.LockSelectionByDefault = false;
// Obtener proyectos seleccionados
Project[] proyectos = seleccion.GetSelectedProjects();
// Validar que hay al menos un proyecto
if (proyectos.Length == 0)
{
new BaseException("No hay proyecto abierto",
MessageLevel.Warning).FixMessage();
return;
}
// Trabajar con el primer proyecto
Project proyecto = proyectos[0];
string nombre = proyecto.ProjectName;
new BaseException("Proyecto actual: " + nombre,
MessageLevel.Message).FixMessage();
}

Explicación:

  • SelectionSet: Clase que maneja la selección actual en EPLAN
  • LockSelectionByDefault = false: No bloquear la selección
  • GetSelectedProjects(): Obtiene array de proyectos seleccionados
  • Si hay múltiples proyectos abiertos, devuelve todos
private Project ObtenerProyectoActual()
{
try
{
SelectionSet seleccion = new SelectionSet();
seleccion.LockSelectionByDefault = false;
Project[] proyectos = seleccion.GetSelectedProjects();
if (proyectos == null || proyectos.Length == 0)
{
new BaseException(
"No hay proyecto abierto.\n\n" +
"Por favor, abre un proyecto en EPLAN antes de ejecutar este script.",
MessageLevel.Warning).FixMessage();
return null;
}
return proyectos[0];
}
catch (Exception ex)
{
new BaseException(
"Error al obtener proyecto actual:\n" + ex.Message,
MessageLevel.Error).FixMessage();
return null;
}
}
// Uso
[Start]
public void Ejecutar()
{
Project proyecto = ObtenerProyectoActual();
if (proyecto == null)
return; // Salir si no hay proyecto
// Continuar con el procesamiento...
}

Project proyecto = ObtenerProyectoActual();
// Nombre del proyecto
string nombre = proyecto.ProjectName;
// Descripción
string descripcion = proyecto.ProjectDescription;
// Ruta completa
string ruta = proyecto.ProjectFullName;
// Validez del objeto
bool esValido = proyecto.IsValid;
// Identificador único
int objectId = proyecto.ObjectId;
// Descripción puede ser null
string descripcion = proyecto.ProjectDescription;
if (string.IsNullOrEmpty(descripcion))
{
descripcion = "(Sin descripción)";
}
// ProjectFullName incluye carpeta y extensión
string rutaCompleta = proyecto.ProjectFullName;
string carpeta = System.IO.Path.GetDirectoryName(rutaCompleta);
string archivo = System.IO.Path.GetFileName(rutaCompleta);

EPLAN expone muchas propiedades adicionales a través del sistema Properties:

using Eplan.EplApi.DataModel;
Project proyecto = ObtenerProyectoActual();
// Acceder a Properties
AnyPropertyId propId = new AnyPropertyId(
Properties.Project.PROJ_COMPANYNAME);
string empresa = proyecto.Properties[propId].ToString();
// Otras propiedades comunes
string ciudad = proyecto.Properties[
new AnyPropertyId(Properties.Project.PROJ_COMPANY_TOWN)].ToString();
string pais = proyecto.Properties[
new AnyPropertyId(Properties.Project.PROJ_COMPANY_COUNTRY)].ToString();

Propiedades importantes:

PropiedadDescripciónEjemplo
PROJ_COMPANYNAMENombre de empresa”ACME Corp”
PROJ_COMPANY_TOWNCiudad”Madrid”
PROJ_CUSTOMERCliente”Cliente XYZ”
PROJ_PROJECTNUMBERNúmero de proyecto”2025-001”
PROJ_ORDERNUMBERNúmero de pedido”ORD-12345”
PROJ_DRAWINGDATEFecha de planos”2025-01-15”
private string ObtenerPropiedad(Project proyecto, int propertyId,
string valorPorDefecto = "N/A")
{
try
{
AnyPropertyId propId = new AnyPropertyId(propertyId);
if (!proyecto.Properties.ExistsProperty(propId))
{
return valorPorDefecto;
}
string valor = proyecto.Properties[propId].ToString();
if (string.IsNullOrWhiteSpace(valor))
{
return valorPorDefecto;
}
return valor;
}
catch
{
return valorPorDefecto;
}
}
// Uso
string empresa = ObtenerPropiedad(proyecto,
Properties.Project.PROJ_COMPANYNAME, "(Sin empresa)");

Project proyecto = ObtenerProyectoActual();
Page[] paginas = proyecto.Pages;
int totalPaginas = paginas.Length;
new BaseException(
string.Format("El proyecto tiene {0} páginas", totalPaginas),
MessageLevel.Message).FixMessage();
Project proyecto = ObtenerProyectoActual();
int totalFunciones = 0;
int totalDispositivos = 0;
foreach (Page pagina in proyecto.Pages)
{
totalFunciones += pagina.Functions.Length;
totalDispositivos += pagina.Devices.Length;
}
string mensaje = string.Format(
"ESTADÍSTICAS DEL PROYECTO:\n\n" +
"Páginas: {0}\n" +
"Funciones: {1}\n" +
"Dispositivos: {2}",
proyecto.Pages.Length,
totalFunciones,
totalDispositivos);
new BaseException(mensaje, MessageLevel.Message).FixMessage();
private void AnalizarProyecto(Project proyecto)
{
int totalPaginas = 0;
int totalFunciones = 0;
int totalDispositivos = 0;
int totalConexiones = 0;
Dictionary<string, int> funcionesPorTipo = new Dictionary<string, int>();
foreach (Page pagina in proyecto.Pages)
{
totalPaginas++;
Function[] funciones = pagina.Functions;
totalFunciones += funciones.Length;
totalDispositivos += pagina.Devices.Length;
// Analizar funciones
foreach (Function funcion in funciones)
{
// Contar conexiones
totalConexiones += funcion.Connections.Length;
// Contar por tipo
string tipo = funcion.FunctionDefinition;
if (string.IsNullOrEmpty(tipo))
tipo = "Sin tipo";
if (!funcionesPorTipo.ContainsKey(tipo))
{
funcionesPorTipo[tipo] = 0;
}
funcionesPorTipo[tipo]++;
}
}
// Generar reporte
string reporte = "ANÁLISIS COMPLETO DEL PROYECTO\n";
reporte += "========================================\n\n";
reporte += string.Format("Páginas: {0}\n", totalPaginas);
reporte += string.Format("Funciones: {0}\n", totalFunciones);
reporte += string.Format("Dispositivos: {0}\n", totalDispositivos);
reporte += string.Format("Conexiones: {0}\n\n", totalConexiones);
reporte += "FUNCIONES POR TIPO:\n";
reporte += "----------------------------------------\n";
foreach (var kvp in funcionesPorTipo)
{
reporte += string.Format(" {0}: {1}\n", kvp.Key, kvp.Value);
}
new BaseException(reporte, MessageLevel.Message).FixMessage();
}

using Eplan.EplApi.Base;
// 1. MESSAGE (Información)
BaseException info = new BaseException(
"Proceso completado correctamente",
MessageLevel.Message);
info.FixMessage();
// 2. WARNING (Advertencia)
BaseException warning = new BaseException(
"Atención: Algunas páginas no tienen numeración",
MessageLevel.Warning);
warning.FixMessage();
// 3. ERROR (Error)
BaseException error = new BaseException(
"Error: No se pudo abrir el archivo",
MessageLevel.Error);
error.FixMessage();

Diferencias visuales en EPLAN:

  • Message: Ícono de información (azul)
  • Warning: Ícono de advertencia (amarillo)
  • Error: Ícono de error (rojo)
// Mensaje multilínea
string mensaje = "REPORTE DE VALIDACIÓN\n";
mensaje += "========================================\n";
mensaje += string.Format("Proyecto: {0}\n", proyecto.ProjectName);
mensaje += string.Format("Páginas: {0}\n", proyecto.Pages.Length);
mensaje += "========================================\n";
new BaseException(mensaje, MessageLevel.Message).FixMessage();
// Mensaje con formato
string mensajeFormateado = string.Format(
"El proyecto '{0}' tiene:\n\n" +
" • {1} páginas\n" +
" • {2} funciones\n" +
" • {3} dispositivos",
proyecto.ProjectName,
totalPaginas,
totalFunciones,
totalDispositivos);
new BaseException(mensajeFormateado, MessageLevel.Message).FixMessage();

6.3 Preguntar al usuario (MessageBox alternativo)

Sección titulada «6.3 Preguntar al usuario (MessageBox alternativo)»
// BaseException solo muestra, no pregunta
// Para diálogos interactivos, usa System.Windows.Forms
using System.Windows.Forms;
DialogResult resultado = MessageBox.Show(
"¿Desea continuar con el proceso?",
"Confirmar",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question);
if (resultado == DialogResult.Yes)
{
// Usuario confirmó
ProcesarProyecto();
}
else
{
// Usuario canceló
new BaseException("Proceso cancelado por el usuario",
MessageLevel.Warning).FixMessage();
}

try
{
SelectionSet sel = new SelectionSet();
Project[] proyectos = sel.GetSelectedProjects();
if (proyectos.Length == 0)
{
throw new InvalidOperationException("No hay proyecto abierto");
}
Project proyecto = proyectos[0];
// Trabajar con proyecto...
}
catch (InvalidOperationException ex)
{
// Error conocido - mensaje amigable
new BaseException(
"No se puede continuar:\n\n" + ex.Message,
MessageLevel.Warning).FixMessage();
}
catch (System.Runtime.InteropServices.COMException ex)
{
// Error de COM (EPLAN API usa COM internamente)
new BaseException(
"Error de comunicación con EPLAN:\n\n" +
"Intente cerrar y reabrir EPLAN.\n\n" +
"Detalles técnicos: " + ex.Message,
MessageLevel.Error).FixMessage();
}
catch (Exception ex)
{
// Error genérico
new BaseException(
"Error inesperado:\n\n" + ex.Message + "\n\n" + ex.StackTrace,
MessageLevel.Error).FixMessage();
}
private bool ValidarProyecto(Project proyecto)
{
// 1. Verificar que el objeto sea válido
if (proyecto == null)
{
new BaseException("El proyecto es null",
MessageLevel.Error).FixMessage();
return false;
}
if (!proyecto.IsValid)
{
new BaseException("El proyecto no es válido",
MessageLevel.Error).FixMessage();
return false;
}
// 2. Verificar que tenga páginas
if (proyecto.Pages == null || proyecto.Pages.Length == 0)
{
new BaseException(
"El proyecto no tiene páginas.\n\n" +
"No se puede continuar el procesamiento.",
MessageLevel.Warning).FixMessage();
return false;
}
// 3. Verificar que no esté vacío
int totalFunciones = 0;
foreach (Page pagina in proyecto.Pages)
{
totalFunciones += pagina.Functions.Length;
}
if (totalFunciones == 0)
{
DialogResult resultado = MessageBox.Show(
"El proyecto no tiene funciones (componentes).\n\n" +
"¿Desea continuar de todos modos?",
"Proyecto vacío",
MessageBoxButtons.YesNo,
MessageBoxIcon.Warning);
return resultado == DialogResult.Yes;
}
return true;
}

//
// Proyecto: Validador Inteligente de Proyectos EPLAN
// Capítulo: 13
// Descripción: Script completo que valida un proyecto EPLAN y genera
// un reporte detallado con información, estadísticas y
// detección de posibles problemas
// Autor: C.D. López
// Fecha: Enero 2025
//
// Uso:
// 1. Abrir un proyecto en EPLAN
// 2. Ejecutar: Utilidades > Scripts > ValidadorProyecto
// 3. Se mostrará un reporte completo de validación
//
using System;
using System.Collections.Generic;
using System.Linq;
using Eplan.EplApi.Base;
using Eplan.EplApi.ApplicationFramework;
using Eplan.EplApi.DataModel;
public class ValidadorProyecto
{
[Start]
public void Ejecutar()
{
try
{
// ====================================
// 1. OBTENER PROYECTO ACTUAL
// ====================================
Project proyecto = ObtenerProyectoActual();
if (proyecto == null)
return;
// ====================================
// 2. VALIDAR PRECONDICIONES
// ====================================
if (!ValidarProyecto(proyecto))
return;
// ====================================
// 3. RECOPILAR INFORMACIÓN
// ====================================
string reporte = GenerarReporteCompleto(proyecto);
// ====================================
// 4. MOSTRAR REPORTE
// ====================================
new BaseException(reporte, MessageLevel.Message).FixMessage();
}
catch (Exception ex)
{
string mensajeError = string.Format(
"ERROR EN VALIDADOR DE PROYECTO\n" +
"========================================\n\n" +
"Mensaje: {0}\n\n" +
"Tipo: {1}\n\n" +
"Stack Trace:\n{2}",
ex.Message,
ex.GetType().Name,
ex.StackTrace);
new BaseException(mensajeError, MessageLevel.Error).FixMessage();
}
}
// ====================================
// OBTENER PROYECTO ACTUAL
// ====================================
private Project ObtenerProyectoActual()
{
try
{
SelectionSet seleccion = new SelectionSet();
seleccion.LockSelectionByDefault = false;
Project[] proyectos = seleccion.GetSelectedProjects();
if (proyectos == null || proyectos.Length == 0)
{
new BaseException(
"NO HAY PROYECTO ABIERTO\n\n" +
"Por favor, abre un proyecto en EPLAN antes de ejecutar este script.",
MessageLevel.Warning).FixMessage();
return null;
}
return proyectos[0];
}
catch (Exception ex)
{
new BaseException(
"Error al obtener proyecto actual:\n\n" + ex.Message,
MessageLevel.Error).FixMessage();
return null;
}
}
// ====================================
// VALIDAR PROYECTO
// ====================================
private bool ValidarProyecto(Project proyecto)
{
// Verificar validez del objeto
if (!proyecto.IsValid)
{
new BaseException(
"El proyecto no es válido.\n\n" +
"Es posible que el proyecto esté corrupto o no se haya cargado correctamente.",
MessageLevel.Error).FixMessage();
return false;
}
// Verificar que tenga páginas
if (proyecto.Pages == null || proyecto.Pages.Length == 0)
{
new BaseException(
"El proyecto no tiene páginas.\n\n" +
"No hay contenido para validar.",
MessageLevel.Warning).FixMessage();
return false;
}
return true;
}
// ====================================
// GENERAR REPORTE COMPLETO
// ====================================
private string GenerarReporteCompleto(Project proyecto)
{
string reporte = "VALIDADOR INTELIGENTE DE PROYECTOS EPLAN\n";
reporte += "========================================\n\n";
// Sección 1: Información básica
reporte += GenerarSeccionInformacionBasica(proyecto);
// Sección 2: Propiedades del proyecto
reporte += GenerarSeccionPropiedades(proyecto);
// Sección 3: Estadísticas
reporte += GenerarSeccionEstadisticas(proyecto);
// Sección 4: Análisis de páginas
reporte += GenerarSeccionPaginas(proyecto);
// Sección 5: Problemas detectados
reporte += GenerarSeccionProblemas(proyecto);
// Sección 6: Conclusión
reporte += GenerarSeccionConclu sion(proyecto);
return reporte;
}
// ====================================
// SECCIÓN: INFORMACIÓN BÁSICA
// ====================================
private string GenerarSeccionInformacionBasica(Project proyecto)
{
string seccion = "INFORMACIÓN BÁSICA:\n";
seccion += "----------------------------------------\n";
seccion += string.Format(" Nombre: {0}\n", proyecto.ProjectName);
string descripcion = proyecto.ProjectDescription;
if (string.IsNullOrEmpty(descripcion))
descripcion = "(Sin descripción)";
seccion += string.Format(" Descripción: {0}\n", descripcion);
seccion += string.Format(" Ruta: {0}\n", proyecto.ProjectFullName);
seccion += string.Format(" Es válido: {0}\n", proyecto.IsValid ? "" : "No");
seccion += string.Format(" ObjectId: {0}\n\n", proyecto.ObjectId);
return seccion;
}
// ====================================
// SECCIÓN: PROPIEDADES
// ====================================
private string GenerarSeccionPropiedades(Project proyecto)
{
string seccion = "PROPIEDADES DEL PROYECTO:\n";
seccion += "----------------------------------------\n";
string empresa = ObtenerPropiedad(proyecto,
Properties.Project.PROJ_COMPANYNAME);
seccion += string.Format(" Empresa: {0}\n", empresa);
string ciudad = ObtenerPropiedad(proyecto,
Properties.Project.PROJ_COMPANY_TOWN);
seccion += string.Format(" Ciudad: {0}\n", ciudad);
string cliente = ObtenerPropiedad(proyecto,
Properties.Project.PROJ_CUSTOMER);
seccion += string.Format(" Cliente: {0}\n", cliente);
string numeroProyecto = ObtenerPropiedad(proyecto,
Properties.Project.PROJ_PROJECTNUMBER);
seccion += string.Format(" Nº Proyecto: {0}\n\n", numeroProyecto);
return seccion;
}
// ====================================
// SECCIÓN: ESTADÍSTICAS
// ====================================
private string GenerarSeccionEstadisticas(Project proyecto)
{
int totalPaginas = 0;
int totalFunciones = 0;
int totalDispositivos = 0;
int totalConexiones = 0;
foreach (Page pagina in proyecto.Pages)
{
totalPaginas++;
totalFunciones += pagina.Functions.Length;
totalDispositivos += pagina.Devices.Length;
foreach (Function funcion in pagina.Functions)
{
totalConexiones += funcion.Connections.Length;
}
}
string seccion = "ESTADÍSTICAS:\n";
seccion += "----------------------------------------\n";
seccion += string.Format(" Total de páginas: {0,6}\n", totalPaginas);
seccion += string.Format(" Total de funciones: {0,6}\n", totalFunciones);
seccion += string.Format(" Total de dispositivos: {0,6}\n", totalDispositivos);
seccion += string.Format(" Total de conexiones: {0,6}\n", totalConexiones);
if (totalPaginas > 0)
{
double promFunciones = (double)totalFunciones / totalPaginas;
double promDispositivos = (double)totalDispositivos / totalPaginas;
seccion += "\n Promedios por página:\n";
seccion += string.Format(" Funciones: {0,6:F2}\n", promFunciones);
seccion += string.Format(" Dispositivos: {0,6:F2}\n", promDispositivos);
}
seccion += "\n";
return seccion;
}
// ====================================
// SECCIÓN: ANÁLISIS DE PÁGINAS
// ====================================
private string GenerarSeccionPaginas(Project proyecto)
{
string seccion = "ANÁLISIS DE PÁGINAS:\n";
seccion += "----------------------------------------\n";
Page[] paginas = proyecto.Pages;
// Mostrar primeras 5 y últimas 5
int maxMostrar = Math.Min(5, paginas.Length);
for (int i = 0; i < maxMostrar; i++)
{
Page pagina = paginas[i];
seccion += string.Format(" {0,3}. {1,-30} | Func: {2,3} | Dev: {3,3}\n",
pagina.PageNumber,
TruncarTexto(pagina.Name, 30),
pagina.Functions.Length,
pagina.Devices.Length);
}
if (paginas.Length > 10)
{
seccion += string.Format(" ... ({0} páginas intermedias omitidas)\n",
paginas.Length - 10);
for (int i = paginas.Length - 5; i < paginas.Length; i++)
{
Page pagina = paginas[i];
seccion += string.Format(" {0,3}. {1,-30} | Func: {2,3} | Dev: {3,3}\n",
pagina.PageNumber,
TruncarTexto(pagina.Name, 30),
pagina.Functions.Length,
pagina.Devices.Length);
}
}
else if (paginas.Length > 5)
{
for (int i = maxMostrar; i < paginas.Length; i++)
{
Page pagina = paginas[i];
seccion += string.Format(" {0,3}. {1,-30} | Func: {2,3} | Dev: {3,3}\n",
pagina.PageNumber,
TruncarTexto(pagina.Name, 30),
pagina.Functions.Length,
pagina.Devices.Length);
}
}
seccion += "\n";
return seccion;
}
// ====================================
// SECCIÓN: PROBLEMAS DETECTADOS
// ====================================
private string GenerarSeccionProblemas(Project proyecto)
{
List<string> problemas = new List<string>();
// 1. Verificar páginas vacías
int paginasVacias = 0;
foreach (Page pagina in proyecto.Pages)
{
if (pagina.Functions.Length == 0 && pagina.Devices.Length == 0)
{
paginasVacias++;
}
}
if (paginasVacias > 0)
{
problemas.Add(string.Format("Hay {0} página(s) vacía(s)", paginasVacias));
}
// 2. Verificar descripción del proyecto
if (string.IsNullOrEmpty(proyecto.ProjectDescription))
{
problemas.Add("El proyecto no tiene descripción");
}
// 3. Verificar propiedades básicas
string empresa = ObtenerPropiedad(proyecto, Properties.Project.PROJ_COMPANYNAME);
if (empresa == "N/A")
{
problemas.Add("No se ha especificado el nombre de la empresa");
}
string cliente = ObtenerPropiedad(proyecto, Properties.Project.PROJ_CUSTOMER);
if (cliente == "N/A")
{
problemas.Add("No se ha especificado el cliente");
}
// Generar sección
string seccion = "PROBLEMAS DETECTADOS:\n";
seccion += "----------------------------------------\n";
if (problemas.Count == 0)
{
seccion += " ✓ No se detectaron problemas\n";
}
else
{
foreach (string problema in problemas)
{
seccion += string.Format(" ⚠ {0}\n", problema);
}
}
seccion += "\n";
return seccion;
}
// ====================================
// SECCIÓN: CONCLUSIÓN
// ====================================
private string GenerarSeccionConclusion(Project proyecto)
{
string seccion = "CONCLUSIÓN:\n";
seccion += "========================================\n";
int totalFunciones = 0;
foreach (Page pagina in proyecto.Pages)
{
totalFunciones += pagina.Functions.Length;
}
if (totalFunciones == 0)
{
seccion += "⚠ El proyecto está VACÍO\n";
}
else if (totalFunciones < 10)
{
seccion += "✓ El proyecto es muy PEQUEÑO\n";
}
else if (totalFunciones < 100)
{
seccion += "✓ El proyecto tiene tamaño MEDIANO\n";
}
else
{
seccion += "✓ El proyecto es GRANDE\n";
}
seccion += "\nValidación completada correctamente.\n";
seccion += "========================================\n";
return seccion;
}
// ====================================
// UTILIDADES
// ====================================
private string ObtenerPropiedad(Project proyecto, int propertyId,
string valorPorDefecto = "N/A")
{
try
{
AnyPropertyId propId = new AnyPropertyId(propertyId);
if (!proyecto.Properties.ExistsProperty(propId))
{
return valorPorDefecto;
}
string valor = proyecto.Properties[propId].ToString();
if (string.IsNullOrWhiteSpace(valor))
{
return valorPorDefecto;
}
return valor;
}
catch
{
return valorPorDefecto;
}
}
private string TruncarTexto(string texto, int maxLongitud)
{
if (string.IsNullOrEmpty(texto))
return "";
if (texto.Length <= maxLongitud)
return texto;
return texto.Substring(0, maxLongitud - 3) + "...";
}
}

// Propiedades directas (más simple)
string nombre = proyecto.ProjectName; // Acceso directo
// Properties (más flexible, más propiedades)
AnyPropertyId propId = new AnyPropertyId(Properties.Project.PROJ_COMPANYNAME);
string empresa = proyecto.Properties[propId].ToString();

Cuándo usar cada una:

  • Propiedades directas: Para datos básicos siempre disponibles
  • Properties: Para propiedades específicas de EPLAN, configurables
SelectionSet sel = new SelectionSet();
sel.LockSelectionByDefault = false; // No bloquear
  • true: Bloquea objetos al seleccionarlos (evita modificaciones)
  • false: No bloquea (solo lectura, más seguro para scripts)

Recomendación: Usa false para scripts de lectura/análisis.


En este capítulo aprendiste:

  • Atributo [Start]: Punto de entrada del script
  • Estructura de script: Template completo recomendado
  • Obtener proyecto: SelectionSet y GetSelectedProjects()
  • Leer propiedades: Directas y mediante Properties
  • Contar elementos: Páginas, funciones, dispositivos
  • Mostrar mensajes: BaseException con tres niveles
  • Manejo de errores: Específicos de EPLAN API
  • Proyecto completo: Validador inteligente funcional

Conceptos clave:

  • Todo script necesita [Start] para ejecutarse
  • SelectionSet es la forma estándar de obtener el proyecto actual
  • Siempre valida que el proyecto exista y sea válido
  • BaseException es la forma correcta de mostrar mensajes en EPLAN
  • Properties da acceso a configuraciones específicas de EPLAN

Capítulo 12: Arquitectura de EPLAN API

Capítulo 14: ActionCallingContext

En el próximo capítulo aprenderás a pasar parámetros a scripts, hacer scripts parametrizables desde la GUI de EPLAN, y crear herramientas más flexibles y reutilizables.


  • 📖 EPLAN API Documentation: EplanAPI.chm
  • 📖 Project Class: Sección DataModel
  • 📖 Properties: Lista completa de propiedades disponibles
  • 💻 Código completo: code/cap-13/

P: ¿Puedo tener múltiples métodos con [Start]?

Sección titulada «P: ¿Puedo tener múltiples métodos con [Start]?»

R: No. Solo puedes tener UN método [Start] por archivo de script. EPLAN no sabría cuál ejecutar.

P: ¿El método [Start] tiene que llamarse “Ejecutar”?

Sección titulada «P: ¿El método [Start] tiene que llamarse “Ejecutar”?»

R: No. Puede llamarse como quieras: Run(), Main(), Procesar(), etc. Lo importante es el atributo [Start].

R: GetSelectedProjects() devuelve un array vacío (Length == 0). Siempre valida esto antes de continuar.

P: ¿BaseException realmente lanza una excepción?

Sección titulada «P: ¿BaseException realmente lanza una excepción?»

R: No, es un nombre confuso. BaseException es solo la clase de EPLAN para mostrar mensajes. No lanza excepciones reales (de ahí FixMessage() para mostrarla).

P: ¿Puedo modificar el proyecto en un script?

Sección titulada «P: ¿Puedo modificar el proyecto en un script?»

R: Sí, pero debes tener cuidado. Este capítulo se enfoca en lectura. La modificación la veremos en capítulos posteriores.

R: EPLAN los compila automáticamente al ejecutarlos. Si hay errores de sintaxis, EPLAN lo indicará.


Antes de pasar al siguiente capítulo, asegúrate de:

  • Entender qué es [Start] y por qué es necesario
  • Poder obtener el proyecto actual con SelectionSet
  • Saber leer propiedades básicas (ProjectName, etc.)
  • Poder acceder a Properties con AnyPropertyId
  • Saber contar páginas, funciones y dispositivos
  • Usar BaseException para mostrar mensajes
  • Validar precondiciones antes de procesar
  • Haber ejecutado el ValidadorProyecto completo
  • (Opcional) Modificar el validador con tus propias mejoras

¡Felicitaciones! Has creado tu primer script EPLAN funcional completo. 🎉

Ya puedes leer información de proyectos, validar datos, y generar reportes profesionales.

¿Listo para hacer scripts parametrizables? ¡Vamos al Capítulo 14! 🚀


Última actualización: Enero 2025 Tiempo de lectura estimado: 70-80 minutos Código de ejemplo: code/cap-13/

Todos los scripts de este capítulo están disponibles en GitHub:

📥 Ver código en GitHub →

Los scripts son 100% funcionales y usan únicamente APIs gratuitas de EPLAN.


🔓 Desbloquea el Contenido Completo

¿Te gustó este capítulo? Hay 25 capítulos más esperándote con:

  • ✅ Scripts profesionales completos
  • ✅ Casos de estudio reales
  • ✅ Suite de automatización integrada
  • ✅ Ahorra 80-95% de tiempo en tareas repetitivas