web报表页面及json数据公式解析计算器

前一段时间,为了满足公司的web报表系统的需求,利用javascript开发了一个自定义公式解析计算器。开发人员可以根据一定规则,自定义web页面元素或者json字段之间的公式关系,实现算术运算和一些逻辑运算。

 

另外,还对页面的输入,数据的有效位数等进行了处理,每个数据字段的有效位数,开发人员都可以自定义。

 

该公式解析计算器的具体使用的例子,在我另外一篇博客文章中(http://huangyuanmu.iteye.com/admin/blogs/469180),有兴趣的话,可以看看。

 

下边给出具体实现代码:

/**
 *  模拟java的包,或者C#中的命名空间的概念
 * */
var tohot = tohot ? tohot : {};
tohot.commons = tohot.commons ? tohot.commons : {};
tohot.commons.declaration = tohot.commons.declaration ? tohot.commons.declaration : {};
/**
 * 报表公式计算器实现
 */
var tohotCalculator = tohot.commons.declaration.ExpressionCalculator = tohot.commons.declaration.ExpressionCalculator ? tohot.commons.declaration.ExpressionCalculator : {

	description : "通用web报表公式解析计算器,根据自定义的报表计算公式,自动进行公式解析和报表数据计算,操作web报表页面数据和json数据。",
	author : "huangyuanmu",
	version : "1.0(2009-07-29)",

	report : {},

	// 根据公式,获取计算以后的值
	getValue : function(report,formular_str,dataType)
	{

		// 解析公式
		function _parseFormular() {
			if (mathing_begin)
	          {
	            mathing_str += formular_str.substr(i,1);
	            return true;
	          }
	          else
	          {
	            if (IsVar)
	            {
	              formular_str_ana += ")";
	              CurVar_Length += ")".length;
	              //判断当前的变量的值是否为空
	              tmpEl = eval(formular_str_ana.substr(CurVar_start,CurVar_Length));
	              if (isNaN(tmpEl))
	              {
	                formular_str_ana = formular_str_ana.substr(0,CurVar_start);
	                formular_str_ana += "0";
	              }
	            }
	            formular_str_ana += formular_str.substr(i,1);
	            IsVar = false;
	            return true;
	          }
	          return false;
		}

	    var formular_str_ana;
	    var returnValue;
	    var IsVar;   //表示该处的字符表示变量
	    var CurVar_start,CurVar_Length;   //表示当前的变量型字符串
	    var mathing_begin = false;   //字符串的匹配操作是否开始
	    var mathing_str = "";  //接受并解析匹配字符串
	    returnValue = 0;
	    IsVar = false;
	    var el_chang  =  "report.";
	    formular_str_ana = "";

	    if(dataType == null){
	    	dataType = "2";
	    }

	    for (i = 0;i<formular_str.length;i++)
	    {
	      switch(formular_str.substr(i,1))
	      {
	        case "$":
	        {
	          if (mathing_begin)
	          {
	            mathing_str += formular_str.substr(i,1);
	            break;
	          }
	          else
	          {
	            //变量的开始
	            CurVar_start = formular_str_ana.length;
	            formular_str_ana +=  "parseFloat("  + el_chang;
	            CurVar_Length = ("parseFloat(" + el_chang).length;
	            IsVar = true;
	            break;
	          }
	        }
	        case "@":
	        {
	          //匹配字符串的解释
	          if (mathing_begin)
	          {
	            //匹配字符串结束
	            mathing_begin = false;
	            mathing_str_arr = mathing_str.split(";");
	            formular_str_ana += "/^" + mathing_str_arr[0] + "$/i.test(";
	            if (mathing_str_arr[1].substr(0,1)  == "$")
	            {
	              formular_str_ana += "report" + "." + mathing_str_arr[1].substr(1,mathing_str_arr[1].length-1) + ")";
	            }
	            else
	            {
	              //非变量
	              formular_str_ana += "'" + mathing_str_arr[1].substr(0,mathing_str_arr[1].length) + "')";
	            }
	          }
	          else
	          {
	            //匹配字符串开始
	            mathing_begin = true;
	            mathing_str = "";
	          }
	          break;
	        }
	        case "+":
	        {
				if(_parseFormular()) {
					break;
				}
	        }
	        case "-":
	        {
	          if(_parseFormular()) {
					break;
				}
	        }
	        case "*":
	        {
	          if(_parseFormular()) {
					break;
				}
	        }
	        case "/":
	        {
	          if(_parseFormular()) {
					break;
				}
	        }
	        case "%":
	        {
	          if(_parseFormular()) {
					break;
				}
	        }
	        case ")":
	        {
	          if(_parseFormular()) {
					break;
				}
	        }
	        case "?":
	        {
	          if(_parseFormular()) {
					break;
				}
	        }
	        case ":":
	        {
	          if(_parseFormular()) {
					break;
				}
	        }
	        case "<":
	        {
	          if(_parseFormular()) {
					break;
				}
	        }
	        case "=":
	        {
	          if(_parseFormular()) {
					break;
				}
	        }
	        case ">":
	        {
	          if(_parseFormular()) {
					break;
				}
	        }
	        case "!":
	        {
	          if(_parseFormular()) {
					break;
				}
	        }
	        case "|":
	        {
	          if(_parseFormular()) {
					break;
				}
	        }
	        case "&":
	        {
	          if(_parseFormular()) {
					break;
				}
	        }
	        default:
	        {
	          if (mathing_begin)
	          {
	            mathing_str += formular_str.substr(i,1);
	            break;
	          }
	          else
	          {
	            if (IsVar)
	            {
	              CurVar_Length++;
	            }
	            formular_str_ana += formular_str.substr(i,1);
	          }
	        }
	      }
	    }
	    if (IsVar)
	    {
	      formular_str_ana += ")";
	      CurVar_Length += ")".length;
	      //判断当前的变量的值是否为空
	      tmpEl = eval(formular_str_ana.substr(CurVar_start,CurVar_Length));
	      if (isNaN(tmpEl))
	      {
	        formular_str_ana = formular_str_ana.substr(0,CurVar_start);
	        formular_str_ana += "0";
	      }
	      IsVar = false;
	    }
	    if (mathing_begin)
	    {
	      //匹配字符串结束
	      mathing_begin = false;
	      mathing_str_arr = mathing_str.split(",");
	      formular_str_ana += "/" + mathing_str_arr[0] + "/i.test(";
	      if (mathing_str_arr[1].substr(0,1) == "$")
	      {
	        formular_str_ana += "report" + "." + mathing_str_arr[1].substr(1,mathing_str_arr[1].length-1) + ")";
	      }
	      else
	      {
	        //非变量
	        formular_str_ana += "'" + mathing_str_arr[1].substr(0,mathing_str_arr[1].length) + "')";
	      }
	    }
	    returnValue = eval(formular_str_ana);
	    // 如果公式计算的值小于0.005,则认为为零
	    if (Math.abs((returnValue - 0.00))<0.005)
	    {
	    	returnValue = tohotCalculator.formatData("0",dataType);
	    }else{
			returnValue = tohotCalculator.formatData(returnValue + "",dataType);
	    }
	    return returnValue;
	},

	// 格式化整数
	formatInteger: function (IntegerStr){
	    //获取字符串的长度和首字符和次字符,然后进行判断
	    var strLen = IntegerStr.length;
	    var firstStr = IntegerStr.substr(0,1);
	    var secondStr = IntegerStr.substr(1,1);
	    var tmpStr = IntegerStr;
	    //针对正数的处理
	    if(firstStr != "-"){
	      if ((firstStr == "0") && (strLen > 1)){
	        tmpStr = tmpStr.substr(1,strLen-1);
	        tmpStr = tohotCalculator.formatInteger(tmpStr);
	      }
	    }
	    else{
	      //负数的处理
	      if((secondStr == "0") && (strLen > 2)){
	        tmpStr = "-" + tmpStr.substr(2,strLen-2);
	        tmpStr = tohotCalculator.formatInteger(tmpStr);
	      }
	    }
	    return tmpStr;
	},

	 // 格式化浮点数
	 formatFloat: function (FloatStr){
	    //将字符串组合成整数部分和小数部分
	    var FloatStrArr = FloatStr.split(".");
	    var Integer_part = FloatStrArr[0];
	    var Float_part = FloatStrArr[1];
	    var FloatPartLen = Float_part.length;
	    //处理整数部分
	    if((Integer_part == "-") || (Integer_part == "")){
	      Integer_part += "0";
	    }
	    Integer_part = tohotCalculator.formatInteger(Integer_part);
	    //处理小数部分
	    if(FloatPartLen == 0){
	      Float_part += "00";
	    }
	    else{
	      if(FloatPartLen == 1){
	        Float_part += "0";
	      }
	    }
	    //合并
	    return (Integer_part + "." + Float_part);
	},

	// 数据验证,并设置json对象元素的值
	formatData: function (DataStr,DataType){
		var returnValue = "0.00";
		var IntegerCode,FloatCode;//数字的整数验证码和小数验证码
	    IntegerCode = /^[-]?[0-9]+$/i; //整数
	    FloatCode = /^[-]?[0-9]*[.][0-9]+$/i;
	    //整数
	    if (DataStr != ""){
			    if(DataType == "1")
			    {
			      if (DataStr.match(IntegerCode) == null)
			      {
			        if ((DataStr.match(FloatCode) == null))
			           {
			           	 returnValue = "0";
			           }
			           else{
			           	 var reVal = parseFloat(tohotCalculator.formatFloat(DataStr));
			             returnValue = ""+reVal.toFixed(0);
			           }
			      }
			      else{
			        returnValue = tohotCalculator.formatInteger(DataStr);
			      }
			    }
			    else if((DataType == "2") || (DataType == "3") || (DataType == "4"))
			         {
			          if (DataStr.match(IntegerCode) == null)
			     		 {
				           if ((DataStr.match(FloatCode) == null))
				           {
				           	 if(DataType == "2")
			     	   			returnValue = "0.00";
			     	   		if(DataType == "3")
			     	   			returnValue = "0.0000";
			     	   		if(DataType == "4")
			     	   			returnValue = "0.000000";
				           }
				           else{
				           	 var reVal = parseFloat(tohotCalculator.formatFloat(DataStr));
				             returnValue = reVal.toFixed(parseInt(DataType)+ (parseInt(DataType) - 2));
				           }
				         }
						else{
							if(DataType == "2")
			     	   			returnValue = tohotCalculator.formatInteger(DataStr + ".00");
			     	   		if(DataType == "3")
			     	   			returnValue = tohotCalculator.formatInteger(DataStr + ".0000");
			     	   		if(DataType == "4")
			     	   			returnValue = tohotCalculator.formatInteger(DataStr + ".000000");
			     		 }
			     	}else{
				           returnValue = "0.00";
				         }

	    }else{
	    	if(DataType == "1"){
	    	  	returnValue = "0";
	    	}else if(DataType == "2"){
			    returnValue = "0.00";
		   	}else if(DataType == "3"){
		   		returnValue = "0.0000";
		   	}else if(DataType == "4"){
		   		returnValue = "0.000000";
		   	}else{
		   		 returnValue = "0.00";
		   	}
	    }
	    return returnValue;
	},

	doCalculateFormular : function (formular) {

		var formualr_is_arr = /[,]/i;

		//解析公式
	      if (formular.match(formualr_is_arr) == null)
	      {
	        //单个公式
	        each_formular_arr = formular.split("^");
	        // 解析目标json值的有效位数
		    var targetArray = each_formular_arr[1].split("#");
	        // 设置报表json对象的值
	        var value = tohotCalculator.getValue(tohotCalculator.report,targetArray[0],targetArray[1]);
	        eval("tohotCalculator.report." + each_formular_arr[0] + "=value");
			// 设置页面元素的值
	        var el = eval(each_formular_arr[0]);
	    	el.value = value;
	      }
	      else
	      {
	        //公式数组
	        all_formular_arr = formular.split(",");
	        for (k=0;k<all_formular_arr.length;k++)
	        {
	          //单个公式
	          	each_formular_arr = all_formular_arr[k].split("^");
	          	// 解析目标json值的有效位数
		    	var targetArray = each_formular_arr[1].split("#");
	        	// 设置报表json对象的值
	        	var value = tohotCalculator.getValue(tohotCalculator.report,targetArray[0],targetArray[1]);
		        eval("tohotCalculator.report." + each_formular_arr[0] + "=value");
				// 设置页面元素的值
		        var el = eval(each_formular_arr[0]);
		    	el.value = value;
	        }
	      }
	},

	// 计算整个json报表对象,在保存报表的时候调用
	doCalculateJson : function (reportFormular) {

		_calculatorJson(reportFormular);

		// 计算报表json对象的公式触发
		function _calculatorJson(reportFormular) {
			var EachArrStr = "";
		    var FoumularArr; //公式数组
		    var formualr_is_arr = /[,]/i;
		    var e1;

			//解析公式
			for(key in reportFormular){
				formular = reportFormular[key];
				if (formular.match(formualr_is_arr) == null)
				{
				    //单个公式
					each_formular_arr = formular.split("^");
					// 解析目标json值的有效位数
		        	var targetArray = each_formular_arr[1].split("#");
					var value = tohotCalculator.getValue(tohotCalculator.report,targetArray[0],targetArray[1]);
					eval("tohotCalculator.report." + each_formular_arr[0] + "=value");
				}
				else
				{
				    //公式数组
					all_formular_arr = formular.split(",");
					for (k=0;k<all_formular_arr.length;k++)
					{
					  	//单个公式
					  	each_formular_arr = all_formular_arr[k].split("^");
					  	// 解析目标json值的有效位数
		        		var targetArray = each_formular_arr[1].split("#");
						var value = tohotCalculator.getValue(tohotCalculator.report,targetArray[0],targetArray[1]);
					 	eval("tohotCalculator.report." + each_formular_arr[0] + "=value");
					}
				}
			}
		}
	},

	// 根据公式计算当前页面的表单元素的值,在页面onblur事件的时候调用
	doCalculateCurr : function (cur_el_name,el_value,formular,DataType){

		_calculatorCurr(cur_el_name,el_value,formular,DataType);

		// 计算当前页面的公式触发
		function _calculatorCurr(cur_el_name,el_value,formular,DataType)
		{
		    var EachArrStr = "";
		    var FoumularArr; //公式数组
		    var formualr_is_arr = /[,]/i;
		    var e1;
		    if(_dataAuth(cur_el_name,el_value,DataType))
		    {
		      //解析公式
		      if (formular.match(formualr_is_arr) == null)
		      {
		        //单个公式
		        each_formular_arr = formular.split("^");

		        // 解析目标单元格的有效位数
		        var targetArray = each_formular_arr[1].split("#");

		        // 设置报表json对象的值
			    var form_el_value = tohotCalculator.formatData(el_value,DataType);
			    eval("tohotCalculator.report." + cur_el_name + "=form_el_value");

		        var value = tohotCalculator.getValue(tohotCalculator.report,targetArray[0],targetArray[1]);
		        eval("tohotCalculator.report." + each_formular_arr[0] + "=value");
				// 设置页面元素的值
		        var el = eval(each_formular_arr[0]);
		    	el.value = value;
		      }
		      else
		      {
		        //公式数组
		        all_formular_arr=formular.split(",");
		        for (k=0;k<all_formular_arr.length;k++)
		        {
		          //单个公式
		          	each_formular_arr = all_formular_arr[k].split("^");

		          	// 解析目标单元格的有效位数
		        	var targetArray = each_formular_arr[1].split("#");

		          	// 设置报表json对象的值
			        var form_el_value = tohotCalculator.formatData(el_value,DataType);
			    	eval("tohotCalculator.report." + cur_el_name + "=form_el_value");

			        var value = tohotCalculator.getValue(tohotCalculator.report,targetArray[0],targetArray[1]);
			        eval("tohotCalculator.report." + each_formular_arr[0] + "=value");
					// 设置页面元素的值
			        var el = eval(each_formular_arr[0]);
			    	el.value = value;
		        }
		      }
		    }
		}

		// 数据验证,并设置页面元素的值
		function _dataAuth(DataStr_el_name,DataStr,DataType){
			var DataStr_el = eval(DataStr_el_name);
			DataStr_el.value = tohotCalculator.formatData(DataStr,DataType);
		    return true;
		}
	}
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值