先上效果图如下:
1、本公式自定义配置计算器的实现基于DataTable.Compute()的用法,该函数用法详细参考文档;本示例支持条件公式、计算公式的配置
2、界面样式
1 <style type="text/css"> 2 .p { 3 width: 40px; 4 height: 40px; 5 background-color: green; 6 border: 1px solid #0e0808; 7 float: left; 8 text-align: center; 9 line-height: 40px; 10 color: white; 11 font-weight: bold; 12 cursor: pointer; 13 } 14 .pblack { 15 width: 100px; 16 } 17 .param { 18 width: 90%; 19 height: 40px; 20 background-color: green; 21 border: 1px solid #0e0808; 22 float: left; 23 text-align: center; 24 line-height: 40px; 25 color: white; 26 font-weight: bold; 27 cursor: pointer; 28 } 29 </style>
3、界面脚本
1 <script type="text/javascript"> 2 3 var KeyList = new Array();//公式对外文本 4 var KeyValueList = new Array();//公司的对内编码 5 6 jQuery(document).ready(function () { 7 8 //选公式 9 jQuery(".p").click(function () { 10 11 jQuery("#TextAreaFormula").focus();//键 12 13 var inputText = jQuery(this).text();//键 14 var inputValue = jQuery(this).data("value");//值 15 16 //1、空格键 17 if (inputText.length == 0 || inputText == "") { 18 inputText = " "; 19 inputValue = " "; 20 } 21 22 //非数字键 23 if ("0123456789".indexOf(String(inputText)) < 0) { 24 if ("C←".indexOf(String(inputText)) >= 0) { 25 switch (String(inputText)) { 26 case "C"://清空键 27 KeyList = []; 28 KeyValueList = []; 29 30 jQuery("#TextAreaFormula").val(""); 31 jQuery("#TextAreaFormulaCode").val(""); 32 33 jQuery("#TextAreaFormula").focus(); 34 return; 35 break; 36 case "←"://退格键 37 //键 38 KeyList.pop(); 39 var strChanged = ""; 40 for (var i = 0; i < KeyList.length; i++) { 41 strChanged += String(KeyList[i]); 42 } 43 jQuery("#TextAreaFormula").val(strChanged.trimEnd()); 44 jQuery("#TextAreaFormula").focus(); 45 46 //值 47 KeyValueList.pop(); 48 var strvalueCharged = ""; 49 for (var i = 0; i < KeyValueList.length; i++) { 50 strvalueCharged += String(KeyValueList[i]); 51 } 52 jQuery("#TextAreaFormulaCode").val(strvalueCharged.trimEnd()); 53 return; 54 break; 55 //case "And": 56 // inputText = " " + "&&" + " "; 57 // inputValue = " " + "&&" + " "; 58 // break; 59 //case "Or": 60 // inputText = " " + "||" + " "; 61 // inputValue = " " + "||" + " "; 62 // break; 63 default: 64 break; 65 } 66 } 67 else if ("." == String(inputText)) { 68 69 } 70 else { //非清空退格小数点键的其他键 71 inputText = " " + inputText + " "; 72 inputValue = " " + inputValue + " "; 73 } 74 } 75 76 //数字和小数点-键 77 var HaveExistStr = jQuery("#TextAreaFormula").val(); 78 jQuery("#TextAreaFormula").val(HaveExistStr + inputText); 79 KeyList.push(inputText); 80 jQuery("#TextAreaFormula").focus(); 81 82 //数字和小数点-值 83 var HaveExistStrValue = jQuery("#TextAreaFormulaCode").val(); 84 jQuery("#TextAreaFormulaCode").val(HaveExistStrValue + inputValue); 85 KeyValueList.push(inputValue); 86 87 }); 88 89 //选参数 90 jQuery(".param").click(function () { 91 jQuery("#TextAreaFormula").focus(); 92 93 var inputText = jQuery(this).text(); 94 var inputValue = jQuery(this).data("value"); 95 inputText = " [" + inputText + "] "; 96 inputValue = " [" + inputValue + "] "; 97 98 var HaveExistStr = jQuery("#TextAreaFormula").val(); 99 jQuery("#TextAreaFormula").val(HaveExistStr.trimEnd() + inputText); 100 KeyList.push(inputText); 101 jQuery("#TextAreaFormula").focus(); 102 103 var HaveExistStrValue = jQuery("#TextAreaFormulaCode").val(); 104 jQuery("#TextAreaFormulaCode").val(HaveExistStrValue.trimEnd() + inputValue); 105 KeyValueList.push(inputValue); 106 107 }); 108 109 }); 110 111 //去除字符串尾部空格或指定字符 112 String.prototype.trimEnd = function (s) { 113 s = (s ? s : "\s"); 114 s = ("(" + s + ")"); 115 var reg_trimEnd = new RegExp(s + "*$", "g"); 116 return this.replace(reg_trimEnd, ""); 117 }; 118 119 120 </script>
4、界面HTML源码
1 <form id="form1" runat="server"> 2 3 <div style="float:left;90%;border:1px solid #ff0000;margin:5px;padding:20px;"> 4 <table> 5 <tr> 6 <td colspan="2"> 7 <textarea id="TextAreaFormula" cols="80" rows="2" style="float:left;680px;" readonly="readonly" runat="server"></textarea> 8 <input id="TextAreaFormulaCode" type="text" style="float:left;681px;" readonly="readonly" runat="server"/> 9 </td> 10 </tr> 11 <tr> 12 <td style="100px;vertical-align:top;"> 13 <div class="param" data-value="BasicSalary">基本工资</div> 14 <div class="param" data-value="OTDays">加班天数</div> 15 <div class="param" data-value="LengthOfService">工龄</div> 16 </td> 17 <td style="280px;"> 18 <div class="p" data-value="(">(</div><div class="p" data-value=")">)</div> 19 <div class="p" data-value="+">+</div><div class="p" data-value="-">-</div> 20 <div class="p" data-value="*">*</div><div class="p" data-value="/">/</div> 21 <div class="p" data-value="0">0</div><div class="p" data-value="1">1</div> 22 <div class="p" data-value="2">2</div><div class="p" data-value="3">3</div> 23 <div class="p" data-value="4">4</div><div class="p" data-value="5">5</div> 24 <div class="p" data-value="6">6</div><div class="p" data-value="7">7</div> 25 <div class="p" data-value="8">8</div><div class="p" data-value="9">9</div> 26 <div class="p" data-value=">">></div><div class="p" data-value=">=">>=</div> 27 <div class="p" data-value="=">=</div> 28 <div class="p" data-value="<"><</div><div class="p" data-value="<="><=</div> 29 <div class="p" data-value=".">.</div> 30 <div class="p" data-value="And">And</div> 31 <div class="p" data-value="Or">Or</div> 32 <div class="p pblack" data-value=""></div> 33 <div class="p" data-value="C">C</div> 34 <div class="p" data-value="←">←</div> 35 </td> 36 </tr> 37 <tr> 38 <td> 39 40 </td> 41 <td> 42 <table> 43 <tr> 44 <td>基本工资金额:</td> 45 <td> 46 <asp:TextBox ID="TextBoxBasicSalary" runat="server">2000</asp:TextBox> 47 </td> 48 </tr> 49 <tr> 50 <td>加班天数:</td> 51 <td><asp:TextBox ID="TextBoxOTDays" runat="server">20</asp:TextBox></td> 52 </tr> 53 <tr> 54 <td>工龄(年):</td> 55 <td><asp:TextBox ID="TextBoxLengthOfService" runat="server">10</asp:TextBox></td> 56 </tr> 57 <tr> 58 <td colspan="2"> 59 <asp:Button ID="Button1" runat="server" Text="配置公式→输入参数值→计算公式的结果" OnClick="Button1_Click" /> 60 </td> 61 </tr> 62 </table> 63 64 <br/> 65 66 <br/> 67 68 <br/> 69 70 </td> 71 </tr> 72 </table> 73 </div> 74 </form>
5、后台代码
1 /// <summary> 2 /// 计算 3 /// </summary> 4 public class ParamModel { 5 6 /// <summary> 7 /// 基本工资 8 /// </summary> 9 public decimal BasicSalary { get; set; } 10 11 /// <summary> 12 /// 加班天数 13 /// </summary> 14 public decimal OTDays { get; set; } 15 16 /// <summary> 17 /// 工龄 18 /// </summary> 19 public decimal LengthOfService { get; set; } 20 21 //还可继续扩充,也可以考虑使用动态类 22 }
1 /// <summary> 2 /// 实例源码 3 /// </summary> 4 /// <param name="sender"></param> 5 /// <param name="e"></param> 6 protected void Button1_Click(object sender, EventArgs e) 7 { 8 var ParamModel = new ParamModel(); 9 ParamModel.BasicSalary = Convert.ToDecimal(this.TextBoxBasicSalary.Text ?? "0"); 10 ParamModel.OTDays = Convert.ToDecimal(this.TextBoxOTDays.Text ?? "0"); 11 ParamModel.LengthOfService = Convert.ToDecimal(this.TextBoxLengthOfService.Text ?? "0"); 12 13 14 DataTable eval = new DataTable(); 15 var formulaText = this.TextAreaFormulaCode.Value;//公式 16 var Str = formulaText; 17 var StrParam = string.Empty; 18 foreach (var PropertyInfo in ParamModel.GetType().GetProperties()) 19 { 20 if (formulaText.IndexOf("[" + PropertyInfo.Name + "]") >= 0) 21 { 22 Str = Str.Replace(("[" + PropertyInfo.Name + "]"), "(" + PropertyInfo.GetValue(ParamModel, null).ToString() + ")");//将表达式中的参数Code替换为实际的值 23 StrParam += string.Format("[{0}]={1},", PropertyInfo.Name, PropertyInfo.GetValue(ParamModel, null).ToString());//表达式中各参数的值 24 } 25 } 26 object result = null; 27 try 28 { 29 result = eval.Compute(Str, "");//文本表达式的运行结果 30 } 31 catch(Exception ex) 32 { 33 Response.Write("公式配置有误,请重新配置!具体错误:" + ex.Message+"<br/>"); 34 return; 35 } 36 StrParam = StrParam.TrimEnd(',');//各参数的值 37 Response.Write(string.Format( 38 "公式含义:{4}<br/>" 39 + "公式编码:{0}<br/>" 40 + "参数取值:<br/>" 41 + "{3}<br/>" 42 + "公式解析:{1} <br/>" 43 + "计算结果:{2}<br/>", 44 formulaText, 45 Str, 46 Convert.ToString(result), 47 StrParam, 48 this.TextAreaFormula.Value)); 49 50 }
6、扩展
在此基础上可以进一步发挥的空间很大
》结合存储设计如数据库等,参数可以动态加载参数;
》诸如参数自定义,自定义的参数再次被用作新参数的配置,参数嵌套使用,可以配置出强大而复杂的计算公式以及条件公式
》结合存储设计再结合C#的动态类,可以使得参数对应的类也动态化;
》当然简单级别的计算并不完全需要面向对象的类的设计,完全使用存储设计,所有参数可以完全依赖如数据库或其他存储方式如XML等来提供