套打.二开案例.按照word模板生成合同
【场景】生成word合同,套打不支持
【原因】按照既有框架无法实现,所有逻辑均由控件+位置渲染实现,而非合同样式
【案例】自定义word模板,自实现word合同生成;获取单据头、单据体、基础资料的子字段
(备注:代码仅做参考,部分代码需要根据自己的场景实现)
<1>word模板定义
![93S`NUW3UG5MCW6JZ6SN3.webp](/download/0100d83fa80c970d49ffa667ef6a5cb3799e.webp)
其中字段占位符使用实现;
```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))
continue;
DynamicObjectCollection objColl = etyObj[curEntity.EntryName] as DynamicObjectCollection;
if (objColl == null || objColl.Count <= 0)
continue;
foreach (var nEtyObj in objColl)
{
tmpObjColl.Add(nEtyObj);
}
}
lastObjColl = tmpObjColl;
}
return lastObjColl;
}
}
public class WordExporter
{
// 模板开头
public string modelStart = "<$";
// 模板结束
public string modelEnd = "$>";
// 模板查找正则表达式
public string regexStr = @"<\$.*?\$>";
// 定义模板中,图片得开头
public string modelPictureStart = "pic_";
// 定义模板中,文字得开头
public string modelTextStart = "txt_";
/// <summary>
/// 通过模板创建word文档
/// </summary>
public MemoryStream ModelCreateWord(string filepath, BillObjGetValueHander billObjHandler)
{
if (billObjHandler == null)
return null;
using (FileStream stream = File.OpenRead(filepath))
{
XWPFDocument doc = new XWPFDocument(stream);
// 遍历段落
foreach (var para in doc.Paragraphs)
{
ReplaceText(para, billObjHandler);
//ReplacePictures(para, t);
}
// 处理表格
//ReplaceTables(doc, t);
// 写入流
MemoryStream ms = new MemoryStream();
doc.Write(ms);
return ms;
}
}
/// <summary>
/// 保存word文档
/// </summary>
/// <param name="ms">MemoryStream流对象</param>
/// <param name="savepath">保存地址</param>
public void SaveWord(MemoryStream ms, string savepath)
{
try
{
FileStream fs = new FileStream(savepath, FileMode.OpenOrCreate);
BinaryWriter w = new BinaryWriter(fs);
w.Write(ms.ToArray());
fs.Close();
}
catch (Exception ex)
{
throw ex;
}
}
#region 模板字符替换
private void ReplaceText(XWPFParagraph para, BillObjGetValueHander billObjHandler)
{
if (para == null)
{
throw new Exception("XWPFParagraph对象引用为null");
}
try
{
string text = para.ParagraphText;
List<string> matchTexts = GetModelName(text);
foreach (string str in matchTexts)
{
if (str.IndexOf(modelTextStart) > -1)
{
string name = str.Replace(modelTextStart, "");
string newText = Convert.ToString(billObjHandler.GetValue(name));
para.ReplaceText(modelStart + str + modelEnd, newText);
}
}
}
catch (Exception ex)
{
throw ex;
}
}
#endregion
/// <summary>
/// 获取段落中的模板参数
/// </summary>
private List<string> GetModelName(string text)
{
try
{
List<string> matchTexts = new List<string>();
Regex reg = new Regex(regexStr);
Match match = reg.Match(text);
bool result = match.Success;
while (result)
{
string matchText = match.Groups[0].Value.Replace(modelStart, "").Replace(modelEnd, "");
matchTexts.Add(matchText);
match = match.NextMatch();
result = match.Success;
}
return matchTexts;
}
catch (Exception ex)
{
throw ex;
}
}
}
}
```
【效果】
![L1COA6_SECOCTJEI~5.webp](/download/0100d514fc2438e8419b955e80cbf35c9a8b.webp)
套打.二开案例.按照word模板生成合同
【场景】生成word合同,套打不支持【原因】按照既有框架无法实现,所有逻辑均由控件+位置渲染实现,而非合同样式【案例】自定义word模板,...
点击下载文档
本文2024-09-16 18:32:55发表“云星空知识”栏目。
本文链接:https://wenku.my7c.com/article/kingdee-k3cloud-22868.html
您需要登录后才可以发表评论, 登录登录 或者 注册
最新文档
热门文章