Data panel
Block Schedule
Counts block references by name, or by name and layer, in the selection or the whole drawing, and places the schedule as a table or saves it to Excel.
On the ribbonButton, Data panel
NeedsAn open drawing; optionally a selection
Command
PYBLOCKSCHEDULEAlias
BSCShortcutNone set (bind one in Shortcuts)
What it does#
Counts block references and writes the result as a schedule: one row per block name (or
per block name and layer), its count, and a Total row at the bottom. The
schedule goes either into the drawing as an AutoCAD table or into an Excel workbook. The
command is PYBLOCKSCHEDULE.
How to use it#
- Select the block references to count, or clear the selection to count every one in model space and on every layout.
- Click Block Schedule (or type
PYBLOCKSCHEDULE). - Choose how to count: Block name, or Block name and layer. The question says how many references it found.
- Choose where the schedule goes: Table in the drawing or Excel workbook.
- For a table, pick its top left corner. It goes into the current space (model space, or the layout you are on) in the drawing's current table style, with a title row, a header row and columns sized to their text.
- For a workbook, pick where to save. The suggested name is
drawing - Block Schedule.xlsx, and the sheet is called Schedule.
Good to know / limits#
- The table is a snapshot. It does not update when blocks are added or erased: run the tool again and delete the old table.
- Rows are sorted by block name, then layer, ignoring case. Dynamic blocks count under their real name, so every variation of one dynamic block is one row.
- Only references placed directly in model space or on a layout count. Blocks nested inside other blocks do not, and xrefs are never counted.
- The table's look (fonts, text height, borders) comes from the current table style. Make the style you want current first.
- If the workbook is open in Excel it cannot be replaced; close it and run again.
Other uses#
- A fixture, equipment or furniture count for one floor: select that floor's area and count just the selection.
- Count by name and layer to find blocks on the wrong layer: a name that appears on two layers stands out.
- Check a drawing before issue: the schedule shows stray blocks you did not expect.
Source#
The tool's own files, word for word as shipped in Data.panel/Block_Schedule.pushbutton. Every pyACAD tool is an ordinary bundle: copy these into your own extension and change what you like.
script.py Runs on a click. View on GitHub# -*- coding: utf-8 -*-
"""Counts block references by name, or by name and layer, and places the result.
Counts the selected block references when there are any, else every one in model
space and the layouts (xrefs are not blocks here). The schedule goes into the
drawing as an AutoCAD table at a picked point, in the current table style, or
into an Excel workbook. Both end with a Total row.
"""
import os
from pyacad import blocks, forms, script, sel, toast, xl
__title__ = 'Block Schedule'
TITLE = 'Block Schedule'
XLSX = 'Excel workbook (*.xlsx)|*.xlsx'
BY_NAME = 'Block name'
BY_LAYER = 'Block name and layer'
TO_TABLE = 'Table in the drawing'
TO_EXCEL = 'Excel workbook'
def plural(count, word):
return '%d %s%s' % (count, word, '' if count == 1 else 's')
def default_path(drawing, what):
"""'<drawing> - <what>.xlsx' beside the drawing; just the name when unsaved."""
if not drawing or drawing == 'untitled':
return 'Drawing - %s.xlsx' % what
folder, name = os.path.split(drawing)
return os.path.join(folder, '%s - %s.xlsx' % (os.path.splitext(name)[0], what))
def write_workbook(path, headers, rows, sheet):
"""Writes a fresh workbook; True when it worked. The Save dialog already
asked before replacing a file, so an old one is removed rather than merged."""
try:
if os.path.exists(path):
os.remove(path)
xl.write(path, rows, headers=headers, sheet=sheet)
except (IOError, OSError) as error:
toast.error('Could not write the workbook', 'Is it open in Excel? %s' % error)
return False
return True
def run():
drawing = script.get_document_path()
if drawing is None:
toast.warning('No drawing is open', 'Open a drawing, then run %s' % TITLE)
return
picked = sel.current()
refs = blocks.snapshots(picked if picked else None)
if not refs:
if picked:
toast.info('No block references in the selection',
'Clear the selection to count the whole drawing')
else:
toast.info('No block references in this drawing')
return
scope = 'the %s selected' % plural(len(refs), 'block reference') if picked \
else 'all %s in the drawing' % plural(len(refs), 'block reference')
grouping = forms.ask_options('Count %s by' % scope, [BY_NAME, BY_LAYER], TITLE)
if grouping is None:
return
headers, rows = blocks.schedule_rows(refs, by_layer=(grouping == BY_LAYER))
kinds = len(set(row[0] for row in rows))
rows.append(['Total'] + [''] * (len(headers) - 2) + [len(refs)])
target = forms.ask_options('Put the schedule in', [TO_TABLE, TO_EXCEL], TITLE)
if target is None:
return
summary = '%s, %s' % (plural(kinds, 'block'), plural(len(refs), 'reference'))
if target == TO_TABLE:
point = sel.pick_point('Pick the top left corner of the schedule: ')
if point is None:
return
blocks.insert_table(point, headers, rows, title=TITLE)
toast.success('Block schedule placed', summary)
return
path = forms.save_file(XLSX, default_path(drawing, TITLE), 'Export block schedule')
if path and write_workbook(path, headers, rows, 'Schedule'):
toast.success('Block schedule exported: ' + summary, path)
if '__commandpath__' in globals():
run()bundle.yaml The bundle contract: the keys pyACAD reads for this tool. View on GitHubtitle: Block Schedule
tooltip: Counts block references by name, or by name and layer, in the selection or the whole drawing. Places the schedule as a table in the drawing or saves it to Excel.
context: doc
keytip: DS
alias: BSC