datatable.compute计算表达式

喜欢而已 提交于 2019-12-06 08:21:51
运输费用公式定义:
 
支持iif()函数,向上取整函数
提供对外计算方法
用到,winform控件,datatable.compute,string字符串操作。
界面如下

 

using Genersoft.Drp.Common;
using Genersoft.Drp.LS.Control;
using Genersoft.Drp.TP.Client;

using Genersoft.GS.Public.Biz.Client;
using Genersoft.GS.Public.Biz.Control;
using Genersoft.GS.Public.Focus.GuiControl;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace Genersoft.Drp.TP.Control.BaseData
{
    public partial class TspExpenseformulaForm : Form
    {
        //计算表达式参数名称显示
        public string vsCostsFormulaName = "";
        //计算表达式参数编号显示
        public string vsCostsFormula = "";
        public TspExpenseformulaForm()
        {
            PubFunctionControlLS.InitForm(this, InitializeComponent);
            PubFunctionControlLS.AdjustSkin(this, true);
        }

        private Dictionary<string, string> dictParams = new Dictionary<string, string>();
        private void TspExpenseformulaForm_Load(object sender, EventArgs e)
        {

            this.txtFormula.Text = vsCostsFormulaName;
            //设置行变色
            this.dgvParams.RowsDefaultCellStyle.BackColor = Color.Bisque;
            this.dgvParams.AlternatingRowsDefaultCellStyle.BackColor = Color.Beige;

            this.dgvFunc.RowsDefaultCellStyle.BackColor = Color.Bisque;
            this.dgvFunc.AlternatingRowsDefaultCellStyle.BackColor = Color.Beige;

            this.dgvFunc.AllowUserToAddRows = false;

            this.FormBorderStyle = FormBorderStyle.FixedDialog;
            //this.dgvParams.AllowUserToAddRows = false;去掉最后一行空白行
            //this.dgvParams.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.AllCells;设置自适应列宽
            //加载函数
            DgvFuncLoad();
            //加载参数
            DgvParamsLoad();

        }

        private void DgvParamsLoad()
        {
            //取自定义项
            //DataSet dsDisplay = TspCostsFormulaClient.Current.GetTspTaskBillsCustomFields("TspTaskBills", "TspTaskBills");//统计依据表头表体自定义项部分

            DataTable dtcus = PubFunctionClient.GetService(null).GetCustomFieldInfo("TspTaskBills", "TspTaskBills", " IsDeleted='0' ");
            this.dgvParams.Columns.Add("ParamCode", "字段语义化");
            this.dgvParams.Columns.Add("ParamName","参数名称");
            this.dgvParams.Columns["ParamCode"].Visible = false;
            this.dgvParams.Rows.Add("TspTaskBills.BaseTspCost", "基本运费");
            this.dgvParams.Rows.Add("TspTaskBills.BaseTspPrice", "基本单价");
            this.dgvParams.Rows.Add("TspTaskBills.TotalQuantity", "运输任务总数量");
            this.dgvParams.Rows.Add("TspTaskBills.TotalTransGrWeight", "运输任务总重量");
            this.dgvParams.Rows.Add("TspTaskBills.TotalTransVolume", "运输任务总体积");
            dictParams.Add("基本运费", "TspTaskBills.BaseTspCost");
            dictParams.Add("基本单价", "TspTaskBills.BaseTspPrice");
            dictParams.Add("运输任务总数量", "TspTaskBills.TotalQuantity");
            dictParams.Add("运输任务总重量", "TspTaskBills.TotalTransGrWeight");
            dictParams.Add("运输任务总体积", "TspTaskBills.TotalTransVolume");

            foreach (DataRow dr in dtcus.Rows)
            {
                this.dgvParams.Rows.Add(string.Format("TspTaskBills.{0}", dr["FieldName"]), string.Format(@"运输任务{0}", dr["DisplayName"]));

                dictParams.Add(string.Format(@"运输任务{0}", dr["DisplayName"]), string.Format("TspTaskBills.{0}", dr["FieldName"]));
            }





        }

        private void DgvFuncLoad()
        {
            this.dgvFunc.Columns.Add("FuncName", "名称");
            this.dgvFunc.Rows.Add("IIF( , , )");
            this.dgvFunc.Rows.Add("向上取整{ }");
            //this.dgvFunc.Rows.Add("Sum( , )");
            //this.dgvFunc.Rows.Add("Avg( )");
            //this.dgvFunc.Rows.Add("Min( )");
            //this.dgvFunc.Rows.Add("Max( )");


        }
        private void ClearToolStripMenuItem_Click(object sender, EventArgs e)
        {
            
            this.txtFormula.Clear();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnMath_Click(object sender, EventArgs e)
        {
            
            Button btn = (Button)sender;
            txtFormula.SelectedText=btn.Text;
            //txtFormula.Text = this.txtFormula.Text.Insert();

        }

        /// <summary>
        /// 确定
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SureToolStripMenuItem_Click(object sender, EventArgs e)
        {
          
            ReplaceParams();
            //替换参数
            string checkResult = this.CheckCostFormula();
            if(checkResult=="1")
            {
                DialogResult = DialogResult.OK;
                this.Close();
            }
        }
        private void ReplaceParams()
        {
            this.vsCostsFormula = this.txtFormula.Text;
            this.vsCostsFormulaName = this.txtFormula.Text;
            //string all = @"这是一段测试数据[我们100]这是一段测试数据[你们200]这是一段测试数据[他们100 谁们300]";
            Regex reg = new Regex(@"\[(.+?)]");
      
            foreach (Match m in reg.Matches(this.vsCostsFormula))
            {

                if (dictParams.Keys.Contains(m.Groups[1].ToString()))
                {
                    this.vsCostsFormula = this.vsCostsFormula.Replace(m.Groups[1].ToString(), dictParams[m.Groups[1].ToString()]);
                }
            }

            this.vsCostsFormula = this.vsCostsFormula.Replace("编号", "");
            this.vsCostsFormula = this.vsCostsFormula.Replace("内码", "");
            this.vsCostsFormula = this.vsCostsFormula.ToUpper();
            //获取[]中的参数名称



        }


        private void DgvParams_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            
           txtFormula.SelectedText =string.Format(@"[{0}]", Convert.ToString(this.dgvParams.Rows[e.RowIndex].Cells["ParamName"].Value)); 
        }

        private void DgvFunc_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {

            txtFormula.SelectedText =Convert.ToString(this.dgvFunc.Rows[e.RowIndex].Cells["FuncName"].Value);


        }

        private void CheckToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.ReplaceParams();

            this.CheckCostFormula();



        }
       /// <summary>
       /// 校验
       /// </summary>
       /// <returns></returns>
        private string CheckCostFormula()
        {
            string strExpress = "";
            //服务端校验
            //this.GetTspCostsFormulaResult();

            try
            {
                strExpress = Convert.ToString(this.vsCostsFormula);
          


                if (PubFunctionDrp.IsStringEmpty(strExpress))
                {
                    this.txtFormula.Focus();
                    MessageBoxEx.Show("计算表达式不能为空!");
                    return "0";
                }
              
                if (strExpress.Contains("]["))
                {
                    MessageBox.Show("存在相邻的数据列之间没有运算符,请检查!");
                    return "0";
                }
                //先赋值
                List<string> listParams = dictParams.Values.ToList();

                foreach (string strParam in listParams)
                {
                    strExpress = strExpress.Replace(strParam.ToUpper(), "1.33");
                }

                if (strExpress.Contains("向上取整"))
                {
                    //拿出向上取整的整个表达式

                    strExpress= this.CellingFuncCompute(strExpress);


                }            
 
                #region
                //如果表达式中包含聚合函数,则替换为ID和Value列,验证聚合函数是否正确
                //if (strExpress.Contains("SUM") || strExpress.Contains("COUNT") || strExpress.Contains("MIN")
                //        || strExpress.Contains("MAX") || strExpress.Contains("AVG") || strExpress.Contains("ROUND")
                //        || strExpress.Contains("POWER"))
                //    {
                //        dt.Columns.Add("ID", typeof(string));
                //        dt.Columns.Add("Value", typeof(decimal));

                //        strExpress = strExpress.Replace("SUM('1')", "Sum(ID)");
                //        strExpress = strExpress.Replace("COUNT('1')", "Count(ID)");
                //        strExpress = strExpress.Replace("MIN('1')", "Min(ID)");
                //        strExpress = strExpress.Replace("MAX('1')", "Max(ID)");
                //        strExpress = strExpress.Replace("AVG('1')", "Avg(ID)");
                //        strExpress = strExpress.Replace("ROUND('1')", "Round(ID)");

                //        strExpress = strExpress.Replace("SUM(1)", "Sum(Value)");
                //        strExpress = strExpress.Replace("COUNT(1)", "Count(Value)");
                //        strExpress = strExpress.Replace("MIN(1)", "Min(Value)");
                //        strExpress = strExpress.Replace("MAX(1)", "Max(Value)");
                //        strExpress = strExpress.Replace("AVG(1)", "Avg(Value)");
                //        strExpress = strExpress.Replace("ROUND('1')", "Round(Value)");


                //        if (strExpress.Contains("IIF"))
                //        {
                //            strExpress = strExpress.Replace("SUM(ID)", "'1'");
                //            strExpress = strExpress.Replace("COUNT(ID)", "'1'");
                //            strExpress = strExpress.Replace("MIN(ID)", "'1'");
                //            strExpress = strExpress.Replace("MAX(ID)", "'1'");
                //            strExpress = strExpress.Replace("AVG(ID)", "'1'");
                //            strExpress = strExpress.Replace("ROUND(ID)", "'1'");

                //            strExpress = strExpress.Replace("SUM(Value)", "1");
                //            strExpress = strExpress.Replace("COUNT(Value)", "1");
                //            strExpress = strExpress.Replace("MIN(Value)", "1");
                //            strExpress = strExpress.Replace("MAX(Value)", "1");
                //            strExpress = strExpress.Replace("AVG(Value)", "1");
                //            strExpress = strExpress.Replace("ROUND(Value)", "1");
                //        }
                //    }
                //int MaxCount = 0;
                //while (strExpress.Contains("ROUND"))
                //{
                //    var mx = Regex.Matches(strExpress, "ROUND\\([0-9]+[.]?[0-9]*,[0-9]+[.]?[0-9]*\\)", RegexOptions.IgnoreCase);
                //    if (mx != null && mx.Count > 0)
                //    {
                //        strExpress = strExpress.Replace(mx[0].Value, "1");
                //    }
                //    else
                //    {
                //        MaxCount++;
                //    }
                //    if (MaxCount >= 50)
                //    {
                //        MessageBoxEx.Show("Round函数校验不通过,请检查!");
                //    return;
                //    }
                //}
                //MaxCount = 0;
                //while (strExpress.Contains("POWER"))
                //{
                //    var mx = Regex.Matches(strExpress, "POWER\\([0-9]+[.]?[0-9]*,[0-9]+[.]?[0-9]*\\)", RegexOptions.IgnoreCase);
                //    if (mx != null && mx.Count > 0)
                //    {
                //        strExpress = strExpress.Replace(mx[0].Value, "1");
                //    }
                //    else
                //    {
                //        MaxCount++;
                //    }
                //    if (MaxCount >= 50)
                //    {
                //        MessageBoxEx.Show("Power函数校验不通过,请检查!");
                //    }
                //}
                #endregion
                //如果抛出异常,则计算表达式验证失败,否则验证成功

                DatableComputeFunc(strExpress);

                MessageBoxEx.Show("校验成功!");
                //MessageBoxEx.Show("校验成功!");

                return "1";

            }
      
            catch (Exception ex)
            {
                MessageBoxEx.Show("校验失败"+ex);
                return "0";
            }
        }


        private string CellingFuncCompute(string strExpress)
        {
            int idxStart = 0;//开始位置索引
            int idxEnd = 0;//结束位置索引
            string strMathCelling = "";//向上取整表达式
            int count = Regex.Matches(strExpress, "向上取整").Count;
            int count1 = 0;
            for (int i = 0; i < count; i++)
            {

                idxStart = strExpress.IndexOf("向上取整");
                if (idxStart == -1)
                {
                    break;
                }

                idxEnd = strExpress.IndexOf("}", idxStart);
                strMathCelling = strExpress.Substring(idxStart, idxEnd - idxStart + 1);
                count1 = Regex.Matches(strMathCelling, "向上取整").Count - 1;
                if (count1 > 0)
                {

                    for (int j = count1; j > 0; j--)
                    {
                        idxStart = strMathCelling.IndexOf("向上取整");
                        if (idxStart == -1)
                        {
                            break;
                        }
                        idxStart = strMathCelling.IndexOf("{", idxStart);

                        idxEnd = strMathCelling.IndexOf("}", idxStart);
                        strMathCelling = strMathCelling.Substring(idxStart + 1, idxEnd - idxStart);
                        continue;
                    }



                }
                //strExpress = strExpress.Replace(strCelling, "向上取整i");

                string result = DatableComputeFunc(strMathCelling.Replace("向上取整", ""));

                strExpress = strExpress.Replace(strMathCelling, Convert.ToString(Math.Ceiling(Convert.ToDecimal(result))));
                //计算



            }

            return strExpress;

        }

        private string DatableComputeFunc(string strExpress)
        {
            //如果表达式中包含聚合函数,则判断使用聚合函数的数据列,是否是本表单的
            if (strExpress.Contains("IIF") || strExpress.Contains("Sum") || strExpress.Contains("Count")
                || strExpress.Contains("Min") || strExpress.Contains("Max") || strExpress.Contains("Avg")
                || strExpress.Contains("Power") || strExpress.Contains("Round"))
            {
                strExpress = strExpress.Replace("{", "");
                strExpress = strExpress.Replace("}", "");
                strExpress = strExpress.Replace("@", "");

                string[] computeS = new string[] { "IIF", "Sum", "Count", "Min", "Max", "Avg", "Power", "Round" };

                string strTemp = strExpress;
                for (int i = 0; i < computeS.Length; i++)
                {
                    if (strExpress.Contains(computeS[i].ToString()))
                    {
                        strTemp = strTemp.Replace(computeS[i].ToString(), "#");
                    }
                }

                string[] tempSS = strTemp.Split('#');

                for (int i = 1; i < tempSS.Length; i++)
                {
                    strTemp = tempSS[i];

                    Match match = Regex.Match(strTemp, "\\[[^\\]]*\\]"); //匹配字段
                    string tableName = match.Value.ToString();
                    //校验列

                }
            }







            DataTable dt = new DataTable();
            //如果包含多个'',替换为'。如果包含%',替换为%。
            if (strExpress.Contains("''"))
            {
                strExpress = strExpress.Replace("''", "'");
            }
            if (strExpress.Contains("%'"))
            {
                strExpress = strExpress.Replace("%'", "%");
            }
            if (strExpress.Contains("{"))
            {
                strExpress = strExpress.Replace("{", "");
            }
            if (strExpress.Contains("}"))
            {
                strExpress = strExpress.Replace("}", "");
            }

            if (strExpress.Contains("["))
            {
                strExpress = strExpress.Replace("[", "");
            }
            if (strExpress.Contains("]"))
            {
                strExpress = strExpress.Replace("]", "");
            }

            strExpress = strExpress.ToUpper();
            object test = dt.Compute(strExpress, "");
            return Convert.ToString(test);
        }


        private void GetTspCostsFormulaResult()
        {
            DataSet dataSet = new DataSet();

            DataTable dataTable = new DataTable();
            dataTable.TableName = "TspTaskBills";
            dataTable.Columns.Add("TspOrgID");
            dataTable.Columns.Add("VendorID");
            dataTable.Columns.Add("TspTypeID");
            dataTable.Columns.Add("CostsID");
            dataTable.Columns.Add("TotalQuantity");
            dataTable.Columns.Add("TotalTransGrWeight");
            dataTable.Columns.Add("TotalTransVolume");
            dataTable.Columns.Add("BaseTspCost");
            dataTable.Columns.Add("VendorCode");
            dataTable.Columns.Add("TspTypeCode");
            dataTable.Columns["TotalTransGrWeight"].DefaultValue = "200";//默认值放前面
            DataRow dataRow = dataTable.NewRow();
            dataRow["TspOrgID"] = "00000000000000000015";
            dataRow["VendorID"] = "0001";
            dataRow["VendorCode"] = "0001";
            dataRow["TspTypeID"] = "1";
            dataRow["TspTypeCode"] = "1";
            dataRow["CostsID"] = "00000000000000008251";
            dataRow["TotalQuantity"] = "3";
            dataRow["TotalTransGrWeight"] = "2";
          
            dataRow["TotalTransVolume"] = "1";
            dataRow["BaseTspCost"] = "7";
            dataTable.Rows.Add(dataRow);
            DataRow dataRow1 = dataTable.NewRow();
            dataRow1["TspOrgID"] = "00000000000000000015";
            dataRow1["VendorID"] = "0001";
            dataRow1["VendorCode"] = "0001";
            dataRow1["TspTypeID"] = "1";
            dataRow1["TspTypeCode"] = "1";
            dataRow1["CostsID"] = "00000000000000008251";
            dataRow1["TotalQuantity"] = "5";
            dataRow1["TotalTransGrWeight"] = "6";

            dataRow1["TotalTransVolume"] = "7";
            dataRow1["BaseTspCost"] = "8";

            dataTable.Rows.Add(dataRow1);

            DataRow dataRow2 = dataTable.NewRow();
            dataRow2["TspOrgID"] = "00000000000000000015";
            dataRow2["VendorID"] = "0000007";
            dataRow2["VendorCode"] = "0000007";
            dataRow2["TspTypeID"] = "1";
            dataRow2["TspTypeCode"] = "1";
            dataRow2["CostsID"] = "00000000000000004615";
            dataRow2["TotalQuantity"] = "5";
            //dataRow2["TotalTransGrWeight"] = "6";

            dataRow2["TotalTransVolume"] = "7";
            dataRow2["BaseTspCost"] = "8";

            dataTable.Rows.Add(dataRow2);




        


            foreach (DataRow dr in dataTable.Rows)
            {
                dr["BaseTspCost"] = 100;
            }

            dataSet.Tables.Add(dataTable);

            DataSet dataSetResult = new DataSet();
            dataSetResult = TspCostsFormulaClient.Current.GetTspCostsFormulaResult(dataSet);









        }

        private void CancelToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DialogResult = DialogResult.Cancel;
            this.Close();
        }

        private void CloseToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }
    }
}

代码如上

对于对外计算接口,定义一个webservice,传入值datatable包含参数对应值的数据源,计算写法与校验的一样就可以。

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!