# Tables in resumes: what PDF and DOCX text extraction returns

> We put a resume's experience and skills in tables, saved PDF and DOCX versions and read each with three extractors. The DOCX read cleanly; the PDFs didn't.

|  |  |
| --- | --- |
| Category | Original research |
| Published | October 19, 2026 |
| Reading time | 7 min |
| Rendered page | https://atsprep.com/blog/resume-tables-text-extraction |
| This document | https://atsprep.com/blog/resume-tables-text-extraction.md |

A table in a resume is a set of cells the reader has to put back in order, and a PDF doesn't record which cell comes first. In our fixtures the Word table read cleanly as a DOCX. As PDFs, the same rows came back two ways: pdf.js read across each row, and pdftotext pulled the date column away from the roles. Our checker read the lines correctly but used to file no roles at all from the Word export; we fixed that on 20 October 2026 after these tests.

## The short version

- Word table as DOCX: our importer read 2 roles, 5 bullets and 5 skills, one cell per line.
- pdf.js read both table PDFs row by row: “2021 - Present Senior Data Analyst, Northwind Traders Inc.”.
- pdftotext split each date from its role in the Chromium PDF, and listed every date and skill before any role in the Word export.
- pdftotext also reordered the skills grid to SQL, Python, dbt, Excel, Tableau.
- Our checker used to file 0 roles from the Word table PDF and put job titles under Skills. Since our fix on 20 October 2026 it files 2 roles, 5 bullets and 5 skills.

## What each reader made of the table

The fixtures put dates in a narrow left cell and the role with its bullets in the right cell, with skills in a three-across grid below.

*Table fixtures by reader*

| Fixture | pdf.js | pdftotext | ATSPrep checker |
| --- | --- | --- | --- |
| HTML table saved as PDF (Chromium) | row by row | dates split from roles, skills reordered | 2 roles, 5 bullets, 5 skills |
| Word table (DOCX) | not a PDF | not a PDF | 2 roles, 5 bullets, 5 skills |
| The same Word table saved as PDF | row by row | every date and skill before the roles | 2 roles, 5 bullets, 5 skills |

## Tables in a PDF

A PDF has no table object in its page content. Cell borders are lines, and the text in each cell is placed independently. An extractor either follows the order the text was written in, as pdf.js does, or rebuilds rows and columns from position, as pdftotext's default mode does.

In the Word table exported by LibreOffice 26.8.1.1, pdftotext treated the date column as its own block and returned both dates and every skill before the first role. pdf.js returned clean rows, and so did our checker's line text, but its section mapping used to fail: no roles, no bullets, and job titles and bullets filed under Skills. It took the gap between the date cells and the entries for the gap between two columns.

We fixed that on 20 October 2026 after these tests. A narrow left strip that holds every heading while the wider right side holds none is now read as part of a table, not as a column of its own, so the checker keeps each date with its role.

*Before: Word table saved as PDF (pdftotext 26.10.0, table-word-pdf.pdf)*

```text
2021 - Present
2018 - 2021
SKILLS
SQL
dbt
Python
Excel
Senior Data Analyst, Northwind Traders Inc.
[U+F0B7] Cut weekly reporting time from 6 hours to 40
minutes by automating SQL pipelines
[U+F0B7] Built a churn model that three regional sales
teams now use to plan renewals
[U+F0B7] Trained 12 analysts on dbt and code review
Data Analyst, Contoso Ltd.
[U+F0B7] Rebuilt the finance dashboard in Tableau
[U+F0B7] Wrote the data dictionary used by every new
hire
Tableau
```

*Since the fix: what the ATSPrep checker files under Skills (table-word-pdf.pdf)*

```text
SQL
Python
Tableau
dbt
Excel
```

*After: the same content as a single column (the ATSPrep checker, order-single-column.pdf)*

```text
Maya Ortiz
maya.ortiz@example.com | (555) 010-4477 | Denver, CO
EXPERIENCE
Senior Data Analyst, Northwind Traders Inc. | 2021 - Present
• Cut weekly reporting time from 6 hours to 40 minutes by automating SQL pipelines
• Built a churn model that three regional sales teams now use to plan renewals
• Trained 12 analysts on dbt and code review
SKILLS
SQL, Python, Tableau, dbt, Excel
EDUCATION
B.S. Statistics, Lakeview University, 2018
```

## Skills grids

A grid of skills is the most common resume table. pdf.js returned it row by row, so the words stayed in the order typed. pdftotext read it column by column and returned SQL, Python, dbt, Excel, Tableau. Nothing was lost, but a parser that expects one skill per cell or a comma list gets neither.

*Skills grid (pdf.js 6.3.289, table-experience.pdf)*

```text
SKILLS
SQL Python Tableau
dbt Excel
```

*Skills grid (pdftotext 26.10.0, table-experience.pdf)*

```text
SKILLS
SQL
Python
dbt
Excel
Tableau
```

## Tables in a DOCX

A DOCX stores a table as rows of cells in document order, so the reading order is written into the file. Our importer read the Word table one cell per line, with every role, bullet and skill in place. If a portal accepts DOCX and your resume must keep a table, the DOCX is the safer upload.

*Word table, as DOCX (the ATSPrep checker, table-word.docx)*

```text
EXPERIENCE
2021 - Present
Senior Data Analyst, Northwind Traders Inc.
• Cut weekly reporting time from 6 hours to 40 minutes by automating SQL pipelines
• Built a churn model that three regional sales teams now use to plan renewals
• Trained 12 analysts on dbt and code review
2018 - 2021
Data Analyst, Contoso Ltd.
• Rebuilt the finance dashboard in Tableau
```

## What ATS vendors say about tables

Greenhouse's support article on unsuccessful resume parses (checked 19 October 2026) lists "Complex resumes with tables, headers, and footers" among the formatting issues that can lead to a partial parse that has to be corrected by hand.

## Formatting best practices for tables and text extraction

- Put each role on one line: title, employer and dates, followed by its bullets. No table needed.
- Write skills as a comma-separated line under a SKILLS heading.
- If you keep a table, upload the DOCX where the portal allows it.
- Never put contact details or job titles in table cells.
- Check a PDF export in two readers. If dates and roles come back apart, take the table out.

## How we tested

We built every fixture from the same fictional one-page resume, changing one thing at a time. PDFs come from Chromium 153.0.8010.12 (printed through Playwright 1.63.0) and from LibreOffice 26.8.1.1 converting our DOCX files, the way Word users export. Each file was read three ways: pdf.js 6.3.289 getTextContent, poppler pdftotext 26.10.0 in its default mode, and the importer the ATSPrep checker runs in your browser. DOCX files have no PDF text layer, so only our importer reads them. The code blocks on this page are the readers' output, copied by script; private-use and control characters are written as [U+XXXX] because they would otherwise be invisible.

These are three common open readers, not any employer's applicant tracking system. Commercial parsers use their own extractors, so treat a failure here as a risk to remove, not a prediction of what a specific system will do.

## Common questions

### Are tables ATS friendly in a resume?

Not reliably in a PDF. In our test the same table PDF came back row by row in pdf.js and with dates pulled away from roles in pdftotext, and our checker filed no roles from the Word table export until we fixed it on 20 October 2026. As a DOCX the same table read cleanly. Greenhouse lists complex resumes with tables among its parse failure causes.

### What are ATS resume formatting best practices for tables and text extraction?

Use one column, write each role as a line with title, employer and dates, list skills as a comma-separated line, and keep contact details as body text. If you need a table, upload a DOCX. Then check the export in an extractor and confirm every role comes back next to its dates.

### Does a table in a DOCX extract better than a table in a PDF?

In our fixtures, yes. A DOCX stores cells in document order and our importer read every role, bullet and skill. The PDF export of the same table came back in different orders from pdf.js and pdftotext.

### How should I list skills without a table?

One line under a SKILLS heading, separated by commas: SQL, Python, Tableau, dbt, Excel. That line came back identically from every reader we tested.

## Sources and further reading

1. [Unsuccessful resume parse](https://support.greenhouse.io/hc/en-us/articles/200989175-Unsuccessful-resume-parse), Greenhouse Support
2. [pdftotext(1) manual page, poppler-utils](https://manpages.debian.org/testing/poppler-utils/pdftotext.1.en.html), Debian
3. [PDFPageProxy.getTextContent, PDF.js API](https://mozilla.github.io/pdf.js/api/draft/module-pdfjsLib-PDFPageProxy.html), Mozilla
4. [Test fixture: table-experience.pdf](/research/extraction-fixtures/table-experience.pdf), ATSPrep
5. [Test fixture: table-word.docx](/research/extraction-fixtures/table-word.docx), ATSPrep
6. [Test fixture: table-word-pdf.pdf](/research/extraction-fixtures/table-word-pdf.pdf), ATSPrep

## Related

- [Resume tables under extraction: same problem, milder form](https://atsprep.com/blog/resume-tables-ats-extraction.md)
- [PDF vs DOCX resume: which one to send](https://atsprep.com/blog/pdf-vs-docx-for-ats.md)
- [Resume PDF reading order: columns, sidebars and text boxes](https://atsprep.com/blog/resume-pdf-reading-order-columns.md)

## About ATSPrep

ATSPrep (https://atsprep.com) is a free resume and application workspace. Match experience to a posting, strengthen claims with evidence, and track the next action. Its PDF check shows text recovered by ATSPrep's extractor, not an employer's proprietary ATS or hiring decision.

- **Price:** free. Checking, importing, editing and downloading cost nothing, and downloads carry no watermark. Everything listed here is free.
- **Account:** none needed to check, import or edit a resume. A free sign-in is needed to download after the first file, to sync, and for more checks or more than 5 AI edits.
- **Your file:** parsed and exported inside the browser. The resume file itself is never uploaded.
- **Optional:** text leaves the browser only when you press a button: semantic match and AI edits (the lines involved), a job link (the link) and Pip voice calls (your speech). Never your contact details, and none of it is stored.
- **Connection:** some tools load on first use and need a connection to download. Local storage is not a cloud backup.
- **Accepts:** PDF, DOCX, TXT, Markdown, or pasted plain text.

Start here: https://atsprep.com/studio
