经常使用C#开发,总会接触到对Word文档的编辑操作,排除开.Net自带的Office操作组件不说,之所以不说是由于其运行时需要Word环境,且其资料相较比较完善,需要了解的看客可以自行去百度或阅读MSDN。
本文过程中产出的Demo代码,会放在CSDN与Git上。
CSDN中Demo路径为:https://download.csdn.net/download/a13407142317/12176058
其中VS版本为VS2019(使用改版本是要跟上.Net的更新步幅)
使用环境如下:emmm…也就是使用【.Net Framework 4】(之所以为这个是因为专业领域导致的研究支撑环境,望各位见谅)
一、本段介绍的时C#中三种操作Word文档的开源组件
1.Docx
其官网网站为:[http://docx.codeplex.com/](http://docx.codeplex.com/)
git访问地址为:[https://github.com/xceedsoftware/DocX](https://github.com/xceedsoftware/DocX)
作者存放CSDN地址:
2.Aspose.Words
其网站地址为:[https://www.evget.com/product/564/update?uid=12720](https://www.evget.com/product/564/update?uid=12720)
作者存放CSDN地址:
3.NPOI
是的NPOI也可以导出Word
我将尽我所知道的从以下几点来比对和使用上述两种Word开源组件
1.介绍以及功能实现(本篇文章)
2.两者能支持的异同点
3.两者操作Word文档的效率
4.两者存在什么缺陷
其次在以上的基础上使用桥接模式封装出统一的操作对象。
最后共享自我实现一个输出Word的代码组织,欢迎大家斧正。
介绍以及功能实现。
一下为准备好的Demo代码,组织结构如下,前文中已经附上了资源连接,有需要的看客老爷可以下载
1.DocX的介绍以及功能实现
1.1. 简介
DocX是一个在不需要安装word的情况下对word进行操作的开源轻量级.net组件,是由爱尔兰的一个叫Cathal Coffey的博士生开发出来的。DocX使得操作word非常轻便,有利于减轻开发负担,提升程序效率。DocX在Codeplex和Github上都有开源。
1.2.安装与获取途径
-
http://docx.codeplex.com/releases下载获取
-
NUGET获取 在vs环境下,打开包管理控制台执行 Install-Package DocX【本文采用此方法】
-
https://github.com/WordDocX/DocX
1.3功能实现
1.3.1创建Word文档以及在Word文档中输入字符串信息
- 创建Docx文件
/// <summary>
/// 创建Docx
/// </summary>
/// <param name="strFilePath">文件路径</param>
/// <returns></returns>
public static bool CreateFile(string strFilePath)
{
try
{
DocX document = DocX.Create(strFilePath);
document.Save();
return true;
}
catch (Exception ex)
{
return false;
}
}
效果如下:
- 创建文件并向其中输入信息
/// <summary>
/// 创建文档并填充字符串信息
/// </summary>
/// <param name="strFilePath">文件路径</param>
/// <param name="strFillInfo">字符串填充信息</param>
/// <returns></returns>
public static bool CreateFileAndFillStringInfo(string strFilePath, string strFillInfo)
{
try
{
DocX document = DocX.Create(strFilePath);
Paragraph p = document.InsertParagraph();
p.Append(strFillInfo);
document.Save();
return true;
}
catch (Exception ex)
{
return false;
}
}
效果如下:
1.3.2打开Word文档并对Word文档并进行编辑
/// <summary>
/// 打开文件并填充信息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnOpenFileAndFillInfo_Click(object sender, EventArgs e)
{
Docx_WordHelper pDocx_WordHelper = new Docx_WordHelper(ModleFilePath);
pDocx_WordHelper.AddStringInfo(FillInfo);
pDocx_WordHelper.SaveAs(DocxFileOutputPath);
}
-------------------------------------------------------------------
public Docx_WordHelper(string strFilePath)
{
CurrentDocument = DocX.Load(strFilePath);
}
public void AddStringInfo(string strInfo)
{
Paragraph p = CurrentDocument.InsertParagraph();
p.Append(strInfo);
}
/// <summary>
/// 另存文件
/// </summary>
/// <param name="strFilePath"></param>
/// <returns></returns>
public bool SaveAs(string strFilePath)
{
try
{
CurrentDocument.SaveAs(strFilePath);
return true;
}
catch (Exception ex)
{
return false;
}
}
效果如下:
1.3.2.1替换字符串
替换字符有很多重载函数,自行挖掘,此处就不一一列举了。
/// <summary>
/// 替换字符
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnReplaceText_Click(object sender, EventArgs e)
{
CurrentDocx_WordHelper.ReplaceText("[Name]", "落霞与孤鹜齐飞,秋水共长天一色");
}
-----------------------------------------------------------------
#region 替换字符信息
public void ReplaceText(string strOldInfo, string strNewInfo)
{
CurrentDocument.ReplaceText(strOldInfo, strNewInfo);
}
#endregion
效果如下:
1.模板文件
替换后效果如下:
1.3.2.2指定位置插入各类信息
- 字符串
在指定位置插入字符串信息,建议最好的方法便是替换字符串,一方便、二便是能够保留替换前字符串的样式。以下中通过width=0,使用最合适的宽度并同比例缩小高度。 - 添加图片
private void btnAddImageByLocation_Click(object sender, EventArgs e)
{
CurrentDocx_WordHelper.FindLocationByText("[NameImage]");
CurrentDocx_WordHelper.AddImage(GoChinaFilePath);
CurrentDocx_WordHelper.ReplaceText("[NameImage]","");
}
-----------------------------------------------------------------------
/// <summary>
/// 通过字符串定位
/// </summary>
/// <param name="strInfo"></param>
public void FindLocationByText(string strInfo)
{
CurrentParagraph = CurrentDocument.Paragraphs.First(a => a.Text == strInfo);
}
/// <summary>
/// 添加图片
/// </summary>
/// <param name="strImageFilePath"></param>
public void AddImage(string strImageFilePath, int Width = 0, int Height = 0)
{
Image img = CurrentDocument.AddImage(strImageFilePath);
Picture pic = img.CreatePicture();
if (Width != 0)
{
pic.Width = Width;
pic.Height = Height;
}
else
{
int dWidth = Convert.ToInt32(CurrentDocument.PageWidth - 250);
int dHeigth = Convert.ToInt32(pic.Height * dWidth / pic.Width);
pic.Width = dWidth;
pic.Height = dHeigth;
}
Paragraph p1 = CurrentParagraph.InsertPicture(pic);
}
效果如下:
- 表与图标
private void btnAddTableByLocation_Click(object sender, EventArgs e)
{
DataTable dt = new DataTable();
DataColumn dc1 = new DataColumn();
dc1.ColumnName = "字段一";
dt.Columns.Add(dc1);
DataColumn dc2 = new DataColumn();
dc2.ColumnName = "字段二";
dt.Columns.Add(dc2);
DataColumn dc3 = new DataColumn();
dc3.ColumnName = "字段三";
dt.Columns.Add(dc3);
for (int i = 0; i < 3; i++)
{
DataRow dr = dt.NewRow();
for (int j = 0; j < 3; j++)
{
dr[j] = j;
}
dt.Rows.Add(dr);
}
CurrentDocx_WordHelper.FindLocationByText("[FillTable]");
CurrentDocx_WordHelper.AddTable(dt);
CurrentDocx_WordHelper.ReplaceText("[FillTable]", "");
}
--------------------------------------------------------------------------------------------
/// <summary>
/// 插入表
/// </summary>
/// <param name="dt"></param>
public void AddTable(DataTable dt)
{
Table table=CurrentParagraph.InsertTableAfterSelf(dt.Rows.Count + 1, dt.Columns.Count);
table.Design = TableDesign.ColorfulGridAccent2;
table.Alignment = Alignment.center;
for (int i = 0; i < dt.Columns.Count; i++)
{
table.Rows[0].Cells[i].Paragraphs[0].Append(dt.Columns[i].ColumnName);
}
int index = 1;
foreach (DataRow dr in dt.Rows)
{
for (int i = 0; i < dt.Columns.Count; i++)
{
table.Rows[index].Cells[i].Paragraphs[0].Append(dr[i].ToString());
}
index++;
}
}
效果如下:
最后在依次执行上述后实现如下效果,向最美逆行和钟南山院士致敬
2.Aspose.Words的介绍以及功能实现
2.1. 简介
Aspose.Words是一款先进的类库,可以直接在各个应用程序中执行各种文档处理任务。在不使用Microsoft Word的情况下,仍然可以生成,更改,转换,渲染和打印文档,并且支持DOC,OOXML,RTF,HTML,OpenDocument, PDF, XPS, EPUB和其他格式。
Aspose.Words for .NET支持.NET框架(包括C#、VB.NET、ASP.NET等等)、ASP, ColdFusion、Perl、Power Builder、 PHP、 Python 和 Mono。
2.2.安装与获取途径
- NUGET获取 在vs环境下,打开包管理控制台执行 Install-Package Aspose.Words【本文采用此方法,此种方法存在许可证,对于这种,能解决,百度去,本文就不说了…】
2.3功能实现
- 创建Docx文件
1.3.1创建Word文档
那么仿照Docx代码如下:
using Aspose.Words;
using Aspose.Words.Replacing;
using Aspose.Words.Tables;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
namespace OpenCodeAsposeWordDemo
{
public class AsposeWord_WordHelper
{
private Document CurrentDocument = null;
private DocumentBuilder CurrentDocumentBuilder = null;
/// <summary>
/// 当前文档文件路径
/// </summary>
public string CurrentStringFilePath
{
get;
private set;
}
public AsposeWord_WordHelper()
{
}
public AsposeWord_WordHelper(string strFilePath)
{
OpenFile(strFilePath);
}
/// <summary>
/// 创建文件
/// </summary>
/// <param name="strFilePath"></param>
/// <returns></returns>
public bool CreateFile(string strFilePath)
{
try
{
OpenFile(strFilePath);
return true;
}
catch (Exception ex)
{
return false;
}
}
/// <summary>
/// 打开文件
/// </summary>
/// <param name="strFilePath"></param>
public void OpenFile(string strFilePath)
{
CurrentStringFilePath = strFilePath;
CurrentDocument = new Document(strFilePath);
CurrentDocumentBuilder = new DocumentBuilder(CurrentDocument);
}
public void Save()
{
CurrentDocument.Save(CurrentStringFilePath);
}
public void SaveAs(string strFilePath)
{
CurrentDocument.Save(strFilePath);
}
#region 替换字符信息
public void ReplaceText(string strOldInfo, string strNewInfo)
{
CurrentDocument.Range.Replace(strOldInfo, strNewInfo, new FindReplaceOptions());
}
#endregion
#region 指定位置添加信息
/// <summary>
/// 通过字符串定位
/// </summary>
/// <param name="strInfo"></param>
public void FindLocationByText(string strInfo)
{
CurrentDocumentBuilder.MoveToBookmark(strInfo);
}
/// <summary>
/// 添加描述信息
/// </summary>
/// <param name="strInfo"></param>
public void AddString(string strInfo)
{
CurrentDocumentBuilder.Font.Size = 18;
CurrentDocumentBuilder.Font.Name = "宋体";
CurrentDocumentBuilder.Bold = true;
CurrentDocumentBuilder.Writeln(strInfo);
}
/// <summary>
/// 通过书签添加字符串信息
/// </summary>
/// <param name="strBookmarkName"></param>
/// <param name="strInfo"></param>
public void AddStringByBookMark(string strBookmarkName, string strInfo)
{
CurrentDocumentBuilder.MoveToBookmark(strInfo);
CurrentDocumentBuilder.Font.Size = 18;
CurrentDocumentBuilder.Font.Name = "宋体";
CurrentDocumentBuilder.Bold = true;
CurrentDocumentBuilder.Writeln(strInfo);
}
/// <summary>
/// 添加图片
/// </summary>
/// <param name="strImageFilePath"></param>
public void AddImage(string strImageFilePath, int Width = 0, int Height = 0)
{
CurrentDocumentBuilder.InsertImage(strImageFilePath);
}
/// <summary>
/// 通过书签添加图片
/// </summary>
/// <param name="strBookmarkName"></param>
/// <param name="strInfo"></param>
public void AddImageByBookMark(string strBookmarkName, string strImageFilePath, int Width = 0, int Height = 0)
{
CurrentDocumentBuilder.MoveToBookmark(strBookmarkName);
CurrentDocumentBuilder.InsertImage(strImageFilePath);
}
/// <summary>
/// 添加超链接
/// </summary>
/// <param name="strLinkAddress"></param>
public void AddLink(string strLinkAddress, string strLinkName)
{
CurrentDocumentBuilder.InsertHyperlink(strLinkAddress, strLinkName, false);
}
/// <summary>
/// 通过书签添加超链接
/// </summary>
/// <param name="strBookmarkName"></param>
/// <param name="strInfo"></param>
public void AddLinkByBookMark(string strBookmarkName, string strLinkName, string strLinkAddress)
{
CurrentDocumentBuilder.MoveToBookmark(strBookmarkName);
CurrentDocumentBuilder.InsertHyperlink(strLinkAddress, strLinkName, false);
}
/// <summary>
/// 插入表
/// </summary>
/// <param name="dt"></param>
public void AddTable(DataTable dt)
{
int RowIndex = 1;
CurrentDocumentBuilder.StartTable();
RowFormat rowf = CurrentDocumentBuilder.RowFormat;
rowf.Height = 40;
//设置单元格是否水平合并,None为不合并
CurrentDocumentBuilder.CellFormat.HorizontalMerge = CellMerge.None;
//设置单元格是否垂直合并,None为不合并
CurrentDocumentBuilder.CellFormat.VerticalMerge = CellMerge.None;
//设置单元格宽
CurrentDocumentBuilder.CellFormat.Width = 80;
//单元格垂直对齐方向
CurrentDocumentBuilder.CellFormat.VerticalAlignment = CellVerticalAlignment.Center;
//单元格水平对齐方向
CurrentDocumentBuilder.ParagraphFormat.Alignment = ParagraphAlignment.Center;
//单元格内文字设为多行(默认为单行,会影响单元格宽)
//单元格内添加文字
CurrentDocumentBuilder.CellFormat.FitText = true;
foreach (DataColumn dc in dt.Columns)
{
//插入一个单元格
CurrentDocumentBuilder.InsertCell();
CurrentDocumentBuilder.Write(dc.ColumnName);
}
CurrentDocumentBuilder.EndRow();
for (int i = 0; i < dt.Rows.Count; i++)
{
DataRow dr = dt.Rows[i];
Aspose.Words.Tables.Row r2 = new Aspose.Words.Tables.Row(CurrentDocument);
foreach (DataColumn dc in dt.Columns)
{
//插入一个单元格
CurrentDocumentBuilder.InsertCell();
CurrentDocumentBuilder.Write(dr[dc].ToString());
}
CurrentDocumentBuilder.EndRow(); //添加一行
}
CurrentDocumentBuilder.EndTable();
}
#endregion
}
}
Aspose的许可会发生什么问题,问题如下:
至此本片文章结束
psCSDN的代码粘贴不能有空行,不然会出现bug