Ekstrak Teks dari Dokumen MS Word di C#

Ekstraksi teks dari dokumen Word sering dilakukan dalam berbagai skenario. Misalnya untuk menganalisis teks, mengekstrak bagian tertentu dari suatu dokumen dan menggabungkannya menjadi satu dokumen, dan sebagainya. Pada artikel ini, Anda akan belajar cara mengekstrak teks dari dokumen Word secara terprogram dalam C#. Selain itu, kami akan membahas cara mengekstraksi konten di antara elemen tertentu seperti paragraf, tabel, dll. Secara dinamis.

Perpustakaan C# untuk Mengekstrak Teks dari Dokumen Word

Aspose.Words for .NET adalah pustaka tangguh yang memungkinkan Anda membuat dokumen MS Word dari awal. Selain itu, ini memungkinkan Anda memanipulasi dokumen Word yang ada untuk enkripsi, konversi, ekstraksi teks, dll. Kami akan menggunakan pustaka ini untuk mengekstrak teks dari dokumen Word DOCX atau DOC. Anda dapat mengunduh DLL API atau menginstalnya langsung dari NuGet menggunakan konsol pengelola paket.

PM> Install-Package Aspose.Words

Ekstraksi Teks dalam Dokumen Word menggunakan C#

Dokumen MS Word terdiri dari berbagai elemen yang meliputi paragraf, tabel, gambar, dll. Oleh karena itu, persyaratan ekstraksi teks dapat bervariasi dari satu skenario ke skenario lainnya. Misalnya, Anda mungkin perlu mengekstrak teks di antara paragraf, bookmark, komentar, dll.

Setiap jenis elemen dalam dokumen Word direpresentasikan sebagai node. Oleh karena itu, untuk memproses dokumen, Anda harus bermain dengan node. Jadi mari kita mulai dan lihat cara mengekstrak teks dari dokumen Word dalam berbagai skenario.

Ekstrak Teks dari Dokumen Word di C#

Pada bagian ini, kita akan menerapkan ekstraktor teks C# untuk dokumen Word dan alur kerja ekstraksi teks adalah sebagai berikut:

  • Pertama, kita akan menentukan node yang ingin kita sertakan dalam proses ekstraksi teks.
  • Kemudian, kami akan mengekstrak konten di antara node yang ditentukan (termasuk atau tidak termasuk node awal dan akhir).
  • Terakhir, kami akan menggunakan tiruan dari node yang diekstrak, misalnya untuk membuat dokumen Word baru yang terdiri dari konten yang diekstrak.

Sekarang mari kita tulis sebuah metode bernama ExtractContent yang akan kita lewati node dan beberapa parameter lain untuk melakukan ekstraksi teks. Metode ini akan mengurai dokumen dan mengkloning node. Berikut ini adalah parameter yang akan kita berikan pada metode ini.

  1. StartNode dan EndNode masing-masing sebagai titik awal dan akhir untuk ekstraksi konten. Ini bisa berupa node level blok (Paragraph , Table) atau level inline (misalnya Run, FieldStart, BookmarkStart, dll.).
    1. Untuk melewati bidang, Anda harus melewati objek FieldStart yang sesuai.
    2. Untuk melewati bookmark, node BookmarkStart dan BookmarkEnd harus dilewati.
    3. Untuk komentar, node CommentRangeStart dan CommentRangeEnd harus digunakan.
  2. IsInclusive menentukan apakah penanda disertakan dalam ekstraksi atau tidak. Jika opsi ini disetel ke false dan node yang sama atau node berurutan dilewatkan, maka daftar kosong akan dikembalikan.

Berikut ini adalah implementasi lengkap dari metode ExtractContent yang mengekstrak konten antar node yang dilewatkan.

public static ArrayList ExtractContent(Node startNode, Node endNode, bool isInclusive)
{
    // Pertama periksa apakah node yang diteruskan ke metode ini valid untuk digunakan.
    VerifyParameterNodes(startNode, endNode);

    // Buat daftar untuk menyimpan node yang diekstraksi.
    ArrayList nodes = new ArrayList();

    // Catat node asli yang diteruskan ke metode ini sehingga kami dapat memisahkan node penanda jika diperlukan.
    Node originalStartNode = startNode;
    Node originalEndNode = endNode;

    // Ekstrak konten berdasarkan node level blok (paragraf dan tabel). Lintasi node induk untuk menemukannya.
    // Kami akan membagi konten node pertama dan terakhir tergantung apakah node penanda inline
    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 saat ini yang kami ekstrak dari dokumen.
    Node currNode = startNode;

    // Mulailah mengekstraksi konten. Memproses semua node level blok dan secara khusus membagi node pertama dan terakhir bila diperlukan sehingga pemformatan paragraf dipertahankan.
    // Metodenya sedikit lebih rumit daripada ekstraktor biasa karena kita perlu memperhitungkan faktor dalam mengekstraksi menggunakan node, bidang, bookmark, dll sebaris untuk membuatnya sangat berguna.
    while (isExtracting)
    {
        // Klon node saat ini dan turunannya untuk mendapatkan salinannya.
        Node cloneNode = currNode.Clone(true);
        isEndingNode = currNode.Equals(endNode);

        if ((isStartingNode || isEndingNode) && cloneNode.IsComposite)
        {
            // Kita perlu memproses setiap penanda secara terpisah, jadi alihkan ke metode terpisah.
            if (isStartingNode)
            {
                ProcessMarker((CompositeNode)cloneNode, nodes, originalStartNode, isInclusive, isStartingNode, isEndingNode);
                isStartingNode = false;
            }

            // Kondisional perlu dipisahkan karena penanda awal dan akhir level blok mungkin node yang sama.
            if (isEndingNode)
            {
                ProcessMarker((CompositeNode)cloneNode, nodes, originalEndNode, isInclusive, isStartingNode, isEndingNode);
                isExtracting = false;
            }
        }
        else
            // Node bukan penanda awal atau akhir, cukup tambahkan salinan ke daftar.
            nodes.Add(cloneNode);

        // Pindah ke node berikutnya dan ekstrak. Jika simpul berikutnya adalah nol, itu berarti sisa konten ditemukan di bagian yang berbeda.
        if (currNode.NextSibling == null && isExtracting)
        {
            // Pindah ke bagian berikutnya.
            Section nextSection = (Section)currNode.GetAncestor(NodeType.Section).NextSibling;
            currNode = nextSection.Body.FirstChild;
        }
        else
        {
            // Pindah ke node berikutnya dalam tubuh.
            currNode = currNode.NextSibling;
        }
    }

    // Kembalikan node di antara penanda node.
    return nodes;
}

Beberapa metode pembantu juga diperlukan oleh metode ExtractContent untuk menyelesaikan operasi ekstraksi teks, yang diberikan di bawah ini.

public static List<Paragraph> ParagraphsByStyleName(Document doc, string styleName)
{
    // Buat larik untuk mengumpulkan paragraf dengan gaya yang ditentukan.
    List<Paragraph> paragraphsWithStyle = new List<Paragraph>();

    NodeCollection paragraphs = doc.GetChildNodes(NodeType.Paragraph, true);

    // Telusuri semua paragraf untuk menemukan paragraf dengan gaya yang ditentukan.
    foreach (Paragraph paragraph in paragraphs)
    {
        if (paragraph.ParagraphFormat.Style.Name == styleName)
            paragraphsWithStyle.Add(paragraph);
    }

    return paragraphsWithStyle;
}
private static void VerifyParameterNodes(Node startNode, Node endNode)
{
    // Urutan pemeriksaan ini dilakukan adalah penting.
    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");

    // Periksa simpul akhir setelah simpul awal di pohon DOM
    // Pertama periksa apakah mereka berada di bagian yang berbeda, lalu jika mereka tidak memeriksa posisinya di badan bagian yang sama.
    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)
{
    // Uji apakah simpul tersebut adalah turunan dari simpul Paragraf atau Tabel dan juga bukan paragraf atau tabel, paragraf di dalam kelas komentar yang mungkin merupakan turunan dari paragraf.
    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)
{
    // Jika kita berurusan dengan node level blok, lihat saja apakah itu harus dimasukkan dan tambahkan ke daftar.
    if (!IsInline(node))
    {
        // Jangan tambahkan node dua kali jika penandanya adalah node yang sama
        if (!(isStartMarker && isEndMarker))
        {
            if (isInclusive)
                nodes.Add(cloneNode);
        }
        return;
    }

    // Jika marker adalah node FieldStart, periksa apakah akan disertakan atau tidak.
    // Kami berasumsi untuk penyederhanaan bahwa FieldStart dan FieldEnd muncul di paragraf yang sama.
    if (node.NodeType == NodeType.FieldStart)
    {
        // Jika penanda adalah simpul awal dan tidak disertakan, lewati ke ujung bidang.
        // Jika penanda adalah simpul akhir dan akan dimasukkan maka pindah ke bidang akhir sehingga bidang tidak akan dihapus.
        if ((isStartMarker && !isInclusive) || (!isStartMarker && isInclusive))
        {
            while (node.NextSibling != null && node.NodeType != NodeType.FieldEnd)
                node = node.NextSibling;

        }
    }

    // Jika salah satu penanda adalah bagian dari komentar, maka untuk menyertakan komentar itu sendiri, kita perlu memindahkan penunjuk ke depan ke Komentar
    // Node ditemukan setelah node CommentRangeEnd.
    if (node.NodeType == NodeType.CommentRangeEnd)
    {
        while (node.NextSibling != null && node.NodeType != NodeType.Comment)
            node = node.NextSibling;

    }

    // Temukan node yang sesuai di node kloning kami berdasarkan indeks dan kembalikan.
    // Jika node awal dan akhir sama, beberapa node anak mungkin sudah dihapus. Kurangi
    // Selisih untuk mendapatkan indeks yang tepat.
    int indexDiff = node.ParentNode.ChildNodes.Count - cloneNode.ChildNodes.Count;

    // Node anak dihitung identik.
    if (indexDiff == 0)
        node = cloneNode.ChildNodes[node.ParentNode.IndexOf(node)];
    else
        node = cloneNode.ChildNodes[node.ParentNode.IndexOf(node) - indexDiff];

    // Hapus node ke/dari penanda.
    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();
    }

    // Setelah memproses node komposit mungkin menjadi kosong. Jika memiliki tidak memasukkannya.
    if (!(isStartMarker && isEndMarker))
    {
        if (cloneNode.HasChildNodes)
            nodes.Add(cloneNode);
    }

}
public static Document GenerateDocument(Document srcDoc, ArrayList nodes)
{
    // Buat dokumen kosong.
    Document dstDoc = new Document();
    // Hapus paragraf pertama dari dokumen kosong.
    dstDoc.FirstSection.Body.RemoveAllChildren();

    // Impor setiap node dari daftar ke dalam dokumen baru. Pertahankan pemformatan asli dari node.
    NodeImporter importer = new NodeImporter(srcDoc, dstDoc, ImportFormatMode.KeepSourceFormatting);

    foreach (Node node in nodes)
    {
        Node importNode = importer.ImportNode(node, true);
        dstDoc.FirstSection.Body.AppendChild(importNode);
    }

    // Kembalikan dokumen yang dihasilkan.
    return dstDoc;
}

Sekarang kami siap menggunakan metode ini dan mengekstrak teks dari dokumen Word.

Ekstrak Teks antar Paragraf dalam Dokumen Word

Mari kita lihat cara mengekstrak konten di antara dua paragraf dalam dokumen Word DOCX. Berikut ini adalah langkah-langkah untuk melakukan operasi ini di C#.

  • Pertama, muat dokumen Word menggunakan kelas Document.
  • Dapatkan referensi paragraf awal dan akhir menjadi dua objek menggunakan metode Document.FirstSection.Body.GetChild(NodeType.PARAGRAPH, int, boolean).
  • Panggil metode ExtractContent(startPara, endPara, True) untuk mengekstrak node menjadi objek.
  • Panggil metode pembantu GenerateDocument(Document, extractNodes) untuk membuat dokumen yang terdiri dari konten yang diekstraksi.
  • Terakhir, simpan dokumen yang dikembalikan menggunakan metode Document.Save(string).

Contoh kode berikut menunjukkan cara mengekstrak teks antara paragraf ke-7 dan ke-11 dalam dokumen Word di C#.

// Muat dokumen Word
Document doc = new Document("document.docx");

// Kumpulkan node (metode GetChild menggunakan indeks berbasis 0)
Paragraph startPara = (Paragraph)doc.FirstSection.Body.GetChild(NodeType.Paragraph, 6, true);
Paragraph endPara = (Paragraph)doc.FirstSection.Body.GetChild(NodeType.Paragraph, 10, true);

// Ekstrak konten di antara simpul-simpul ini dalam dokumen. Sertakan penanda ini dalam ekstraksi.
ArrayList extractedNodes = ExtractContent(startPara, endPara, true);

// Masukkan konten ke dalam dokumen baru dan simpan ke disk.
Document dstDoc = GenerateDocument(doc, extractedNodes);
dstDoc.Save("output.docx");

Ekstrak Teks antara Berbagai Jenis Node dalam Dokumen Word

Anda juga dapat mengekstraksi konten di antara berbagai jenis node. Untuk demonstrasi, mari ekstrak konten antara paragraf dan tabel dan simpan ke dalam dokumen Word baru. Berikut ini adalah langkah-langkah untuk melakukan operasi ini.

  • Muat dokumen Word menggunakan kelas Document.
  • Dapatkan referensi node awal dan akhir menjadi dua objek menggunakan metode Document.FirstSection.Body.GetChild(NodeType, int, boolean).
  • Panggil metode ExtractContent(startPara, endPara, True) untuk mengekstrak node menjadi objek.
  • Panggil metode pembantu GenerateDocument(Document, extractNodes) untuk membuat dokumen yang terdiri dari konten yang diekstraksi.
  • Simpan dokumen yang dikembalikan menggunakan metode Document.Save(string).

Contoh kode berikut menunjukkan cara mengekstrak teks antara paragraf dan tabel di C#.

// Muat dokumen 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);

// Ekstrak konten di antara simpul-simpul ini dalam dokumen. Sertakan penanda ini dalam ekstraksi.
ArrayList extractedNodes = ExtractContent(startPara, endTable, true);

// Masukkan konten ke dalam dokumen baru dan simpan ke disk.
Document dstDoc = GenerateDocument(doc, extractedNodes);
dstDoc.Save("output.docx");

Ekstrak Teks antar Paragraf berdasarkan Gaya

Sekarang mari kita lihat cara mengekstrak konten antar paragraf berdasarkan gaya. Untuk demonstrasi, kita akan mengekstrak konten antara “Heading 1” pertama dan “Heading 3” pertama dalam dokumen Word. Langkah-langkah berikut menunjukkan cara mencapainya di C#.

  • Pertama, muat dokumen Word menggunakan kelas Document.
  • Kemudian, ekstrak paragraf menjadi objek menggunakan metode pembantu ParagraphsByStyleName(Document, “Heading 1”).
  • Ekstrak paragraf ke objek lain menggunakan metode bantuan ParagraphsByStyleName(Document, “Heading 3”).
  • Panggil metode ExtractContent(startPara, endPara, True) dan teruskan elemen pertama di kedua larik paragraf sebagai parameter pertama dan kedua.
  • Panggil metode pembantu GenerateDocument(Document, extractNodes) untuk membuat dokumen yang terdiri dari konten yang diekstraksi.
  • Terakhir, simpan dokumen yang dikembalikan menggunakan metode Document.Save(string).

Contoh kode berikut menunjukkan cara mengekstrak konten antar paragraf berdasarkan gaya.

// Muat dokumen Word
Document doc = new Document("document.docx");

// Kumpulkan daftar paragraf menggunakan gaya tajuk masing-masing.
List<Paragraph> parasStyleHeading1 = ParagraphsByStyleName(doc, "Heading 1");
List<Paragraph> parasStyleHeading3 = ParagraphsByStyleName(doc, "Heading 3");

// Gunakan contoh paragraf pertama dengan gaya tersebut.
Node startPara1 = (Node)parasStyleHeading1[0];
Node endPara1 = (Node)parasStyleHeading3[0];

// Ekstrak konten di antara simpul-simpul ini dalam dokumen. Jangan sertakan penanda ini dalam ekstraksi.
ArrayList extractedNodes = ExtractContent(startPara1, endPara1, false);

// Masukkan konten ke dalam dokumen baru dan simpan ke disk.
Document dstDoc = GenerateDocument(doc, extractedNodes);
dstDoc.Save("output.docx");

Baca selengkapnya

Anda dapat menjelajahi skenario lain untuk mengekstraksi teks dari dokumen Word menggunakan artikel dokumentasi ini.

Dapatkan Lisensi API Gratis

Anda bisa mendapatkan lisensi sementara untuk menggunakan Aspose.Words for .NET tanpa batasan evaluasi.

Kesimpulan

Pada artikel ini, Anda telah mempelajari cara mengekstrak teks dari dokumen MS Word menggunakan C#. Selain itu, Anda telah melihat cara mengekstraksi konten antara jenis node yang serupa atau berbeda dalam dokumen Word secara terprogram. Dengan demikian, Anda dapat membuat ekstraktor teks MS Word Anda sendiri di C#. Selain itu, Anda dapat menjelajahi fitur lain dari Aspose.Words for .NET menggunakan dokumentasi. Jika Anda memiliki pertanyaan, jangan ragu untuk memberi tahu kami melalui forum kami.

Lihat juga

Tip: Anda mungkin ingin mencentang Aspose PowerPoint to Word Converter karena ini menunjukkan proses konversi dokumen presentasi ke Word yang populer.