การแยกข้อความจากเอกสาร Word มักดำเนินการในสถานการณ์ต่างๆ ตัวอย่างเช่น เพื่อวิเคราะห์ข้อความ เพื่อแยกส่วนเฉพาะของเอกสารและรวมเข้าด้วยกันเป็นเอกสารเดียว เป็นต้น ในบทความนี้ คุณจะได้เรียนรู้วิธีการแยกข้อความจากเอกสาร Word โดยทางโปรแกรมใน C# นอกจากนี้ เราจะกล่าวถึงวิธีการแยกเนื้อหาระหว่างองค์ประกอบเฉพาะ เช่น ย่อหน้า ตาราง ฯลฯ แบบไดนามิก
C# Library เพื่อดึงข้อความจากเอกสาร Word
Aspose.Words for .NET เป็นไลบรารีอันทรงพลังที่ช่วยให้คุณสามารถสร้างเอกสาร MS Word ได้ตั้งแต่เริ่มต้น นอกจากนี้ ยังให้คุณจัดการเอกสาร Word ที่มีอยู่สำหรับการเข้ารหัส การแปลง การดึงข้อความ ฯลฯ เราจะใช้ไลบรารีนี้เพื่อแยกข้อความจากเอกสาร Word DOCX หรือ DOC คุณสามารถ ดาวน์โหลด DLL ของ API หรือติดตั้งโดยตรงจาก NuGet โดยใช้คอนโซลตัวจัดการแพ็คเกจ
PM> Install-Package Aspose.Words
การแยกข้อความในเอกสาร Word โดยใช้ C#
เอกสาร MS Word ประกอบด้วยองค์ประกอบต่างๆ ซึ่งรวมถึงย่อหน้า ตาราง รูปภาพ เป็นต้น ดังนั้นข้อกำหนดในการแยกข้อความจึงอาจแตกต่างกันไปในแต่ละสถานการณ์ ตัวอย่างเช่น คุณอาจต้องแยกข้อความระหว่างย่อหน้า ที่คั่นหน้า ความคิดเห็น ฯลฯ
องค์ประกอบแต่ละประเภทในเอกสาร Word จะแสดงเป็นโหนด ดังนั้นในการประมวลผลเอกสาร คุณจะต้องเล่นกับโหนด เรามาเริ่มกันและดูวิธีแยกข้อความจากเอกสาร Word ในสถานการณ์ต่างๆ
แยกข้อความจากเอกสาร Word ใน C
ในส่วนนี้ เราจะใช้ตัวแยกข้อความ C# สำหรับเอกสาร Word และขั้นตอนการทำงานของการแยกข้อความจะเป็นดังนี้:
- ขั้นแรก เราจะกำหนดโหนดที่เราต้องการรวมไว้ในขั้นตอนการแยกข้อความ
- จากนั้นเราจะแยกเนื้อหาระหว่างโหนดที่ระบุ (รวมถึงหรือไม่รวมโหนดเริ่มต้นและสิ้นสุด)
- สุดท้าย เราจะใช้การโคลนของโหนดที่แยกออกมา เช่น เพื่อสร้างเอกสาร Word ใหม่ที่ประกอบด้วยเนื้อหาที่แยกออกมา
ตอนนี้มาเขียนเมธอดชื่อ ExtractContent ซึ่งเราจะส่งโหนดและพารามิเตอร์อื่นๆ เพื่อดำเนินการแยกข้อความ วิธีนี้จะแยกวิเคราะห์เอกสารและโคลนโหนด ต่อไปนี้คือพารามิเตอร์ที่เราจะส่งผ่านไปยังวิธีนี้
- StartNode และ EndNode เป็นจุดเริ่มต้นและจุดสิ้นสุดสำหรับการแยกเนื้อหา ตามลำดับ สิ่งเหล่านี้สามารถเป็นได้ทั้งโหนดระดับบล็อก (ย่อหน้า ตาราง) หรือระดับอินไลน์ (เช่น Run, FieldStart, BookmarkStart เป็นต้น)
- ในการส่งฟิลด์ คุณควรส่งวัตถุ FieldStart ที่สอดคล้องกัน
- ในการส่งผ่านบุ๊กมาร์ก ควรผ่านโหนด BookmarkStart และ BookmarkEnd
- สำหรับความคิดเห็น ควรใช้โหนด CommentRangeStart และ CommentRangeEnd
- IsInclusive กำหนดว่าเครื่องหมายรวมอยู่ในการแยกหรือไม่ หากตั้งค่าตัวเลือกนี้เป็น False และโหนดเดียวกันหรือโหนดที่ต่อเนื่องกันจะถูกส่งกลับ รายการว่างจะถูกส่งกลับ
ต่อไปนี้เป็นการนำเมธอด ExtractContent ไปใช้อย่างสมบูรณ์ซึ่งจะแยกเนื้อหาระหว่างโหนดที่ส่งผ่าน
public static ArrayList ExtractContent(Node startNode, Node endNode, bool isInclusive)
{
// ตรวจสอบก่อนว่าโหนดที่ผ่านไปยังเมธอดนี้ถูกต้องสำหรับการใช้งาน
VerifyParameterNodes(startNode, endNode);
// สร้างรายการเพื่อจัดเก็บโหนดที่แยกออกมา
ArrayList nodes = new ArrayList();
// เก็บบันทึกของโหนดดั้งเดิมที่ส่งผ่านไปยังวิธีนี้ เพื่อให้เราสามารถแยกโหนดเครื่องหมายได้หากจำเป็น
Node originalStartNode = startNode;
Node originalEndNode = endNode;
// แยกเนื้อหาตามโหนดระดับบล็อก (ย่อหน้าและตาราง) สำรวจผ่านโหนดหลักเพื่อค้นหา
// เราจะแบ่งเนื้อหาของโหนดแรกและโหนดสุดท้าย โดยขึ้นอยู่กับว่าโหนดเครื่องหมายอยู่ในบรรทัดหรือไม่
while (startNode.ParentNode.NodeType != NodeType.Body)
startNode = startNode.ParentNode;
while (endNode.ParentNode.NodeType != NodeType.Body)
endNode = endNode.ParentNode;
bool isExtracting = true;
bool isStartingNode = true;
bool isEndingNode = false;
// โหนดปัจจุบันที่เรากำลังแยกออกจากเอกสาร
Node currNode = startNode;
// เริ่มแยกเนื้อหา ประมวลผลโหนดระดับบล็อกทั้งหมดและแยกโหนดแรกและโหนดสุดท้ายโดยเฉพาะเมื่อจำเป็น เพื่อให้การจัดรูปแบบย่อหน้ายังคงอยู่
// วิธีการนี้ซับซ้อนกว่าตัวแยกข้อมูลทั่วไปเล็กน้อยเนื่องจากเราจำเป็นต้องแยกส่วนโดยใช้โหนดอินไลน์ ฟิลด์ บุ๊กมาร์ก ฯลฯ เพื่อให้มีประโยชน์จริงๆ
while (isExtracting)
{
// โคลนโหนดปัจจุบันและโหนดย่อยเพื่อรับสำเนา
Node cloneNode = currNode.Clone(true);
isEndingNode = currNode.Equals(endNode);
if ((isStartingNode || isEndingNode) && cloneNode.IsComposite)
{
// เราจำเป็นต้องประมวลผลเครื่องหมายแต่ละรายการแยกกัน ดังนั้นส่งต่อไปยังวิธีอื่นแทน
if (isStartingNode)
{
ProcessMarker((CompositeNode)cloneNode, nodes, originalStartNode, isInclusive, isStartingNode, isEndingNode);
isStartingNode = false;
}
// เงื่อนไขต้องแยกจากกันเนื่องจากเครื่องหมายเริ่มต้นและสิ้นสุดระดับบล็อกอาจเป็นโหนดเดียวกัน
if (isEndingNode)
{
ProcessMarker((CompositeNode)cloneNode, nodes, originalEndNode, isInclusive, isStartingNode, isEndingNode);
isExtracting = false;
}
}
else
// โหนดไม่ใช่เครื่องหมายเริ่มต้นหรือจุดสิ้นสุด เพียงเพิ่มสำเนาลงในรายการ
nodes.Add(cloneNode);
// ย้ายไปยังโหนดถัดไปและแตกไฟล์ หากโหนดถัดไปเป็น null นั่นหมายถึงพบเนื้อหาที่เหลือในส่วนอื่น
if (currNode.NextSibling == null && isExtracting)
{
// ย้ายไปยังส่วนถัดไป
Section nextSection = (Section)currNode.GetAncestor(NodeType.Section).NextSibling;
currNode = nextSection.Body.FirstChild;
}
else
{
// ย้ายไปยังโหนดถัดไปในเนื้อหา
currNode = currNode.NextSibling;
}
}
// ส่งกลับโหนดระหว่างเครื่องหมายโหนด
return nodes;
}
วิธีตัวช่วยบางอย่างจำเป็นสำหรับวิธี ExtractContent เพื่อดำเนินการแยกข้อความให้สำเร็จ ซึ่งแสดงไว้ด้านล่าง
public static List<Paragraph> ParagraphsByStyleName(Document doc, string styleName)
{
// สร้างอาร์เรย์เพื่อรวบรวมย่อหน้าของสไตล์ที่กำหนด
List<Paragraph> paragraphsWithStyle = new List<Paragraph>();
NodeCollection paragraphs = doc.GetChildNodes(NodeType.Paragraph, true);
// ดูทุกย่อหน้าเพื่อค้นหาผู้ที่มีสไตล์ที่ระบุ
foreach (Paragraph paragraph in paragraphs)
{
if (paragraph.ParagraphFormat.Style.Name == styleName)
paragraphsWithStyle.Add(paragraph);
}
return paragraphsWithStyle;
}
private static void VerifyParameterNodes(Node startNode, Node endNode)
{
// ลำดับในการตรวจสอบเหล่านี้มีความสำคัญ
if (startNode == null)
throw new ArgumentException("Start node cannot be null");
if (endNode == null)
throw new ArgumentException("End node cannot be null");
if (!startNode.Document.Equals(endNode.Document))
throw new ArgumentException("Start node and end node must belong to the same document");
if (startNode.GetAncestor(NodeType.Body) == null || endNode.GetAncestor(NodeType.Body) == null)
throw new ArgumentException("Start node and end node must be a child or descendant of a body");
// ตรวจสอบว่าโหนดสิ้นสุดอยู่หลังโหนดเริ่มต้นในแผนผัง DOM
// ขั้นแรกให้ตรวจดูว่าอยู่ในส่วนต่างๆ หรือไม่ จากนั้นหากไม่ได้ตรวจสอบตำแหน่งในเนื้อความของส่วนเดียวกันกับที่อยู่
Section startSection = (Section)startNode.GetAncestor(NodeType.Section);
Section endSection = (Section)endNode.GetAncestor(NodeType.Section);
int startIndex = startSection.ParentNode.IndexOf(startSection);
int endIndex = endSection.ParentNode.IndexOf(endSection);
if (startIndex == endIndex)
{
if (startSection.Body.IndexOf(startNode) > endSection.Body.IndexOf(endNode))
throw new ArgumentException("The end node must be after the start node in the body");
}
else if (startIndex > endIndex)
throw new ArgumentException("The section of end node must be after the section start node");
}
private static bool IsInline(Node node)
{
// ทดสอบว่าโหนดเป็น desendant ของโหนดย่อหน้าหรือตาราง และไม่ใช่ย่อหน้าหรือตารางในย่อหน้าในคลาสความคิดเห็นซึ่งอยู่ถัดจากย่อหน้าที่เป็นไปได้
return ((node.GetAncestor(NodeType.Paragraph) != null || node.GetAncestor(NodeType.Table) != null) && !(node.NodeType == NodeType.Paragraph || node.NodeType == NodeType.Table));
}
private static void ProcessMarker(CompositeNode cloneNode, ArrayList nodes, Node node, bool isInclusive, bool isStartMarker, bool isEndMarker)
{
// หากเรากำลังจัดการกับโหนดระดับบล็อก ให้ดูว่าควรรวมหรือไม่และเพิ่มลงในรายการ
if (!IsInline(node))
{
// อย่าเพิ่มโหนดสองครั้งหากเครื่องหมายเป็นโหนดเดียวกัน
if (!(isStartMarker && isEndMarker))
{
if (isInclusive)
nodes.Add(cloneNode);
}
return;
}
// หากเครื่องหมายเป็นโหนด FieldStart ให้ตรวจสอบว่าจำเป็นต้องรวมหรือไม่
// เราถือว่า FieldStart และ FieldEnd ปรากฏในย่อหน้าเดียวกันเพื่อความง่าย
if (node.NodeType == NodeType.FieldStart)
{
// หากเครื่องหมายเป็นโหนดเริ่มต้นและไม่ได้รวมไว้ ให้ข้ามไปที่จุดสิ้นสุดของฟิลด์
// ถ้าเครื่องหมายเป็นโหนดสิ้นสุดและจะถูกรวมไว้ ให้ย้ายไปยังฟิลด์สิ้นสุดเพื่อไม่ให้ฟิลด์ถูกลบออก
if ((isStartMarker && !isInclusive) || (!isStartMarker && isInclusive))
{
while (node.NextSibling != null && node.NodeType != NodeType.FieldEnd)
node = node.NextSibling;
}
}
// หากเครื่องหมายใดเป็นส่วนหนึ่งของความคิดเห็น หากต้องการรวมความคิดเห็นนั้น เราจำเป็นต้องเลื่อนตัวชี้ไปข้างหน้าเพื่อแสดงความคิดเห็น
// พบโหนดหลังโหนด CommentRangeEnd
if (node.NodeType == NodeType.CommentRangeEnd)
{
while (node.NextSibling != null && node.NodeType != NodeType.Comment)
node = node.NextSibling;
}
// ค้นหาโหนดที่เกี่ยวข้องในโหนดโคลนของเราตามดัชนีแล้วส่งคืน
// หากโหนดเริ่มต้นและโหนดสิ้นสุดเหมือนกัน แสดงว่าโหนดย่อยบางโหนดอาจถูกลบออกไปแล้ว ลบออก
// ผลต่างเพื่อให้ได้ดัชนีที่เหมาะสม
int indexDiff = node.ParentNode.ChildNodes.Count - cloneNode.ChildNodes.Count;
// โหนดลูกนับเหมือนกัน
if (indexDiff == 0)
node = cloneNode.ChildNodes[node.ParentNode.IndexOf(node)];
else
node = cloneNode.ChildNodes[node.ParentNode.IndexOf(node) - indexDiff];
// ลบโหนดจนถึง/ออกจากเครื่องหมาย
bool isSkip = false;
bool isProcessing = true;
bool isRemoving = isStartMarker;
Node nextNode = cloneNode.FirstChild;
while (isProcessing && nextNode != null)
{
Node currentNode = nextNode;
isSkip = false;
if (currentNode.Equals(node))
{
if (isStartMarker)
{
isProcessing = false;
if (isInclusive)
isRemoving = false;
}
else
{
isRemoving = true;
if (isInclusive)
isSkip = true;
}
}
nextNode = nextNode.NextSibling;
if (isRemoving && !isSkip)
currentNode.Remove();
}
// หลังจากประมวลผลแล้ว โหนดคอมโพสิตอาจว่างเปล่า ถ้ายังไม่ได้รวมไว้
if (!(isStartMarker && isEndMarker))
{
if (cloneNode.HasChildNodes)
nodes.Add(cloneNode);
}
}
public static Document GenerateDocument(Document srcDoc, ArrayList nodes)
{
// สร้างเอกสารเปล่า
Document dstDoc = new Document();
// ลบย่อหน้าแรกออกจากเอกสารเปล่า
dstDoc.FirstSection.Body.RemoveAllChildren();
// นำเข้าแต่ละโหนดจากรายการไปยังเอกสารใหม่ รักษารูปแบบเดิมของโหนด
NodeImporter importer = new NodeImporter(srcDoc, dstDoc, ImportFormatMode.KeepSourceFormatting);
foreach (Node node in nodes)
{
Node importNode = importer.ImportNode(node, true);
dstDoc.FirstSection.Body.AppendChild(importNode);
}
// ส่งคืนเอกสารที่สร้างขึ้น
return dstDoc;
}
ตอนนี้เราพร้อมที่จะใช้วิธีการเหล่านี้และดึงข้อความจากเอกสาร Word แล้ว
แยกข้อความระหว่างย่อหน้าในเอกสาร Word
มาดูวิธีแยกเนื้อหาระหว่างสองย่อหน้าในเอกสาร Word DOCX ต่อไปนี้เป็นขั้นตอนในการดำเนินการนี้ใน C#
- ขั้นแรก ให้โหลดเอกสาร Word โดยใช้คลาส Document
- รับการอ้างอิงของย่อหน้าเริ่มต้นและสิ้นสุดเป็นสองวัตถุโดยใช้เมธอด Document.FirstSection.Body.GetChild(NodeType.PARAGRAPH, int, boolean)
- เรียกใช้เมธอด ExtractContent(startPara, endPara, True) เพื่อแยกโหนดออกเป็นวัตถุ
- โทรเมธอดตัวช่วย GenerateDocument(Document, extractedNodes) เพื่อสร้างเอกสารที่ประกอบด้วยเนื้อหาที่แยกออกมา
- สุดท้าย บันทึกเอกสารที่ส่งคืนโดยใช้เมธอด Document.Save(string)
ตัวอย่างโค้ดต่อไปนี้แสดงวิธีการแยกข้อความระหว่างย่อหน้าที่ 7 และ 11 ในเอกสาร Word ใน C#
// โหลดเอกสาร Word
Document doc = new Document("document.docx");
// รวบรวมโหนด (เมธอด GetChild ใช้ดัชนีแบบ 0)
Paragraph startPara = (Paragraph)doc.FirstSection.Body.GetChild(NodeType.Paragraph, 6, true);
Paragraph endPara = (Paragraph)doc.FirstSection.Body.GetChild(NodeType.Paragraph, 10, true);
// แยกเนื้อหาระหว่างโหนดเหล่านี้ในเอกสาร รวมเครื่องหมายเหล่านี้ในการแยก
ArrayList extractedNodes = ExtractContent(startPara, endPara, true);
// ใส่เนื้อหาลงในเอกสารใหม่และบันทึกลงในดิสก์
Document dstDoc = GenerateDocument(doc, extractedNodes);
dstDoc.Save("output.docx");
แยกข้อความระหว่างโหนดประเภทต่างๆ ในเอกสาร Word
คุณยังสามารถแยกเนื้อหาระหว่างโหนดประเภทต่างๆ สำหรับการสาธิต ลองแยกเนื้อหาระหว่างย่อหน้ากับตารางแล้วบันทึกลงในเอกสาร Word ใหม่ ต่อไปนี้เป็นขั้นตอนในการดำเนินการนี้
- โหลดเอกสาร Word โดยใช้คลาส Document
- รับการอ้างอิงของโหนดเริ่มต้นและสิ้นสุดเป็นสองวัตถุโดยใช้เมธอด Document.FirstSection.Body.GetChild(NodeType, int, boolean)
- เรียกใช้เมธอด ExtractContent(startPara, endPara, True) เพื่อแยกโหนดออกเป็นวัตถุ
- โทรเมธอดตัวช่วย GenerateDocument(Document, extractedNodes) เพื่อสร้างเอกสารที่ประกอบด้วยเนื้อหาที่แยกออกมา
- บันทึกเอกสารที่ส่งคืนโดยใช้เมธอด Document.Save(string)
ตัวอย่างโค้ดต่อไปนี้แสดงวิธีการแยกข้อความระหว่างย่อหน้าและตารางใน C#
// โหลดเอกสาร Word
Document doc = new Document("document.docx");
Paragraph startPara = (Paragraph)doc.LastSection.GetChild(NodeType.Paragraph, 2, true);
Table endTable = (Table)doc.LastSection.GetChild(NodeType.Table, 0, true);
// แยกเนื้อหาระหว่างโหนดเหล่านี้ในเอกสาร รวมเครื่องหมายเหล่านี้ในการแยก
ArrayList extractedNodes = ExtractContent(startPara, endTable, true);
// ใส่เนื้อหาลงในเอกสารใหม่และบันทึกลงในดิสก์
Document dstDoc = GenerateDocument(doc, extractedNodes);
dstDoc.Save("output.docx");
แยกข้อความระหว่างย่อหน้าตามสไตล์
มาดูวิธีแยกเนื้อหาระหว่างย่อหน้าตามสไตล์กัน สำหรับการสาธิต เราจะแยกเนื้อหาระหว่าง “หัวเรื่อง 1” แรกและ “หัวเรื่อง 3” แรกในเอกสาร Word ขั้นตอนต่อไปนี้แสดงให้เห็นถึงวิธีการบรรลุสิ่งนี้ใน C#
- ขั้นแรก ให้โหลดเอกสาร Word โดยใช้คลาส Document
- จากนั้นแยกย่อหน้าลงในวัตถุโดยใช้เมธอดตัวช่วย ParagraphsByStyleName(Document, “Heading 1”)
- แยกย่อหน้าลงในวัตถุอื่นโดยใช้เมธอดตัวช่วย ParagraphsByStyleName(Document, “Heading 3”)
- เรียกใช้เมธอด ExtractContent(startPara, endPara, True) และส่งองค์ประกอบแรกในอาร์เรย์ย่อหน้าทั้งสองเป็นพารามิเตอร์ตัวที่หนึ่งและตัวที่สอง
- โทรเมธอดตัวช่วย GenerateDocument(Document, extractedNodes) เพื่อสร้างเอกสารที่ประกอบด้วยเนื้อหาที่แยกออกมา
- สุดท้าย บันทึกเอกสารที่ส่งคืนโดยใช้เมธอด Document.Save(string)
ตัวอย่างโค้ดต่อไปนี้แสดงวิธีการแยกเนื้อหาระหว่างย่อหน้าตามสไตล์
// โหลดเอกสาร Word
Document doc = new Document("document.docx");
// รวบรวมรายการของย่อหน้าโดยใช้รูปแบบหัวเรื่องที่เกี่ยวข้อง
List<Paragraph> parasStyleHeading1 = ParagraphsByStyleName(doc, "Heading 1");
List<Paragraph> parasStyleHeading3 = ParagraphsByStyleName(doc, "Heading 3");
// ใช้ตัวอย่างแรกของย่อหน้ากับสไตล์เหล่านั้น
Node startPara1 = (Node)parasStyleHeading1[0];
Node endPara1 = (Node)parasStyleHeading3[0];
// แยกเนื้อหาระหว่างโหนดเหล่านี้ในเอกสาร อย่ารวมเครื่องหมายเหล่านี้ในการแยก
ArrayList extractedNodes = ExtractContent(startPara1, endPara1, false);
// ใส่เนื้อหาลงในเอกสารใหม่และบันทึกลงในดิสก์
Document dstDoc = GenerateDocument(doc, extractedNodes);
dstDoc.Save("output.docx");
อ่านเพิ่มเติม
คุณสามารถสำรวจสถานการณ์อื่นๆ ในการแยกข้อความจากเอกสาร Word โดยใช้บทความคู่มือ this
รับใบอนุญาต API ฟรี
คุณสามารถรับ ใบอนุญาตชั่วคราว เพื่อใช้ Aspose.Words for .NET โดยไม่มีข้อจำกัดในการประเมิน
บทสรุป
ในบทความนี้ คุณได้เรียนรู้วิธีแยกข้อความจากเอกสาร MS Word โดยใช้ C# นอกจากนี้ คุณได้เห็นวิธีแยกเนื้อหาระหว่างโหนดประเภทเดียวกันหรือต่างชนิดกันในเอกสาร Word โดยทางโปรแกรม ดังนั้น คุณสามารถสร้างตัวแยกข้อความ MS Word ของคุณเองใน C# นอกจากนี้ คุณสามารถสำรวจคุณลักษณะอื่นๆ ของ Aspose.Words for .NET โดยใช้ เอกสารประกอบ ในกรณีที่คุณมีคำถามใดๆ โปรดแจ้งให้เราทราบผ่านทาง ฟอรัม ของเรา
ดูสิ่งนี้ด้วย
เคล็ดลับ: คุณอาจต้องกาเครื่องหมาย Aspose PowerPoint to Word Converter เนื่องจากจะสาธิตกระบวนการแปลงเอกสารงานนำเสนอเป็น Word ที่ได้รับความนิยม