公共类
公共属性
标题级别 对应的标题样式 汉字与数字标题对应关系
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());
}
}
}
}
核心代码
生成pdf里面相关部分 如段落(标题/文本) 表格 图片 目录 书签
using Aspose.Pdf;
using Aspose.Pdf.Annotations;
using Aspose.Pdf.Facades;
using Aspose.Pdf.Text;
using Common.Bo;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
namespace Common.Util
{
/// <summary>
/// Aspose.Pdf
/// 生成table
/// 生成段落:标题/普通文本
/// 生成书签
/// 插入图片
/// 合并pdf
/// 生成目录
/// </summary>
public class AsposePdfUtil : CommonStyle
{
#region pdf里面标题级别与字体大小对照关系
public static Dictionary<int, float> numberFontDict = new Dictionary<int, float>()
{
{1,25},{2,22},{3,19},{4,17},{5,15},{6,14.2f}
};
#endregion
#region 标题对应的行展示最大字符数 标题越小 展示字符越多
public static Dictionary<int, int> numberMaxShowNumsDict = new Dictionary<int, int>()
{
{1,18},{2,20},{3,22},{4,24},{5,26},{6,28}
};
#endregion
public static ReadOnlyDictionary<string, string> pdfFormatterDict = new ReadOnlyDictionary<string, string>
(
new Dictionary<string, string>{
{ ".pdf",default},
}
);
//默认字体 =》宋体
public static Aspose.Pdf.Text.Font defaultFont = FontRepository.FindFont("SimSun");
//pdf的宽度
public const double pdfPageWidth = 610f;
/// <summary>
/// 创建document
/// </summary>
/// <param name="comPath"></param>
/// <param name="comDoc"></param>
/// <param name="comBuilder"></param>
public static void CreateWordDocument(string comPath, out Document comDoc)
{
comDoc = new Document(comPath);
}
/// <summary>
/// 创建表格
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="document"></param>
/// <param name="list"></param>
/// <param name="columNames"></param>
/// <param name="propNames"></param>
/// <param name="customFunc"></param>
/// <param name="serialNum"></param>
/// <param name="projectInfo"></param>
public static void CreateTable<T>(Document document, IList<T> list,
string[] columNames, string[] propNames, Action<Document> customFunc = null, bool serialNum = false, string tableTitleRemark = 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(document, list, titleColumsDict, customFunc, serialNum, tableTitleRemark);
}
/// <summary>
/// 创建表格
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="doc"></param>
/// <param name="list"></param>
/// <param name="titleColumsDict"></param>
/// <param name="customFunc"></param>
/// <param name="serialNum"></param>
/// <param name="projectInfo"></param>
public static void CreateTable<T>(Document doc, IList<T> list, Dictionary<string, Func<T, string>> titleColumsDict
, Action<Document> customFunc = null, bool serialNum = false, string tableTitleRemark = null)
{
//表格不存在
if (!list.Any())
{
return;
}
string[] columNames = titleColumsDict.Select(p => p.Key).ToArray();
Type tbc = typeof(T);
Page page = doc.Pages.Add();
page.SetPageSize(pdfPageWidth, page.PageInfo.Height);//设置每个页码的大小一致
StringBuilder _columnWidthSbf = new StringBuilder(serialNum ? "30" : "");
int colWidth = (int)((page.GetPageRect(true).Width - (serialNum ? 50 : 0)) / columNames.Length - 2);
foreach (var item in columNames)
{
_columnWidthSbf.Append($" {colWidth}");
}
//下面的
int offsetTop = 30;
//额外的信息
if (!string.IsNullOrWhiteSpace(tableTitleRemark))
{
Aspose.Pdf.Table tab0 = new Aspose.Pdf.Table();
Paragraphs paragraphs0 = page.Paragraphs;
paragraphs0.Add(tab0);
tab0.ColumnWidths = _columnWidthSbf.ToString();
tab0.DefaultCellBorder = new Aspose.Pdf.BorderInfo(Aspose.Pdf.BorderSide.None, 0.1F);
tab0.Border = new Aspose.Pdf.BorderInfo(Aspose.Pdf.BorderSide.None, 0.1F, Aspose.Pdf.Color.FromRgb(System.Drawing.Color.White));
tab0.Margin = new Aspose.Pdf.MarginInfo(5, 2, 2, 5);
tab0.DefaultCellPadding = new Aspose.Pdf.MarginInfo(5, 1, 1, 2);
tab0.Top = offsetTop;//表格上边距
tab0.Left = 5;//表格左边距
Aspose.Pdf.Row row0 = tab0.Rows.Add();
var cell = row0.Cells.Add();
TextFragment fragment1 = CreateFragment(tableTitleRemark, 10);
//fragment1.TextState.Underline = true;
cell.Paragraphs.Add(fragment1);
cell.ColSpan = serialNum ? 1 + columNames.Length : columNames.Length;
offsetTop += 42;//让下面的主表格内容有点距离
}
Aspose.Pdf.Table tab1 = new Aspose.Pdf.Table();
Paragraphs paragraphs = page.Paragraphs;
paragraphs.Add(tab1);
tab1.ColumnWidths = _columnWidthSbf.ToString();
tab1.DefaultCellBorder = new Aspose.Pdf.BorderInfo(Aspose.Pdf.BorderSide.All, 0.1F);
tab1.Border = new Aspose.Pdf.BorderInfo(Aspose.Pdf.BorderSide.All, 0.1F, Aspose.Pdf.Color.FromRgb(System.Drawing.Color.Black));
tab1.Margin = new Aspose.Pdf.MarginInfo(5, 2, 2, 5);
//Set the default cell padding to the MarginInfo object
tab1.DefaultCellPadding = new Aspose.Pdf.MarginInfo(5, 1, 1, 2);
//不能这么设置不然整个页码都被内容挤垮了
//tab1.ColumnAdjustment = ColumnAdjustment.AutoFitToContent;
tab1.Top = offsetTop;//表格上边距
tab1.Left = 5;//表格左边距
//创建第一行(表头)
Aspose.Pdf.Row row1 = tab1.Rows.Add();
if (serialNum)
{
TextFragment fragment1 = CreateFragment("序号", 11.2f);
fragment1.TextState.FontStyle = FontStyles.Bold;
Cell cell = row1.Cells.Add();
cell.Paragraphs.Add(fragment1);
}
foreach (var item in columNames)
{
TextFragment fragment1 = CreateFragment(item, 11.2f);
fragment1.TextState.FontStyle = FontStyles.Bold;
Cell cell = row1.Cells.Add();
cell.Paragraphs.Add(fragment1);
}
//创建内容
//添加每行数据
for (int i = 0; i < list.Count; i++)
{
Aspose.Pdf.Row contentRow = tab1.Rows.Add();
//操作序号列
if (serialNum)
{
//向此单元格中添加内容
TextFragment fragment1 = CreateFragment((i + 1).ToString(), 10.2f);
//fragment1.TextState.HorizontalAlignment = HorizontalAlignment.Left;
Cell cell = contentRow.Cells.Add();
cell.Paragraphs.Add(fragment1);
}
foreach (var tcItem in titleColumsDict)
{
//向此单元格中添加内容
TextFragment fragment1 = CreateFragment(tcItem.Value.Invoke(list[i]) ?? "", 10.2f);
//fragment1.TextState.HorizontalAlignment = HorizontalAlignment.Center;
Cell cell = contentRow.Cells.Add();
cell.Paragraphs.Add(fragment1);
}
}
customFunc?.Invoke(doc);
}
/// <summary>
/// create a Fragment
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
private static TextFragment CreateFragment(string text, float fontSize)
{
TextFragment fragment1 = new TextFragment(text);
fragment1.TextState.Font = defaultFont;
fragment1.TextState.FontSize = fontSize;
fragment1.TextState.FontStyle = FontStyles.Regular;
return fragment1;
}
/// <summary>
/// 当前的domBuiler操作 插入图片 ==》追加pdf内容
/// </summary>
/// <param name="doc"></param>
/// <param name="filePath"></param>
public static void AppendImageAndPdf(Document doc, string filePath)
{
//文件资源不存在 ==》不插入图片
if (!File.Exists(filePath))
{
return;
}
//如果是pdf
if (filePath != null && filePath.EndsWith(".pdf", StringComparison.CurrentCultureIgnoreCase))
{
MergePdf(doc, new Document(filePath));
}
else
{
int imgWidth2 = 0;
int imgHeight2 = 0;
Page page = doc.Pages.Add();
page.SetPageSize(pdfPageWidth, page.PageInfo.Height);//设置每个页码的大小一致
using (System.Drawing.Image image = System.Drawing.Image.FromFile(filePath))
{
imgWidth2 = image.Width;
imgHeight2 = image.Height;
//适配宽高
AdaptWh(page, ref imgWidth2, ref imgHeight2);
//doc.InsertImage(image, RelativeHorizontalPosition.Page, 10.0, RelativeVerticalPosition.Page, 5.0, imgWidth2, imgHeight2, WrapType.None);*/
}
//按页面缩放 图片
page.AddImage(filePath, new Aspose.Pdf.Rectangle(10, 5, imgWidth2 + 10, page.GetPageRect(true).Height - 5));
}
}
/// <summary>
/// 合并pdf
/// </summary>
/// <param name="mainDoc"></param>
/// <param name="fullName"></param>
public static void MergePdf(Document mainDoc, Document mergeDoc)
{
#region 搜索页码 将页码信息置空
TextFragmentAbsorber textFragmentAbsorber = new TextFragmentAbsorber("[—第]\\s{0,4}[0-9\\u4e00-\\u9fa5]{1,6}\\s{0,4}[—页]");
TextSearchOptions textSearchOptions = new TextSearchOptions(true);
textFragmentAbsorber.TextSearchOptions = textSearchOptions;
mergeDoc.Pages.Accept(textFragmentAbsorber);
TextFragmentCollection textFragmentCollection = textFragmentAbsorber?.TextFragments;
if (textFragmentCollection != null)
{
foreach (TextFragment textFragment in textFragmentCollection)
{
textFragment.Text = "";
}
}
#endregion
mainDoc.Pages.Add(mergeDoc.Pages);
}
/// <summary>
/// 插入自定义标题 (实际是操作书签)
/// </summary>
/// <param name="comBuilder"></param>
/// <param name="title"></param>
/// <param name="titleLevel"></param>
/// <param name="newPage">插入新的一页 一般为true是防止图片把文字覆盖了</param>
/// <param name="otherCss">额外的样式</param>
/// <param name="isTitle">是否是1-5级标题 如果 字体加粗</param>
public static void InsertDefinedTitle(Document doc, string title, int titleLevel, bool newPage = true, bool isTitle = true)
{
int pos = title.IndexOf('.');
pos = pos < 0 ? 0 : pos+1;
string abosultTitle = Regex.Replace(title.Substring(pos).Trim(), "\\s", "");
if (isTitle)
{
//此处防止titleLevel设置错误 校验纠正
foreach (var regRule in TitleRegexRule)
{
if (regRule.Key.IsMatch(title))
{
titleLevel = regRule.Value;
break;
}
}
}
Page page;
if (newPage || doc.Pages.Count == 0)
{
page = doc.Pages.Add();
page.SetPageSize(pdfPageWidth, page.PageInfo.Height);//设置每个页码的大小一致
}
else
{
page = doc.Pages[doc.Pages.Count];
}
//上边距140px 默认
//double marginTop = 140;
//marginTop = CalRelativePos(page, marginTop);
TextFragment fragment0 = new TextFragment(title);
fragment0.TextState.Font = defaultFont;
fragment0.TextState.FontSize = numberFontDict[titleLevel] - 1;
fragment0.TextState.FontStyle = isTitle ? FontStyles.Bold : FontStyles.Regular;
fragment0.HorizontalAlignment = HorizontalAlignment.Center;
page.Paragraphs.Add(fragment0);
#region 创建书签
if (isTitle)
{
AddMarkBook(doc, title, page);
}
#endregion
}
public static void AddMarkBook(Document doc, string title, Page page)
{
OutlineItemCollection pdfOutline = new OutlineItemCollection(doc.Outlines);
pdfOutline.Title = title;
pdfOutline.Italic = true;
pdfOutline.Bold = true;
// Set the destination page number
pdfOutline.Action = new GoToAction(doc.Pages[page.Number]);
// Add bookmark in the document's outline collection.
doc.Outlines.Add(pdfOutline);
}
/// <summary>
/// 图片适配(页面宽高)
/// </summary>
/// <param name="imgWidth"></param>
/// <param name="imgHeight"></param>
public static void AdaptWh(Page curPage, ref int imgWidth, ref int imgHeight)
{
int maxWidth = (int)(curPage.PageInfo.Width * 0.92);
int maxHeight = (int)(curPage.PageInfo.Height * 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="positionPage ">定位的页面,如果addPage 为true则是在此位置插入一个新页 </param>
/// <param name="addPage ">如果为true为新增一页并在里面创建目录(非必填)</param>
/// <param name="firstBookMark">如果需要在最上方插入书签(非必填)</param>
public static PdfBookmarkEditor CreateToc(Document doc, int positionPage = 1, bool addPage = true, string firstBookMark = null)
{
//默认访问 PDF 文件的第一页
Page tocPage;
if (addPage)
{
//在指定位置插入一页
tocPage = doc.Pages.Insert(positionPage);
}
else
{
//在指定位置操作
tocPage = doc.Pages[positionPage];
}
//创建对象来表示 TOC 信息
TocInfo tocInfo = new TocInfo();
TextFragment title = new TextFragment("目录");
title.TextState.Font = defaultFont;
//这个设置了 会一定概率渲染失败 在生成段落阶段
//title.TextState.FontSize = 24;
title.TextState.FontStyle = FontStyles.Bold;
//设置目录标题
tocInfo.Title = title;
tocPage.TocInfo = tocInfo;
//创建将用作目录元素的字符串对象
PdfBookmarkEditor bookmarkEditor = new PdfBookmarkEditor();
bookmarkEditor.BindPdf(doc);
Aspose.Pdf.Facades.Bookmarks bookmarks = bookmarkEditor.ExtractBookmarks();
int index = 0;
foreach (Aspose.Pdf.Facades.Bookmark bookmark in bookmarks)
{
//创建标题对象 目录级别
Aspose.Pdf.Heading heading2 = new Aspose.Pdf.Heading(1);
heading2.TextState.Font = defaultFont;
heading2.TextState.FontSize = 9.3f;
heading2.TextState.LineSpacing = 5;
heading2.TextState.WordSpacing = 2;
heading2.TextState.FontStyle = FontStyles.Regular;
heading2.IsAutoSequence = false;
heading2.IsInLineParagraph = false;
heading2.HorizontalAlignment = HorizontalAlignment.Left;
//TextFragment
TextSegment segment2 = new TextSegment();
heading2.TocPage = tocPage;
#region 2-4级菜单 首行缩进
foreach (var regRule in titleRegexRule)
{
if (regRule.Key.IsMatch(bookmark.Title))
{
StringBuilder sb = new StringBuilder();
for (int i = 1; i < regRule.Value; i++)
{
sb.Append(" ");//首行缩进
}
segment2.Text = sb.ToString() + bookmark.Title;
break;
}
}
//没有匹配
if (string.IsNullOrEmpty(bookmark.Title))
{
segment2.Text = bookmark.Title;
}
#endregion
//进行换行操作
if (segment2.Text?.Length > 50)
{
segment2.Text = segment2.Text.Insert(50, "\r\n");
}
heading2.Segments.Add(segment2);
//指定标题对象的目标页面
heading2.DestinationPage = doc.Pages[bookmark.PageNumber];
//目的地页面
heading2.Top = doc.Pages[bookmark.PageNumber].Rect.Height;
//将标题添加到包含目录的页面
tocPage.Paragraphs.Add(heading2);
}
if (!string.IsNullOrEmpty(firstBookMark))
{
Aspose.Pdf.Facades.Bookmarks bookmarks2 = bookmarkEditor.ExtractBookmarks();
List<Bookmark> bookMarkList = new List<Bookmark>() { new Bookmark { Action = "GoTo", Title = firstBookMark, PageNumber = 1 } };
foreach (var item in bookmarks2)
{
bookMarkList.Add(new Bookmark
{
Action = item.Action,
Title = item.Title,
PageDisplay = item.PageDisplay,
PageNumber = item.PageNumber,
});
}
bookmarkEditor.DeleteBookmarks();
foreach (var item in bookMarkList)
{
bookmarkEditor.CreateBookmarks(item);
}
}
return bookmarkEditor;
}
/// <summary>
/// 创建页码
/// </summary>
public static void CreatePageNumber(Document doc, int startingNumber = 1)
{
// 创建页码
PageNumberStamp pageNumberStamp = new PageNumberStamp();
pageNumberStamp.Background = false;
pageNumberStamp.Format = "第 # 页";
pageNumberStamp.BottomMargin = 10;
pageNumberStamp.HorizontalAlignment = HorizontalAlignment.Center;
pageNumberStamp.StartingNumber = startingNumber;//默认起始页是第一页
pageNumberStamp.TextState.Font = FontRepository.FindFont("SimSun");//宋体
pageNumberStamp.TextState.FontSize = 10F;
pageNumberStamp.TextState.FontStyle = FontStyles.Regular;
pageNumberStamp.TextState.ForegroundColor = Aspose.Pdf.Color.Black;
foreach (Aspose.Pdf.Page page in doc.Pages)
{
//page.SetPageSize(pdfPageWidth, page.PageInfo.Height);//设置每个页码的大小一致
page.AddStamp(pageNumberStamp);
}
}
/// <summary>
/// 转化成pdf并合并到主pdf结构里面
/// </summary>
/// <param name="doc"></param>
/// <param name="temporaryFile"></param>
/// <param name="comDoc"></param>
public static void ConvertAndMergePdf(Document doc, Document mergePdfFile, Aspose.Words.Document comDoc,bool deleteMergeFile =false)
{
//合并当前word转化的pdf
MergePdf(doc, mergePdfFile);
if (deleteMergeFile)
{
File.Delete(mergePdfFile.FileName);
}
}
}
}
文章评论