JT Read From Excel
Pull one cell out of a spreadsheet and turn it into a prompt
- cell_text
- row_number
- column_number
JT Read From Excel does one thing with zero ambiguity: you give it a row and column, it reads that cell and returns the text. That's it. No search, no lookup, no parsing - a direct read of a spreadsheet position, handed back as a STRING that any text input in your workflow will accept.
Why you'd reach for it
This node is the "data-in" half of turning ComfyUI into a batch generator driven by a spreadsheet. The pattern: column A holds a list of subjects, and you want to generate one image per row. Hook JT Serial Counter up to a row index, feed it here, and the cell text flows straight into a prompt - your data lives in Excel where anyone can edit it, not buried in a workflow JSON. Pair it with JT Save Text to Excel for a read-modify-write loop, or with JT Find Text From Excel when you need to locate a row before reading it.
The inputs
- Excel_Filepath (STRING) - the folder containing the file. Default
/path; always change it. - Excel_Filename (STRING) - file name;
.xlsxis appended if you omit the extension. - Row_Number (INT) - 1-based row, up to 1,048,576.
- Column_Number (INT) - 1-based column, up to 16,384.
Outputs: cell_text (STRING - the value, or empty string if the cell is blank), plus row_number and column_number echoed back so you can confirm where you actually read.
How it works, and where it's opinionated
It loads the workbook with data_only=True (formula cells return their cached values), reads the active sheet, and returns the cell as a string. Empty cells come back as "", not an error, which is the behavior you want when scripting.
But there's a quirk in the source worth knowing before it bites you: the node validates your row/column against the sheet's used range, not Excel's theoretical limits. Ask for row 50 in a sheet that only has 20 rows of data and it raises an error - it won't politely return an empty cell. So you can't use this node to probe beyond the last row of actual data; you have to know roughly where the content lives. Within the used range, blanks are fine; outside it, you get an error box instead of an empty string.
Another small oddity: the reader creates the folder if the directory doesn't exist. Harmless, but weird for a read node, and if you point it at a folder you can't write to, the whole thing can fail before it ever tries to read.
Gotchas
- The
/pathdefault again: set a real folder or the node goes wandering in your filesystem root. - It reads the first sheet only. Data on tab two is invisible to it.
- Missing file → wrapped
RuntimeError, loud and clear. Missing row within the file → also an error, which is the real gotcha to remember.
Installing it
Part of Comfyui_JTnodes - one clone gets all eight nodes:
cd ComfyUI/custom_nodes
git clone https://github.com/Jint8888/Comfyui_JTnodes
pip install "openai>=1.0.0" "openpyxl>=3.0.0"
or "Comfyui_JTnodes" in ComfyUI Manager. openpyxl is what powers every Excel node here, and since the repo has no requirements.txt, Manager won't install it for you - run that pip line yourself or the whole pack fails to import (it also loads openai at startup). Restart ComfyUI; the node lives under JT > JT/text.
Keep the README caveat in mind: it's written in Chinese. For an English speaker, the source code is honestly the better documentation - and it's small enough to skim. For a direct spreadsheet read feeding a prompt pipeline, this node is simple, predictable, and does the job.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| Excel_Filepath | STRING | /path | — |
| Excel_Filename | STRING | table | — |
| Row_Number | INT | 11–1048576 | — |
| Column_Number | INT | 11–16384 | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| cell_text | STRING | — |
| row_number | INT | — |
| column_number | INT | — |