Report¶
A Report runs a report that was built in the Quickbase interface. Get one from Table.report(), by name or ID. Getting one doesn't contact Quickbase, so a report that doesn't exist raises UnknownReportError on first use.
The examples below use tasks, made as shown here. Every new table has a report named List All. A live test runs every example with both clients and checks its output. The exception is summary_rows(), because a summary report can only be built in the interface. AsyncReport has the same methods, which you await, but run() is called without it.
from pyquickbase import Quickbase
with Quickbase(
realm="acme", token="your_user_token"
) as qb:
tasks = qb.app("bq1234567").table("Job Tasks")
from pyquickbase import AsyncQuickbase
async with AsyncQuickbase(
realm="acme", token="your_user_token"
) as qb:
tasks = qb.app("bq1234567").table("Job Tasks")
Run a report¶
For the full picture, see Reading records.
Run a report¶
Iterate over the report's records, fetching further pages as needed.
Records hold only the report's columns, so record.id raises KeyError if Record ID# isn't one of them. Each run adds to the report's usage count in Quickbase.
Parameters
page_sizeint, default1000
Records to request per call to Quickbase.max_totalint | None, optional
Stop after this many records in all, across pages.
Returns RecordIterator
An iterator of Record, which only contacts Quickbase once you start iterating.
Raises
UnknownReportError: The table has no such report, or several share the name.UnsupportedReportError: It isn't a complete table report, such as a summary, chart, or ask-the-user report. Their raw results are available throughqb.request().
run(
*, page_size: int = 1000, max_total: int | None = None
) -> RecordIterator
Example
report = tasks.report("List All")
titles = [record["Title"] for record in report.run()]
print(sorted(titles))
report = tasks.report("List All")
titles = [record["Title"] async for record in report.run()]
print(sorted(titles))
Output
['Frame walls', 'Hang drywall', 'Pour slab']
Fetch one page of a report¶
Fetch one page of the report's records, for controlling paging yourself.
Records hold only the report's columns, and each run adds to the report's usage count in Quickbase.
Parameters
limitint, default100
The most records to return.skipint, default0
How many records to pass over first. Use the previous page'snext_skip.
Returns Page
A Page, whose total counts every record in the report.
Raises
UnknownReportError: The table has no such report, or several share the name.UnsupportedReportError: It isn't a complete table report, such as a summary, chart, or ask-the-user report.
run_page(*, limit: int = 100, skip: int = 0) -> Page
Example
report = tasks.report("List All")
page = report.run_page(limit=2)
print(page.total, page.has_more, page.next_skip)
report = tasks.report("List All")
page = await report.run_page(limit=2)
print(page.total, page.has_more, page.next_skip)
Output
3 True 2
Get a summary report's rows¶
Get a summary or chart report's rows, as {column label: value}.
Quickbase does the calculating, using the report as it was built in the UI. Values are what Quickbase returns, so a chart's dates are text in the app's format, such as 01-01-2026. Each run adds to the report's usage count in Quickbase.
Parameters
page_sizeint, default1000
Rows to request per call to Quickbase.max_totalint | None, optional
Stop after this many rows in all, across pages.
Returns list[dict[str, Any]]
The rows. A summary report's total column is labeled like Hours (tot).
Raises
UnknownReportError: The table has no such report, or several share the name.UnsupportedReportError: It's a table report, whichrun()reads as records. Or Quickbase can't run it, such as a report that asks the user for a value, or two of its columns have the same label.InvalidResponseError: Quickbase stopped returning rows before the end.
summary_rows(
*, page_size: int = 1000, max_total: int | None = None
) -> list[dict[str, Any]]
Example
report = tasks.report("Hours by Status")
for row in report.summary_rows():
print(row["Status"], row["Hours (tot)"])
report = tasks.report("Hours by Status")
for row in await report.summary_rows():
print(row["Status"], row["Hours (tot)"])
Look up the report's details¶
For the full picture, see Reading records.
Get the report's details¶
Get the report's metadata, from the table's cached list of reports.
Returns ReportInfo
A ReportInfo.
Raises
UnknownReportError: The table has no such report, or several share the name. An ID takes priority over a name.
info() -> ReportInfo
Example
report = tasks.report("List All")
info = report.info()
print(info.name, info.type)
report = tasks.report("List All")
info = await report.info()
print(info.name, info.type)
Output
List All table
Link to the Quickbase interface¶
For the full picture, see Using pyquickbase from an AI agent.
Link to the report¶
Link to the report in Quickbase, for viewing it or changing how it's built.
It only contacts Quickbase to look up the report's and table's IDs, as info() does, and the client's cache usually has them.
Parameters
editbool, defaultFalse
Link to the page that changes the report's settings, rather than the report.
Returns str
The URL, on the client's realm.
Raises
UnknownReportError: The table has no such report, or several share the name, or the client's policy hides it.UnknownTableError: The app has no such table, or the client's policy hides it.
url(*, edit: bool = False) -> str
Example
report = tasks.report("List All")
print(report.url())
print(report.url(edit=True))
report = tasks.report("List All")
print(await report.url())
print(await report.url(edit=True))
Output
https://acme.quickbase.com/nav/app/bq1234567/table/bqtasks123/action/q?qid=1
https://acme.quickbase.com/nav/app/bq1234567/table/bqtasks123/action/viewBuild?qid=1