套打.二开案例.树形单据体子集横向打印
【场景】属性单据体,子集横向打印
![_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】可以利...
点击下载文档
本文2024-09-23 04:12:29发表“云星空知识”栏目。
本文链接:https://wenku.my7c.com/article/kingdee-k3cloud-163819.html
您需要登录后才可以发表评论, 登录登录 或者 注册
最新文档
热门文章