先上效果图如下:
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;width: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;width:680px;" readonly="readonly" runat="server"></textarea> 8 <input id="TextAreaFormulaCode" type="text" style="float:left;width:681px;" readonly="readonly" runat="server"/> 9 </td>10 </tr>11 <tr>12 <td style="width: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="width: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 try28 {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等来提供