
【场景】套打数据表格动态列,在表单模型和列表模型的实现差异
【案例】实现采购订单,单个单据的动态列套打、连续套打的动态列套打、以及合并套打的动态列套打
<1>单个单据的动态列套打
[套打数据表格动态列](https://vip.kingdee.com/article/78446215485965568?productLineId=1)
效果:

<2>连续套打的动态列
效果:


<3>合并套打的动态列
效果:

【实现逻辑】
实现差异:
<1>在列表插件中,需要知道当前任务对应的单据内码,因此需要知道打印任务列表;
<2>同时获取尺码数据部分,需要自行加载单据数据包获取(列表不一定有)
<3>针对合并套打,需要把多个单的尺码数据全部合并一起算
<4>如果支持连续套打所选分录,那么在计算尺码时需要根据列表选中行过滤(这个在这个帖子中没有实现,但是不复杂)
记录打印任务列表:

根据连续套打和合并套打,计算当前次是哪个单据或哪些单据:

列表插件获取尺码数据:

【完整代码】
```csharp
using Kingdee.BOS.Core.DynamicForm.PlugIn;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args;
using Kingdee.BOS.Core.List.PlugIn;
using Kingdee.BOS.Core.Metadata.EntityElement;
using Kingdee.BOS.Core.Metadata.FieldElement;
using Kingdee.BOS.Core.NotePrint;
using Kingdee.BOS.Orm.DataEntity;
using Kingdee.BOS.ServiceHelper;
using Kingdee.BOS.Util;
using System;
using System.Collections.Generic;
using System.Linq;
namespace DynamicFormPlugIn.NotePrint
{
[System.ComponentModel.Description("动态列插件基类")]
public class DynamicColumnHandler
{
/*
* 案例:自定义数据表格输出列
* */
///
/// 数据表格标识
///
private string DataGridId = "dataGrid1";
///
/// 动态列标识
///
private string DynamicColumnId = "column3";
private string FieldKey_MaterialId = "FMaterialId_Id";
private NotePrintArg notePrintArg = null;
public void OnQueryDynamicColumns(QueryDynamicColumnsEventArgs e)
{
if (e.DataGridId == DataGridId && e.DynamicColumnId == DynamicColumnId && e.DataSourceId == KeyConst.EntityKey)
{
notePrintArg = new NotePrintArg();
PrepareDynamicSize(notePrintArg);
if (notePrintArg == null || !notePrintArg.SizeSet.Any())
return;
var orderSizeList = notePrintArg.SizeSet.ToList();
orderSizeList.Sort();
List<DynamicColumn> dynamicCols = new List<DynamicColumn>();
//创建以"NotePrint_Size"的自定义取值标识,用作绑定数据包显示
foreach (var sizeItem in orderSizeList)
{
var dyanmicColumn = new DynamicColumn()
{
Caption = sizeItem == -1 ? "未定义" : string.Format("尺码{0}", sizeItem),
FieldKey = string.Format("NotePrint_{0}", sizeItem),
IsStatistic = false
};
dynamicCols.Add(dyanmicColumn);
}
e.DynamicColumns = dynamicCols;
}
}
public void OnPrepareNotePrintData(PreparePrintDataEventArgs e)
{
if (!e.NotePrintTplId.EqualsIgnoreCase(KeyConst.TemplateId))
return;
if (!e.DataSourceId.EqualsIgnoreCase(KeyConst.EntityKey) || e.DataObjects.Length == 0)
return;
if (notePrintArg == null || notePrintArg.SizeSet.Count == 0 || notePrintArg.IdSizeCntMap.Count == 0)
return;
var objectType = e.DynamicObjectType;
foreach (var sizeItem in notePrintArg.SizeSet)
{
var key = string.Format("NotePrint_{0}", sizeItem);
objectType.RegisterProperty(key, typeof(string));
}
List<DynamicObject> displayData = new List<DynamicObject>();
HashSet<int> fillMaterialSet = new HashSet<int>();
foreach (var dataRow in e.DataObjects)
{
var material = System.Convert.ToInt32(dataRow[FieldKey_MaterialId]);
if (fillMaterialSet.Contains(material))
continue;
fillMaterialSet.Add(material);
var newRow = new DynamicObject(objectType);
foreach (var prop in dataRow.DynamicObjectType.Properties)
{
newRow[prop] = dataRow[prop];
}
if (notePrintArg.IdSizeCntMap.ContainsKey(material))
{
foreach (var sizeQtyItem in notePrintArg.IdSizeCntMap[material])
{
var key = string.Format("NotePrint_{0}", sizeQtyItem.Key);
newRow[key] = sizeQtyItem.Value;
}
}
displayData.Add(newRow);
}
e.DataObjects = displayData.ToArray();
}
public DynamicColumnHandler(Action<NotePrintArg> prepareDynamicSizeAct)
{
PrepareDynamicSize = prepareDynamicSizeAct;
}
///
/// 准备尺寸参数
///
/// <param name="arg"></param>
public readonly Action<NotePrintArg> PrepareDynamicSize;
}
public class NotePrintArg
{
///
/// 尺寸集合
///
public HashSet<int> SizeSet;
///
/// 针对不同物料尺寸的个数
///
public Dictionary<int, Dictionary<int, int>> IdSizeCntMap;
public NotePrintArg()
{
SizeSet = new HashSet<int>();
IdSizeCntMap = new Dictionary<int, Dictionary<int, int>>();
}
}
internal static class KeyConst
{
public static string TemplateId = "ee6b0ddb-d507-44b2-b0f0-c5f093fbc807";
public static string EntityKey = "FPOOrderEntry";
public static string FieldKey_Material = "FMaterialId";
public static string FieldKey_Size = "F_BHR_Text";
public static string FieldKey_Qty = "FQty";
}
[System.ComponentModel.Description("列表动态列插件")]
[Kingdee.BOS.Util.HotUpdate]
public class ListDynamicColumnPlugIn : AbstractListPlugIn
{
/*
* 不一样的实现逻辑,
* <1>连续套打时,你需要知道当前干预的动态列是第几个单
* <2>连续套打所选分录时,需要指导选了哪些分录打印
*/
#region 通用逻辑
DynamicColumnHandler handler;
public override void OnInitialize(InitializeEventArgs e)
{
handler = new DynamicColumnHandler(PrepareDynamicSize);
}
public override void OnQueryDynamicColumns(QueryDynamicColumnsEventArgs e)
{
if (handler == null)
return;
handler.OnQueryDynamicColumns(e);
}
public override void OnPrepareNotePrintData(PreparePrintDataEventArgs e)
{
if (handler == null)
return;
handler.OnPrepareNotePrintData(e);
}
#endregion
private List<PrintJob> printJobList;
private int curJobIdx = 0;
private int curJobItemIdx = 0;
public override void BeforeNotePrintCommand(BeforeNotePrintEventArgs e)
{
if (e.PrintJobs == null)
return;
//保存下点击时对应模板的打印任务
List<PrintJob> filterPrintJobs = new List<PrintJob>();
foreach(var printJob in e.PrintJobs)
{
//节纸不支持不同单据的动态列不同,只会加载一次模板
if (printJob == null || printJob.IsEconomizePaper)
continue;
List<PrintJobItem> jobItems = new List<PrintJobItem>();
foreach(var jobItem in printJob.PrintJobItems)
{
if (!jobItem.TemplateId.EqualsIgnoreCase(KeyConst.TemplateId))
continue;
jobItems.Add(jobItem);
}
if(jobItems != null)
{
PrintJob filterJob = new PrintJob()
{
IsMergedPrint = printJob.IsMergedPrint,
PrintJobItems = jobItems
};
filterPrintJobs.Add(filterJob);
}
}
printJobList = filterPrintJobs;
curJobIdx = 0;
curJobItemIdx = 0;
}
private void PrepareDynamicSize(NotePrintArg arg)
{
/*
* 先要知道这个是哪个单,合并套打还是连续套打
* 这个代码确实有点复杂,如果不这么实现的话可以仅针对自定义菜单的时候才走这个逻辑