
【场景】属性单据体,子集横向打印

【案例1】可以利用原来的数据库视图,增加子单据体,但是如果层级是多级的话,子单据体也不支持
[数据库视图拆分打印](https://vip.kingdee.com/article/302821751594042112)
【案例2】插件直接修改数据包
<0>数据准备,树形单据体,父项内码和子项内码维护

<1>配置套打模板,子集使用动态字段标识,本案例为
```csharp
string.Format("Dynamic_{0}_L{1}", fieldKey, level)
```

[备注]这个逻辑本质上可以和数据表格动态列一并实现,但是不是这篇文章的重点
<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;
}