-
Notifications
You must be signed in to change notification settings - Fork 979
command query
Query document elements using CSS-like selectors.
officecli query <file> <selector> [--find <text>] [--json | --compact [--fields k,v,...]]
Searches the document for elements matching a CSS-like selector expression. Returns all matching elements with their paths and properties. Read-only.
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
file |
FileInfo | Yes | - | Office document path |
selector |
string | Yes | - | CSS-like selector expression |
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
--find |
string | No | - | Case-insensitive text/value substring filter — hard rename of the legacy --text flag. |
--json |
bool | No | false |
Output as structured JSON. Mutually exclusive with --compact. |
--compact |
bool | No | false |
(v1.0.134+, pptx/docx only) One line per element instead of the full JSON tree — see --compact output below. |
--fields |
string | No | - | Comma-separated Format keys appended as extra k=v columns in --compact output (e.g. --fields x,y,width). Only meaningful with --compact. |
| Operator | Meaning | Example |
|---|---|---|
= |
Exact match | [style=Heading1] |
!= |
Not equal | [font!=Arial] |
~= |
Contains text | [text~=quarterly] |
>= |
Greater or equal (numeric) | [size>=24pt] |
<= |
Less or equal (numeric) | [size<=12pt] |
Notes:
-
Filter diagnostics (v1.0.124+): when no matches are returned,
--jsonoutput includes a structuredfilterDiagnosticobject naming the unknown key (or the operator that didn't match) and adid-you-meanlist — matches on both the full key and the last segment of a dotted key. Emitted operator-independently, so[size>=99]on the wrong element type explains why instead of returning silent-empty. - Can combine:
shape[fill=FF0000][size>=24pt](implicit AND) -
Boolean
and/or:cell[value>5000 or value<100],cell[(type=Number or type=Date) and value>0]. Applies toquery,set, andremoveacross all three formats via the shared filter engine. -
not(...)negation (v1.0.134+):not(expr)negates the inner expression —cell[not(value=hi)]matches every cell whose value isn'thi.not(key)alone (no operator) is exists-negation —cell[not(bold)]matches cells whereboldis absent/falsy, the "column is empty" case that previously had no spelling. Word-bounded: a column literally namednotstill works as a predicate ([not=5]) and can be exists-checked with quotes (["not"]). -
Top-level comma union (v1.0.133+): a comma outside any
[...]/(...)/quotes splits the selector into independently-evaluated parts whose results are unioned (deduped by path) —row[Dept=Sales],row[Dept=Marketing]matches rows satisfying either predicate, acrossquery/set/removeon all three formats. A comma inside brackets is not a union split:row[Dept=A,B]stays one predicate string passed to the handler. Positional unions (shape[1],shape[3]) worked before this fix; predicate unions (row[Dept=Sales],row[Dept=Marketing]) previously collapsed to an impossible AND and silently matched nothing outside PowerPoint. -
Has-attribute exists:
[link]matches any element where the attribute is present and non-empty. -
Excel row-by-column-name:
Sheet1!row[Salary>5000]matches rows where the named column's value satisfies the predicate (also works on detected header-row tables). OR'd table-column predicates insiderow[…]fail loud, never silent. - Color-aware:
[fill=#FF0000]matches[fill=FF0000] - Dimension-aware: compares
2cmvs1incorrectly - Special keys
textandtypematch node content and type -
\!=accepted for zsh compatibility
parent[filter] > child[filter]
Unknown selectors match any XML element by local name (case-insensitive).
The query command returns a list of DocumentNodes matching the selector. The output varies depending on whether --json is used.
The text output starts with a match count, followed by each matching node listed with its path, text content, and formatting attributes.
Matches: {count}
/body/p[1]: Heading text
style: Heading1
alignment: center
/body/p[3]: Another paragraph
style: Normal
Example:
Matches: 3
/body/p[1]: Introduction
style: Heading1
alignment: center
font: Arial
/body/p[4]: Chapter One
style: Heading1
alignment: left
/body/p[9]: Chapter Two
style: Heading1
alignment: left
With --json, the output is an object containing the match count and an array of DocumentNode results.
{
"Matches": 3,
"Results": [
{
"Path": "/body/p[1]",
"Type": "Paragraph",
"Text": "Introduction",
"Preview": null,
"Style": "Heading1",
"ChildCount": 1,
"Format": {
"alignment": "center",
"font": "Arial"
},
"Children": []
},
{
"Path": "/body/p[4]",
"Type": "Paragraph",
"Text": "Chapter One",
"Preview": null,
"Style": "Heading1",
"ChildCount": 1,
"Format": {
"alignment": "left"
},
"Children": []
}
]
}Each element in the Results array is a DocumentNode with the same fields as described in get Output Format: Path, Type, Text, Preview, Style, ChildCount, Format, and Children.
For agent loops that only need path + text to locate an edit target, the full JSON tree is tens of fields of noise per node — on multi-page decks the output can run to tens of thousands of characters and get truncated by observation limits, silently hiding matches. --compact renders one TSV-ish line per element instead:
{path}<TAB>[{label}]<TAB>"{text, ≤60 chars, \t/\n/"/\\ escaped, … if truncated}"
{path}<TAB>[table {R}x{C}] (tables fold to one line, no cell descent)
{path}<TAB>[{label}]<TAB>(empty) (no text)
total: N of M elements[ / K slides] (always the final line, even on 0 matches)
-
pptx labels carry the semantic type (
title/placeholder/textbox/shape); docx paragraphs label by style name. -
Nequals the element lines above (a folded table counts as 1) —lineCount-1 == Nmechanically proves the reader saw every match. -
Mcounts all top-level frames regardless of selector (docx excludessectPr— layout metadata isn't addressable). -
--fields x,y,widthappends opt-ink=vcolumns after the text column (a missing key emitsk=). -
This is a stability contract — column order, the TAB separator,
…truncation,(empty),[label]brackets, and the total-line shape may only gain new trailing columns, never change or reorder existing ones. -
xlsx rejects
--compact—view textis already the per-row compact form; the error points atview text --rangeinstead. -
--jsonand--compactare mutually exclusive.
officecli query deck.pptx shape --compact
officecli query deck.pptx shape --compact --fields x,y,width- Word query - Word selectors and attributes
- Excel query - Excel selectors and attributes
- PowerPoint query - PowerPoint selectors and attributes
- Command Reference
- get - Get specific elements by path
- view - View document content
Based on OfficeCLI v1.0.134