前言
最近遇到了一個需求,就是要把大量的doc格式檔案轉換為docx檔案,因此就動手做了一個批次轉換的小工具。
背景
doc檔案是什麼?
"doc" 檔案是一種常見的檔案格式,通常用於儲存文字文件。它是 Microsoft Word 文件的副檔名。"doc" 是 "document" 的縮寫,表示這是一個文件檔案。這種檔案格式通常包含文字、影像、表格、圖形等內容,可以使用 Microsoft Word 或其他相容的文書處理軟體進行開啟和編輯。
docx檔案是什麼?
"docx" 檔案是 Microsoft Word 2007 及更高版本中使用的文件檔案格式的副檔名。它是 Office Open XML (OOXML) 標準的一部分,是一種基於 XML 的開放標準格式,用於儲存文字文件、影像、表格、圖形等內容。與早期的 ".doc" 格式相比,".docx" 格式具有更高的相容性和可擴充套件性,並且檔案大小通常更小。由於其開放的特性,許多其他文書處理軟體也支援 ".docx" 格式。
為什麼要將doc檔案轉化為docx檔案?
將 ".doc" 檔案轉換為 ".docx" 檔案的主要原因包括:
- 更先進的格式:".docx" 使用 Office Open XML 格式,這是一種更現代、更有效的檔案格式。它採用了基於 XML 的結構,使得檔案更容易解析和處理,同時也提供了更好的相容性和可擴充套件性。
- 減小檔案大小:由於 ".docx" 檔案採用了更高效的壓縮技術和檔案結構,相比 ".doc" 檔案通常會更小,這對於儲存和傳輸檔案是有利的。
- 相容性:許多最新版本的文書處理軟體更支援 ".docx" 格式,而較舊的 ".doc" 格式可能會在一些軟體中出現相容性問題。將檔案轉換為 ".docx" 格式可以確保在不同平臺和軟體中的良好相容性。
- 格式穩定性:".docx" 格式的結構更加穩定,不容易出現檔案損壞或格式錯誤的問題,從而提高了文件的可靠性。
綜上所述,將 ".doc" 檔案轉換為 ".docx" 檔案可以提高檔案的效率、相容性和穩定性,是一種值得推薦的做法。
實踐
方案使用C#透過Microsoft Office Interop實現將.doc檔案轉換為.docx檔案。
新增引用:
前提是需要電腦上安裝有word。
頁面設計如下所示:
選擇doc檔案所在的資料夾:
// 建立一個新的FolderBrowserDialog
FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
// 設定FolderBrowserDialog的屬性
folderBrowserDialog.Description = "請選擇待轉換的doc檔案所在的資料夾";
// 顯示FolderBrowserDialog,並獲取結果
if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
{
docFolderPath = folderBrowserDialog.SelectedPath;
richTextBox1.Text += $"你選擇的待轉換的doc檔案所在的資料夾是:{docFolderPath}\r\n";
}
選擇儲存docx檔案的資料夾:
// 建立一個新的FolderBrowserDialog
FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
// 設定FolderBrowserDialog的屬性
folderBrowserDialog.Description = "請選擇儲存docx檔案的資料夾";
// 顯示FolderBrowserDialog,並獲取結果
if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
{
// 使用者已選擇一個資料夾,可以透過folderBrowserDialog.SelectedPath獲取所選資料夾的路徑
docxFolderPath = folderBrowserDialog.SelectedPath;
richTextBox1.Text += $"你選擇的儲存docx檔案的資料夾是:{docFolderPath}\r\n";
}
開始轉換按鈕事件處理函式:
if (docFolderPath == null || docxFolderPath == null)
{
MessageBox.Show("請先選擇doc檔案所在的資料夾與儲存docx檔案的資料夾");
}
else
{
await DocToDocx();
}
為了避免阻塞介面,使用了非同步方法。
DocToDocx方法如下所示:
public async System.Threading.Tasks.Task DocToDocx()
{
// 使用Task.Run來啟動一個新的非同步任務
await System.Threading.Tasks.Task.Run(() =>
{
// 建立 Word 應用程式例項
Microsoft.Office.Interop.Word.Application wordApp = new Microsoft.Office.Interop.Word.Application();
int i = 1;
// 遍歷所有.doc檔案
foreach (string docFile in GetFiles(docFolderPath, "*.doc"))
{
// 開啟輸入的 .doc 檔案
Document doc = wordApp.Documents.Open(docFile);
// 獲取不帶副檔名的檔名
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(docFile);
// 將副檔名改為.docx
string docxFileName = Path.ChangeExtension(fileNameWithoutExtension, ".docx");
string docxFilePath = Path.Combine(docxFolderPath, docxFileName);
// 將 .doc 檔案儲存為 .docx 格式
doc.SaveAs2(docxFilePath, WdSaveFormat.wdFormatXMLDocument);
// 關閉 .doc 檔案
doc.Close();
// 釋放 Document 物件的資源
System.Runtime.InteropServices.Marshal.ReleaseComObject(doc);
// 使用Invoke方法來更新richTextBox1
richTextBox1.Invoke((Action)(() =>
{
richTextBox1.Text += $"第{i}個檔案:{docFile}轉換完成 {DateTime.Now}\r\n";
// 設定插入點到文字的最後
richTextBox1.SelectionStart = richTextBox1.Text.Length;
// 滾動到插入點
richTextBox1.ScrollToCaret();
}));
i++;
}
// 退出 Word 應用程式
wordApp.Quit();
// 釋放資源
System.Runtime.InteropServices.Marshal.ReleaseComObject(wordApp);
// 使用Invoke方法來更新richTextBox1
richTextBox1.Invoke((Action)(() =>
{
richTextBox1.Text += $"轉換完成 {DateTime.Now}\r\n";
}));
});
GetFiles方法如下所示:
// 這個方法返回一個IEnumerable<string>,表示檔案的路徑
public IEnumerable<string> GetFiles(string path, string searchPattern)
{
// 獲取資料夾下的所有檔案
string[] files = Directory.GetFiles(path, searchPattern);
// 遍歷所有檔案
foreach (string file in files)
{
// 返回當前檔案
yield return file;
}
}
這裡使用了yield
關鍵字,使用yield
的好處如下:
- 延遲執行:迭代器的執行會被延遲,直到迭代器被消費時才開始。這意味著如果你有一個大的資料集合需要處理,但並不需要立即處理所有資料,那麼使用yield可以幫助你節省記憶體和計算資源。
- 簡化程式碼:yield可以使你的程式碼更簡潔,更易於閱讀和理解。你不需要建立一個臨時的集合來儲存你的結果,而是可以直接使用yield return來返回結果。
- 無需一次性生成所有結果:當處理大量資料時,一次性生成所有結果可能會消耗大量記憶體。使用yield可以在每次迭代時只生成一個結果,從而節省記憶體。
實現原理其實很簡單,就是用新版本的word開啟再儲存就行了。
// 開啟輸入的 .doc 檔案
Document doc = wordApp.Documents.Open(docFile);
// 獲取不帶副檔名的檔名
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(docFile);
// 將副檔名改為.docx
string docxFileName = Path.ChangeExtension(fileNameWithoutExtension, ".docx");
string docxFilePath = Path.Combine(docxFolderPath, docxFileName);
// 將 .doc 檔案儲存為 .docx 格式
doc.SaveAs2(docxFilePath, WdSaveFormat.wdFormatXMLDocument);
// 關閉 .doc 檔案
doc.Close();
// 釋放 Document 物件的資源
System.Runtime.InteropServices.Marshal.ReleaseComObject(doc);
需要轉換的doc檔案所在的資料夾:
軟體使用截圖:
實現效果:
實現了批次doc檔案轉換為docx檔案。
如果不熟悉C#也可以透過Python實現。
以下是一個檔案轉換的示例程式碼,經過測試可行:
import os
import win32com.client
def convert_doc_to_docx(doc_path):
# 建立Word應用程式物件
word = win32com.client.Dispatch("Word.Application")
# 開啟.doc檔案
doc = word.Documents.Open(doc_path)
# 設定新的檔案路徑
docx_path = os.path.splitext(doc_path)[0] + ".docx"
# 儲存檔案為.docx格式
doc.SaveAs(docx_path, FileFormat=16) # 16 represents wdFormatXMLDocument
# 關閉文件
doc.Close()
# 關閉Word應用程式
word.Quit()
# 使用函式
convert_doc_to_docx("Path")
由於時間精力有限,沒有寫成批次處理的形式。
還有一種方案就是在word裡寫VBA。
採用哪種方案可以根據自己的熟練度。