Word自動化(C# + Python)(持續更新中...)

目錄

  • 前言
  • 讀取Word內容
  • NPOI
  • NPOI安裝
  • NPOI提取Word內容
  • 用Costura.Fody打包DLL
  • python-docx
  • 讀取PDF內容
  • python-docx自動生成Word
  • 全局字體
  • 內容字體
  • 單元格合併
  • 最後

前言

Word就是那種很難用, 很醜陋, 可是你不得不用的東西, 在這一點上, 它甚至比Windows更甚(畢竟Gates是經過幫水果寫Office纔有機會接觸Macintash和施樂的嘛, 你聽過的, 兩個小偷的故事). Windows能夠用macOS + PlayStation進行1000%的替代, 沒有多打0(手動滑稽). 可是Office不可以, 並非沒有比Office更好的東西, 這是一個歷史殘留問題, 就像牙膏廠CPU裏面, 那些莫名其妙的字段同樣.html

總之, 這裏經過使用一些庫, Python的python-docx, C#的pdfbox和npoi, 來讓對Word和PDF的處理變得更加自動化一些.python

最後, 若是你想設計一些定製化的功能, 仍是但願能夠從官方文檔進行學習, 而不是經過看博客. 尤爲是當你只可以用某度, 而不是某歌, 那些前幾頁給出的搜索結果老舊又不頂用, 說真的, 用某度還不如在博客網站進行站內搜索, 不過我最近發現某日頭條的全網搜索給出的結果還不錯, 若是你不能某歌, 能夠用下某日頭條, 再不濟用某應(Bing)也好過某度.linux


讀取Word內容

好了, 很少說廢話了. 直接看從Word獲取內容. 這裏能夠用C#的NPOI和python-docx實現.apache


NPOI

NPOI安裝

來看下維基的介紹. Apache POI是Apache軟件基金會的開放源碼庫, POI提供API給Java程序對Microsoft Office格式文件讀和寫的功能. .NET的開發人員則能夠利用NPOI(POI for .NET)來訪問POI的功能.緩存

其實, 最近這幾年, 巨硬經過推出像.NET Core這樣的跨平臺應用程序開發框架, 已經讓C#有了一點起死回生的跡象, 我不喜歡巨硬, 但我很推崇這種戰略, 固然了, 甚至在硬件上推出了Duo這樣的Surface安卓設備. 雖然以前寫Unity遊戲的時候用過一些C#, 可是此次是我第一次從軟件開發的角度使用C#, 不得不說, NuGet令我印象深入, 很好用.bash

這裏假設你已經裝了vs2019或者舊一點的版本, 可是注意, .NET Framework的程序依舊只能在Windows進行開發, 由於我暫時尚未摸像Mono這樣的環境, 若是你感興趣, 能夠試下.markdown

  • 新建.NET Framework控制檯應用:

  • 而後你只須要在搜索框輸入nuget, 點擊管理NuGet程序包:

  • 以後搜索NPOI, 點擊安裝, 就能夠了. 可能比起mac的brew install, linux的apt-get install和python的pip3 install多了兩步, 可是我已經很滿意了, 比什麼找DLL, 拷貝DLL之類的, 要顯得9102的多.

  • 安裝以後, 在右側的解決方案引用裏面, 已經能夠看到添加的庫了:


NPOI提取Word內容

其實NPOI很是強大, 足以用來作和Word有關的一切了, 可是, 這裏只演示一下提取Word中的內容, 由於後面有python-docx這樣更加輕巧的庫, 不須要vs不須要Windows, 你就能夠處理docx類型的文件了.框架

源碼以下:學習

using NPOI.XWPF.UserModel;
using System.IO;
using System.Text;

namespace getWord
{
    class Program
    {
        static void Main(string[] args)
        {
            string in_path = System.Console.ReadLine();
            string out_path = System.Console.ReadLine();
            Stream stream = File.OpenRead(in_path);
            XWPFDocument doc = new XWPFDocument(stream);

            string text = "";
            string tmp_text;
            foreach (var para in doc.Paragraphs)
            {
                tmp_text = para.ParagraphText;
                if (tmp_text.Trim() != "")
                    text += tmp_text + "\n";
            }

            StreamWriter swPdfChange = new StreamWriter(out_path, false, Encoding.GetEncoding("gb2312"));
            swPdfChange.Write(text);
            swPdfChange.Close();
        }
    }
}
複製代碼

我從控制檯讀取了輸入輸出路徑, 而後循環讀取Word內容寫入緩存, 最後轉碼成gb2312到輸出文件.字體

最終, 我仍是但願你去NPOI官網看看.


用Costura.Fody打包DLL

若是你就這樣直接生成Release版本, 你會被老闆罵的狗血淋頭, 太不專業了. 至少你應該把DLL打包進EXE或DLL.

你能夠把DLL做爲資源文件進行打包, 可是這樣不優雅, 很土. 一樣, 咱們用9102年應該用的方法.

在NuGet搜索Costura.Fody, 安裝便可. 這樣的話, 編譯成Release版本的時候, 直接就打包成一個EXE文件了.


python-docx

好了, 到了Python, 一切都舒服了, 忘記剛纔爲了寫C#安裝的好幾個G甚至幾十個G的vs吧, 畢竟Gates說過'640K is more memory than anyone will ever need.'(手動滑稽) 如今你只須要:

pip3 install python-docx
複製代碼

並且, 官方文檔寫得很不錯, 而且我發如今做業部落(對, 就是個人macOS上有什麼裏面推薦的那個cmd markdown)的一篇python-docx中文, 幾乎就是官方中文. 因此, 我基本就靠這兩個外加谷歌, 完成了所有的內容學習, 固然, 你會發現, 難點仍是在Table處理和樣式修改那裏.

import docx

doc = docx.Document('./t.docx')

doc_text = ''
doc_table_text = ''

for paragraph in doc.paragraphs:
    doc_text += paragraph.text + '\n'

for table in doc.tables:
    for row in table.rows:
        for cell in row.cells:
            doc_table_text += cell.text + '\n'

with open('./tt.txt', 'w') as f:
    f.write(doc_text)
    f.write(doc_table_text)

# doc.save ('./tt.docx')
複製代碼

代碼其實很好懂, 關於python-docx的一些細節操做, 除了官方文檔, 我在後面的自動化生成Word裏面也會分享一些個人處理經驗, 固然, 更多的是處理時候的坑(手動無奈).


讀取PDF內容

一樣, 此次用的是C#的庫, 名爲Pdfbox. 其實呢, 這個Pdfbox是個Java庫. 是由Apache PDFBox團隊爲.NET生成的.

using org.apache.pdfbox.pdmodel;
using org.apache.pdfbox.util;
using System.IO;
using System.Text;

namespace getPDFCon
{
    class Program
    {
        static void Main(string[] args)
        {
            string in_path = System.Console.ReadLine();
            string out_path = System.Console.ReadLine();

            PDDocument doc = PDDocument.load(in_path);
            PDFTextStripper pdfStripper = new PDFTextStripper();
            string text = pdfStripper.getText(doc);
            // Console.WriteLine(Utf8ToGB2312(text));
            // Console.ReadKey();
            StreamWriter swPdfChange = new StreamWriter(out_path, false, Encoding.GetEncoding("gb2312"));
            swPdfChange.Write(text);
            swPdfChange.Close();
        }
    }
}
複製代碼

和以前讀取Word幾乎是同樣的思路, 很少說了.


python-docx自動生成Word

這裏我來細說一下, python-docx的一些操做. 從樣式修改, 表格合併處理這些難點來談. 後續也會逐步更新新遇到的坑.

全局字體

首先, 你能夠設置全局字體.

doc.styles['Normal'].font.name = u'宋體'
doc.styles['Normal'].font.size = Pt (9)
doc.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), u'宋體')
複製代碼

注意, 若是是漢字, 第三行是必需要加的, 不然不生效. 第二行是設置字體大小, 你須要用from docx.shared import Pt進行導包. 固然, 你直接導入整個docx包就完事了.

內容字體

若是你想只修改某段內容的字體, 不影響全局, 以前的方案就不行.

p = doc.add_paragraph ()
font = p.add_run ('標題').font
font.bold = True
font.size = Pt (14)
p.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER
複製代碼

這裏看到一個p.add_run, 這是給當前Paragraph實例添加的Run實例, 也就是運行時候的一些設置, 只對當前Paragraph實例生效. 來看下和直接設置Paragraph實例屬性的比較.

doc = Document ()

p = doc.add_paragraph ()
font = p.add_run ('標題1').font
font.bold = True
font.size = Pt (14)
p.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER

p2 = doc.add_paragraph ()
p2.text = ('標題2')
p2.style.font.size = Pt (20)

p3 = doc.add_paragraph ()
p3.text = ('標題3')
p3.style.font.size = Pt (40)

doc.save ('a.docx')
複製代碼

這段代碼在想象中應該是段落內容愈來愈大, 對吧, 可是很遺憾, 對於標題3的字體設置會覆蓋標題2的字體設置, 可是經過run對象進行設置的標題1就不會受到影響, 來看圖說話:

這樣一來, 想要很好處理某段內容的風格, 就必須使用run. 不然就會關聯其餘. 修改下代碼, 都設置成add_run, 看看是否如此:

很好, 這纔是想要的效果. 同理, 在表格內容裏面也是如此, 很少贅述.

可是還有一點要注意, 好比你已經經過, p.text進行文字賦值, 可是, 你又用, p.add_run ('標題').font進行設置, 那麼你會獲得兩分內容. 因此, 這裏要特別注意, 若是經過樣式填充, 就不用再用text字段進行賦值.


單元格合併

好比我如今創建一張表, 嘗試合併. 而後你會發現, 合併以後, 把兩分內容都保留了, 若是這是你須要的, 天然沒有問題. 可是若是不是, 你就要思考內容合併的策略, 你不可能一個一個設置. 一個比較合理的策略就是用臨時變量保留你要的內容, 合併完成以後, 將臨時變量內容覆蓋合併後的內容.


最後

其實, 不管是NPOI仍是python-docx, 已是很是不錯的庫了, 均可以很好地幫助開發者進行自動化word的生成. 若是你不這麼以爲, 我舉個反例. Microsoft.Office.Interop.Word是巨硬提供的com組件, 那麼要如何使用它呢, 你要先裝Windows, 再裝Office, Office2013對應這個com組件的15.x版本, Office2007對應組件的12.x. 而後你寫完代碼, 每次運行還須要啓動Word, 能夠後臺啓動, 但終歸是啓動了, 因此效率很是低.

固然, 本章內容還會在後續使用當中持續更新, 直到我以爲沒有必要更新了. 喜歡能夠點個贊, 有意見或者建議, 評論區見哦~

相關文章
相關標籤/搜索