
【场景】生成word合同,套打不支持
【原因】按照既有框架无法实现,所有逻辑均由控件+位置渲染实现,而非合同样式
【案例】自定义word模板,自实现word合同生成;获取单据头、单据体、基础资料的子字段
(备注:代码仅做参考,部分代码需要根据自己的场景实现)
<1>word模板定义

其中字段占位符使用实现;
```config
<$txt_fieldKey$>
<$txt_basefieldKey.subprop$>
```
<2>插件代码
图片、表格逻辑没有实现,可参考[npoi word模板](https://www.cnblogs.com/zhoushangwu/p/15603425.html)
```csharp
using Kingdee.BOS.Core.DynamicForm.PlugIn;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args;
using Kingdee.BOS.Core.Metadata;
using Kingdee.BOS.Core.Metadata.EntityElement;
using Kingdee.BOS.Core.Metadata.FieldElement;
using Kingdee.BOS.Orm.DataEntity;
using Kingdee.BOS.ServiceHelper;
using NPOI.XWPF.UserModel;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Text.RegularExpressions;
namespace DynamicFormPlugIn.NotePrint
{
[Kingdee.BOS.Util.HotUpdate]
public class CustomWordExportPlugIn : AbstractDynamicFormPlugIn
{
public override void BarItemClick(BarItemClickEventArgs e)
{
if (!string.Equals(e.BarItemKey, "tb_CustomWordExport", StringComparison.OrdinalIgnoreCase))
return;
string formId = "PUR_PurchaseOrder";
int pk = 107463;
string templateFilePath = Kingdee.BOS.Util.PathUtils.GetPhysicalPath("TempfilePath", "template.docx");
string saveFilePath = Kingdee.BOS.Util.PathUtils.GetPhysicalPath("TempfilePath", string.Format("{0}_{1}.docx", formId, pk));
FormMetadata metadata = MetaDataServiceHelper.Load(this.Context, formId) as FormMetadata;
DynamicObject[] billObjs = BusinessDataServiceHelper.Load(this.Context, new object[1] { pk }, metadata.BusinessInfo.GetDynamicObjectType());
if (billObjs == null || billObjs.Length <= 0)
return;
DynamicObject billObj = billObjs[0];
BillObjGetValueHander billValHandler = new BillObjGetValueHander(metadata, billObj);
WordExporter wordExporter = new WordExporter();
using (var wordStream = wordExporter.ModelCreateWord(templateFilePath, billValHandler))
{
wordExporter.SaveWord(wordStream, saveFilePath);
}
}
}
public class BillObjGetValueHander
{
private readonly FormMetadata FormMetaData;
private BusinessInfo BillBusinessInfo
{
get { return FormMetaData.BusinessInfo; }
}
private readonly DynamicObject DataObj;
public BillObjGetValueHander(FormMetadata metadata, DynamicObject billObj)
{
FormMetaData = metadata;
DataObj = billObj;
}
/// <summary>
/// 处理字段取值
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public object GetValue(string key)
{
var spiliKeys = key.Split('.');
var fieldKey = spiliKeys[0];
var field = BillBusinessInfo.GetField(fieldKey);
if (field == null || string.IsNullOrWhiteSpace(field.PropertyName))
return null;
var entityObjs = GetEntitytObjs(field.Entity);
if (entityObjs.Count <= 0)
return null;
var entityObj = entityObjs[0];
if (!entityObj.DynamicObjectType.Properties.ContainsKey(field.PropertyName))
return null;
object dataVal = entityObj[field.PropertyName];
DynamicObject baseDataObj = dataVal as Kingdee.BOS.Orm.DataEntity.DynamicObject;
BaseDataField baseDataField = field as BaseDataField;
if (baseDataField != null && baseDataObj != null)
{
string subFieldKey = baseDataField.NameProperty.PropertyName;
if (spiliKeys.Length > 1)
{
subFieldKey = spiliKeys[1];
}
if(baseDataObj.DynamicObjectType.Properties.ContainsKey(subFieldKey))
{
return baseDataObj[subFieldKey];
}
return null;
}
//部分字段格式化可能会依赖视图,需要构造一个虚拟视图,此处不实现
//var fieldAp = FormMetaData.LayoutInfos[0].GetFieldAppearance(key);
//if(fieldAp != null)
//{
// return fieldAp.FormatListCellValue(dataVal, null, null);
//}
return dataVal;
}
/// <summary>
/// 处理图片
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public object GetPic(string key)
{
//todo
return null;
}
/// <summary>
/// 获取表格
/// </summary>
/// <param name="keys"></param>
/// <returns></returns>
public DataTable GetTable(List<string> keys)
{
//todo
return null;
}
/// <summary>
/// 处理获取实体数据包
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
private List<DynamicObject> GetEntitytObjs(Entity entity)
{
List<DynamicObject> objList = new List<DynamicObject>() { DataObj };
if (entity is HeadEntity)
{
return objList;
}
//FILO 层级路径
Stack<Entity> entityStk = new Stack<Entity>();
var rEntity = entity;
while (rEntity is SubEntryEntity)
{
entityStk.Push(rEntity);
rEntity = ((SubEntryEntity)rEntity).ParentEntity;
}
entityStk.Push(rEntity);
List<DynamicObject> lastObjColl = objList;
List<DynamicObject> tmpObjColl = null;
while (entityStk.Count > 0)
{
EntryEntity curEntity = entityStk.Pop() as EntryEntity;
if (curEntity == null)
continue;
tmpObjColl = new List<DynamicObject>();
foreach (var etyObj in lastObjColl)
{
if (!etyObj.DynamicObjectType.Properties.ContainsKey(curEntity.EntryName))
con