一个支持DOCX、PPTX、Html等文件合并、拆分、互相转换的C#开源项目

简介: 这是一个Open XML 文档编程接口开发的,并扩展了Open XML SDK的功能。

OpenXML是一个基于XML的Office文档格式,包括docx、excel、pptx以及图表等格式,该规范是由微软开发并发布的。虽然OpenXML功能很强大,但是在实际开发过程中,我们还是会面临不少困难,毕竟其功能比较基础。

所以今天给大家推荐一个使用 Open XML 文档(DOCX、XLSX 和 PPTX)编程接口,在此基础上进行了很多优化、并实现DOCX、PPTX、Html等文件合并、拆分、互相转换等实用的功能。

项目简介

这是一个Open XML 文档编程接口开发的,并扩展了Open XML SDK的功能。

它支持以下功能:

1、将docx、pptx文件拆分为多个文件;

2、将多个docx、pptx文件合并为一个文件;

3、使用XML数据模板生成docx文件;

4、doxc文档高保值转换为Html页面;

5、html页面高保值转换为docx文档;

6、支持正则表达式搜索和替换 DOCX/PPTX 中的内容;

7、支持docx、pptx文件,管理跟踪修订,包括检测跟踪修订和接受跟踪修订;

8、更新 DOCX/PPTX 文件中的图表,包括更新缓存数据以及嵌入的 XLSX;

9、对比两个doxc文件,并生成带有修订跟踪标记的doxc文档,并支持检索修订列表;

10、支持从doxc文档检索,包括使用样式、层次结构、使用的语言与字体;

11、与直接编写标记相比,使用简单得多的代码编写XLSX文件,包括一种可以编写数百万行的XLSX文档的流式方法。

12、支持从Excel提取数据,包括内容的格式。

技术架构

1、平台:net45;net46;netstandard2.0 开发

2、开发工具:Visual Studio 2017

项目结构

图片

使用方法

该项目集成了各种功能的使用示例,下面挑几个常用的分享:

Hyml转Docx

public static void ConvertToHtml(string file, string outputDirectory)
    {
var fi = new FileInfo(file);
        Console.WriteLine(fi.Name);
byte[] byteArray = File.ReadAllBytes(fi.FullName);
using (MemoryStream memoryStream = new MemoryStream())
        {
            memoryStream.Write(byteArray, 0, byteArray.Length);
using (WordprocessingDocument wDoc = WordprocessingDocument.Open(memoryStream, true))
            {
var destFileName = new FileInfo(fi.Name.Replace(".docx", ".html"));
if (outputDirectory != null && outputDirectory != string.Empty)
                {
                    DirectoryInfo di = new DirectoryInfo(outputDirectory);
if (!di.Exists)
                    {
throw new OpenXmlPowerToolsException("Output directory does not exist");
                    }
                    destFileName = new FileInfo(Path.Combine(di.FullName, destFileName.Name));
                }
var imageDirectoryName = destFileName.FullName.Substring(0, destFileName.FullName.Length - 5) + "_files";
int imageCounter = 0;

var pageTitle = fi.FullName;
var part = wDoc.CoreFilePropertiesPart;
if (part != null)
                {
                    pageTitle = (string) part.GetXDocument().Descendants(DC.title).FirstOrDefault() ?? fi.FullName;
                }

// TODO: Determine max-width from size of content area.
                HtmlConverterSettings settings = new HtmlConverterSettings()
                {
                    AdditionalCss = "body { margin: 1cm auto; max-width: 20cm; padding: 0; }",
                    PageTitle = pageTitle,
                    FabricateCssClasses = true,
                    CssClassPrefix = "pt-",
                    RestrictToSupportedLanguages = false,
                    RestrictToSupportedNumberingFormats = false,
                    ImageHandler = imageInfo =>
                    {
                        DirectoryInfo localDirInfo = new DirectoryInfo(imageDirectoryName);
if (!localDirInfo.Exists)
                            localDirInfo.Create();
                        ++imageCounter;
string extension = imageInfo.ContentType.Split('/')[1].ToLower();
                        ImageFormat imageFormat = null;
if (extension == "png")
                            imageFormat = ImageFormat.Png;
else if (extension == "gif")
                            imageFormat = ImageFormat.Gif;
else if (extension == "bmp")
                            imageFormat = ImageFormat.Bmp;
else if (extension == "jpeg")
                            imageFormat = ImageFormat.Jpeg;
else if (extension == "tiff")
                        {
// Convert tiff to gif.
                            extension = "gif";
                            imageFormat = ImageFormat.Gif;
                        }
else if (extension == "x-wmf")
                        {
                            extension = "wmf";
                            imageFormat = ImageFormat.Wmf;
                        }

// If the image format isn't one that we expect, ignore it,
// and don't return markup for the link.
if (imageFormat == null)
return null;

string imageFileName = imageDirectoryName + "/image" +
                            imageCounter.ToString() + "." + extension;
try
                        {
                            imageInfo.Bitmap.Save(imageFileName, imageFormat);
                        }
catch (System.Runtime.InteropServices.ExternalException)
                        {
return null;
                        }
string imageSource = localDirInfo.Name + "/image" +
                            imageCounter.ToString() + "." + extension;

                        XElement img = new XElement(Xhtml.img,
new XAttribute(NoNamespace.src, imageSource),
                            imageInfo.ImgStyleAttribute,
                            imageInfo.AltText != null ?
new XAttribute(NoNamespace.alt, imageInfo.AltText) : null);
return img;
                    }
                };
                XElement htmlElement = HtmlConverter.ConvertToHtml(wDoc, settings);

// Produce HTML document with <!DOCTYPE html > declaration to tell the browser
// we are using HTML5.
var html = new XDocument(
new XDocumentType("html", null, null, null),
                    htmlElement);
var htmlString = html.ToString(SaveOptions.DisableFormatting);
                File.WriteAllText(destFileName.FullName, htmlString, Encoding.UTF8);
            }
        }
    }

Docx、PPTX文档合并

var n = DateTime.Now;
var tempDi = new DirectoryInfo(string.Format("ExampleOutput-{0:00}-{1:00}-{2:00}-{3:00}{4:00}{5:00}", n.Year - 2000, n.Month, n.Day, n.Hour, n.Minute, n.Second));
            tempDi.Create();

var sourceDi = new DirectoryInfo("../../");
foreach (var file in sourceDi.GetFiles("*.docx"))
                File.Copy(file.FullName, Path.Combine(tempDi.FullName, file.Name));
foreach (var file in sourceDi.GetFiles("*.pptx"))
                File.Copy(file.FullName, Path.Combine(tempDi.FullName, file.Name));

var fileList = Directory.GetFiles(tempDi.FullName, "*.docx");
foreach (var file in fileList)
            {
var fi = new FileInfo(file);
                Console.WriteLine(fi.Name);
var newFileName = "Updated-" + fi.Name;
var fi2 = new FileInfo(Path.Combine(tempDi.FullName, newFileName));
                File.Copy(fi.FullName, fi2.FullName);

using (var wDoc = WordprocessingDocument.Open(fi2.FullName, true))
                {
var chart1Data = new ChartData
                    {
                        SeriesNames = new[] {
"Car",
"Truck",
"Van",
"Bike",
"Boat",
                        },
                        CategoryDataType = ChartDataType.String,
                        CategoryNames = new[] {
"Q1",
"Q2",
"Q3",
"Q4",
                        },
                        Values = new double[][] {
new double[] {
100, 310, 220, 450,
                        },
new double[] {
200, 300, 350, 411,
                        },
new double[] {
80, 120, 140, 600,
                        },
new double[] {
120, 100, 140, 400,
                        },
new double[] {
200, 210, 210, 480,
                        },
                    },
                    };
                    ChartUpdater.UpdateChart(wDoc, "Chart1", chart1Data);

var chart2Data = new ChartData
                    {
                        SeriesNames = new[] {
"Series"
                        },
                        CategoryDataType = ChartDataType.String,
                        CategoryNames = new[] {
"Cars",
"Trucks",
"Vans",
"Boats",
                        },
                        Values = new double[][] {
new double[] {
320, 112, 64, 80,
                        },
                    },
                    };
                    ChartUpdater.UpdateChart(wDoc, "Chart2", chart2Data);

var chart3Data = new ChartData
                    {
                        SeriesNames = new[] {
"X1",
"X2",
"X3",
"X4",
"X5",
"X6",
                        },
                        CategoryDataType = ChartDataType.String,
                        CategoryNames = new[] {
"Y1",
"Y2",
"Y3",
"Y4",
"Y5",
"Y6",
                        },
                        Values = new double[][] {
new double[] {      3.0,      2.1,       .7,      .7,      2.1,      3.0,      },
new double[] {      3.0,      2.1,       .8,      .8,      2.1,      3.0,      },
new double[] {      3.0,      2.4,      1.2,     1.2,      2.4,      3.0,      },
new double[] {      3.0,      2.7,      1.7,     1.7,      2.7,      3.0,      },
new double[] {      3.0,      2.9,      2.5,     2.5,      2.9,      3.0,      },
new double[] {      3.0,      3.0,      3.0,     3.0,      3.0,      3.0,      },
                    },
                    };
                    ChartUpdater.UpdateChart(wDoc, "Chart3", chart3Data);

var chart4Data = new ChartData
                    {
                        SeriesNames = new[] {
"Car",
"Truck",
"Van",
                        },
                        CategoryDataType = ChartDataType.DateTime,
                        CategoryFormatCode = 14,
                        CategoryNames = new[] {
                            ToExcelInteger(new DateTime(2013, 9, 1)),
                            ToExcelInteger(new DateTime(2013, 9, 2)),
                            ToExcelInteger(new DateTime(2013, 9, 3)),
                            ToExcelInteger(new DateTime(2013, 9, 4)),
                            ToExcelInteger(new DateTime(2013, 9, 5)),
                            ToExcelInteger(new DateTime(2013, 9, 6)),
                            ToExcelInteger(new DateTime(2013, 9, 7)),
                            ToExcelInteger(new DateTime(2013, 9, 8)),
                            ToExcelInteger(new DateTime(2013, 9, 9)),
                            ToExcelInteger(new DateTime(2013, 9, 10)),
                            ToExcelInteger(new DateTime(2013, 9, 11)),
                            ToExcelInteger(new DateTime(2013, 9, 12)),
                            ToExcelInteger(new DateTime(2013, 9, 13)),
                            ToExcelInteger(new DateTime(2013, 9, 14)),
                            ToExcelInteger(new DateTime(2013, 9, 15)),
                            ToExcelInteger(new DateTime(2013, 9, 16)),
                            ToExcelInteger(new DateTime(2013, 9, 17)),
                            ToExcelInteger(new DateTime(2013, 9, 18)),
                            ToExcelInteger(new DateTime(2013, 9, 19)),
                            ToExcelInteger(new DateTime(2013, 9, 20)),
                        },
                        Values = new double[][] {
new double[] {
1, 2, 3, 2, 3, 4, 5, 4, 5, 6, 5, 4, 5, 6, 7, 8, 7, 8, 8, 9,
                        },
new double[] {
2, 3, 3, 4, 4, 5, 6, 7, 8, 7, 8, 9, 9, 9, 7, 8, 9, 9, 10, 11,
                        },
new double[] {
2, 3, 3, 3, 3, 2, 2, 2, 3, 2, 3, 3, 4, 4, 4, 3, 4, 5, 5, 4,
                        },
                    },
                    };
                    ChartUpdater.UpdateChart(wDoc, "Chart4", chart4Data);
                }
            }

            fileList = Directory.GetFiles(tempDi.FullName, "*.pptx");
foreach (var file in fileList)
            {
var fi = new FileInfo(file);
                Console.WriteLine(fi.Name);
var newFileName = "Updated-" + fi.Name;
var fi2 = new FileInfo(Path.Combine(tempDi.FullName, newFileName));
                File.Copy(fi.FullName, fi2.FullName);

using (var pDoc = PresentationDocument.Open(fi2.FullName, true))
                {
var chart1Data = new ChartData
                    {
                        SeriesNames = new[] {
"Car",
"Truck",
"Van",
                        },
                        CategoryDataType = ChartDataType.String,
                        CategoryNames = new[] {
"Q1",
"Q2",
"Q3",
"Q4",
                        },
                        Values = new double[][] {
new double[] {
320, 310, 320, 330,
                        },
new double[] {
201, 224, 230, 221,
                        },
new double[] {
180, 200, 220, 230,
                        },
                    },
                    };
                    ChartUpdater.UpdateChart(pDoc, 1, chart1Data);
                }
            }

执行Excel公式

var n = DateTime.Now;
var tempDi = new DirectoryInfo(string.Format("ExampleOutput-{0:00}-{1:00}-{2:00}-{3:00}{4:00}{5:00}", n.Year - 2000, n.Month, n.Day, n.Hour, n.Minute, n.Second));
            tempDi.Create();

// Change sheet name in formulas
using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument(
                SmlDocument.FromFileName("../../Formulas.xlsx")))
            {
using (SpreadsheetDocument doc = streamDoc.GetSpreadsheetDocument())
                {
                    WorksheetAccessor.FormulaReplaceSheetName(doc, "Source", "'Source 2'");
                }
                streamDoc.GetModifiedSmlDocument().SaveAs(Path.Combine(tempDi.FullName, "FormulasUpdated.xlsx"));
            }

// Change sheet name in formulas
using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument(
                SmlDocument.FromFileName("../../Formulas.xlsx")))
            {
using (SpreadsheetDocument doc = streamDoc.GetSpreadsheetDocument())
                {
                    WorksheetPart sheet = WorksheetAccessor.GetWorksheet(doc, "References");
                    WorksheetAccessor.CopyCellRange(doc, sheet, 1, 1, 7, 5, 4, 8);
                }
                streamDoc.GetModifiedSmlDocument().SaveAs(Path.Combine(tempDi.FullName, "FormulasCopied.xlsx"));
            }

具体示例代码如下:

图片

项目地址: https://github.com/OpenXmlDev/Open-Xml-PowerTools

- End -

专注分享编程知识、热门有用有趣的开源项目

相关文章
|
2月前
|
Web App开发 前端开发 搜索推荐
创建HTML文件
【10月更文挑战第14天】创建HTML文件
61 4
|
2月前
|
存储 C#
【C#】大批量判断文件是否存在的两种方法效率对比
【C#】大批量判断文件是否存在的两种方法效率对比
52 1
|
2月前
|
JSON 数据格式
LangChain-20 Document Loader 文件加载 加载MD DOCX EXCEL PPT PDF HTML JSON 等多种文件格式 后续可通过FAISS向量化 增强检索
LangChain-20 Document Loader 文件加载 加载MD DOCX EXCEL PPT PDF HTML JSON 等多种文件格式 后续可通过FAISS向量化 增强检索
135 2
|
2月前
|
JavaScript 前端开发 容器
Vue生成PDF文件攻略:html2canvas与jspdf联手,中文乱码与自动换行难题攻克
Vue生成PDF文件攻略:html2canvas与jspdf联手,中文乱码与自动换行难题攻克
220 0
|
2月前
|
XML 存储 缓存
C#使用XML文件的详解及示例
C#使用XML文件的详解及示例
116 0
|
4月前
写一个HTML文件
【8月更文挑战第27天】写一个HTML文件。
47 1
|
4月前
|
监控 安全 C#
使用C#如何监控选定文件夹中文件的变动情况?
使用C#如何监控选定文件夹中文件的变动情况?
125 19
|
4月前
|
编译器 C# Windows
C#基础:手动编译一个.cs源代码文件并生成.exe可执行文件
通过上述步骤,应该能够高效准确地编译C#源代码并生成相应的可执行文件。此外,这一过程强调了对命令行编译器的理解,这在调试和自动化编译流程中是非常重要的。
366 2
|
4月前
|
文字识别 C# Python
使用C#将几个Excel文件合并去重分类
使用C#将几个Excel文件合并去重分类
39 3
|
4月前
【Azure 应用服务】部署Azure Web App时,是否可以替换hostingstart.html文件呢?
【Azure 应用服务】部署Azure Web App时,是否可以替换hostingstart.html文件呢?