In this guide
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.
| 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.
- 012021 - Present
- 022018 - 2021
- 03SKILLS
- 04SQL
- 05dbt
- 06Python
- 07Excel
- 08Senior Data Analyst, Northwind Traders Inc.
- 09[U+F0B7] Cut weekly reporting time from 6 hours to 40
- 10minutes by automating SQL pipelines
- 11[U+F0B7] Built a churn model that three regional sales
- 12teams now use to plan renewals
- 13[U+F0B7] Trained 12 analysts on dbt and code review
- 14Data Analyst, Contoso Ltd.
- 15[U+F0B7] Rebuilt the finance dashboard in Tableau
- 16[U+F0B7] Wrote the data dictionary used by every new
- 17hire
- 18Tableau
- 01SQL
- 02Python
- 03Tableau
- 04dbt
- 05Excel
- 01Maya Ortiz
- 02maya.ortiz@example.com | (555) 010-4477 | Denver, CO
- 03EXPERIENCE
- 04Senior Data Analyst, Northwind Traders Inc. | 2021 - Present
- 05• Cut weekly reporting time from 6 hours to 40 minutes by automating SQL pipelines
- 06• Built a churn model that three regional sales teams now use to plan renewals
- 07• Trained 12 analysts on dbt and code review
- 08SKILLS
- 09SQL, Python, Tableau, dbt, Excel
- 10EDUCATION
- 11B.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.
- 01SKILLS
- 02SQL Python Tableau
- 03dbt Excel
- 01SKILLS
- 02SQL
- 03Python
- 04dbt
- 05Excel
- 06Tableau
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.
- 01EXPERIENCE
- 022021 - Present
- 03Senior Data Analyst, Northwind Traders Inc.
- 04• Cut weekly reporting time from 6 hours to 40 minutes by automating SQL pipelines
- 05• Built a churn model that three regional sales teams now use to plan renewals
- 06• Trained 12 analysts on dbt and code review
- 072018 - 2021
- 08Data Analyst, Contoso Ltd.
- 09• 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
- Unsuccessful resume parse, Greenhouse Support
- pdftotext(1) manual page, poppler-utils, Debian
- PDFPageProxy.getTextContent, PDF.js API, Mozilla
- Test fixture: table-experience.pdf, ATSPrep
- Test fixture: table-word.docx, ATSPrep
- Test fixture: table-word-pdf.pdf, ATSPrep
Put it into practice on a real resume.
Each example is a complete resume with role keywords and bullets that show proof. Open one in the Studio and make it yours, then download it. The first download needs no account.

