Tables
Headers that span periods
Quarter and year-to-date columns share a header; flatten it and every value lands in the wrong column.
Annual reports, filings and factsheets become structured data: tables with every span, charts as values, each figure traced to its page.
| Q3 | Nine months | |||
|---|---|---|---|---|
| € thousands | 2025 | 2024 | 2025 | 2024 |
| Revenue | ||||
| Industrial robots | 48,210 | 41,560 | 139,880 | 118,420 |
| Service and spare parts | 12,930 | 11,210 | 37,660 | 32,150 |
| Software subscriptions | 5,420 | 3,980 | 15,110 | 10,870 |
| Total revenue | 66,560 | 56,750 | 192,650 | 161,440 |
| Cost of sales | (38,140) | (33,590) | (111,230) | (96,020) |
Financial documents are built for print. Their numbers sit in spanning tables, in drawings and in footnotes, exactly where text extraction loses them.
Tables
Quarter and year-to-date columns share a header; flatten it and every value lands in the wrong column.
Charts
Segment splits and trends often appear only as bars and lines, with no printed value to copy.
Context
"In thousands", negatives in parentheses and footnote markers change what a figure means.
One engine reads the report, another fills your schema, and every value keeps the page and region it came from for audit.
01
Every page becomes typed elements: tables, charts, text, footnotes.
02
Tables keep their spans; charts come back as the table they plot.
03
Named figures fill your schema, each with a confidence.
04
Values load as JSON or CSV, with page and box for every number.
No number is printed on these bars. The parser calibrates the axis, measures each bar and returns the table behind the picture, legend and units included.
| Die temperature | Raw | Compensated |
|---|---|---|
| 0 °C | 2.1 | 0.3 |
| 20 °C | 0.4 | 0.1 |
| 40 °C | 2.6 | 0.3 |
| 60 °C | 4.9 | 0.5 |
Eight values, eight exact. Legend: Drift (mV).
The same parser runs inside .NET with LM-Kit.NET, or over REST, a command line and MCP with LM-Kit One.
using LMKit.Document.Parsing; using var parser = new DocumentParser(ParsingEffort.High); ParsedDocument filing = parser.Parse("annual-report.pdf"); foreach (ParsedPage page in filing.Pages) foreach (ChartContent chart in page.Elements.Select(e => e.Content).OfType<ChartContent>()) { Console.WriteLine($"Page {page.PageNumber}: {chart.Caption}"); Console.WriteLine(chart.Text); // the plotted values as a table }
# A folder of filings, parsed to lossless JSON: tables, charts, page and box per element
lmkit run document-parsing --in ./filings --out ./parsed --effort High --output-format Json
Drafts, board packs and pre-release results are the documents that can least go to a cloud parser. Here, no page leaves your network.
Confidential
Parsing runs on machines you administer, fully air-gapped if required. LM-Kit never receives the document.
Auditable
Each element keeps its page, box and confidence, so a reviewer jumps straight to the region behind a figure.
Predictable
Backfill ten years of filings on hardware you already run; reporting season is a scheduling question.
Yes. The parser returns every bar, line, pie and stacked chart as the data table it plots, with its legend and units. Values are measured from the drawing and checked against it, so a figure printed nowhere as text still becomes a number.
Yes. Row and column spans survive as HTML in the Markdown and JSON output, so a header that covers two periods stays above both columns, and negatives in parentheses and bold totals are kept.
Every element carries its page, bounding box, reading position and confidence. A reviewer or a downstream system can open the exact region a value came from.
No. The parser runs inside your .NET application with LM-Kit.NET, or on your servers with LM-Kit One, including fully air-gapped machines. LM-Kit never receives the documents.
Financial reports