Skip to content

Markdown

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_size int, default 1000
    Records to request per call to Quickbase.
  • max_total int | 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 through qb.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

  • limit int, default 100
    The most records to return.
  • skip int, default 0
    How many records to pass over first. Use the previous page's next_skip.

Returns Page

A Page, whose total counts every record in the report.

Raises

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_size int, default 1000
    Rows to request per call to Quickbase.
  • max_total int | 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, which run() 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

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

  • edit bool, default False
    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