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.