PDFlibPas convertește conținut PDF în două formate editabile fără automatizare Office. ExportPageMarkdown și ExportDocumentMarkdown returnează Markdown semantic cu titluri deduse, liste ordonate și neordonate și tabele pipe, în timp ce SaveDOCXToFile și SaveDOCXToStream scriu un pachet WordprocessingML conținând paragrafe, titluri, numerotare nativă de liste, tabele detectate, stilizare de font, salturi de pagină și imagini PNG poziționate
Ambele rulează complet în Pascal, pe un server, fără Word instalat și fără COM. Această constrângere este motivul pentru care funcționalitatea există într-o bibliotecă PDF, nu într-un instrument desktop
De ce este „PDF în Word” cu adevărat dificil?
Pentru că o pagină PDF nu conține paragrafe. Conține operatori de afișare de text care plasează run-uri de glife la coordonate, în orice ordine le-a emis producătorul, fără nicio obligație de a indica dacă două run-uri aparțin aceleiași propoziții, cu atât mai puțin aceluiași element de listă. Formatul a fost proiectat să descrie exact o pagină tipărită, și reușește asta aruncând structura care a produs pagina
Așa că fiecare convertor trebuie să reconstruiască ce a aruncat generatorul. Gruparea liniilor vine din spațierea verticală și alinierea baseline. Limitele de paragraf vin din schimbări de spațiere și indentare. Un titlu este o linie al cărei font este mai mare sau mai gros decât corpul de text și care se distinge de ce urmează. O listă este o serie de paragrafe care încep cu un caracter bulă sau un tipar numeric. Un tabel este o grilă de blocuri de text ale căror margini se aliniază pe rânduri și coloane. Fiecare dintre acestea este o inferență, iar inferența înseamnă un rezultat bun pe documente care urmează convenții tipografice obișnuite și unul mediocru pe documente care nu o fac
PDF-urile tagged sunt excepția, și una mare. Când documentul poartă un arbore de structură, rolurile de paragraf, titlu, listă și tabel sunt înregistrate, nu ghicite, motiv pentru care munca de accesibilitate descrisă în structura de accesibilitate a PDF-ului tagged se răsplătește și în calitatea conversiei. Dacă tu controlezi producătorul, taggarea output-ului tău este cel mai eficient lucru pe care îl poți face pentru oricine trebuie mai târziu să îl convertească
Exportul Markdown, o pagină pe rând
Traseul Markdown este cel de folosit atunci când destinația este un flux de text: un site de documentație, un index de căutare, un corpus de retrieval pentru un asistent. Opțiunile sunt o mască de biți: PDF_MARKDOWN_INCLUDE_PAGE_MARKERS, PDF_MARKDOWN_DETECT_HEADINGS, PDF_MARKDOWN_PRESERVE_STYLES, cu PDF_MARKDOWN_DEFAULT combinând toate cele trei
var
Pdf: TPDFlib;
Md: WideString;
begin
Pdf := TPDFlib.Create;
try
Pdf.LoadFromFile('handbook.pdf', '');
// O singură pagină, ca string
Md := Pdf.ExportPageMarkdown(1, PDF_MARKDOWN_DEFAULT);
// Un interval de pagini, transmis în flux pe disc ca UTF-8 fără BOM
Pdf.SaveMarkdownToFile('1-40',
PDF_MARKDOWN_DETECT_HEADINGS or PDF_MARKDOWN_PRESERVE_STYLES,
'handbook.md');
finally
Pdf.Free;
end;
end;
Marcajele de pagină își câștigă locul în munca de retrieval. O bucată de text care poartă pagina din care provine poate fi citată precis, iar un cititor care urmează citarea ajunge exact unde se află afirmația. Dezactivează-le când Markdown-ul este destinat lecturii umane, unde limitele de pagină din layout-ul sursă sunt zgomot
Punctele de intrare pentru streaming contează pentru documente mari. SaveMarkdownToStream și SaveMarkdownToFile scriu UTF-8 o pagină pe rând și nu tamponează output-ul complet, așa că un manual de 900 de pagini nu devine mai întâi un string de 900 de pagini în memorie. Absența unui byte-order mark este de asemenea deliberată: un BOM pe un fișier Markdown derutează un număr surprinzător de mare de generatoare de site-uri statice și instrumente de diff
DOCX fără Office pe mașină
Scriitorul DOCX produce chiar el pachetul: intrări ZIP scrise ca Deflate brut cu verificări CRC, părțile WordprocessingML și relațiile care le leagă. Nimic nu apelează Word, ceea ce înseamnă că conversia rulează pe un server fără interfață, într-un cont de serviciu, într-un container, în toate locurile în care automatizarea Office este fie nelicențiată, fie instabilă, fie interzisă
var
Pdf: TPDFlib;
Target: TFileStream;
begin
Pdf := TPDFlib.Create;
Target := TFileStream.Create('handbook.docx', fmCreate);
try
Pdf.LoadFromFile('handbook.pdf', '');
Pdf.SaveDOCXToStream('1-40',
PDF_DOCX_INCLUDE_IMAGES or PDF_DOCX_DETECT_HEADINGS or
PDF_DOCX_PRESERVE_STYLES or PDF_DOCX_PRESERVE_PAGE_BREAKS,
Target);
finally
Target.Free;
Pdf.Free;
end;
end;
Datele de imagine sunt scrise pe măsură ce fiecare pagină este procesată, nu colectate și adăugate la final, așa că memoria de vârf urmărește o pagină, nu întregul document. Ordinea explicită a paginilor este păstrată, iar pagina PDF selectată este restaurată ulterior, ceea ce contează atunci când exportul este un pas dintr-o sarcină mai lungă care avea o pagină selectată din alte motive
Ce îți oferă împachetarea deterministă?
Reproductibilitate byte cu byte. Două conversii ale aceleiași intrări cu aceleași opțiuni produc același pachet, ceea ce înseamnă că poți face hash la output pentru a detecta o schimbare, poți diff-ui două build-uri ale unui document generat și poți face cache agresiv fără să te temi că o intrare identică a produs un artefact diferit
Automatizarea Office nu poate promite asta. Include timestamp-uri, identificatori de revizie și metadate dependente de mașină, astfel încât același document convertit de două ori diferă în moduri care distrug hash-ul. Același raționament conduce identificatorii de fișier PDF deterministe discutați în ID-uri PDF deterministe pentru build-uri reproductibile: când output-ul este reproductibil, verificarea devine o comparație, nu o inspecție
Unde este bun output-ul, și unde nu este
Fii onest cu utilizatorii tăi despre asta, pentru că această calitate a conversiei variază mai mult în funcție de intrare decât de convertor. PDF-urile tagged și documentele de afaceri generate curat, facturi, rapoarte, contracte, se convertesc bine: titlurile ajung titluri, tabelele supraviețuiesc, listele se renumerotează corect în Word. Layout-urile academice pe două coloane se convertesc acceptabil dacă geometria coloanelor este regulată. Tabelele care se întind peste salturi de pagină sunt reasamblate prin inferență și uneori despărțite. Materialele de marketing intens design-uite, unde textul este plasat pentru efect vizual, nu în ordine de citire, se convertesc slab, iar nicio cantitate de inferență nu repară asta
Documentele scanate sunt un caz separat cu totul. O pagină care este o singură imagine mare nu conține obiecte de text, așa că nu este nimic de exportat până când nu există un strat de text; traseul OCR care produce unul este o precondiție, nu o opțiune. Înainte să rulezi un lot mare, eșantionează o duzină de fișiere reprezentative și analizează output-ul, și ia în calcul enumerarea elementelor de pagină mai întâi, așa cum este descris în căutarea de text și enumerarea elementelor de pagină, pentru a vedea ce conțin efectiv paginile
Pentru fluxuri de asistenți și retrieval, traseul Markdown este de obicei ținta mai bună: titlurile devin limite de chunk, tabelele rămân lizibile ca tabele pipe, iar marcajele de pagină dau fiecărui chunk o locație citabilă. Pentru editare umană, DOCX este răspunsul, pentru că ce vrea utilizatorul nu este textul, ci abilitatea de a-l schimba
PDFlibPas este o bibliotecă PDF pentru Delphi, C++Builder și Lazarus cu interfețe DLL și ActiveX corespunzătoare, astfel încât aceleași apeluri de export sunt disponibile din C#, C++ sau gazde de scripting. Documentația completă și o versiune de test sunt pe pagina bibliotecii PDFlibPas Delphi