Foros del Web » Programando para Internet » PHP »

Parsear fórmulas tipo Excel en PHP (preg_replace)

Estas en el tema de Parsear fórmulas tipo Excel en PHP (preg_replace) en el foro de PHP en Foros del Web. Buenas a todos y gracias por leer. Mi problema es el siguiente: en una aplicación de administración de sueldos tengo que tomar una fórmula estilo ...
  #1 (permalink)  
Antiguo 14/10/2009, 10:38
Avatar de dggluz  
Fecha de Ingreso: abril-2009
Ubicación: Buenos Aires, Argentina
Mensajes: 525
Antigüedad: 15 años
Puntos: 50
Parsear fórmulas tipo Excel en PHP (preg_replace)

Buenas a todos y gracias por leer. Mi problema es el siguiente: en una aplicación de administración de sueldos tengo que tomar una fórmula estilo función de MS Excel y procesarla. Por ejemplo: si los empleados tienen un plus por presentismo (supongamos que es un 10% de su sueldo, en caso de que hayan faltado menos de 5 veces), entonces el usuario ingresará (por formulario, u otra vía que no viene al caso) una fórmula que será similara a:
Código:
=SI(Ausentes<5; REDONDEAR(SueldoBase; 2); 0)
Mi idea era traducir la fórmula a PHP y luego calcularla con eval; sé que no es muy recomendable ejecutar con eval código ingresado por el usuario por temas de seguridad, pero en este caso eso no es problema.
Pensé hacer una función que se encargara del problema y resolverla con preg_replace, pero estoy teniendo algunos problemas:
Código PHP:
    function parseExcel($cadena='')
    {
        
// Acceso a las variables globales:
        
global $fResultado$mes$ano;
        
        
// Reemplazo de los alias por variables:
        
$cadena=str_replace("SueldoBase"$fResultado['sueldo'], $cadena);
        
$cadena=str_replace("DiasTrabajados"$fResultado['diasTrabajadosMes'], $cadena);
        
$cadena=str_replace("DiasMes"date("t"strtotime($ano."-".$mes."-1")), $cadena);
        
$cadena=str_replace("Ausentes"date("t"strtotime($ano."-".$mes."-1"))-$fResultado['diasTrabajadosMes'], $cadena);
        
        
// Reemplazo de las reglas;
        
$cadena=preg_replace("/[ ]*SI[ ]*\([ ]*([^\);]*?)[ ]*;[ ]*([^\);]*?)[ ]*;[ ]*([^\);]*?)[ ]*\)/miU""(\\1)?\\2:\\3"$cadena);
        
$cadena=preg_replace("/[ ]*REDONDEAR[ ]*\([ ]*([^\);]*?)[ ]*;[ ]*([^\);]*?)[ ]*\)/miU""round(\\1, \\2)"$cadena);

        
// Para que el = tenga sentido...
        
$cadena="\$aux".$cadena.";";

        
// Imprimimos la expresión para debug
//        echo $cadena."<br />";

        // Evalua la expresión y devuelve el resultado
        
eval($cadena);
        return 
$aux;
    } 
El problema es que no sé cómo hacer para que me reconozca bien algunas fórmulas, por ejemplo si le pongo:
Código:
=SI(Ausentes<5; REDONDEAR(SueldoBase; 2); 0)
, con la siguiente info:
Código PHP:
    $mes=10;
    
$ano=2009;
    
$fResultado=array(
                        
'sueldo'=>2555.35,
                        
'diasTrabajadosMes'=>28
    
); 
va a intentar ejecutar:
Código PHP:
$aux=(3<5)?round(2555.35 0.1:10); 
que es un código con errores sintácticos, cuando en realidad quiero que ejecute:
Código PHP:
$aux=(3<5)?round(2555.35 0.11):0
Tengan en cuenta que no siempre la consulta de afuera va a ser SI, el orden puede ser cualquiera.
Me parece que no vale la pena desarrollar un autómata para esta labor; también se me ocurrió intentar detectar los paréntesis e ir llamando la función (sería otra la función, obvio) recursivamente para justamente poder ordenar bien las funciones Excel anidadas. Sin embargo, quiero resolverlo con preg_replace ya que me parece lo más prolijo y no me gustan las funciones recursivas por el manejo que hacen en memoria. Intenté usando algunos modificadores, sobre todo PCRE_UNGREEDY (como está en el ejemplo que puse), pero no obtuve los resultados deseados.
¡Ayúdenme por favor! ¡Gracias!
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 16:50.