编程与数学 03-008 《看潮企业管理软件》项目开发 14 单据审批 6-3

编程与数学 03-008 《看潮企业管理软件》项目开发 14 单据审批 6-3

摘要:本文档详细阐述了《看潮企业管理软件》中单据审批功能模型的设计与实现。该模块基于C# WinForms和DevExpress控件库开发,采用三层架构设计,实现了单据的审批、登记、流转、回退等核心业务流程。系统支持多标签页单据头展示、网格化明细数据管理、公式自动计算、权限精细控制及批量操作处理。通过状态机管理单据生命周期,实现了制单、审核、登账的严格分离,确保业务数据的完整性和审计追踪。文档涵盖界面设计、业务逻辑代码及模型应用价值,为企业ERP系统提供了标准化、可配置的业务流程管理解决方案。
关键词:单据审批、ERP系统、WinForms、DevExpress、工作流引擎、权限控制、业务建模、状态管理
人工智能助手:DeepSeek、Kimi

三、窗体功能代码

csharp 复制代码
// 前半部分
/*
 * 文件名称: Uf06Djsp.cs
 * 功能描述: 单据审批功能业务逻辑代码文件
 * 主要用途: 
 *  1. 实现单据审批、登记、流转等核心业务流程
 *  2. 提供单据数据的加载、显示、编辑和保存功能
 *  3. 支持单据的审批(审核)登记(登账)回退、流转等操作
 *  4. 提供单据打印、文件导出、关联信息查看等辅助功能
 *  5. 集成公式计算、数据验证、权限控制等业务逻辑
 * 核心功能模块:
 *  - 单据数据载入与展示
 *  - 审批流程控制(审核/取消审核)
 *  - 登记流程控制(登记/反登记)
 *  - 流程管理(流转、回退)
 *  - 批量操作(全部审核、全部登记、部分操作)
 *  - 数据编辑与保存
 *  - 打印与文件导出
 *  - 关联信息查看
 * 技术特点:
 *  - 使用DevExpress控件库构建用户界面
 *  - 支持多标签页单据头显示
 *  - 网格视图显示单据明细
 *  - 集成公式自动计算引擎
 *  - 支持文件附件管理
 *  - 提供快捷键操作支持
 * 重要数据结构:
 *  - dt1: 单据头数据表
 *  - dt2: 单据体数据表
 *  - dtrw: 任务流程数据表
 *  - dqdt2: 当前单据明细数据表
 * 关键业务流程:
 *  1. 数据载入 → 2. 单据浏览 → 3. 编辑/审批 → 4. 保存/提交 → 5. 流程处理
 */

using DevExpress.Utils.Menu;
using DevExpress.XtraBars;
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.Controls;
using DevExpress.XtraEditors.Repository;
using DevExpress.XtraGrid;
using DevExpress.XtraGrid.Columns;
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraLayout;
using DevExpress.XtraReports.UI;
using DevExpress.XtraRichEdit;
using DevExpress.XtraTab;
using System;
using System.Data;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using static KcErp.KcDybjsb;
using static KcErp.KcMain;
using static KcErp.KcDb;
using static KcErp.KcEditfm;
using static KcErp.KcEditgd;
using static KcErp.KcFile;

namespace KcErp
{
    public partial class Uf06Djsp : DevExpress.XtraEditors.XtraForm
    {
        #region public
        // 公共字段,用于存储单据相关配置信息
        public string dyoid = "";               // 打印单据ID
        public string fdjmc = "";               // 单据名称
        public string fgnbh = "";               // 功能编号
        public string fgnmc = "";               // 功能名称
        public string ft1 = "";                 // 功能表1(单据头表名)
        public string ft1djrzd = "";            // 单据登账人字段
        public string ft1djtj = "";             // 单据登记条件表达式
        public int ft1ecol = 0;                 // 单据头编辑列数
        public string ft1gxzd = "";             // 单据头更新字段列表
        public string ft1htbh = "";             // 回退编号
        public string ft1htmc = "";             // 回退名称
        public string ft1list = "";             // 单据头字段列表
        public string ft1lzbh = "";             // 流转编号
        public string ft1lzbjzd = "";           // 流转标记字段
        public string ft1lzmc = "";             // 流转名称
        public string ft1oid = "";              // 单据头主键字段
        public string ft1order = "";            // 单据头排序字段
        public string ft1qj = "";               // 单据期间字段
        public string ft1rwbh = "";             // 任务编号
        public string ft1rwmc = "";             // 任务名称
        public bool ft1rxdj = false;            // 是否允许登账
        public string ft1sprzd = "";            // 审批人字段
        public string ft1tjts = "";             // 提交提示信息
        public string ft1tz = "";               // 制单人字段
        public string ft1where = "";            // 单据头查询条件
        public string ft2 = "";                 // 功能表2(单据体表名)
        public string ft2czbjzd = "";           // 单据体操作标记字段
        public string ft2djbjzd = "";           // 单据体登账标记字段
        public string ft2gxzd = "";             // 单据体更新字段列表
        public string ft2list = "";             // 单据体字段列表
        public string ft2mdzd = "";             // 码段输入字段列表
        public string ft2mid = "";              // 单据体明细ID字段
        public string ft2nryczd = "";           // 内容字段(用于隐藏)
        public string ft2oid = "";              // 单据体外键字段(关联单据头)
        public string ft2order = "";            // 单据体排序字段
        public string ft2qj = "";               // 单据体期间字段
        public string ft2tpzd = "";             // 图片文件输入字段列表
        public string ft2where = "";            // 单据体查询条件
        public string ftbb = "";                // 功能表版本
        public string fxz = "";                 // 功能权限限制字符串
        #endregion

        #region dim
        // 私有字段,用于内部状态管理和数据处理
        string[] bymstrcp;                      // 必要字段标题数组
        string[] bymstrfd;                      // 必要字段名称数组
        DataTable ckdtdy;                       // 参考定义数据表
        string[] ckjb;                          // 参考级别数组
        string[] ckmc;                          // 参考名称数组
        string[] ckzdbb;                        // 参考字段版本数组
        string[] ckzdyb;                        // 参考字段原表数组
        bool djenter = false;                   // 单据输入状态标志
        int dqdjh = -1;                         // 当前单据行索引
        int dqdjs = 0;                          // 当前单据总数
        DataTable dqdt2;                        // 当前单据明细数据表
        string dqmid = "";                      // 当前明细ID
        int dqmrow = -1;                        // 当前明细行索引
        string dqoid = "";                      // 当前单据ID
        DataTable dt1;                          // 单据头数据表
        DataTable dt2;                          // 单据体数据表
        DataTable dt2sx = new DataTable();      // 单据体筛选数据表
        DataTable dtgs;                         // 公式数据表
        DataTable dtrw;                         // 任务流程数据表
        DataTable dttj1;                        // 载入条件数据表
        DataTable dtzd1;                        // 单据头字段定义表
        DataTable dtzd2;                        // 单据体字段定义表
        bool fh = false;                        // 返回标志
        FmGLsr fmgl;                           // 关联信息窗体对象
        string[] ft1fd;                         // 单据头字段数组
        string ft1wjzd = "";                    // 单据头文件字段
        string[] ft2fd;                         // 单据体字段数组
        string ft2wjzd = "";                    // 单据体文件字段
        string glmzd = "";                      // 关联字段
        string glozd = "";                      // 关联字段
        bool gsjsz = false;                     // 公式计算中标志
        bool hasdjmc = false;                   // 是否有单据名称字段
        string jszdstr = "";                    // 计算字段字符串
        string jzzd = "";                       // 禁止字段列表
        bool loaderr = false;                   // 加载错误标志
        bool loadfm = false;                    // 加载表单中标志
        bool loading = false;                   // 数据载入中标志
        public GridView mtgv = new GridView();  // 主表格视图对象
        bool sctj = false;                      // 删除条件标志(未使用)
        bool sfdj = false;                      // 是否已登账
        bool sflz = false;                      // 是否已流转
        bool sfsp = false;                      // 是否已审批
        bool sftj = false;                      // 是否已提交
        bool sfzf = false;                      // 是否已作废
        int sfzj = 0;                           // 是否增加标志(0:正常 1:增加同级 2:增加下级 3:修改)
        bool sfzr = false;                      // 是否载入标志
        bool xzbj = false;                      // 是否允许编辑
        bool xzck = false;                      // 是否允许查看参考信息
        bool xzdc = false;                      // 是否允许导出
        bool xzdy = false;                      // 是否允许打印
        bool xzwj = false;                      // 是否允许文件操作
        string zrtjstr = "";                    // 载入条件字符串
        #endregion

        // 布局控件对象
        private LayoutControl mdlc = new LayoutControl();
        private LayoutControl tplc = new LayoutControl();

        // 构造函数
        public Uf06Djsp()
        {
            InitializeComponent();
            
            // 绑定窗体事件
            this.Load += Rf_load;
            this.Disposed += GN06_DJSP_Disposed;
            this.FormClosed += GN06_DJSP_FormClosed;
            
            // 绑定按钮点击事件
            this.Btpg1.Click += Btpg1_itemclick;
            this.Btpg2.Click += Btpg2_itemclick;
            this.Btpg3.Click += Btpg3_itemclick;
            this.Btpg4.Click += Btpg4_itemclick;
            
            // 绑定Ribbon按钮点击事件
            this.BarZR.ItemClick += Barzr_itemclick;
            this.BarHelp.ItemClick += Barhelp_itemclick;
            this.Barexit.ItemClick += Barexit_itemclick;
            this.BarPreview.ItemClick += Barpreview_itemclick;
            this.BarPrint.ItemClick += Barprint_itemclick;
            this.Barwjdc.ItemClick += Barwjdc_itemclick;
            this.BardjOK.ItemClick += Bardjok_itemclick;
            this.BardjCancel.ItemClick += Bardjcancel_itemclick;
            this.BardjXG.ItemClick += Bardjxg_itemclick;
            this.BarTJ.ItemClick += Bartj_itemclick;
            this.BarCZ.ItemClick += Textss;
            this.Barbplz.ItemClick += Barbplz_itemclick;
            this.Barbplzall.ItemClick += Barbplzall_itemclick;
            this.Barbpht.ItemClick += Barbpht_itemclick;
            this.Barbphtall.ItemClick += Barbphtall_itemclick;
            this.BarDJSP.ItemClick += Bardjsp_itemclick;
            this.BarFullSP.ItemClick += Barfullsp_itemclick;
            this.BarBFSP.ItemClick += Barbfsp_itemclick;
            this.BarDJDJ.ItemClick += Bardjdj_itemclick;
            this.BarFullDJ.ItemClick += Barfulldj_itemclick;
            this.BarBFDJ.ItemClick += Barbfdj_itemclick;
            
            this.VisibleChanged += Fm_visiblechanged;
        }

        // 静态方法:加载单据头字段值到布局控件
        private static void Fmecload(ref LayoutControl lcrt, ref DataRow dr)
        {
            LayoutControlGroup lc = lcrt.Root;
            string[] itag;
            
            // 遍历布局控件中的所有项目
            for (int lt = 0; lt < lc.Items.ItemCount; lt++)
            {
                itag = (lc.Items[lt].Tag?.ToString() ?? "").Split(',');
                if (itag.Length == 5)  // Tag格式:控件类型,字段类型,字段名,数据类型,是否必填
                {
                    BaseEdit ec;
                    LayoutControlItem ci = lc.Items[lt] as LayoutControlItem;
                    if (ci != null)
                    {
                        switch (itag[1])  // 根据字段类型处理
                        {
                            case "richtextedit":
                            case "richtextread":
                                // 富文本控件
                                RichEditControl rtfc = ci.Control as RichEditControl;
                                if (!DBNull.Value.Equals(dr[itag[2]]))
                                {
                                    rtfc.RtfText = dr[itag[2]].ToString();
                                }
                                else
                                {
                                    rtfc.RtfText = "";
                                }
                                rtfc.ReadOnly = true;  // 设置为只读
                                break;
                            default:
                                // 其他编辑控件
                                ec = ci.Control as BaseEdit;
                                if (!DBNull.Value.Equals(dr[itag[2]]))
                                {
                                    ec.EditValue = dr[itag[2]];
                                }
                                else
                                {
                                    ec.EditValue = DBNull.Value;
                                }
                                ec.Properties.ReadOnly = true;  // 设置为只读
                                break;
                        }
                    }
                }
            }
        }

        // 静态方法:清空布局控件中的编辑项目
        private static void Fmxmcls(ref LayoutControl lcrt, bool rw)
        {
            LayoutControlGroup lc = lcrt.Root;
            string[] itag;
            
            for (int lt = 0; lt < lc.Items.ItemCount; lt++)
            {
                itag = (lc.Items[lt].Tag?.ToString() ?? "").Split(',');
                if (itag.Length == 5)
                {
                    BaseEdit ec;
                    LayoutControlItem ci = lc.Items[lt] as LayoutControlItem;
                    if (ci != null)
                    {
                        if (itag[1] == "richtextedit" || itag[1] == "richtextread")
                        {
                            // 富文本控件
                            RichEditControl rtfc = ci.Control as RichEditControl;
                            rtfc.RtfText = "";  // 清空内容
                            rtfc.ReadOnly = rw;
                            if (!rw)
                            {
                                rtfc.ReadOnly = (itag[1].IndexOf("read") > 0);  // 根据类型设置只读
                            }
                        }
                        
                        ec = ci.Control as BaseEdit;
                        if (ec != null)
                        {
                            // 根据数据类型设置默认值
                            switch (itag[3])  // 数据类型
                            {
                                case "char":
                                case "nchar":
                                case "text":
                                case "ntext":
                                case "varchar":
                                case "nvarchar":
                                    ec.EditValue = "";  // 字符串类型清空
                                    break;
                                case "int":
                                case "smallint":
                                case "bigint":
                                case "decimal":
                                case "numeric":
                                case "float":
                                case "real":
                                    ec.EditValue = 0;  // 数值类型设为0
                                    break;
                                case "date":
                                case "datetime":
                                case "datetime2":
                                case "smalldatetime":
                                case "datetimeofset":
                                    ec.EditValue = Getywdate();  // 日期类型设为业务日期
                                    break;
                                case "time":
                                    ec.EditValue = DateTime.Now.TimeOfDay;  // 时间类型设为当前时间
                                    break;
                                case "bit":
                                    ec.EditValue = false;  // 布尔类型设为false
                                    break;
                                case "binary":
                                case "image":
                                    ec.EditValue = DBNull.Value;  // 二进制类型设为空
                                    break;
                                default:
                                    ec.EditValue = DBNull.Value;
                                    break;
                            }
                            ec.Properties.ReadOnly = rw;  // 设置只读属性
                            if (!rw)
                            {
                                ec.Properties.ReadOnly = (itag[1].IndexOf("read") > 0);  // 根据类型设置只读
                            }
                        }
                    }
                }
            }
        }

        // 静态方法:设置布局控件中项目的只读属性
        private static void Fmxmec(ref LayoutControl lcrt, bool rw)
        {
            LayoutControlGroup lc = lcrt.Root;
            string[] itag;
            
            for (int lt = 0; lt < lc.Items.ItemCount; lt++)
            {
                itag = (lc.Items[lt].Tag?.ToString() ?? "").Split(',');
                if (itag.Length == 5)
                {
                    BaseEdit ec;
                    LayoutControlItem ci = lc.Items[lt] as LayoutControlItem;
                    if (ci != null)
                    {
                        if (itag[1] == "richtextedit" || itag[1] == "richtextread")
                        {
                            // 富文本控件
                            RichEditControl rtfc = ci.Control as RichEditControl;
                            rtfc.ReadOnly = rw;
                            if (!rw)
                            {
                                rtfc.ReadOnly = (itag[1].IndexOf("read") > 0);  // 根据类型设置只读
                            }
                        }
                        
                        ec = ci.Control as BaseEdit;
                        if (ec != null)
                        {
                            ec.Properties.ReadOnly = rw;  // 设置只读属性
                            if (!rw)
                            {
                                ec.Properties.ReadOnly = (itag[1].IndexOf("read") > 0);  // 根据类型设置只读
                            }
                        }
                    }
                }
            }
        }

        // 静态方法:清空关联信息布局控件中的项目
        private static void Glxxfmcls(ref LayoutControlGroup lc)
        {
            string[] itag;
            
            for (int lt = 0; lt <= lc.Items.Count - 1; lt++)
            {
                itag = (lc.Items[lt].Tag?.ToString() ?? "").Split(',');
                if (itag.Length == 5)
                {
                    BaseEdit ec;
                    LayoutControlItem ci;
                    ci = (LayoutControlItem)lc.Items[lt];
                    if (ci != null)
                    {
                        ec = (BaseEdit)ci.Control;
                        if (ec != null)
                        {
                            // 根据数据类型设置默认值
                            switch (itag[3])
                            {
                                case "char":
                                case "nchar":
                                case "text":
                                case "ntext":
                                case "varchar":
                                case "nvarchar":
                                    ec.EditValue = "";  // 字符串类型清空
                                    break;
                                case "int":
                                case "smallint":
                                case "bigint":
                                case "decimal":
                                case "numeric":
                                case "float":
                                case "real":
                                    ec.EditValue = 0;  // 数值类型设为0
                                    break;
                                case "date":
                                case "datetime":
                                case "datetime2":
                                case "smalldatetime":
                                case "datetimeofset":
                                    ec.EditValue = Getywdate();  // 日期类型设为业务日期
                                    break;
                                case "time":
                                    ec.EditValue = DateTime.Now.TimeOfDay;  // 时间类型设为当前时间
                                    break;
                                case "bit":
                                    ec.EditValue = false;  // 布尔类型设为false
                                    break;
                                case "binary":
                                case "image":
                                    ec.EditValue = DBNull.Value;  // 二进制类型设为空
                                    break;
                                default:
                                    ec.EditValue = DBNull.Value;
                                    break;
                            }
                            ec.Properties.ReadOnly = true;  // 关联信息始终只读
                        }
                    }
                }
            }
        }

        // 静态方法:加载关联信息字段值到布局控件
        private static void Glxxfmload(ref LayoutControlGroup lc, ref DataRow dr)
        {
            string[] itag;
            
            for (int lt = 0; lt <= lc.Items.Count - 1; lt++)
            {
                itag = (lc.Items[lt].Tag?.ToString() ?? "").Split(',');
                if (itag.Length == 5)
                {
                    BaseEdit ec;
                    LayoutControlItem ci;
                    ci = (LayoutControlItem)lc.Items[lt];
                    if (ci != null)
                    {
                        ec = (BaseEdit)ci.Control;
                        if (!DBNull.Value.Equals(dr[itag[2]]))
                        {
                            ec.EditValue = dr[itag[2]];  // 设置字段值
                        }
                        else
                        {
                            ec.EditValue = DBNull.Value;  // 空值处理
                        }
                        ec.Properties.ReadOnly = true;  // 关联信息始终只读
                    }
                }
            }
        }

        // 事件处理:部分登记按钮点击
        private void Barbfdj_itemclick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            // 登记 部分 选择范围
            try
            {
                // 检查业务期间是否变化
                if (pYWQJ != KcDb.DBString("select max(ny) as ny from mlny"))
                {
                    MsgOxShow("系统业务期间已经发生变化,当前操作无法完成,请重新启动本软件后再继续使用!");
                    return;
                }
                
                int ksh = 0;  // 开始行
                int jsh = 0;  // 结束行
                
                // 显示范围选择对话框
                FmDJFW fmfw = new FmDJFW();
                fmfw.T1.Text = "1";
                fmfw.T2.Text = dt1.Rows.Count.ToString();
                if (fmfw.ShowDialog(this) != System.Windows.Forms.DialogResult.OK)
                {
                    return;
                }
                
                ksh = Convert.ToInt32(fmfw.T1.Text);
                jsh = Convert.ToInt32(fmfw.T2.Text);
                if (jsh > dt1.Rows.Count)
                {
                    jsh = dt1.Rows.Count;
                }
                if (ksh > jsh || ksh <= 0)
                {
                    return;
                }
                fmfw.Dispose();
                
                string czjg;
                int wcsl = 0;  // 完成数量
                
                // 遍历选择范围内的单据
                for (int r = ksh - 1; r < jsh; r++)
                {
                    // 检查单据是否在当前步骤
                    if (!(dt1.Rows[r][ft1lzbjzd].Equals(ft1rwbh + ft1rwmc)))
                    {
                        continue;
                    }
                    
                    // 检查是否已登记
                    if (dt1.Rows[r][ft1djrzd].ToString() != "")
                    {
                        continue;
                    }
                    
                    // 检查登记条件
                    if (!Getdjtj(r))
                    {
                        continue;
                    }
                    
                    try
                    {
                        // 执行登记操作
                        czjg = KcDb.DBexec("select x9_djdj('" + pDQYH + "','" + pBJMC + "','" + fdjmc + "','" + dt1.Rows[r][ft1oid] + "')");
                        if (czjg == pDQYH)  // 登记成功
                        {
                            // 更新单据头登记信息
                            dt1.Rows[r][ft1djrzd] = pDQYH;
                            
                            // 更新单据体登记标记
                            dt2.DefaultView.RowFilter = ft2oid + "='" + dt1.Rows[r][ft1oid] + "'";
                            if (dt2.DefaultView.Count > 0)
                            {
                                for (int t2r = dt2.DefaultView.Count - 1; t2r >= 0; t2r--)
                                {
                                    dt2.DefaultView[t2r][ft2djbjzd] = true;
                                }
                            }
                            
                            // 更新任务记录
                            DataRow[] dr = dtrw.Select("bpid='" + dt1.Rows[r][ft1oid].ToString() + "' and rwbh='" + ft1rwbh + "'");
                            if (dr.Length > 0)
                            {
                                int rwr = dtrw.Rows.IndexOf(dr[0]);
                                if (rwr >= 0)
                                {
                                    dtrw.Rows[rwr]["wcsj"] = DateTime.Now;  // 完成时间
                                    dtrw.Rows[rwr]["wcry"] = pDQYH;         // 完成人员
                                    dtrw.Rows[rwr]["rwzy"] = pBJMC + " " + pDQYH + " 登记";  // 任务摘要
                                    dtrw.Rows[rwr]["rwexec"] = "";         // 执行内容
                                    dtrw.Rows[rwr]["sfwc"] = true;         // 是否完成
                                }
                            }
                            wcsl += 1;  // 计数
                        }
                    }
                    catch
                    {
                        wcsl += 0;  // 错误不计入
                    }
                }
                
                // 保存更改
                DataTable udtrw = null;
                udtrw = dtrw.GetChanges();
                DataTable udt2 = null; // 表二
                udt2 = dt2.GetChanges();
                DataTable udt1 = null; // 表一
                udt1 = dt1.GetChanges();
                
                KcDb.GetDtSaven(ft1, udt1, ft2, udt2, "x9_bprw", udtrw, ft1djrzd, ft2djbjzd, "wcsj,wcry,rwzy,rwexec,sfwc");
                dt1.AcceptChanges();
                dt2.AcceptChanges();
                dtrw.AcceptChanges();
                
                udtrw = null;
                udt2 = null;
                udt1 = null;
                
                sftj = true;  // 标记已提交
                Djload();     // 重新加载单据
                MsgXxShow("部分单据登记操作已经完成,本次共完成 " + wcsl.ToString().Trim() + " 张单据的处理,请检查结果是否正确");
                KcDb.DBclose();
            }
            catch (Exception ex)
            {
                MsgExShow("登记部分单据", ex.Message, ex.Source, ex.StackTrace);
            }
        }

        // 事件处理:部分审核按钮点击
        private void Barbfsp_itemclick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            bool spcz;  // 审核操作:true=审核,false=取消审核
            spcz = !sfsp;  // 根据当前状态确定操作类型
            
            int ksh = 0;  // 开始行
            int jsh = 0;  // 结束行
            int wcsl = 0;  // 完成数量
            
            try
            {
                // 显示范围选择对话框
                FmDJFW fmfw = new FmDJFW();
                {
                    fmfw.T1.Text = "1";
                    fmfw.T2.Text = dt1.Rows.Count.ToString();
                    fmfw.ShowDialog(this);
                    if (!fmfw.sfok)  // 用户取消
                    {
                        return;
                    }
                    ksh = Convert.ToInt32(fmfw.T1.Text);
                    jsh = Convert.ToInt32(fmfw.T2.Text);
                    if (jsh > dt1.Rows.Count)
                    {
                        jsh = dt1.Rows.Count;
                    }
                    if (ksh > jsh || ksh <= 0)
                    {
                        return;
                    }
                }
                fmfw.Dispose();
                
                string czsql;
                string czjg;
                
                // 遍历选择范围内的单据
                for (int r = ksh - 1; r <= jsh - 1; r++)
                {
                    // 检查单据是否在当前步骤
                    if (!(dt1.Rows[r][ft1lzbjzd].Equals(ft1rwbh + ft1rwmc))) // 已经流转或回退
                    {
                        continue;
                    }
                    
                    // 检查是否已签收
                    if (dt1.Rows[r][ft1djrzd].ToString().Trim() != "")      // 已经签收
                    {
                        continue;
                    }
                    
                    if (spcz)  // 审核操作
                    {
                        if (dt1.Rows[r][ft1sprzd].ToString() != "")   // 已经审核
                        {
                            continue;
                        }
                    }
                    else  // 取消审核操作
                    {
                        // 取消
                        if (dt1.Rows[r][ft1sprzd].ToString() == "")   // 未经审核
                        {
                            continue;
                        }
                        else
                        {
                            if (dt1.Rows[r][ft1sprzd].ToString() != pDQYH)     // 他人审核 
                            {
                                continue;
                            }
                        }
                    }
                    
                    try
                    {
                        // 执行审核/取消审核操作
                        czsql = "select x9_djsp('" + pDQYH + "','" + pBJMC + "','" + fdjmc + "','" + dt1.Rows[r][ft1oid] + "','" + ft1rwmc + "'," + (spcz ? "true" : "false") + ")";
                        czjg = KcDb.DBexec(czsql);
                        if (czjg == pDQYH)  // 操作成功
                        {
                            // 更新单据头审核信息
                            dt1.Rows[r][ft1sprzd] = spcz ? pDQYH : "";
                            
                            // 更新单据体操作标记
                            dt2.DefaultView.RowFilter = ft2oid + "='" + dt1.Rows[r][ft1oid] + "'";
                            if (dt2.DefaultView.Count > 0)
                            {
                                for (int t2r = dt2.DefaultView.Count - 1; t2r >= 0; t2r--)
                                {
                                    dt2.DefaultView[t2r][ft2czbjzd] = spcz;
                                }
                            }
                            
                            // 更新任务记录
                            DataRow[] dr;
                            dr = dtrw.Select("bpid='" + dt1.Rows[r][ft1oid].ToString() + "' and rwbh='" + ft1rwbh + "'");
                            if (dr.Length > 0)
                            {
                                int rwr = dtrw.Rows.IndexOf(dr[0]);
                                if (rwr >= 0)
                                {
                                    dtrw.Rows[rwr]["wcsj"] = DateTime.Now;  // 完成时间
                                    dtrw.Rows[rwr]["wcry"] = pDQYH;         // 完成人员
                                    dtrw.Rows[rwr]["rwzy"] = pBJMC + pDQYH + " " + (spcz ? "" : "取消") + " " + ft1rwmc;  // 任务摘要
                                }
                            }
                            wcsl += 1;  // 计数
                        }
                    }
                    catch (Exception ex)
                    {
                        wcsl += 0;  // 错误不计入
                    }
                    // 更新状态值
                }
                
                // 保存更改
                DataTable udtrw; //
                udtrw = dtrw.GetChanges();
                DataTable udt2; // 表二
                udt2 = dt2.GetChanges();
                DataTable udt1; // 表一
                udt1 = dt1.GetChanges();
                
                if (KcDb.GetDtSaven(ft1, udt1, ft2, udt2, "x9_bprw", udtrw, ft1sprzd, ft2czbjzd, "wcsj,wcry,rwzy"))
                {
                    dt1.AcceptChanges();
                    dt2.AcceptChanges();
                    dtrw.AcceptChanges();
                }
                
                udtrw = null;
                udt2 = null;
                udt1 = null;
                
                sftj = true;  // 标记已提交
                Djload();     // 重新加载单据
                MsgXxShow("部分" + (spcz ? "" : "取消") + ft1rwmc + "操作已经完成,本次共完成 " + wcsl.ToString().Trim() + " 张单件的处理!");
                KcDb.DBclose();
            }
            catch (Exception ex)
            {
                MsgExShow("部分" + (spcz ? "" : "取消") + ft1rwmc + "部分单件", ex.Message, ex.Source, ex.StackTrace);
            }
        }

        // 事件处理:回退按钮点击(单张单据)
        private void Barbpht_itemclick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            // 回退
            try
            {
                // 检查当前状态
                if (sflz || sfsp || sfzf || sfdj)
                {
                    return;
                }
                
                // 检查单据是否在当前步骤
                if (!(dt1.Rows[dqdjh][ft1lzbjzd].Equals(ft1rwbh + ft1rwmc)))
                {
                    return;
                }
                
                // 检查是否已登记
                if (dt1.Rows[dqdjh][ft1djrzd].ToString() != "")
                {
                    return;
                }
                
                // 确认对话框
                if (MsgSfShow("流程管理回退表示当前步骤任务将取消,并返回上一步骤重新进行处理,是否继续?") != System.Windows.Forms.DialogResult.OK)
                {
                    return;
                }
                
                // 执行回退操作
                Bpht(dqdjh);
                
                // 保存更改
                DataTable udtrw; //
                udtrw = dtrw.GetChanges();
                DataTable udt2; // 表二
                udt2 = dt2.GetChanges();
                DataTable udt1; // 表一
                udt1 = dt1.GetChanges();
                
                if (KcDb.GetDtSaven(ft1, udt1, ft2, udt2, "x9_bprw", udtrw, ft1lzbjzd + "," + ft1sprzd, ft1lzbjzd + "," + ft2czbjzd, ""))
                {
                    dt1.AcceptChanges();
                    dt2.AcceptChanges();
                    dtrw.AcceptChanges();
                }
                
                udtrw = null;
                udt2 = null;
                udt1 = null;
                
                // 执行回退后处理
                string bmstr = "";
                string tjstr = "";
                try
                {
                    bmstr = bmstr + "(" + dt1.Rows[dqdjh][ft1oid].ToString().Trim() + ")";
                    string tjsql = "select x9_tj_4djht('" + pDQYH + "','" + fdjmc + "','" + ft1rwbh + ft1rwmc + "','" + bmstr + "')";
                    tjstr = KcDb.DBexec(tjsql);
                }
                catch (Exception ex)
                {
                    MsgExShow("单件[" + bmstr + "]回退后处理", ex.Message, ex.Source, ex.StackTrace);
                }
                
                sftj = true;  // 标记已提交
                Djload();     // 重新加载单据
                MsgXxShow("回退操作已经完成\r\n" + tjstr);
                KcDb.DBclose();
            }
            catch (Exception ex)
            {
                MsgExShow("提交单件回退", ex.Message, ex.Source, ex.StackTrace);
            }
        }

        // 事件处理:全部回退按钮点击
        private void Barbphtall_itemclick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            // 全部回退
            try
            {
                // 检查当前状态
                if (sflz || sfsp || sfzf || sfdj)
                {
                    return;
                }
                
                // 确认对话框
                if (MsgSfShow("流程管理回退表示当前步骤任务将取消,并返回上一步骤重新进行处理,是否继续?") != System.Windows.Forms.DialogResult.OK)
                {
                    return;
                }
                
                string tjstr = "";
                string bmstr = "";
                
                // 遍历所有单据
                for (int r = 0; r <= dt1.Rows.Count - 1; r++)
                {
                    // 检查是否已登记
                    if (dt1.Rows[r][ft1djrzd].ToString() == "")
                    {
                        // 检查是否在当前步骤且未审核
                        if ((dt1.Rows[r][ft1lzbjzd].Equals(ft1rwbh + ft1rwmc)) && dt1.Rows[r][ft1sprzd].ToString().Trim() == "")
                        {
                            bmstr = bmstr + "(" + dt1.Rows[r][ft1oid].ToString().Trim() + ")";
                            Bpht(r);  // 执行回退
                        }
                    }
                }
                
                // 保存更改
                DataTable udtrw; //
                udtrw = dtrw.GetChanges();
                DataTable udt2; // 表二
                udt2 = dt2.GetChanges();
                DataTable udt1; // 表一
                udt1 = dt1.GetChanges();
                
                if (KcDb.GetDtSaven(ft1, udt1, ft2, udt2, "x9_bprw", udtrw, ft1lzbjzd + "," + ft1sprzd, ft1lzbjzd + "," + ft2czbjzd, ""))
                {
                    dt1.AcceptChanges();
                    dt2.AcceptChanges();
                    dtrw.AcceptChanges();
                }
                
                udtrw = null;
                udt2 = null;
                udt1 = null;
                
                sftj = true;  // 标记已提交
                
                // 执行回退后处理
                try
                {
                    string tjsql = "select x9_tj_4djht('" + pDQYH + "','" + fdjmc + "','" + ft1rwbh + ft1rwmc + "','" + bmstr + "')";
                    tjstr = KcDb.DBexec(tjsql);
                }
                catch (Exception ex)
                {
                    MsgExShow("单件[" + bmstr + "]回退后处理", ex.Message, ex.Source, ex.StackTrace);
                }
                
                Btpg1_itemclick(null, null);  // 回到第一张单据
                MsgXxShow("全部回退操作已经完成\r\n" + tjstr);
                KcDb.DBclose();
            }
            catch (Exception ex)
            {
                MsgExShow("提交全部回退", ex.Message, ex.Source, ex.StackTrace);
            }
        }

        // 事件处理:流转按钮点击(单张单据)
        private void Barbplz_itemclick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            // 流转
            if (sflz || (!sfsp) || sfzf || sfdj)
            {
                return;
            }
            
            try
            {
                // 检查单据是否在当前步骤
                if (!(dt1.Rows[dqdjh][ft1lzbjzd].Equals(ft1rwbh + ft1rwmc)))
                {
                    return;
                }
                
                // 检查是否已登记
                if (dt1.Rows[dqdjh][ft1djrzd].ToString() != "")
                {
                    return;
                }
                
                // 确认对话框
                if (MsgSfShow("流程管理流转表示当前步骤任务已经完成,将进入下一步骤进行处理,是否继续?") != System.Windows.Forms.DialogResult.OK)
                {
                    return;
                }
                
                // 检查是否已完成审核
                if (dt1.Rows[dqdjh][ft1sprzd].ToString() == "")
                {
                    MsgXxShow("未能完成" + ft1rwmc + ",不能进行流转操作");
                    return;
                }
                
                // 执行流转操作
                Djlz(dqdjh);
                
                // 保存更改
                DataTable udtrw; //
                udtrw = dtrw.GetChanges();
                DataTable udt2; // 表二
                udt2 = dt2.GetChanges();
                DataTable udt1; // 表一
                udt1 = dt1.GetChanges();
                
                if (KcDb.GetDtSaven(ft1, udt1, ft2, udt2, "x9_bprw", udtrw, ft1lzbjzd, ft1lzbjzd, ""))
                {
                    dt1.AcceptChanges();
                    dt2.AcceptChanges();
                    dtrw.AcceptChanges();
                }
                
                udtrw = null;
                udt2 = null;
                udt1 = null;
                
                sftj = true;  // 标记已提交
                
                // 执行流转后处理
                string bmstr = "";
                string tjstr = "";
                bmstr = bmstr + "(" + dt1.Rows[dqdjh][ft1oid].ToString().Trim() + ")";
                try
                {
                    string tjsql = "select x9_tj_4djlz('" + pDQYH + "','" + fdjmc + "','" + ft1rwbh + ft1rwmc + "','" + bmstr + "')";
                    tjstr = KcDb.DBexec(tjsql);
                }
                catch (Exception ex)
                {
                    MsgExShow("单件[" + bmstr + "]流转后处理", ex.Message, ex.Source, ex.StackTrace);
                }
                
                Djload();  // 重新加载单据
                MsgXxShow("单件流转操作已经完成\r\n" + tjstr);
                KcDb.DBclose();
            }
            catch (Exception ex)
            {
                MsgExShow("提交单件流转", ex.Message, ex.Source, ex.StackTrace);
            }
        }

        // 事件处理:全部流转按钮点击
        private void Barbplzall_itemclick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            // 流转
            if (sflz || (!sfsp) || sfzf || sfdj)
            {
                return;
            }
            
            try
            {
                // 确认对话框
                if (MsgSfShow("流程管理流转表示当前步骤任务已经完成,将进入下一步骤进行处理,是否继续?") != System.Windows.Forms.DialogResult.OK)
                {
                    return;
                }
                
                string tjstr = "";
                string bmstr = "";
                
                // 遍历所有单据
                for (int r = 0; r <= dt1.Rows.Count - 1; r++)
                {
                    // 检查是否已登记
                    if (dt1.Rows[r][ft1djrzd].ToString() == "")
                    {
                        // 检查是否已审核且在当前步骤
                        if (dt1.Rows[r][ft1sprzd].ToString() != "")
                        {
                            if (dt1.Rows[r][ft1lzbjzd].Equals(ft1rwbh + ft1rwmc))
                            {
                                bmstr = bmstr + "(" + dt1.Rows[r][ft1oid].ToString().Trim() + ")";
                                Djlz(r);  // 执行流转
                            }
                        }
                    }
                }
                
                // 保存更改
                DataTable udtrw; //
                udtrw = dtrw.GetChanges();
                DataTable udt2; // 表二
                udt2 = dt2.GetChanges();
                DataTable udt1; // 表一
                udt1 = dt1.GetChanges();
                
                if (KcDb.GetDtSaven(ft1, udt1, ft2, udt2, "x9_bprw", udtrw, ft1lzbjzd, ft1lzbjzd, ""))
                {
                    dt1.AcceptChanges();
                    dt2.AcceptChanges();
                    dtrw.AcceptChanges();
                }
                
                udtrw = null;
                udt2 = null;
                udt1 = null;
                
                sftj = true;  // 标记已提交
                
                // 执行流转后处理
                try
                {
                    string tjsql = "select x9_tj_4djlz('" + pDQYH + "','" + fdjmc + "','" + ft1rwbh + ft1rwmc + "','" + bmstr + "')";
                    tjstr = KcDb.DBexec(tjsql);
                }
                catch (Exception ex)
                {
                    MsgExShow("单件[" + bmstr + "]流转后处理", ex.Message, ex.Source, ex.StackTrace);
                }
                
                Btpg1_itemclick(null, null);  // 回到第一张单据
                MsgXxShow("全部流转操作已经完成\r\n" + tjstr);
                KcDb.DBclose();
            }
            catch (Exception ex)
            {
                MsgExShow("提交单件流转", ex.Message, ex.Source, ex.StackTrace);
            }
        }

        // 事件处理:取消按钮点击
        private void Bardjcancel_itemclick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            if (dqdjh >= 0)  // 有当前单据
            {
                sfzj = 0;  // 重置编辑状态
                Djload();   // 重新加载单据
            }
            else  // 无当前单据
            {
                Fmxmclear(true);  // 清空表单
                mtgv.OptionsBehavior.ReadOnly = true;  // 设置网格只读
                dt2.DefaultView.RowFilter = "false";  // 清空筛选
                dqdt2.Rows.Clear();  // 清空当前明细
                sfzj = 0;  // 重置编辑状态
                Barenabled();  // 更新按钮状态
            }
        }

        // 事件处理:登记按钮点击(单张单据)
        private void Bardjdj_itemclick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            // 登记
            if (!sfsp) return;  // 未审核不能登记
            
            try
            {
                // 检查单据是否在当前步骤
                if (!(dt1.Rows[dqdjh][ft1lzbjzd].Equals(ft1rwbh + ft1rwmc)))
                {
                    MsgOxShow("单据已被流转或回退,不能完成当前操作");
                    return;
                }
                
                // 检查业务期间是否变化
                if (pYWQJ != KcDb.DBString("select max(ny) as ny from mlny"))
                {
                    MsgOxShow("系统业务期间已经发生变化,当前操作无法完成,请重新启动本软件后再继续使用!");
                    return;
                }
                
                // 检查登记条件
                if (!Getdjtj(dqdjh))
                {
                    MsgOxShow("当前单据未能满足登记条件 " + ft1djtj);
                    return;
                }
                
                // 检查是否未登记
                if (dt1.Rows[dqdjh][ft1djrzd].ToString() == "")
                {
                    // 确认对话框
                    if (MsgSfShow("单据登记后将无法更改,确定要进行登记操作吗?") != System.Windows.Forms.DialogResult.OK)
                    {
                        return;
                    }
                    
                    // 执行登记操作
                    string czjg = KcDb.DBexec("select x9_djdj('" + pDQYH + "','" + pBJMC + "','" + fdjmc + "','" + dqoid + "')");
                    if (czjg == pDQYH)  // 登记成功
                    {
                        // 更新单据头登记信息
                        dt1.Rows[dqdjh][ft1djrzd] = pDQYH;
                        
                        // 更新单据体登账标记
                        if (dt2.DefaultView.Count > 0)
                        {
                            for (int t2r = dt2.DefaultView.Count - 1; t2r >= 0; t2r--)
                            {
                                dt2.DefaultView[t2r][ft2djbjzd] = true;
                            }
                        }
                        
                        // 更新任务记录
                        DataRow[] dr = dtrw.Select("bpid='" + dt1.Rows[dqdjh][ft1oid].ToString() + "' and rwbh='" + ft1rwbh + "'");
                        if (dr.Length > 0)
                        {
                            int rwr = dtrw.Rows.IndexOf(dr[0]);
                            if (rwr >= 0)
                            {
                                dtrw.Rows[rwr]["wcsj"] = DateTime.Now;  // 完成时间
                                dtrw.Rows[rwr]["wcry"] = pDQYH;         // 完成人员
                                dtrw.Rows[rwr]["rwzy"] = pBJMC + pDQYH + " 登记";  // 任务摘要
                                dtrw.Rows[rwr]["rwexec"] = "";         // 执行内容
                                dtrw.Rows[rwr]["sfwc"] = true;         // 是否完成
                            }
                        }
                    }
                    else
                    {
                        MsgOxShow(czjg);  // 显示错误信息
                        return;
                    }
                }
                else  // 已登记,执行反登记
                {
                    // 确认对话框
                    if (MsgSfShow("单据反登记是将单据恢复到未登记状态,请确定当前单据支持反登记,确定要进行反登记操作吗?") != System.Windows.Forms.DialogResult.OK)
                    {
                        return;
                    }
                    
                    // 执行反登记操作
                    string czjg = KcDb.DBexec("select x9_djdj('" + pDQYH + "','" + pBJMC + "','" + fdjmc + "','" + dqoid + "')");
                    if (czjg == pDQYH)  // 反登记成功
                    {
                        // 更新单据头登记信息
                        dt1.Rows[dqdjh][ft1djrzd] = "";
                        
                        // 更新单据体登账标记
                        if (dt2.DefaultView.Count > 0)
                        {
                            for (int t2r = dt2.DefaultView.Count - 1; t2r >= 0; t2r--)
                            {
                                dt2.DefaultView[t2r][ft2djbjzd] = false;
                            }
                        }
                        
                        // 更新任务记录
                        DataRow[] dr = dtrw.Select("bpid='" + dt1.Rows[dqdjh][ft1oid].ToString() + "' and rwbh='" + ft1rwbh + "'");
                        if (dr.Length > 0)
                        {
                            int rwr = dtrw.Rows.IndexOf(dr[0]);
                            if (rwr >= 0)
                            {
                                dtrw.Rows[rwr]["wcsj"] = DateTime.Now;  // 完成时间
                                dtrw.Rows[rwr]["wcry"] = pDQYH;         // 完成人员
                                dtrw.Rows[rwr]["rwzy"] = pBJMC + pDQYH + " 反登记";  // 任务摘要
                                dtrw.Rows[rwr]["sfwc"] = false;         // 是否完成
                            }
                        }
                    }
                    else
                    {
                        MsgOxShow(czjg);  // 显示错误信息
                        return;
                    }
                }
                
                // 保存更改
                DataTable udtrw = null;
                udtrw = dtrw.GetChanges();
                DataTable udt2 = null; // 表二
                udt2 = dt2.GetChanges();
                DataTable udt1 = null; // 表一
                udt1 = dt1.GetChanges();
                
                KcDb.GetDtSaven(ft1, udt1, ft2, udt2, "x9_bprw", udtrw, ft1djrzd, ft2djbjzd, "wcsj,wcry,rwzy,rwexec,sfwc");
                dtrw.AcceptChanges();
                dt1.AcceptChanges();
                dt2.AcceptChanges();
                
                udtrw = null;
                udt2 = null;
                udt1 = null;
                
                sftj = true;  // 标记已提交
                Djload();     // 重新加载单据
                
                if (fmgl != null)
                {
                    fmgl.Tag = "";  // 清空关联信息缓存
                }
                KcDb.DBclose();
            }
            catch (Exception ex)
            {
                MsgExShow("登记单据[" + dqoid + "]", ex.Message, ex.Source, ex.StackTrace);
            }
        }

        // 事件处理:确定按钮点击(保存编辑)
        private void Bardjok_itemclick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            try
            {
                string firstmc = "";
                string nextmc;
                string nextmctext;
                
                LcZT.Text = "保存中";
                this.Refresh();
                
                // 提交网格编辑器
                mtgv.PostEditor();
                mtgv.FocusedRowHandle = 1;
                mtgv.FocusedRowHandle = 0;
                DJTab.Focus();
                
                firstmc = mtgv.VisibleColumns[0].FieldName;
                nextmc = mtgv.VisibleColumns[1].FieldName;
                nextmctext = mtgv.VisibleColumns[1].Caption;
                
                gsjsz = false;  // 标记公式计算结束
                
                // 保存数据
                Savedjo();   // 保存单据头
                Savedjm();   // 保存单据体
                
                sfzj = 0;    // 重置编辑状态
                sftj = false; // 标记未提交
                Djload();    // 重新加载单据
            }
            catch (Exception ex)
            {
                MsgExShow("保存单据", ex.Message, ex.Source, ex.StackTrace);
            }
        }

        // 事件处理:审核按钮点击(单张单据)
        private void Bardjsp_itemclick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            // 审核单据
            try
            {
                if (sfzf)  // 已作废不能审核
                {
                    return;
                }
                
                // 检查是否已登记
                if (dt1.Rows[dqdjh][ft1djrzd].ToString() != "")
                {
                    MsgOxShow("单件已被签收,不能完成当前操作");
                    return;
                }
                
                // 检查单据是否在当前步骤
                if (!(dt1.Rows[dqdjh][ft1lzbjzd].Equals(ft1rwbh + ft1rwmc)))
                {
                    MsgOxShow("单件已被流转或回退。不能完成当前操作");
                    return;
                }
                
                // 检查是否他人审核(取消时)
                if (sfsp)
                {
                    if (dt1.Rows[dqdjh][ft1sprzd].ToString() != pDQYH)     // 他人审核 
                    {
                        MsgOxShow("不能取消他人操作");
                        return;
                    }
                }
                
                // 执行审核/取消审核操作
                string czsql = "select x9_djsp('" + pDQYH + "','" + pBJMC + "','" + fdjmc + "','" + dqoid + "','" + ft1rwmc + "'," + (sfsp ? "false" : "true") + ")";
                string czjg = KcDb.DBexec(czsql);
                if (czjg == pDQYH)  // 操作成功
                {
                    // 更新单据头审核信息
                    dt1.Rows[dqdjh][ft1sprzd] = sfsp ? "" : pDQYH;
                    
                    // 更新单据体操作标记
                    if (dt2.DefaultView.Count > 0)
                    {
                        for (int t2r = dt2.DefaultView.Count - 1; t2r >= 0; t2r--)
                        {
                            dt2.DefaultView[t2r][ft2czbjzd] = sfsp ? 0 : 1;
                        }
                    }
                    
                    // 更新任务记录
                    DataRow[] dr;
                    dr = dtrw.Select("bpid='" + dt1.Rows[dqdjh][ft1oid].ToString() + "' and rwbh='" + ft1rwbh + "'");
                    if (dr.Length > 0)
                    {
                        int rwr = dtrw.Rows.IndexOf(dr[0]);
                        if (rwr >= 0)
                        {
                            dtrw.Rows[rwr]["wcsj"] = DateTime.Now;  // 完成时间
                            dtrw.Rows[rwr]["wcry"] = pDQYH;         // 完成人员
                            dtrw.Rows[rwr]["rwzy"] = pBJMC + pDQYH + " " + (sfsp ? "取消" : "") + " " + ft1rwmc;  // 任务摘要
                        }
                    }
                    
                    // 保存更改
                    DataTable udtrw; //
                    udtrw = dtrw.GetChanges();
                    DataTable udt2; // 表二
                    udt2 = dt2.GetChanges();
                    DataTable udt1; // 表一
                    udt1 = dt1.GetChanges();
                    
                    if (KcDb.GetDtSaven(ft1, udt1, ft2, udt2, "x9_bprw", udtrw, ft1sprzd, ft2czbjzd, "wcsj,wcry,rwzy"))
                    {
                        dt1.AcceptChanges();
                        dt2.AcceptChanges();
                        dtrw.AcceptChanges();
                    }
                    
                    udtrw = null;
                    udt2 = null;
                    udt1 = null;
                    
                    sftj = true;  // 标记已提交
                    Djload();     // 重新加载单据
                }
                else
                {
                    MsgOxShow(czjg);  // 显示错误信息
                }
                
                if (fmgl != null)
                {
                    fmgl.Tag = "";  // 清空关联信息缓存
                }
                KcDb.DBclose();
            }
            catch (Exception ex)
            {
                MsgExShow(ft1rwmc + "或取消" + ft1rwmc + "单件[" + dqoid + "]", ex.Message, ex.Source, ex.StackTrace);
            }
        }

        // 事件处理:编辑按钮点击
        private void Bardjxg_itemclick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            if (!sfzr) return;  // 未载入不能编辑
            if (!xzbj) return;  // 无编辑权限
            
            try
            {
                sfzj = 2;  // 标记为编辑状态
                Barenabled();  // 更新按钮状态
                Fmxmrw(false);  // 设置表单可编辑
                mtgv.OptionsBehavior.ReadOnly = false;  // 设置网格可编辑
                
                // 设置编辑字段的颜色
                Color cxfc = ColorTranslator.FromHtml(pCXFC);
                Color cxbc = ColorTranslator.FromHtml(pCXBC);
                string[] fdlist = ft2gxzd.Split(',');  // 可更新字段列表
                
                // 遍历网格列,设置编辑属性
                for (int i = 0; i <= mtgv.VisibleColumns.Count - 1; i++)
                {
                    string cname = mtgv.VisibleColumns[i].FieldName.ToLower();
                    if (Array.IndexOf(fdlist, cname) > -1)  // 可编辑字段
                    {
                        mtgv.VisibleColumns[i].OptionsColumn.AllowEdit = true;
                        mtgv.VisibleColumns[i].OptionsColumn.ReadOnly = false;
                        
                        // 设置颜色
                        if (!(cxfc.R == 0 && cxfc.G == 0 && cxfc.B == 0))
                        {
                            mtgv.VisibleColumns[i].AppearanceCell.ForeColor = cxfc;
                        }
                        if (!(cxbc.R == 0 && cxbc.G == 0 && cxbc.B == 0))
                        {
                            mtgv.VisibleColumns[i].AppearanceCell.BackColor = cxbc;
                        }
                    }
                    else  // 不可编辑字段
                    {
                        mtgv.VisibleColumns[i].OptionsColumn.AllowEdit = true;
                        mtgv.VisibleColumns[i].OptionsColumn.ReadOnly = true;
                    }
                }
                
                // 聚焦到第一行第一列
                mtgv.FocusedRowHandle = 0;
                mtgv.FocusedColumn = mtgv.VisibleColumns[0];
                mtgv.Focus();
                
                // 更新状态显示
                Lczs.Text = "[" + (dqdjh + 1).ToString().Trim() + "/" + dt1.Rows.Count.ToString().Trim() + "张][" + (mtgv.FocusedRowHandle + 1).ToString().Trim() + "/" + mtgv.RowCount.ToString().Trim() + "行]";
                LcZT.Text = "编辑中";
                this.Refresh();
            }
            catch (Exception ex)
            {
                MsgExShow("编辑单据", ex.Message, ex.Source, ex.StackTrace);
            }
        }

        // 方法:更新按钮启用状态
        private void Barenabled()
        {
            // 根据当前状态设置各个按钮的启用状态
            BarZR.Enabled = (sfzj == 0);  // 载入按钮
            BarTJ.Enabled = (sfzj == 0) && (sfzr && (!sftj)) && xzbj;  // 提交按钮
            BardjXG.Enabled = (sfzj == 0) && dqdjs > 0 && (!sfsp) && xzbj && (!sflz);  // 编辑按钮
            BardjCancel.Enabled = (sfzj > 0) && sfzr;  // 取消按钮
            BardjOK.Enabled = (sfzj > 0) && sfzr;  // 确定按钮
            BarDJSP.Enabled = (sfzj == 0) && sfzr && sftj && (!sfdj) && (!sfzf) && (dqdjs > 0) && (!sflz);  // 审核按钮
            BarDJDJ.Enabled = (sfzj == 0) && sfzr && sftj && ft1rxdj && sfsp && (dqdjs > 0) && (!sflz);  // 登记按钮
            BarFullSP.Enabled = (sfzj == 0) && sfzr && sftj && (!sfdj) && (!sfzf) && (dqdjs > 0) && (!sflz);  // 全部审核按钮
            BarFullDJ.Enabled = (sfzj == 0) && sfzr && sftj && ft1rxdj && sfsp && (!(sfdj)) && (dqdjs > 0) && (!sflz);  // 全部登记按钮
            BarBFSP.Enabled = (sfzj == 0) && sfzr && sftj && (!sfdj) && (!sfzf) && (dqdjs > 0) && (!sflz);  // 部分审核按钮
            BarBFDJ.Enabled = (sfzj == 0) && sfzr && sftj && ft1rxdj && sfsp && (!(sfdj)) && (dqdjs > 0) && (!sflz);  // 部分登记按钮
            Barbpht.Enabled = (sfzj == 0) && sfzr && sftj && (!sfsp) && (!sfzf) && (!sflz) && dqdjs > 0 && (ft1htbh != "" && ft1htmc != "");  // 回退按钮
            Barbphtall.Enabled = (sfzj == 0) && sfzr && sftj && (!sfsp) && (!sfzf) && (!sflz) && dqdjs > 0 && (ft1htbh != "" && ft1htmc != "");  // 全部回退按钮
            Barbplz.Enabled = (sfzj == 0) && sfzr && sftj && sfsp && (!sfzf) && (!sflz) && dqdjs > 0 && (ft1lzbh != "" && ft1lzmc != "");  // 流转按钮
            Barbplzall.Enabled = (sfzj == 0) && sfzr && sftj && sfsp && (!sfzf) && (!sflz) && dqdjs > 0 && (ft1lzbh != "" && ft1lzmc != "");  // 全部流转按钮
            BarPreview.Enabled = (sfzj == 0) && sfzr && sftj && sfsp && (!sfzf) && xzdy;  // 预览按钮
            BarPrint.Enabled = (sfzj == 0) && sfzr && sftj && sfsp && (!sfzf) && xzdy;  // 打印按钮
            Btpg1.Enabled = (sfzj == 0) && dqdjs > 0 && dqdjh != 0;  // 首张按钮
            Btpg2.Enabled = (sfzj == 0) && dqdjs > 0 && dqdjh != 0;  // 上一张按钮
            Btpg3.Enabled = (sfzj == 0) && dqdjs > 0 && dqdjh != dqdjs - 1;  // 下一张按钮
            Btpg4.Enabled = (sfzj == 0) && dqdjs > 0 && dqdjh != dqdjs - 1;  // 末张按钮
            BarCZ.Enabled = (sfzj == 0) && dqdjs > 0;  // 查找按钮
            Barwjdc.Enabled = (sfzj == 0) && sfzr && sftj && dqdjs > 0 && xzdc;  // 文件导出按钮
            RpgCk.Enabled = dqdjh > -1;  // 关联信息功能区
        }

        // 事件处理:返回按钮点击
        private void Barexit_itemclick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            try
            {
                SaveFmSet();  // 保存窗口设置
                fh = true;    // 标记为返回状态
                dt1 = null;   // 释放资源
                dt2 = null;
                this.Close();  // 关闭窗口
            }
            catch (Exception ex)
            {
                MsgExShow("返回上级窗口", ex.Message, ex.Source, ex.StackTrace);
            }
        }

        // 事件处理:全部登记按钮点击
        private void Barfulldj_itemclick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            // 登记 全部
            if (pYWQJ != KcDb.DBString("select max(ny) as ny from mlny"))
            {
                MsgOxShow("系统业务期间已经发生变化,当前操作无法完成,请重新启动本软件后再继续使用!");
                return;
            }
            
            // 确认对话框
            if (MsgSfShow("全部登记将一次性登记所有已经符合条件的单据,不符合条件的将被忽略" + Environment.NewLine +
                        "连续操作时将不显示未完成处理单据的返回信息,确定要执行全部登记吗?") != System.Windows.Forms.DialogResult.OK)
            {
                return;
            }
            
            try
            {
                string czjg;
                int wcsl = 0;  // 完成数量
                
                // 遍历所有单据
                for (int r = 0; r < dt1.Rows.Count; r++)
                {
                    // 检查单据是否在当前步骤
                    if (!(dt1.Rows[r][ft1lzbjzd].Equals(ft1rwbh + ft1rwmc)))
                    {
                        continue;
                    }
                    
                    // 检查是否已登记
                    if (dt1.Rows[r][ft1djrzd].ToString() != "")
                    {
                        continue;
                    }
                    
                    // 检查登记条件
                    if (!Getdjtj(r))
                    {
                        continue;
                    }
                    
                    try
                    {
                        // 执行登记操作
                        czjg = KcDb.DBexec("select x9_djdj('" + pDQYH + "','" + pBJMC + "','" + fdjmc + "','" + dt1.Rows[r][ft1oid] + "')");
                        if (czjg == pDQYH)  // 登记成功
                        {
                            // 更新单据头登记信息
                            dt1.Rows[r][ft1djrzd] = pDQYH;
                            
                            // 更新单据体登账标记
                            dt2.DefaultView.RowFilter = ft2oid + "='" + dt1.Rows[r][ft1oid] + "'";
                            if (dt2.DefaultView.Count > 0)
                            {
                                for (int t2r = dt2.DefaultView.Count - 1; t2r >= 0; t2r--)
                                {
                                    dt2.DefaultView[t2r][ft2djbjzd] = true;
                                }
                            }
                            
                            // 更新任务记录
                            DataRow[] dr = dtrw.Select("bpid='" + dt1.Rows[r][ft1oid].ToString() + "' and rwbh='" + ft1rwbh + "'");
                            if (dr.Length > 0)
                            {
                                int rwr = dtrw.Rows.IndexOf(dr[0]);
                                if (rwr >= 0)
                                {
                                    dtrw.Rows[rwr]["wcsj"] = DateTime.Now;  // 完成时间
                                    dtrw.Rows[rwr]["wcry"] = pDQYH;         // 完成人员
                                    dtrw.Rows[rwr]["rwzy"] = pBJMC + " " + pDQYH + " 登记";  // 任务摘要
                                    dtrw.Rows[rwr]["rwexec"] = "";         // 执行内容
                                    dtrw.Rows[rwr]["sfwc"] = true;         // 是否完成
                                }
                            }
                            wcsl += 1;  // 计数
                        }
                        else
                        {
                            MsgOxShow(czjg);  // 显示错误信息
                        }
                    }
                    catch
                    {
                        wcsl += 0;  // 错误不计入
                    }
                }
                
                // 保存更改
                DataTable udtrw = null;
                udtrw = dtrw.GetChanges();
                DataTable udt2 = null; // 表二
                udt2 = dt2.GetChanges();
                DataTable udt1 = null; // 表一
                udt1 = dt1.GetChanges();
                
                KcDb.GetDtSaven(ft1, udt1, ft2, udt2, "x9_bprw", udtrw, ft1djrzd, ft2djbjzd, "wcsj,wcry,rwzy,rwexec,sfwc");
                dt1.AcceptChanges();
                dt2.AcceptChanges();
                dtrw.AcceptChanges();
                
                udtrw = null;
                udt2 = null;
                udt1 = null;
                
                sftj = true;  // 标记已提交
                Djload();     // 重新加载单据
                MsgXxShow("全部单据登记操作已经完成,请检查结果是否正确,本次共完成 " + wcsl.ToString().Trim() + " 张单据的处理!");
                KcDb.DBclose();
            }
            catch (Exception ex)
            {
                MsgExShow("登记全部单据", ex.Message, ex.Source, ex.StackTrace);
            }
        }

        // 事件处理:全部审核按钮点击
        private void Barfullsp_itemclick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            // 审核 全部
            bool spcz;  // 审核操作:true=审核,false=取消审核
            spcz = !sfsp;  // 根据当前状态确定操作类型
            
            try
            {
                // 确认对话框
                if (MsgSfShow("全部" + (spcz ? "" : "取消") + ft1rwmc + "将一次性处理所有单件。\r\n" +
                          "连续操作时将不显示未完成操作单件的错误信息,是否继续?") != System.Windows.Forms.DialogResult.OK)
                {
                    return;
                }
                
                string czsql;
                string czjg;
                int wcsl = 0;  // 完成数量
                
                // 遍历所有单据
                for (int r = 0; r <= dt1.Rows.Count - 1; r++)
                {
                    // 检查单据是否在当前步骤
                    if (!(dt1.Rows[r][ft1lzbjzd].Equals(ft1rwbh + ft1rwmc))) // 已经流转或回退
                    {
                        continue;
                    }
                    
                    // 检查是否已签收
                    if (dt1.Rows[r][ft1djrzd].ToString().Trim() != "")      // 已经签收
                    {
                        continue;
                    }
                    
                    if (spcz)  // 审核操作
                    {
                        if (dt1.Rows[r][ft1sprzd].ToString() != "")   // 已经审核
                        {
                            continue;
                        }
                    }
                    else  // 取消审核操作
                    {
                        // 取消
                        if (dt1.Rows[r][ft1sprzd].ToString() == "")   // 未经审核
                        {
                            continue;
                        }
                        else
                        {
                            if (dt1.Rows[r][ft1sprzd].ToString() != pDQYH)     // 他人审核 
                            {
                                continue;
                            }
                        }
                    }
                    
                    try
                    {
                        // 执行审核/取消审核操作
                        czsql = "select x9_djsp('" + pDQYH + "','" + pBJMC + "','" + fdjmc + "','" + dt1.Rows[r][ft1oid] + "','" + ft1rwmc + "'," + (spcz ? "true" : "false") + ")";
                        czjg = KcDb.DBexec(czsql);
                        if (czjg == pDQYH)  // 操作成功
                        {
                            // 更新单据头审核信息
                            dt1.Rows[r][ft1sprzd] = spcz ? pDQYH : "";
                            
                            // 更新单据体操作标记
                            dt2.DefaultView.RowFilter = ft2oid + "='" + dt1.Rows[r][ft1oid] + "'";
                            if (dt2.DefaultView.Count > 0)
                            {
                                for (int t2r = dt2.DefaultView.Count - 1; t2r >= 0; t2r--)
                                {
                                    dt2.DefaultView[t2r][ft2czbjzd] = spcz;
                                }
                            }
                            
                            // 更新任务记录
                            DataRow[] dr;
                            dr = dtrw.Select("bpid='" + dt1.Rows[r][ft1oid].ToString() + "' and rwbh='" + ft1rwbh + "'");
                            if (dr.Length > 0)
                            {
                                int rwr = dtrw.Rows.IndexOf(dr[0]);
                                if (rwr >= 0)
                                {
                                    dtrw.Rows[rwr]["wcsj"] = DateTime.Now;  // 完成时间
                                    dtrw.Rows[rwr]["wcry"] = pDQYH;         // 完成人员
                                    dtrw.Rows[rwr]["rwzy"] = pBJMC + pDQYH + " " + (spcz ? "" : "取消") + " " + ft1rwmc;  // 任务摘要
                                }
                            }
                            wcsl += 1;  // 计数
                        }
                    }
                    catch (Exception ex)
                    {
                        wcsl += 0;  // 错误不计入
                    }
                }
                
                // 保存更改
                DataTable udtrw; //
                udtrw = dtrw.GetChanges();
                DataTable udt2; // 表二
                udt2 = dt2.GetChanges();
                DataTable udt1; // 表一
                udt1 = dt1.GetChanges();
                
                if (KcDb.GetDtSaven(ft1, udt1, ft2, udt2, "x9_bprw", udtrw, ft1sprzd, ft2czbjzd, "wcsj,wcry,rwzy"))
                {
                    dt1.AcceptChanges();
                    dt2.AcceptChanges();
                    dtrw.AcceptChanges();
                }
                
                udtrw = null;
                udt2 = null;
                udt1 = null;
                
                sftj = true;  // 标记已提交
                Djload();     // 重新加载单据
                MsgXxShow("全部" + (spcz ? "" : "取消") + ft1rwmc + "操作已经完成,本次共完成 " + wcsl.ToString().Trim() + " 张单件的处理!");
                KcDb.DBclose();
            }
            catch (Exception ex)
            {
                MsgExShow("全部" + (spcz ? "" : "取消") + ft1rwmc + "单件", ex.Message, ex.Source, ex.StackTrace);
            }
        }

        // 事件处理:帮助按钮点击
        private void Barhelp_itemclick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            RunHelpyy(this, fgnmc, pSFSJ);  // 运行帮助系统
        }

        // 事件处理:预览按钮点击
        private void Barpreview_itemclick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            Doprintdj(2);  // 执行打印预览
        }

        // 事件处理:打印按钮点击
        private void Barprint_itemclick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            Doprintdj(1);  // 执行打印
        }

        // 事件处理:提交按钮点击
        private void Bartj_itemclick(object sender, ItemClickEventArgs e)
        {
            Dttj();  // 执行数据提交
        }

        // 事件处理:文件导出按钮点击
        private void Barwjdc_itemclick(object sender, ItemClickEventArgs e)
        {
            try
            {
                // 检查是否有数据
                if (dt1.Rows.Count <= 0)
                {
                    MsgOxShow("没有查询结果,无法导出");
                    return;
                }
                if (dt2.Rows.Count <= 0)
                {
                    MsgOxShow("没有查询结果,无法导出");
                    return;
                }
                
                // 导出单据范围选择
                FmDJFW fmfw = new FmDJFW();
                short ksh;
                short jsh;
                fmfw.T1.Text = "1";
                fmfw.T2.Text = dt1.Rows.Count.ToString();
                fmfw.ShowDialog(this);
                if (!fmfw.sfok)  // 用户取消
                {
                    fmfw.Dispose();
                    return;
                }
                
                ksh = short.Parse(fmfw.T1.Text);
                jsh = short.Parse(fmfw.T2.Text);
                if (jsh > dt1.Rows.Count)
                {
                    jsh = (short)dt1.Rows.Count;
                }
                if (ksh > jsh || ksh <= 0)
                {
                    fmfw.Dispose();
                    return;
                }
                fmfw.Dispose();
                
                string djzs = dt1.Rows.Count.ToString().Trim() + "张";
                DataSet dsdc = new DataSet();
                
                // 复制单据头数据
                DataTable dcdt1 = dt1.Copy();
                if (ft1sprzd != "" || ft1djrzd != "")
                {
                    // 清空审批和登记信息(导出时不包含这些信息)
                    for (int r = 0; r <= dcdt1.Rows.Count - 1; r++)
                    {
                        if (ft1sprzd != "")
                        {
                            dcdt1.Rows[r][ft1sprzd] = "";
                        }
                        if (ft1djrzd != "")
                        {
                            dcdt1.Rows[r][ft1djrzd] = "";
                        }
                    }
                }
                dcdt1.TableName = ft1;
                dsdc.Tables.Add(dcdt1);
                
                // 复制单据体数据
                DataTable dcdt2 = dt2.Copy();
                dcdt2.TableName = ft2;
                dsdc.Tables.Add(dcdt2);
                
                dsdc.Tables[0].AcceptChanges();
                dsdc.Tables[1].AcceptChanges();
                
                // 删除多余的行数据(只保留选择范围)
                ksh = (short)(ksh - 1);
                jsh = (short)(jsh - 1);
                string ksoid = "";
                string jsoid = "";
                ksoid = dsdc.Tables[0].Rows[ksh][ft1oid].ToString();
                jsoid = dsdc.Tables[0].Rows[jsh][ft1oid].ToString();
                
                // 删除单据头多余行
                for (int h = 0; h <= dsdc.Tables[0].Rows.Count - 1; h++)
                {
                    if (h < ksh || h > jsh)
                    {
                        dsdc.Tables[0].Rows[h].Delete();
                    }
                }
                dsdc.Tables[0].AcceptChanges();
                
                // 删除单据体多余行(根据单据ID范围)
                for (int h = 0; h <= dsdc.Tables[1].Rows.Count - 1; h++)
                {
                    string dqoid = dsdc.Tables[1].Rows[h][ft2oid].ToString();
                    if (string.Compare(dqoid, ksoid) < 0 || string.Compare(dqoid, jsoid) > 0)
                    {
                        dsdc.Tables[1].Rows[h].Delete();
                    }
                }
                dsdc.Tables[1].AcceptChanges();
                
                // 保存文件对话框
                SaveFileDialog ofd = new SaveFileDialog();
                ofd.Filter = "xml文件|*.xml";
                ofd.InitialDirectory = pFilesXml;
                ofd.FileName = pDBmc + fdjmc.ToString().Trim() + " " + ksoid + " 至 " + jsoid + " 共 " + (jsh - ksh + 1).ToString().Trim() + " 张" + ".xml";
                
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    dsdc.WriteXml(ofd.FileName, XmlWriteMode.WriteSchema);  // 写入XML文件
                    MsgXxShow(ofd.FileName + "导出完成");
                }
                
                // 释放资源
                dcdt1 = null;
                dcdt2 = null;
                dsdc = null;
                ofd = null;
            }
            catch (Exception ex)
            {
                MsgExShow("文件导出", ex.Message, ex.Source, ex.StackTrace);
            }
        }

        // 事件处理:载入按钮点击
        private void Barzr_itemclick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            sfzr = true;  // 标记已载入
            Dtzr();       // 执行数据载入
        }

        // 方法:执行单据回退操作
        private void Bpht(int djh)
        {
            string djoid = dt1.Rows[djh][ft1oid].ToString();
            DataRow[] dr;
            
            // 删除当前及后续任务记录
            dr = dtrw.Select("bpid='" + djoid + "' and rwbh>='" + ft1rwbh + "'");
            if (dr.Length > 0)
            {
                for (int i = dr.Length - 1; i >= 0; i--)
                {
                    int r = dtrw.Rows.IndexOf(dr[i]);
                    if (r >= 0)
                    {
                        dtrw.Rows[r].Delete();
                    }
                }
            }
            
            // 创建回退任务记录
            dr = null;
            dr = dtrw.Select("bpid='" + djoid + "' and rwbh='" + ft1htbh + "'");
            if (dr.Length > 0)
            {
                int rwr = dtrw.Rows.IndexOf(dr[0]);
                if (rwr >= 0)
                {
                    dtrw.Rows[rwr]["wcry"] = "";  // 清空完成人员
                    dtrw.Rows[rwr]["wcsj"] = DBNull.Value;  // 清空完成时间
                    dtrw.Rows[rwr]["rwzy"] = pDQYH + fdjmc + ft1rwmc + " 回退";  // 任务摘要
                    dtrw.Rows[rwr]["rwexec"] = fdjmc + ft1htmc;  // 执行内容
                    dtrw.Rows[rwr]["sfwc"] = false;  // 标记为未完成
                }
            }
            
            // 更新单据状态
            {
                dt1.Rows[djh][ft1lzbjzd] = ft1htbh + ft1htmc;  // 更新流转标记
                dt1.Rows[djh][ft1sprzd] = "";  // 清空审核信息
            }
            
            // 更新单据体状态
            dt2.DefaultView.RowFilter = ft2oid + "='" + dt1.Rows[djh][ft1oid] + "'";
            if (dt2.DefaultView.Count > 0)
            {
                for (int t2r = dt2.DefaultView.Count - 1; t2r >= 0; t2r--)
                {
                    dt2.DefaultView[t2r][ft1lzbjzd] = ft1htbh + ft1htmc;  // 更新流转标记
                    dt2.DefaultView[t2r][ft2czbjzd] = 0;  // 清空操作标记
                }
            }
        }

        // 事件处理:首张按钮点击
        private void Btpg1_itemclick(object sender, EventArgs e)
        {
            // 首张
            if (dqdjs > 0)  // 有单据
            {
                dqdjh = 0;  // 跳转到第一张
                Djload();   // 加载单据
            }
            else  // 无单据
            {
                Fmxmclear(true);  // 清空表单
                Gvclear(ref mtgv);  // 清空网格
                mtgv.OptionsBehavior.ReadOnly = true;  // 设置只读
                Barenabled();  // 更新按钮状态
            }
        }

        // 事件处理:上一张按钮点击
        private void Btpg2_itemclick(object sender, EventArgs e)
        {
            if (dqdjs > 0)  // 有单据
            {
                if (dqdjh > 0)  // 不是第一张
                {
                    dqdjh -= 1;  // 上一张
                    Djload();    // 加载单据
                }
            }
        }

        // 事件处理:下一张按钮点击
        private void Btpg3_itemclick(object sender, EventArgs e)
        {
            // 下一张
            if (dqdjs > 0)  // 有单据
            {
                if (dqdjh < dqdjs - 1)  // 不是最后一张
                {
                    dqdjh += 1;  // 下一张
                    Djload();    // 加载单据
                }
            }
        }

        // 事件处理:末张按钮点击
        private void Btpg4_itemclick(object sender, EventArgs e)
        {
            if (dqdjs > 0)  // 有单据
            {
                dqdjh = dqdjs - 1;  // 跳转到最后一张
                Djload();           // 加载单据
            }
            else  // 无单据
            {
                Fmxmclear(true);  // 清空表单
                Gvclear(ref mtgv);  // 清空网格
                mtgv.OptionsBehavior.ReadOnly = true;  // 设置只读
                Barenabled();  // 更新按钮状态
            }
        }

        // 事件处理:单据体单元格值改变(公式计算)
        private void Dj_cellvaluechanged(object sender, DevExpress.XtraGrid.Views.Base.CellValueChangedEventArgs e)
        {
            // 计算公式
            // 单据行
            if (gsjsz) return;  // 防止递归调用
            gsjsz = true;       // 标记公式计算中
            
            KcDb.DBopen();
            string dqgs = "";
            string dqgsstr = "";
            string testxh = DateTime.Now.ToString("yyyyMMdd HHmmss ffff");
            
            try
            {
                // 更新关联信息
                if (jszdstr.Length <= 0)  // 无计算字段
                {
                    gsjsz = false;
                    return;
                }
                
                string dqzd = e.Column.FieldName.ToLower();     // 当前字段  
                string gsstr = "";    // 公式
                string jsstr = "";    // 计算结果
                string gscol = "";    // 公式列,计算字段
                string gscollx = "";  // 公式列类型
                DataRow[] gsrow;      // 公式行记录
                string tjstr;         // 公式触发计算条件,不计算d表公式
                
                // 查找受当前字段影响的公式
                tjstr = "jszd<>'' and ((jsgs+glzd) like '%" + dqzd + "%') and (not (jzzd like '%" + dqzd +
                                "%')) and (not jszd like 'o.%') and sfyz<=0";
                gsrow = dtgs.Select(tjstr, "jsxh");
                
                for (int c = 0; c < gsrow.Length; c++)
                {
                    gsstr = gsrow[c]["jsgs"].ToString().ToLower();
                    gscol = gsrow[c]["jszd"].ToString();
                    gsstr = Sstr(gsstr);  // 处理字符串
                    dqgs = "设计公式:" + gscol + "=" + gsstr;
                    
                    // 替换系统条件
                    gsstr = Xttj(gsstr);
                    
                    // 替换o表字段值(单据头)
                    if (gsstr.IndexOf("o.") > 0)
                    {
                        gsstr = Getgsft1(gsstr, ref DJTab);
                    }
                    
                    // 替换m表字段值(单据体)
                    if (gsstr.IndexOf("[") > 0 && gsstr.IndexOf("]") > 0)
                    {
                        gsstr = Getgsft2fd(gsstr, e.RowHandle, ref mtgv);
                    }
                    
                    gsstr = Rpnozd(gsstr);  // 替换其他字段
                    dqgsstr = "解析结果:" + gsstr;
                    jsstr = KcDb.DBString("select " + gsstr);  // 执行计算
                    
                    // 根据字段类型设置值
                    gscollx = mtgv.Columns[gscol].ColumnType.Name;
                    switch (gscollx.ToLower())
                    {
                        case "string":
                        case "char":
                        case "datetime":
                        case "date":
                        case "time": // 字符类
                            mtgv.SetRowCellValue(e.RowHandle, gscol, jsstr);
                            break;
                        case "bit":
                        case "boolean":
                            mtgv.SetRowCellValue(e.RowHandle, gscol, Convert.ToBoolean(jsstr));
                            break;
                        default:
                            mtgv.SetRowCellValue(e.RowHandle, gscol, Convert.ToDecimal(jsstr));
                            break;
                    }
                }
                KcDb.DBclose();
            }
            catch (Exception ex)
            {
                MsgExShow("计算单据体公式(" + (e.RowHandle + 1).ToString().Trim() + ")", dqgs + "\r\n" + dqgsstr + "\r\n" + ex.Message, ex.Source, ex.StackTrace);
            }
            gsjsz = false;  // 标记公式计算结束
        }

        // 事件处理:单据体焦点行改变
        private void Dj_focusedrowchanged(object sender, DevExpress.XtraGrid.Views.Base.FocusedRowChangedEventArgs e)
        {
            if (mtgv.FocusedRowHandle < 0) return;
            
            try
            {
                // 更新状态显示:当前单据/总单据 当前行/总行
                Lczs.Text = "[" + (dqdjh + 1).ToString().Trim() + "/" + dt1.Rows.Count.ToString().Trim() + "张][" + (mtgv.FocusedRowHandle + 1).ToString().Trim() + "/" + mtgv.RowCount.ToString().Trim() + "行]";
            }
            catch (Exception ex) { }
        }

        // 事件处理:单据体按钮编辑框按钮点击
        private void Djbuttonedit_buttonclick(object sender, System.EventArgs e)
        {
            ButtonEdit be = sender as ButtonEdit;
            if (mtgv.OptionsBehavior.ReadOnly) return;  // 只读状态不处理
            
            string sxstr = "";
            LayoutControl lc = DJTab.SelectedTabPage.Controls[0] as LayoutControl;
            string cktj = "";
            
            gsjsz = true;  // 标记公式计算中
            FmSRCK fmck = new FmSRCK();
            Gdbuttonedit_srck(ref fmck, this, ref mtgv, ref be, fgnbh, fgnmc, ft2, sxstr, cktj, false);  // 显示参照窗体
            fmck.Dispose();
            
            // 触发公式计算
            object bv = be.EditValue;
            be.EditValue = null;
            gsjsz = false;
            be.EditValue = bv;
        }

        // 事件处理:单据体按钮编辑框键盘按下(回车)
        private void Djbuttonedit_keydown(object sender, System.Windows.Forms.KeyEventArgs e)
        {
            if (e.KeyCode != Keys.Enter) return;  // 只处理回车键
            
            ButtonEdit be = sender as ButtonEdit;
            if (mtgv.OptionsBehavior.ReadOnly) return;  // 只读状态不处理
            
            string sxstr = "";
            LayoutControl lc = DJTab.SelectedTabPage.Controls[0] as LayoutControl;
            string cktj = "";
            
            gsjsz = true;  // 标记公式计算中
            FmSRCK fmck = new FmSRCK();
            Gdbuttonedit_srck(ref fmck, this, ref mtgv, ref be, fgnbh, fgnmc, ft2, sxstr, cktj, true);  // 显示参照窗体(键盘模式)
            fmck.Dispose();
            
            // 触发公式计算
            object bv = be.EditValue;
            be.EditValue = null;
            gsjsz = false;
            be.EditValue = bv;
        }

   }
}
相关推荐
kuankeTech6 天前
“数改智转”加速跑:外贸ERP助力钢铁智能工厂“提质增效”
大数据·人工智能·经验分享·软件开发·erp
Vicky-Min7 天前
NetSuite中保存Bill时遇到Overage的报错原因
oracle·erp
Henry-SAP7 天前
ERP(SAP) MRP 业务视角全局流程解析
人工智能·sap·软件需求·erp·sap pp
spencer_tseng9 天前
ERP CRM SCM MES PLM SRM WMS OMS HRMS
wms·crm·srm·erp·mes·plm·scm
明月看潮生16 天前
编程与数学 03-008 《看潮企业管理软件》项目开发 08 数据字典 3-2
erp·企业开发·项目实践·编程与数学·.net开发·c#编程
明月看潮生16 天前
编程与数学 03-008 《看潮企业管理软件》项目开发 09 功能定义 3-1
企业开发·项目实践·编程与数学·.net开发·c#编程
Henry-SAP18 天前
SAP(ERP) 组织结构业务视角解析
大数据·人工智能·sap·erp·sap pp
大猫子的技术日记20 天前
VibeBlog-AI 时代个人博客Agent项目开源之路[9]: 基于ui-ux-pro-max 的前端重新设计
开源项目·skill·项目实践·vibe-blog
chengrise21 天前
Oracle EBS 成本异常排查全指南:差异分摊、成本回滚场景与解决方案
运维·数据库·oracle·erp·ebs