mx_app() opens a point-and-click version of macrox. You
pick a PDF, draw a box around a table, clean the result up, and download
it, without writing any R code. Everything you do is recorded as a
macro, so the same workflow can be replayed on next year’s report.
This article walks through one realistic example from start to finish: pulling the Calf Births by County, Gender and Sire Type table out of the Department of Agriculture’s AIM Bovine Statistics Report, fixing a column where three numbers were merged into one cell, and saving the recipe.
The app uses packages that are only needed for the interface, so they are optional dependencies of macrox. Install them once:
Then start it:
library(macrox)
mx_app() # your system browser
mx_app("dialog") # a floating RStudio dialog
mx_app("pane") # the RStudio Viewer paneIf any of those packages is missing, mx_app() stops
straight away and lists exactly which ones to install.
The sidebar on the left stays visible on every tab:
.yml) into
the current session.Choose a PDF and open the Extract tab. The page you are looking at is on the left and the extraction controls are on the right.
< and
> buttons (or the left and right arrow keys) until you
reach the page with your table.2 or
more, and macrox joins the header cells into single column names.The four tabs above the form are different ways of telling macrox where the table is:
| Tab | Use it when |
|---|---|
| Box | You know the page and can draw (or type) the area. The most reliable option. |
| Index | You know the page and that it is, say, the second table on it. |
| Fuzzy | The page number changes between reports, but the table’s caption stays similar. |
| Struct | You want records (several fields, one row per entity found) rather
than a grid. Needs GLiNER2, set up with
setup_gliner(). |
The method controls how the table is read:
| Method | Best for |
|---|---|
bbox |
A word-position engine. Good when a page has charts, missing grid lines, or numbers that run together. Pair it with a drawn area. |
lattice |
Clean tables with visible grid lines (needs Java, through tabulapdf). |
stream |
Tables aligned with spaces rather than lines (tabulapdf). |
llm |
Complex or scanned layouts, using an LLM that reads an image of the page. Needs an API key. |
docling |
An offline ML layout model for scanned or complex pages. Run
setup_docling() once first. |
For this page, bbox with four header rows works well. A
notification confirms what was read, and a preview appears under the
Extract button.
Each extracted table gets its own sub-tab in the Tables tab, with its size (here 28 rows by 8 columns) and a row of buttons underneath.
| Button | What it does |
|---|---|
| Rename | Rename columns. |
| Cast types | Convert columns to numeric, integer, date and so on. |
| Filter rows | Drop rows by a condition, for example the Totals
row. |
| Split col | Split one column into several (see below). |
| Undo | Step back through the last few changes to this table. |
| Copy | Copy the table to the clipboard as tab-separated text. |
| Validate | Check the table against rules you write, one per line, as
rule_name: expression. |
| Stats | Summarise each column: type, range or number of unique values, and missing values. |
This table shows a common problem with PDFs. The second
Calf.Births column holds 10,443 21,997 3,753 in a
single cell, because the PDF’s three sub-columns (male, female, total)
ran together. Split col fixes this.
Pick the column, give a separator (a regular expression,
\s+ meaning “any whitespace” by default) and the names of
the new columns. The dialog previews the first three values before you
commit. Click Apply and the single column is replaced
by three.
The same step in a script is split_column():
sess <- mx_session("AIM_Stats_Report_060525.pdf")
sess |> select_table("calf_county", page = 9, method = "bbox", header_rows = 4)
sess |> split_column("calf_county",
col = "Calf.Births.by.County..Gender.born.to.Beef.Bull.County.Female.Total.Male",
into = c("male", "female", "total"))Every extraction and every cleaning action is recorded on the Steps tab. Click a step to see its exact parameters, and remove a step by number if it was a mistake.
This list is the macro. Nothing else needs to be saved for it to be replayable.
The Export tab has two halves.
The macro for this walkthrough starts like this (abridged):
macro:
name: my_macro
source: AIM_Stats_Report_060525.pdf
n_steps: 2
steps:
- step: select_table
label: calf_county
page: 9
table_index: 1
...Next year’s report will have the same layout and a different PDF. There are three ways to run the macro against it.
Outside the app, the same macro replays from R:
See vignette("macros-and-testing") for parameterised
macros, batch replay and snapshot testing in CI.
vignette("llm-integration") for provider setup.To go further, vignette("extraction-methods") covers
bbox tuning, multi-page tables and choosing a method.