分享一个用C#写的Aspose.Words生成word的工具类

news/2024/5/19 22:08:42 标签: c#, word, aspose.words, .netcore, dotnet, pdf

公共类

标题样式

字体大小 margin设置 标题 h1-h6

word">namespace Common.Bo
{
	word">public word">class TitleStyle
	{
		/// <summary>
		/// 标题样式
		/// </summary>
		/// <param name="tag"></param>
		/// <param name="fontSize"></param>
		/// <param name="margin"></param>
		word">public TitleStyle(word">float fontSize, word">string margin)
		{
			FontSize = fontSize;
			Margin = margin;
		}


		/// <summary>
		/// 标题样式
		/// </summary>
		/// <param name="tag"></param>
		/// <param name="fontSize"></param>
		/// <param name="margin"></param>
		word">public TitleStyle(word">string tag, word">float fontSize, word">string margin)
		{
			Tag = tag;
			FontSize = fontSize;
			Margin = margin;
		}

		word">public word">string Tag { word">get; word">set; } = "h1";
		word">public word">float FontSize { word">get; word">set; }
		word">public word">string Margin { word">get; word">set; }
		//"h1","35px","margin-top:0px;"


	}
}

word_44">word的目录信息


namespace Common.Bo
{
	/// <summary>
	/// word目录信息
	/// </summary>
	public class WordMenuInfo
	{
		public string Title { get; set; }
		public int PageNumber { get; set; }
	}
}

公共属性

标题级别 对应的标题样式 汉字与数字标题对应关系

using Aspose.Words;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Text.RegularExpressions;

namespace Common.Bo
{
	public class CommonStyle
	{
		#region 标题级别 如一级标题 三级标题
		protected const int oneTitileLevel = 1;
		protected const int twoTitileLevel = 2;
		protected const int threeTitileLevel = 3;
		protected const int fourTitileLevel = 4;
		protected const int fiveTitileLevel = 5;

		#endregion

		#region 只读的标题样式
		public static ReadOnlyDictionary<int, TitleStyle> titleDict = new ReadOnlyDictionary<int, TitleStyle>(new Dictionary<int, TitleStyle>
		{
				{ 0,new TitleStyle("h1",35,"margin-top:0px;")},
				{ 1,new TitleStyle("h1",35,"margin-top:0px;")},
				{ 2,new TitleStyle("h2",33,"margin-top:0px;")},
				{ 3,new TitleStyle("h3",32,"margin-top:0px;")},
				{ 4,new TitleStyle("h4",30,"margin-top:0px;")},
				{ 5,new TitleStyle("h5",28,"margin-top:0px;")},
		});
		#endregion

		#region 文件格式
		protected static ReadOnlyDictionary<string, string> imageFormatterDict = new ReadOnlyDictionary<string, string>
		(
				new Dictionary<string, string>{
					{ ".jpg",default},
					{ ".jpeg",default},
					{ ".png",default},
					{ ".emf",default},
					{ ".wmf",default},
					{ ".bmp",default},
				}
		);

		protected static ReadOnlyDictionary<string, string> wordFormatterDict = new ReadOnlyDictionary<string, string>
		(
				new Dictionary<string, string>{
					{ ".doc",default},
					{ ".docx",default}
				}
		);
		#endregion


		#region 数字与大小汉字对照标 最大可是999=》九百九十九
		protected static Dictionary<int, string> numberUpCaseDict = new Dictionary<int, string>()
		{
			{0,"零"},{1,"一"},{2,"二"},{3,"三"},{4,"四"},{5,"五"},
			{6,"六"},{7,"七"},{8,"八"},{9,"九"},{10,"十"}
		};
		#endregion

		#region 1-5级 标题格式规则校验与标题级别
		protected static ReadOnlyDictionary<Regex, int> titleRegexRule
			= new ReadOnlyDictionary<Regex, int>(new Dictionary<Regex, int>{
				{new Regex("^\\d{1,3}[\\.、]([^0-9]|s)"),1},
				{new Regex("^\\d{1,3}[\\.、]\\d{1,3}[\\.、]?([^0-9]|s)"),2},
				{new Regex("^\\d{1,3}[\\.、]\\d{1,3}[\\.、]\\d{1,3}[\\.、]?([^0-9]|s)"),3},
				{new Regex("^\\d{1,3}[\\.、]\\d{1,3}[\\.、]\\d{1,3}[\\.、]\\d{1,3}[\\.、]?([^0-9]|s)"),4},
				{new Regex("^\\d{1,3}[\\.、]\\d{1,3}[\\.、]\\d{1,3}[\\.、]\\d{1,3}[\\.、]\\d{1,3}[\\.、]?([^0-9]|s)"),5}
		});
		#endregion


		static CommonStyle()
		{
			int curV;
			StringBuilder sbf;
			for (int i = 11; i < 900; i++)
			{
				sbf = new StringBuilder();

				if ((curV = i / 100) > 0)
				{
					sbf.Append(numberUpCaseDict[curV] + "百");
				}
				if ((curV = i % 100 / 10) > 0)
				{
					sbf.Append(i > 10 && i < 20 ? "十" : numberUpCaseDict[curV] + "十");
				}
				else if (i > 100 && curV > 0)
				{
					sbf.Append("零");
				}

				if ((curV = i % 10) > 0)
				{
					sbf.Append(numberUpCaseDict[curV]);
				}
				numberUpCaseDict.Add(i, sbf.ToString());
			}
		}

	}
}

核心代码

生成word里面相关部分 如标题 文本 表格 图片 目录

using Aspose.Pdf.Operators;
using Aspose.Words;
using Aspose.Words.Drawing;
using Aspose.Words.Tables;
using Common.Bo;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;

namespace Common.Util
{
	/// <summary>
	/// Aspose.Words 
	/// 生成table  
	/// 生成标题
	/// 生成文本  
	/// 插入图片
	/// 生成目录
	/// 获取目录
	/// 合并word
	/// 转化pdf 
	/// 
	/// </summary>
	public class AsposeWordUtil : CommonStyle
	{

		/// <summary>
		/// 创建word document
		/// </summary>
		/// <param name="comPath"></param>
		/// <param name="comDoc"></param>
		/// <param name="comBuilder"></param>
		public static void CreateWordDocument(string comPath, out Document comDoc, out DocumentBuilder comBuilder)
		{
			comDoc = new Document(comPath);
			comBuilder = new DocumentBuilder(comDoc);
			comBuilder.PageSetup.PaperSize = PaperSize.A4;//页面设置为A4
		}

		/// <summary>
		/// 创建表格
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="curBuilder"></param>
		/// <param name="bookName"></param>
		/// <param name="list"></param>
		/// <param name="columNames"></param>
		/// <param name="propNames"></param>
		/// <param name="customFunc"></param>
		/// <param name="serialNum"></param>
		/// <param name="titleRemark"></param>
		public static void CreateTable<T>(DocumentBuilder curBuilder, string bookName, IList<T> list,
			string[] columNames, string[] propNames, Action<DocumentBuilder> customFunc = null, bool serialNum = false, string titleRemark = null)
		{
			Type tbc = typeof(T);
			Dictionary<string, Func<T, string>> titleColumsDict = new Dictionary<string, Func<T, string>>();
			for (int i = 0; i < columNames.Length; i++)
			{
				System.Reflection.PropertyInfo propertyInfo = tbc.GetProperty(propNames[i]);
				titleColumsDict[columNames[i]] = ob => propertyInfo.GetValue(ob, null)?.ToString();
			}
			CreateTable(curBuilder, bookName, list, titleColumsDict, customFunc, serialNum, titleRemark);
		}

		/// <summary>
		/// 创建表格
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="curBuilder"></param>
		/// <param name="bookName">word模板标签名称</param>
		/// <param name="list"></param>
		/// <param name="titleColumsDict">表格列名与取值的Func</param>
		/// <param name="customFunc">自定义函数处理 比如生成合计列</param>
		/// <param name="serialNum">是否需要序号</param>
		/// <param name="titleRemark">在表格之上需要生成文本信息</param>
		public static void CreateTable<T>(DocumentBuilder curBuilder, string bookName, IList<T> list, Dictionary<string, Func<T, string>> titleColumsDict
			 , Action<DocumentBuilder> customFunc = null, bool serialNum = false, string titleRemark = null)
		{
			//移到标签部分
			if (bookName != null)
			{
				curBuilder.MoveToBookmark(bookName);
			}
			//表格不存在
			if (!list.Any())
			{
				return;
			}

			string[] columNames = titleColumsDict.Select(p => p.Key).ToArray();

			//默认填写表头内容
			if (!string.IsNullOrWhiteSpace(titleRemark))
			{
				curBuilder.StartTable();
				curBuilder.ParagraphFormat.Alignment = ParagraphAlignment.Left; // RowAlignment.Center;                
				curBuilder.RowFormat.Height = 20;
				curBuilder.InsertCell();
				curBuilder.CellFormat.Width = 500 * (serialNum ? 1 : 0 + columNames.Length);
				curBuilder.CellFormat.VerticalAlignment = CellVerticalAlignment.Top;
				curBuilder.CellFormat.Borders[0].LineStyle = LineStyle.Single;
				curBuilder.CellFormat.Borders[1].LineStyle = LineStyle.None;
				curBuilder.CellFormat.Borders[2].LineStyle = LineStyle.None;
				curBuilder.CellFormat.Borders[3].LineStyle = LineStyle.None;
				//字体大小  
				curBuilder.Font.Size = 9.5d;
				//是否加粗  
				curBuilder.Bold = false;
				curBuilder.Write(titleRemark);
				curBuilder.EndRow();
				curBuilder.EndTable();
			}

			Type tbc = typeof(T);
			Table table = curBuilder.StartTable();
			curBuilder.ParagraphFormat.Alignment = ParagraphAlignment.Center; // RowAlignment.Center;                
			curBuilder.RowFormat.Height = 20;

			//操作序号列
			if (serialNum)
			{
				curBuilder.InsertCell();
				//使用固定的列宽
				//table.AutoFit(AutoFitBehavior.AutoFitToContents);
				//Table单元格边框线样式  
				curBuilder.CellFormat.Borders.LineStyle = LineStyle.Single;
				//Table此单元格宽度  
				curBuilder.CellFormat.Width = 500;
				curBuilder.CellFormat.VerticalAlignment = CellVerticalAlignment.Center;
				//字体大小  
				curBuilder.Font.Size = 10;
				//是否加粗  
				curBuilder.Bold = true;
				curBuilder.Write("序号");
			}

			//添加列头  
			for (int i = 0; i < columNames.Length; i++)
			{
				curBuilder.InsertCell();

				//使用固定的列宽
				//table.AutoFit(AutoFitBehavior.AutoFitToContents);

				//Table单元格边框线样式  
				curBuilder.CellFormat.Borders.LineStyle = LineStyle.Single;
				//Table此单元格宽度  
				curBuilder.CellFormat.Width = 500;

				curBuilder.CellFormat.VerticalAlignment = CellVerticalAlignment.Center;
				//字体大小  
				curBuilder.Font.Size = 10;
				//是否加粗  
				curBuilder.Bold = true;
				//向此单元格中添加内容  
				//builder.Write(dt.Columns[i].ColumnName);
				curBuilder.Write(columNames[i]);
			}

			curBuilder.EndRow();//结束表头行 下次InsertCell开启新的行
								//添加每行数据  
			for (int i = 0; i < list.Count; i++)
			{
				curBuilder.RowFormat.HeightRule = HeightRule.Auto;

				//操作序号列
				if (serialNum)
				{
					//插入Table单元格  
					curBuilder.InsertCell();
					//Table单元格边框线样式  
					curBuilder.CellFormat.Borders.LineStyle = LineStyle.Single;
					//字体大小  
					curBuilder.Font.Size = 10;
					//是否加粗  
					curBuilder.Bold = false;
					//向此单元格中添加内容  
					curBuilder.Write((i + 1).ToString());
				}

				foreach (var tcItem in titleColumsDict)
				{
					//插入Table单元格  
					curBuilder.InsertCell();

					//Table单元格边框线样式  
					curBuilder.CellFormat.Borders.LineStyle = LineStyle.Single;
					//字体大小  
					curBuilder.Font.Size = 10;
					//是否加粗  
					curBuilder.Bold = false;

					//向此单元格中添加内容  
					curBuilder.Write(tcItem.Value.Invoke(list[i]) ?? "");
				}
				//Table行结束  
				curBuilder.EndRow();
			}

			if (customFunc != null)
			{
				customFunc(curBuilder);
			}

			curBuilder.EndTable();
		}



		/// <summary>
		/// 设置书签具体的值
		/// </summary>
		/// <param name="v"></param>
		/// <param name="projectName"></param>
		public static void SetBookVal(Document doc, string bookName, string value)
		{
			if (!string.IsNullOrEmpty(value))
			{
				doc.Range.Bookmarks[bookName].Text = value;
			}
		}


		/// <summary>
		/// 当前的domBuiler操作 插入图片 ==》追加pdf内容
		/// </summary>
		/// <param name="curBuilder"></param>
		/// <param name="filePath"></param>
		public static void AppendImageAndPdf(DocumentBuilder curBuilder, string filePath)
		{
			//文件资源不存在 ==》不插入图片
			if (!File.Exists(filePath))
			{
				return;
			}
			//如果是文件夹
			if (Directory.Exists(filePath))
			{
				FileInfo[] fileInfoArray = new DirectoryInfo(filePath).GetFiles();

				#region 处理图片
				FileInfo[] fileInfos = fileInfoArray.Where(fi => imageFormatterDict.ContainsKey(fi.Extension.ToLower()))
					.OrderBy(f => f.Name).ToArray();
				foreach (FileInfo item in fileInfos)
				{
					AppendImageAndPdf(curBuilder, item.FullName);//将图片文件追加进去
				}
				#endregion
			}
			else
			{
				using (Image image = Image.FromFile(filePath))
				{
					curBuilder.InsertBreak(BreakType.SectionBreakNewPage);
					int imgWidth2 = image.Width;
					int imgHeight2 = image.Height;
					//适配宽高
					AdaptWh(curBuilder, ref imgWidth2, ref imgHeight2);
					curBuilder.InsertImage(image, RelativeHorizontalPosition.Page, 10.0, RelativeVerticalPosition.Page, 5.0, imgWidth2, imgHeight2, WrapType.None);
				}

			}
		}


		/// <summary>
		/// 插入标题或文本
		/// </summary>
		/// <param name="comBuilder"></param>
		/// <param name="title"></param>
		/// <param name="titleLevel"></param>
		/// <param name="newPage">插入新的一页  一般为true是防止图片把文字覆盖了</param>
		/// <param name="marginCss">额外的样式</param>
		/// <param name="isTitle">是否是1-5级标题 如果不是则用div</param>
		public static void InsertDefinedTitle(DocumentBuilder comBuilder, string title, int titleLevel, bool newPage = false,
			string marginCss = null, bool isTitle = true)
		{
			//防止被图片覆盖
			if (newPage)
			{
				comBuilder.InsertBreak(BreakType.SectionBreakNewPage);
			}
			TitleStyle curValue = null;
			curValue = titleDict.TryGetValue(titleLevel, out curValue) ? curValue : new TitleStyle("h1", 35, "margin-top:0px;");
			marginCss = marginCss ?? (curValue.Margin ?? "margin-top:0px;");
			if (newPage)
			{
				marginCss = "margin-top:300px;";
			}
			string hmark = isTitle ? curValue.Tag : "div";
			string fontSize = curValue.FontSize + "px";
			comBuilder.InsertHtml($"<{hmark} style='text-align:center;font-family:宋体;font-size:{fontSize};{marginCss}'>" + title + $"</{hmark}><br/>");
		}


		/// <summary>
		/// 插入图片
		/// </summary>
		/// <param name="curBuilder"></param>
		/// <param name="filePath"></param>
		/// <param name="imgWidth"></param>
		/// <param name="imgHeight"></param>
		public static void InsertImage(DocumentBuilder curBuilder, string filePath, int? imgWidth = null, int? imgHeight = null, WrapType wrapType = WrapType.None)
		{
			using (Image image = Image.FromFile(filePath))
			{
				int _imgWidth = imgWidth ?? image.Width;
				int _imgHeight = imgHeight ?? image.Height;
				//适配宽高
				if (imgWidth != null && imgHeight != null)
				{
					AdaptWh(curBuilder, ref _imgWidth, ref _imgHeight);
				}
				curBuilder.InsertImage(image, RelativeHorizontalPosition.Page, 10, RelativeVerticalPosition.Page, 5, _imgWidth, _imgHeight, wrapType);
			}
		}


		/// <summary>
		/// 图片适配(页面宽高)
		/// </summary>
		/// <param name="imgWidth"></param>
		/// <param name="imgHeight"></param>
		public static void AdaptWh(DocumentBuilder curBuilder, ref int imgWidth, ref int imgHeight)
		{
			int maxWidth = (int)(curBuilder.PageSetup.PageWidth * 0.92);
			int maxHeight = (int)(curBuilder.PageSetup.PageHeight * 0.92);

			//长宽比视频
			if (imgWidth > maxWidth)
			{
				imgHeight = Convert.ToInt32(decimal.Multiply(decimal.Divide(maxWidth, (int)imgWidth), (int)imgHeight));
				imgWidth = maxWidth;
			}
			if (imgHeight > maxHeight)
			{
				imgWidth = Convert.ToInt32(decimal.Multiply(decimal.Divide(maxHeight, (int)imgHeight), (int)imgWidth));
				imgHeight = maxHeight;
			}
		}


		/// <summary>
		/// 内容归档并书写页面
		/// </summary>
		/// <param name="doc">主doc</param>
		/// <param name="mergeDoc">被合并的doc</param>
		/// <param name="titleList">标题信息</param>
		/// <param name="indexTitle"></param>
		public static void PlaceOnFile(Document doc, Document mergeDoc)
		{
			doc.AppendDocument(mergeDoc, ImportFormatMode.KeepSourceFormatting);
		}

		/// <summary>
		/// 获取目录信息
		/// </summary>
		/// <param name="doc"></param>
		public static List<WordMenuInfo> GetDocMenuInfo(Document doc)
		{
			#region 获取目录信息
			List<WordMenuInfo> pageInfoList = new List<WordMenuInfo>();
			foreach (Aspose.Words.Fields.Field field in doc.Range.Fields)
			{
				if (field.Type.Equals(Aspose.Words.Fields.FieldType.FieldHyperlink))
				{
					string value;
					string[] vs;
					if (!string.IsNullOrWhiteSpace(field.Result))
					{
						//页码内容 此次使用正则获取 标题信息(含页码)
						value = Regex.Replace(field.Result, @"\s{1,20} PAGEREF _Toc\d+\s+\\h", "").Replace("\u0015", "").Replace("\u0014", "");
						value = Regex.Replace(value, @"\s{1,2}[^\d]{1,12}$", "###");
						vs = Regex.Split(value, @"\d{1,12}$");
						pageInfoList.Add(new WordMenuInfo { Title = vs[0], PageNumber = Convert.ToInt32(value.Replace(vs[0], "").Trim()) });
					}
				}
			}
			return pageInfoList;
			#endregion
		}

		/// <summary>
		/// 生成目录
		/// </summary>
		public void CreateToc(DocumentBuilder builder, string bookMark = "目录位置")
		{
			bool moveSuccess = builder.MoveToBookmark(bookMark);
			if (moveSuccess)
			{
				//目录居左
				builder.ParagraphFormat.Alignment = ParagraphAlignment.Left;
				//插入目录,这是固定的
				builder.InsertTableOfContents("\\o \"1-3\" \\h \\z \\u");
				builder.Document.UpdateFields();// 更新域
				//builder.Document.UpdatePageLayout();
			}
		}
	}
}



http://www.niftyadmin.cn/n/5236270.html

相关文章

【risc-v】易灵思efinix FPGA sapphire_soc IP配置参数分享

系列文章目录 分享一些fpga内使用riscv软核的经验&#xff0c;共大家参考。后续内容比较多&#xff0c;会做成一个系列。 本系列会覆盖以下FPGA厂商 易灵思 efinix 赛灵思 xilinx 阿尔特拉 Altera 本文内容隶属于【易灵思efinix】系列。 前言 在efinix fpga中使用riscv是一…

SCAU:链表创建与插入结点(填空)

链表创建与插入结点&#xff08;填空&#xff09; Time Limit:1000MS Memory Limit:65535K 题型: 填空题 语言: G;GCC;VC 描述 代码实现先创新一个链表&#xff0c;然后显示该链表&#xff0c;之后插入一个结点&#xff0c;再显示插入结点的链表。 请填空&#xff0c;完成…

【c++随笔15】c++常用第三方库

【c随笔15】c常用第三方库 一、数据库相关&#xff1a;HDFS、libpq、SQLite、RocksDB、unixODBC、Nanobdc、Ignite &#xff1b; 二、网络通信相关&#xff1a;libcurl、libevent、libssh、mosquitto、nghttp2、libuv&#xff1b; 三、加密和安全相关&#xff1a;1、OpenSSL 四…

生成对抗网络——研讨会

时隔一年&#xff0c;再跟着李沐大师学习了GAN之后&#xff0c;仍旧没能在离散优化中实现通用的应用&#xff0c;实在惭愧&#xff0c;借着组内研讨会的机会&#xff0c;再队GAN的前世今生做一个简单的综述。 GAN产生的背景 目前与GAN相关的应用 去reddit社区的机器学习板块…

根据豆瓣对《流浪地球》的短评数据进行文本分析和挖掘

1背景 2019年2月5日电影《流浪地球》正式在中国内地上映。该电影在举行首映的时候&#xff0c;口德好得出奇&#xff0c;所有去看片的业界大咖都发出了画样赞叹&#xff0c;文化学者能锦说:“中国科幻电影元年开启了。"导演徐峰则说&#xff0c;“里程碑式的电影&#xf…

市面上的AR眼镜:优缺点分析

AR眼镜是近年来备受关注的科技产品之一。它通过将虚拟信息叠加到现实世界中&#xff0c;为用户提供全新的视觉体验。目前&#xff0c;市面上的AR眼镜主要分为两类&#xff1a;消费级AR眼镜和企业级AR眼镜。 消费级AR眼镜 消费级AR眼镜的特点是轻便、时尚、易于佩戴&#xff0…

面试--各种场景问题总结

1.在开发过程中&#xff0c;你是如何保证机票系统的正常运行的&#xff1f; 用户、测试、监控和日志、安全措施、数据备份、系统设计、需求分析 2.在机票系统开发过程中&#xff0c;你最有成就的事情&#xff0c;为什么&#xff1f; 用户体验感、高可用和稳定性、客户满意度、系…

解决 MySQL 5.7 中的字符集兼容性问题

解决 MySQL 5.7 中的字符集兼容性问题 问题描述 错误信息&#xff1a;在 MySQL 5.7 环境中&#xff0c;尝试使用 utf8mb4_0900_ai_ci 字符集排序规则时出现错误。原因&#xff1a;utf8mb4_0900_ai_ci 是 MySQL 8.0 引入的&#xff0c;而不支持 MySQL 5.7。 解决方案 为了使…