套打.二开案例.树形单据体子集横向打印

栏目:云星空知识作者:金蝶来源:金蝶云社区发布:2024-09-23浏览:1

套打.二开案例.树形单据体子集横向打印

【场景】属性单据体,子集横向打印 ![_O2NFY9_P8_7`V~B9B378.webp](/download/010009293017403747a3a58001d976482fc1.webp) 【案例1】可以利用原来的数据库视图,增加子单据体,但是如果层级是多级的话,子单据体也不支持 [数据库视图拆分打印](https://vip.kingdee.com/article/302821751594042112) 【案例2】插件直接修改数据包 <0>数据准备,树形单据体,父项内码和子项内码维护 ![Image_20221216162613.webp](/download/0100d8159d3344af4780b1f38b54c07a0997.webp) <1>配置套打模板,子集使用动态字段标识,本案例为 ```csharp string.Format("Dynamic_{0}_L{1}", fieldKey, level) ``` ![Image_20221216162850.webp](/download/0100702da2effc8e4d16bc977854a51f7e0b.webp) [备注]这个逻辑本质上可以和数据表格动态列一并实现,但是不是这篇文章的重点 <2>表单插件代码实现逻辑 ```csharp using Kingdee.BOS.Core.Bill.PlugIn; using Kingdee.BOS.Core.DynamicForm.PlugIn.Args; using Kingdee.BOS.Orm.DataEntity; using Kingdee.BOS.Orm.Metadata.DataEntity; using Kingdee.BOS.Util; using System; using System.Collections.Generic; using System.Linq; namespace DynamicFormPlugIn.TreeEntity { [Kingdee.BOS.Util.HotUpdate] [System.ComponentModel.Description("树形单据体子集左右打印")] public class SplitSubLevelPrint : AbstractBillPlugIn { /// <summary> /// 树形单据体的Key /// </summary> private const string TreeEntryEntityKey = "F_BHR_Entity"; private List<string> fieldKeys = new List<string>() { "F_BHR_Text","F_BHR_Decimal", }; public override void OnPrepareNotePrintQueryParam(PrepareNotePrintQueryParamEventArgs e) { base.OnPrepareNotePrintQueryParam(e); if (!string.Equals(e.DataSourceId, TreeEntryEntityKey, StringComparison.OrdinalIgnoreCase)) { return; } Action<string> addItem = (fieldKey) => { if (e.QueryParameter.SelectItems.FirstOrDefault(x => x.Key.EqualsIgnoreCase(fieldKey)) != null) return; e.QueryParameter.SelectItems.Add(new Kingdee.BOS.Core.Metadata.SelectorItemInfo(fieldKey)); }; addItem("FROWID"); addItem("FPARENTROWID"); } public override void OnPrepareNotePrintData(PreparePrintDataEventArgs e) { if(!string.Equals(e.DataSourceId, TreeEntryEntityKey, StringComparison.OrdinalIgnoreCase)) { return; } /* * 干预数据包,增加子集动态字段 */ int needAddSubLevel = 2; if (needAddSubLevel < 1) return; List<string> appendFields = new List<string>(); foreach(var key in fieldKeys) { for (int i = 1; i <= needAddSubLevel; ++i) { //增加字段 Dynamic_F_BHR_Text_L1,其中L1代表二级节点 appendFields.Add(LevelObjCale.GetLevelKey(key, i)); } } var tgtObjType = CopyDynamicObjectType(e.DynamicObjectType, appendFields); LevelObjCale calc = new LevelObjCale(e.DataObjects.ToList(), tgtObjType, needAddSubLevel, fieldKeys); var result = calc.GetResult(); //替换数据包和动态类型 e.DataObjects = result.ToArray(); e.DynamicObjectType = tgtObjType; } #region 动态属性处理 /// <summary> /// 拷贝一个动态实体类型,并追加字段(类型objet) /// 当冲突时不添加(验证冲突由外部处理) /// </summary> /// <param name="srcObjectType"></param> /// <param name="appendFieldList"></param> /// <returns></returns> private static DynamicObjectType CopyDynamicObjectType(DynamicObjectType srcObjectType, List<string> appendFieldList) { DynamicObjectType tgtObjectType = new DynamicObjectType(string.Format("{0}_Dynamic", srcObjectType.Name), srcObjectType); AppendDynamicObjectType(tgtObjectType, appendFieldList); return tgtObjectType; } /// <summary> /// 追加动态属性 /// </summary> /// <param name="srcObjectType"></param> /// <param name="appendFieldList"></param> internal static void AppendDynamicObjectType(DynamicObjectType srcObjectType, List<string> appendFieldList) { foreach (var fieldKey in appendFieldList) { if (fieldKey.IsNullOrEmptyOrWhiteSpace()) continue; if (srcObjectType.Properties.ContainsKey(fieldKey)) continue; srcObjectType.RegisterSimpleProperty(fieldKey, typeof(object), attributes: new SimplePropertyAttribute() { Alias = fieldKey }); } } #endregion } class LevelObjCale { private const string RowKey = "FROWID"; private const string ParentRowKey = "FPARENTROWID"; private readonly List<DynamicObject> SrcDataObjs; private readonly List<string> FieldKeys; private readonly DynamicObjectType TgtObjType; private readonly int TgtLevel; public LevelObjCale(List<DynamicObject> srcObjs, DynamicObjectType tgtObjType, int tgtLevel, List<string> fieldKeys) { SrcDataObjs = srcObjs; TgtObjType = tgtObjType; TgtLevel = tgtLevel; FieldKeys = fieldKeys; } public List<DynamicObject> GetResult() { resultObjs = new List<DynamicObject>(); InitLevelMap(); if (rootObjs.Count < 0) { //没有根节点的兼容 return resultObjs; } foreach (var rootObj in rootObjs) { List<DynamicObject> levelObjs = new List<DynamicObject>(); string rowId = ObjectUtils.Object2String(rootObj[RowKey]); levelObjs.Add(rootObj); DfsLevelObjs(0, rowId, levelObjs); } return resultObjs; } private List<DynamicObject> resultObjs; private List<DynamicObject> rootObjs; private Dictionary<string, List<DynamicObject>> parIdObjMap; private void InitLevelMap() { //维护父节点内码 子节点集合的映射 rootObjs = new List<DynamicObject>(); parIdObjMap = new Dictionary<string, List<DynamicObject>>(); for (int i = 0; i < SrcDataObjs.Count; ++i) { string parId = ObjectUtils.Object2String(SrcDataObjs[i][ParentRowKey]); if (parId.IsNullOrEmptyOrWhiteSpace()) { rootObjs.Add(SrcDataObjs[i]); continue; } if (!parIdObjMap.ContainsKey(parId)) { parIdObjMap[parId] = new List<DynamicObject>(); } parIdObjMap[parId].Add(SrcDataObjs[i]); } } private void DfsLevelObjs(int curLevel, string parId, List<DynamicObject> levelObjs) { if (curLevel >= TgtLevel) { //最后一层 CalcTgtObj(levelObjs); return; } if (!parIdObjMap.ContainsKey(parId)) { //没有子节点 CalcTgtObj(levelObjs); return; } var childNodes = parIdObjMap[parId]; for (int i = 0; i < childNodes.Count; ++i) { levelObjs.Add(childNodes[i]); string rowId = ObjectUtils.Object2String(childNodes[i][RowKey]); DfsLevelObjs(curLevel + 1, rowId, levelObjs); levelObjs.RemoveAt(curLevel + 1); } } private bool continueSameLevel = true; private HashSet<string> hasFillObjs = new HashSet<string>(); private bool NeedFillObj(DynamicObject rowObj) { if (!continueSameLevel) return true; string rowId = ObjectUtils.Object2String(rowObj[RowKey]); if (hasFillObjs.Contains(rowId)) return false; hasFillObjs.Add(rowId); return true; } private void CalcTgtObj(List<DynamicObject> levelObjs) { //根据层级数据包计算目标数据包 int curLvel = 0; DynamicObject tgtObj = new DynamicObject(TgtObjType); if (levelObjs.Count > 0) { if (NeedFillObj(levelObjs[0])) { FullSrcObj(levelObjs[0], tgtObj); } } for (curLvel = 1; curLvel < levelObjs.Count; ++curLvel) { if (!NeedFillObj(levelObjs[curLvel])) { continue; } foreach (var key in FieldKeys) { string dynamicKey = GetLevelKey(key, curLvel); tgtObj[dynamicKey] = levelObjs[curLvel][key]; } } resultObjs.Add(tgtObj); } //生成动态字段名称 public static string GetLevelKey(string fieldKey, int level) { return string.Format("Dynamic_{0}_L{1}", fieldKey, level); } #region 数据包处理 private static void FullSrcObj(DynamicObject srcObj, DynamicObject tgtObj) { foreach (var prop in srcObj.DynamicObjectType.Properties) { if (prop == null) continue; if (tgtObj.DynamicObjectType.Properties.ContainsKey(prop.Name)) { tgtObj[prop.Name] = srcObj[prop.Name]; } } } #endregion } } ``` 逻辑:根据树形单据体数据,先找到根节点,根据每个根节点维护子层级; 然后根据层级链路计算得到一个打印的数据包,填充各字段 【效果】只打印到三级(x.x.x) ![image.webp](/download/0100cff8256b11564bb9b153524a31cfbf9a.webp)

套打.二开案例.树形单据体子集横向打印

【场景】属性单据体,子集横向打印![_O2NFY9_P8_7`V~B9B378.webp](/download/010009293017403747a3a58001d976482fc1.webp)【案例1】可以利...
点击下载文档
确认删除?
回到顶部
客服QQ
  • 客服QQ点击这里给我发消息