Examples / text_extraction3 / activex_cpp

Text Extraction3

A complete, runnable activex_cpp program — 78 lines, shipped in your download.

Demonstrates Text

Same example, other languages: c cpp cpp_linux csharp python vbnet

examples/activex_cpp/text_extraction3/text_extraction3.cpp 78 lines
// ============================================================================
//  text_extraction3 -- C++ ActiveX (COM) port, following
//  examples/activex/text_extraction3/text_extraction3.vbs
//
//  Imports a PDF and extracts its text page by page with ExtractText, writing
//  the result to out.txt.
//
//  Unlike the flat pdfExtractText (which hands back a raw wchar pointer plus a
//  length), the COM ExtractText returns the page text through an [out] VARIANT,
//  so this ports with no pointer handling at all -- which is why the VBScript
//  sibling points here as the extraction path that works from any client.
// ============================================================================
#import "..\\..\\wrappers\\activex\\LumasPdfAX.tlb" no_namespace named_guids

#include <windows.h>

#include "axcommon.h"

#include <cstdio>
#include <string>

static const long lcmRecursiveDelayed = 3;   // lcmRecursive Or lcmDelayed

int main() {
    ChdirToExe();
    ComInit com;
    if (!com.ok()) return 1;

    ILumasPDFPtr pdf;
    if (FAILED(pdf.CreateInstance(L"LumasPdf.PDF"))) return 1;
    pdf->RaiseExceptions = VARIANT_FALSE;

    pdf->CreateNewPDFW(B(""));
    pdf->SetCMapDirW(B("E:\\LUMASPDFSDK\\Resource\\CMap"), lcmRecursiveDelayed);
    pdf->SetImportFlags(ifImportAll | ifImportAsPage);

    if (pdf->OpenImportFileW(B("E:\\LUMASPDFSDK\\sample_multipage.pdf"), ptOpen, B("")) < 0) {
        std::printf("OpenImportFile failed\n");
        return 1;
    }
    pdf->ImportPDFFile(1, 1, 1);
    pdf->CloseImportFile();
    pdf->FlattenAnnots(affMarkupAnnots);
    pdf->FlattenForm();

    std::string outFile = OutFile("out.txt");
    FILE* f = fopen(outFile.c_str(), "wb");
    if (!f) return 1;
    // UTF-16LE with BOM, matching the sibling's CreateTextFile(..., True) mode.
    const unsigned char bom[2] = {0xFF, 0xFE};
    fwrite(bom, 1, 2, f);

    auto W = [&](const std::wstring& s) {
        if (!s.empty()) fwrite(s.data(), sizeof(wchar_t), s.size(), f);
    };

    long cnt = pdf->GetPageCount();
    for (long i = 1; i <= cnt; ++i) {
        if (i > 1) W(L"\r\n");
        wchar_t hdr[128];
        swprintf(hdr, 128,
                 L"%%----------------------- Page %ld -----------------------------\r\n", i);
        W(hdr);

        // Area = 0: the whole page. It takes the InPtr path, which rejects
        // Empty/Null, so the integer 0 is what stands in for a nil rectangle.
        _variant_t area((long)0);
        OutVar txt(VT_BSTR);
        if (pdf->ExtractText(i, tefDeleteOverlappingText | tefSortTextX, area, txt.Addr())) {
            _bstr_t s = txt.AsStr();
            if (s.length()) W(std::wstring((const wchar_t*)s, s.length()));
        }
    }
    fclose(f);
    std::printf("Text successfully extracted to %s (%ld pages)\n", outFile.c_str(), cnt);
    return 0;
}

This file is in the SDK at examples/activex_cpp/text_extraction3/text_extraction3.cpp. The build fails if this page and that file ever differ.