C#獲取Word格式文檔頁(yè)數(shù)的方法
1. 背景
有時(shí)候,我們需要獲取一個(gè)Word格式文檔(docx)的頁(yè)數(shù),甚至在某一頁(yè)做某些操作,如果我們使用COM+調(diào)用office或wps這些商用軟件,是相當(dāng)方便的,而使用aspose.word這些商業(yè)庫(kù),也是短短幾行代碼的事情。然而,當(dāng)程序跑在某些特定的環(huán)境(例如沒(méi)有Office軟件的環(huán)境),或者我們資金有限而又有道德潔癖(不愿意使用盜版),獲取docx文件頁(yè)數(shù),這種看似簡(jiǎn)單的問(wèn)題反而變得復(fù)雜,因?yàn)槲覀兂S玫拈_(kāi)源庫(kù)poi/npoi或OpenXML SDK等,并沒(méi)有提供這樣的操作。
本著“自己動(dòng)手,豐衣足食”的原則,那就自己手工寫代碼看看吧,順道把坑踩一遍。
2. docx是一個(gè)zip
既然是要自己寫代碼處理這種問(wèn)題,那么我們要回到問(wèn)題的本質(zhì)——word的docx文檔究竟是什么?.docx 文件本質(zhì)上就是一個(gè) ZIP壓縮包。我們將.docx 文件擴(kuò)展名改為.zip,然后使用解壓縮工具來(lái)打開(kāi)它。解壓后,你會(huì)發(fā)現(xiàn)其中包含許多XML文件和媒體文件(如下圖),它們共同構(gòu)成了Word文檔的內(nèi)容和格式。

可見(jiàn),我們可以從這對(duì)xml文件著手,解決問(wèn)題,而Word的這種docx文檔有什么特點(diǎn)呢?我也請(qǐng)教了AI:
- 基于 Open XML 標(biāo)準(zhǔn):.docx 格式是微軟Word(從2007版本開(kāi)始)所使用的基于Office Open XML標(biāo)準(zhǔn)的文件格式。
- 包含大量XML文件:與舊的二進(jìn)制格式的.doc文件不同,.docx 文件是一個(gè)包含多個(gè)XML文件的壓縮集合。
- 主要內(nèi)容:解壓后,核心的文本內(nèi)容通常保存在
word/document.xml文件中,而文檔的樣式信息、媒體文件等則分別存儲(chǔ)在其他文件夾或文件中。 - 優(yōu)點(diǎn):這種基于XML和壓縮的格式使得文件更小,并且允許更靈活地訪問(wèn)和編輯文檔的內(nèi)部結(jié)構(gòu)。
那么,我們的這個(gè)奇奇怪怪的獲取docx文檔頁(yè)數(shù)的方法,就從word/document.xml文件開(kāi)始了。
3. 使用C#代碼解壓docx文檔
解壓這樣的文檔,并不復(fù)雜,直接用ZipFile這樣的庫(kù)即可,示例代碼如下:
var docxFile = $@"{Environment.CurrentDirectory}{Path.DirectorySeparatorChar}test.docx";
var extractedPath = $@"{Environment.CurrentDirectory}{Path.DirectorySeparatorChar}extracted";
var xmlPath = $@"{extractedPath}{Path.DirectorySeparatorChar}word{Path.DirectorySeparatorChar}document.xml";
if (File.Exists(docxFile))
{
System.IO.Compression.ZipFile.ExtractToDirectory(docxFile, extractedPath, true); // 最后一個(gè)參數(shù)為true,目錄已存在則覆蓋
Console.WriteLine($"Extracted {docxFile} to {extractedPath}");
}
else
{
Console.WriteLine($"File {docxFile} does not exist.");
}
解壓后的目錄如下:

4. 那個(gè)自稱document的XML
進(jìn)入解壓后的word目錄了,我們可以找到document.xml文件,敢自稱document,也肯定是有點(diǎn)東西的,打開(kāi)一看,確實(shí)名副其實(shí):

可見(jiàn)一個(gè)word文檔的整體脈絡(luò)以及主要的行文,都在這里面了。當(dāng)然,文檔里的圖片等資源也是記錄在這里,例如對(duì)某個(gè)資源的引用<a:blip r:embed="rId7"/>等,當(dāng)然這還牽涉到media和document.xml.rels中的引用關(guān)系等等,有機(jī)會(huì)再細(xì)說(shuō)。那么,回到本次描述的“獲取文檔頁(yè)數(shù)”這個(gè)操作,就比較簡(jiǎn)單了,只要我們找到里面的<w:lastRenderedPageBreak/>元素,問(wèn)題就可以解決了。顧名思義,該元素是用于給word文檔分頁(yè)的,相當(dāng)于用它來(lái)“切香腸”,一刀分兩頁(yè),兩刀分三頁(yè),以此類推……
5. 查找并統(tǒng)計(jì)分頁(yè)標(biāo)簽
使用自帶的System.Xml庫(kù),可以對(duì)xml文件進(jìn)行解析,查找并獲取<w:lastRenderedPageBreak/>,實(shí)現(xiàn)定位和統(tǒng)計(jì)等功能(本文就以統(tǒng)計(jì)為例)。
if (File.Exists(xmlPath))
{
var xmlContent = File.ReadAllText(xmlPath);
var xmlDoc = new System.Xml.XmlDocument();
xmlDoc.LoadXml(xmlContent);
var nsmgr = new System.Xml.XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("w", "http://schemas.openxmlformats.org/wordprocessingml/2006/main");
var nodes = xmlDoc.SelectNodes("http://w:lastRenderedPageBreak", nsmgr);
var cnt = nodes?.Count ?? 0;
Console.WriteLine($"使用XML解析的方式找到 <w:lastRenderedPageBreak /> 節(jié)點(diǎn)數(shù)量: {cnt}");
Console.WriteLine($"該文檔共有 {cnt + 1} 頁(yè)");
}
else
{
Console.WriteLine($"File {xmlPath} does not exist.");
}
以本文中的測(cè)試文檔為例,文檔共7頁(yè),查找并計(jì)算出來(lái)的頁(yè)數(shù)也是7頁(yè),結(jié)果與實(shí)際一致。


到此這篇關(guān)于C#獲取Word格式文檔頁(yè)數(shù)的方法的文章就介紹到這了,更多相關(guān)C#獲取Word文檔頁(yè)數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#事務(wù)處理(Execute Transaction)實(shí)例解析
這篇文章主要介紹了C#事務(wù)處理(Execute Transaction)實(shí)例解析,對(duì)于理解和學(xué)習(xí)事務(wù)處理有一定的幫助,需要的朋友可以參考下2014-08-08
淺析WPF中Binding的數(shù)據(jù)校驗(yàn)和類型轉(zhuǎn)換
在WPF開(kāi)發(fā)中,Binding實(shí)現(xiàn)了數(shù)據(jù)在Source和Target之間的傳遞和流通,那在WPF開(kāi)發(fā)中,如何實(shí)現(xiàn)數(shù)據(jù)的校驗(yàn)和類型轉(zhuǎn)換呢,下面就跟隨小編一起學(xué)習(xí)一下吧2024-03-03
C# 委托的三種調(diào)用示例(同步調(diào)用 異步調(diào)用 異步回調(diào))
本文將主要通過(guò)同步調(diào)用、異步調(diào)用、異步回調(diào)三個(gè)示例來(lái)講解在用委托執(zhí)行同一個(gè)加法類的時(shí)候的的區(qū)別和利弊2013-12-12
C#將PDF文檔轉(zhuǎn)換為Markdown文檔的代碼實(shí)現(xiàn)
將PDF文件轉(zhuǎn)換為Markdown格式是一個(gè)非常實(shí)用的需求,尤其是在需要將內(nèi)容從固定布局的PDF文件中提取出來(lái),并轉(zhuǎn)換為更易于編輯和處理的文本格式時(shí),本文將介紹如何通過(guò)C#代碼將PDF文檔轉(zhuǎn)換Markdown(MD)文檔,需要的朋友可以參考下2024-10-10
C#開(kāi)發(fā)教程之利用特性自定義數(shù)據(jù)導(dǎo)出到Excel
這篇文章主要介紹了C#開(kāi)發(fā)教程之利用特性自定義數(shù)據(jù)導(dǎo)出到Excel的相關(guān)資料,需要的朋友可以參考下2016-07-07
C#實(shí)現(xiàn)在控制臺(tái)輸出當(dāng)前系統(tǒng)時(shí)間的方法
這篇文章主要介紹了C#實(shí)現(xiàn)在控制臺(tái)輸出當(dāng)前系統(tǒng)時(shí)間的方法,涉及C#時(shí)間函數(shù)DateTime.Now的使用方法,需要的朋友可以參考下2015-04-04
C# 實(shí)現(xiàn)雪花算法(Snowflake Algorithm)的實(shí)現(xiàn)
雪花算法是Twitter提出的高效分布式ID生成方案,通過(guò)時(shí)間戳、機(jī)器ID和序列號(hào)組合確保唯一性和有序性,下面就來(lái)介紹一下C# 實(shí)現(xiàn)雪花算法(Snowflake Algorithm)的實(shí)現(xiàn),感興趣的可以了解一下2025-05-05
C#通過(guò)ADO.NET訪問(wèn)數(shù)據(jù)的方法詳解
在 C# 的應(yīng)用開(kāi)發(fā)中,數(shù)據(jù)訪問(wèn)是極為關(guān)鍵的部分,ADO.NET作為.NET 框架下用于數(shù)據(jù)訪問(wèn)的核心技術(shù),能夠幫助開(kāi)發(fā)者便捷地與各類數(shù)據(jù)源進(jìn)行交互,本文將深入剖析ADO.NET,帶你掌握使用 C# 通過(guò)ADO.NET訪問(wèn)數(shù)據(jù)的方法,需要的朋友可以參考下2025-02-02

