呆滞料分析报表二开增加自定义字段
1.金蝶云星空表单插件获取单据体数据2.金蝶云星空使用插件打开单据列表3.金蝶云星空修改单据转换规则后保存报错提示4.金蝶云星空多组织下删除基础资料报错5.金蝶云星空业务对象扩展6.金蝶云星空字段之间连续触发值更新7.生产订单执行明细表二开增加字段
8.呆滞料分析报表二开增加自定义字段
9.采购订单列表根据多条件设置单元格背景色10.金蝶云星空历史库存信息批量计算生成11.成品库存周转率报表(一)12.金蝶云星空每日库存信息存储到《历史库存信息》13.成品库存周转率报表(二)14.委外订单执行明细表增加二开字段15.金蝶云星空生产入库单找仓库仓位编码SQL脚本16.金蝶云星空创建执行计划17.金蝶云星空单据体数量汇总-分组列信息18.采购订单列表根据条件设置行背景色19.采购订单打开单据时表格行设置颜色20.金蝶云星空锁库时同时锁定序列号21.应收单审核中可以上传附件22.金蝶晕云星空表单插件:操作子单据体的删除触发父单据体的字段重算23.金蝶云星空解锁时同时解锁序列号24.金蝶云星空一个业务对象下存在两个扩展时处理方案25.金蝶云星空元数据冲突SVN:replaced,tree conflict树冲突解决过程26.创建结算清单时提示冲突解决方案27.金蝶云星空组织间结算清单增加自定义字段说明28.金蝶云星空点击按钮实现指定文件下载29.C#插件实现单据审核不通过报错提示30.金蝶云星空单据体数量合计设置业务背景
物料资料添加了自定义字段,在呆滞料分析无法直观看到,同时不能直观看到物料在仓库多久了。
业务需求
在呆滞料分析报表显示物料的品牌型号,以及计算物料库龄。
方案设计
二开标准产品,添加字段,创建插件继承标准产品插件,重写方法,自定义临时表获取初步查询结果,然后关联计算得到新字段,插入到系统生成的临时表,在报表关闭时删除自定义临时表,替换标准产品插件。
详细设计和实现
标准报表引入到应用
查询《呆滞料分析》引入到应用,同样引入《呆滞料分析过滤》
物料资料添加引用:品牌型号
报表单据体拖拽一个基础资料属性控件,关联物料资料的品牌型号
显示隐藏列:物料资料添加引用-品牌型号
添加一个基础资料属性控件,关联物料资料的品牌型号
创建插件项目
新建类库 Krystal.K3.SCGL.App.Report,添加引用【如果原来已经有类库,可跳过】
修改项目生成位置,到协同工作路径bin下
添加引用
创建类,继承报表原插件
重写BuilderReportSqlAndTempTable。
如果生产日期存在,计算库龄,今天-生产日期,生产日期为空,库龄=0;如果生产日期不显示,那无需计算。

public override void BuilderReportSqlAndTempTable(IRptParams filter, string tableName) { // base.BuilderReportSqlAndTempTable(filter, tableName); //测试表是否存在,是否有数据 //string sql1 = string.Format(@"select top 10000 * from {0}", tableName); //var sd = DBUtils.ExecuteDynamicObject(this.Context, sql1); IDBService dbservice = Kingdee.BOS.App.ServiceHelper.GetService<IDBService>(); rptTempTableNames = dbservice.CreateTemporaryTableName(this.Context, 1); string strTable = rptTempTableNames[0]; //调用基类的方法,获取初步的查询结果到临时表 base.BuilderReportSqlAndTempTable(filter, strTable); //判断临时表是否存在某个字段 string _sql = string.Format(@"{0}SELECT 1 FROM syscolumns, systypes WHERE syscolumns.xusertype = systypes.xusertype AND syscolumns.id = object_id('{1}') and syscolumns.name='FProduceDate'",OtherConst.DIALECT, strTable); var sd = DBUtils.ExecuteDynamicObject(this.Context, _sql); //初步结果处理,然后回写积累的数据到临时表 if (sd!=null && sd.Count>0) { haveProductDate = true; StringBuilder sb = new StringBuilder(); sb.AppendLine("SELECT T1.*,ROUND(isnull(datediff(month,T1.FProduceDate,GETDATE())/12.0,0),2) F_Krystal_StockYears"); sb.AppendFormat(" into {0} ", tableName); sb.AppendFormat(" FROM {0} T1", strTable); //DBUtils.Execute(this.Context, "DROP TABLE " + tableName); DBUtils.Execute(this.Context, sb.ToString()); } else { haveProductDate = false; StringBuilder sb = new StringBuilder(); sb.AppendLine("SELECT T1.*,0 F_Krystal_StockYears"); sb.AppendFormat(" into {0} ", tableName); sb.AppendFormat(" FROM {0} T1", strTable); //DBUtils.Execute(this.Context, "DROP TABLE " + tableName); DBUtils.Execute(this.Context, sb.ToString()); } }
绑定报表列头

public override ReportHeader GetReportHeaders(IRptParams filter) { ReportHeader header = base.GetReportHeaders(filter); //header.AddChild("F_Krystal_StockYears", new LocaleValue("库龄", this.Context.DefaultLocale.LCID), SqlStorageType.SqlDecimal); //List<ListHeader> childs = header.GetChilds(); //childs.Select(s=>s.FieldName.Equals("FProduceDate")).ToList().FirstOrDefault() #region 生产日期存在,才添加库龄标题 //if (!childs.Select(s => s.FieldName.Equals("FProduceDate")).ToList().FirstOrDefault()) //{ // header.AddChild("F_Krystal_StockYears", new LocaleValue("库龄", this.Context.DefaultLocale.LCID), SqlStorageType.SqlDecimal); //} #endregion #region 添加库龄标题,如果生产日期不存在,库龄不可见 //header.AddChild("F_Krystal_StockYears", new LocaleValue("库龄", this.Context.DefaultLocale.LCID), SqlStorageType.SqlDecimal); //if (!haveProductDate) //{ // var sy = childs.Where(s => s.FieldName.Equals("F_Krystal_StockYears")).ToList().FirstOrDefault(); // sy.Visible = false; //} #endregion //header.AddChild("F_Krystal_StockYears", new LocaleValue(ResManager.LoadKDString("库龄", "004021030009048", SubSystemType.SCM)), SqlStorageType.SqlDecimal); #region 生产日期存在,才添加库龄标题 if (haveProductDate) { header.AddChild("F_Krystal_StockYears", new LocaleValue("库龄", this.Context.DefaultLocale.LCID), SqlStorageType.SqlDecimal); } #endregion return header; }
汇总列

/// <summary> /// 字段汇总 /// </summary> /// <param name="filter"></param> /// <returns></returns> public override List<SummaryField> GetSummaryColumnInfo(IRptParams filter) { var lstGroupField = base.GetSummaryColumnInfo(filter); if (haveProductDate)//测试过 生产日期勾选,库龄不勾选不报错 { lstGroupField.Add(new Kingdee.BOS.Core.Report.SummaryField("F_Krystal_StockYears", BOSEnums.Enu_SummaryType.SUM)); } return lstGroupField; }
完整代码

using Kingdee.BOS; using Kingdee.BOS.App.Data; using Kingdee.BOS.Contracts; using Kingdee.BOS.Core.Enums; using Kingdee.BOS.Core.Report; using Kingdee.BOS.Util; using Kingdee.K3.SCM.App.Stock.Report; using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Krystal.K3.App.Report.STK { /// <summary> /// 功能描述 :DullMaterialAnalysisRptExtend /// 创 建 者 :Administrator /// 创建日期 :2024/7/9 17:34:24 /// 最后修改者 :Krystal /// 最后修改日期:2024/7/9 17:34:24 /// </summary> [Description("呆滞料分析服务端插件二开-报表插件"), HotUpdate] public class DullMaterialAnalysisRptExtend: DullMaterialAnalysisRpt { #region <常量> private const string DIALECT = "/*dialect*/"; #endregion <常量> #region <变量> /// <summary> /// 申请的临时表 /// </summary> private string[] rptTempTableNames; /// <summary> /// 生产日期存在,才计算库龄,和显示 /// </summary> private bool haveProductDate = false; #endregion <变量> #region <属性> #endregion <属性> #region <构造方法和析构方法> #endregion <构造方法和析构方法> #region <方法> #endregion <方法> #region <事件> public override ReportHeader GetReportHeaders(IRptParams filter) { ReportHeader header = base.GetReportHeaders(filter); //header.AddChild("F_Krystal_StockYears", new LocaleValue("库龄", this.Context.DefaultLocale.LCID), SqlStorageType.SqlDecimal); //List<ListHeader> childs = header.GetChilds(); //childs.Select(s=>s.FieldName.Equals("FProduceDate")).ToList().FirstOrDefault() #region 生产日期存在,才添加库龄标题 //if (!childs.Select(s => s.FieldName.Equals("FProduceDate")).ToList().FirstOrDefault()) //{ // header.AddChild("F_Krystal_StockYears", new LocaleValue("库龄", this.Context.DefaultLocale.LCID), SqlStorageType.SqlDecimal); //} #endregion #region 添加库龄标题,如果生产日期不存在,库龄不可见 //header.AddChild("F_Krystal_StockYears", new LocaleValue("库龄", this.Context.DefaultLocale.LCID), SqlStorageType.SqlDecimal); //if (!haveProductDate) //{ // var sy = childs.Where(s => s.FieldName.Equals("F_Krystal_StockYears")).ToList().FirstOrDefault(); // sy.Visible = false; //} #endregion //header.AddChild("F_Krystal_StockYears", new LocaleValue(ResManager.LoadKDString("库龄", "004021030009048", SubSystemType.SCM)), SqlStorageType.SqlDecimal); #region 生产日期存在,才添加库龄标题 if (haveProductDate) { header.AddChild("F_Krystal_StockYears", new LocaleValue("库龄", this.Context.DefaultLocale.LCID), SqlStorageType.SqlDecimal); } #endregion return header; } public override void BuilderReportSqlAndTempTable(IRptParams filter, string tableName) { // base.BuilderReportSqlAndTempTable(filter, tableName); //测试表是否存在,是否有数据 //string sql1 = string.Format(@"select top 10000 * from {0}", tableName); //var sd = DBUtils.ExecuteDynamicObject(this.Context, sql1); IDBService dbservice = Kingdee.BOS.App.ServiceHelper.GetService<IDBService>(); rptTempTableNames = dbservice.CreateTemporaryTableName(this.Context, 1); string strTable = rptTempTableNames[0]; //调用基类的方法,获取初步的查询结果到临时表 base.BuilderReportSqlAndTempTable(filter, strTable); //判断临时表是否存在某个字段 string _sql = string.Format(@"{0}SELECT 1 FROM syscolumns, systypes WHERE syscolumns.xusertype = systypes.xusertype AND syscolumns.id = object_id('{1}') and syscolumns.name='FProduceDate'", DIALECT, strTable); var sd = DBUtils.ExecuteDynamicObject(this.Context, _sql); //初步结果处理,然后回写积累的数据到临时表 if (sd != null && sd.Count > 0) { haveProductDate = true; StringBuilder sb = new StringBuilder(); sb.AppendLine("SELECT T1.*,ROUND(isnull(datediff(month,T1.FProduceDate,GETDATE())/12.0,0),2) F_Krystal_StockYears"); sb.AppendFormat(" into {0} ", tableName); sb.AppendFormat(" FROM {0} T1", strTable); //DBUtils.Execute(this.Context, "DROP TABLE " + tableName); DBUtils.Execute(this.Context, sb.ToString()); } else { haveProductDate = false; StringBuilder sb = new StringBuilder(); sb.AppendLine("SELECT T1.*,0 F_Krystal_StockYears"); sb.AppendFormat(" into {0} ", tableName); sb.AppendFormat(" FROM {0} T1", strTable); //DBUtils.Execute(this.Context, "DROP TABLE " + tableName); DBUtils.Execute(this.Context, sb.ToString()); } } /// <summary> /// 字段汇总 /// </summary> /// <param name="filter"></param> /// <returns></returns> public override List<SummaryField> GetSummaryColumnInfo(IRptParams filter) { var lstGroupField = base.GetSummaryColumnInfo(filter); if (haveProductDate)//测试过 生产日期勾选,库龄不勾选不报错 { lstGroupField.Add(new Kingdee.BOS.Core.Report.SummaryField("F_Krystal_StockYears", BOSEnums.Enu_SummaryType.SUM)); } return lstGroupField; } #endregion <事件> } }
编译后挂载dll到报表服务插件
取消标准插件,注册二开插件
测试
重启开发环境
打开测试网页:http://localhost:1200/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误