How to get the total width, height size of a schedule placed on sheet with python?

how to get the total width, height size of a schedule placed on sheet with python?

schedulesheetinstance element

I tried the package geniusloci and springs to get bounding box but the sizes do not match with the size on the schedule, for example cuboid witdh is 106.2333 in Dynamo but in sheet is 102mm, and cuboid length in dynamo is 19.76687 and in sheet is 17.65mm


measuring the schedule on sheet

I tried this python script but same result than using the package nodes, wrong:

# Import the required Revit API classes
import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import FilteredElementCollector, BuiltInCategory, UnitUtils, ScheduleSheetInstance, DisplayUnitType

# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

# Unwrap the Revit elements
doc = DocumentManager.Instance.CurrentDBDocument

# Function to convert length value to millimeters
def convert_to_mm(length):
    return UnitUtils.ConvertFromInternalUnits(length, DisplayUnitType.DUT_MILLIMETERS)

# Function to get the size of the schedule
def get_schedule_size(schedule_instance):
    # Get the sheet containing the schedule
    sheet_id = schedule_instance.OwnerViewId
    sheet = doc.GetElement(sheet_id)

    # Get the bounding box of the schedule on the sheet
    bounding_box = schedule_instance.get_BoundingBox(sheet)

    # Check if the bounding box is available (schedule is visible on the sheet)
    if bounding_box:
        schedule_width = convert_to_mm(bounding_box.Max.X - bounding_box.Min.X)
        schedule_height = convert_to_mm(bounding_box.Max.Y - bounding_box.Min.Y)
        return schedule_width, schedule_height
    else:
        return None, None

# Main script
# Check if IN[0] is a list of elements
if isinstance(IN[0], list):
    schedule_elements = IN[0]
else:
    schedule_elements = [IN[0]]

# Process each element in the list and get the size
output_list = []
for element in schedule_elements:
    schedule_instance = UnwrapElement(element)
    if isinstance(schedule_instance, ScheduleSheetInstance):
        schedule_width, schedule_height = get_schedule_size(schedule_instance)
        if schedule_width and schedule_height:
            output_list.append("Schedule Width: {} mm, Schedule Height: {} mm".format(schedule_width, schedule_height))
        else:
            output_list.append("Schedule is not visible on the sheet.")
    else:
        output_list.append("Invalid element. Please select a ScheduleSheetInstance element.")

OUT = output_list


Bounding box of the instance?

Hi does it work if you select the viewport-schedule on sheet…

I tried the package geniusloci and springs to get bounding box but the sizes do not match with the size on the schedule, for example cuboid witdh is 106.2333 in Dynamo but in sheet is 102mm, and cuboid length in dynamo is 19.76687 and in sheet is 17.65mm


measuring the schedule on sheet

I recall that schedule views have a ‘buffer’, but it has been awhile since I have looked at this.

1 Like

I would like to know what is the current size of schedule placed on sheet, I do not know how…buffer is like an extra crop region size? I do not see any relationship of differences between the length and height of the schedule size on dynamo and measured

is dynamo measuring that hidden box that you see when placing the mouse on top of the schedule on sheet?

1 Like

Yes seems so… Jacob is right there are some scaled viewport…

1 Like

I tried this python script but same result than using the package nodes, wrong:

# Import the required Revit API classes
import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import FilteredElementCollector, BuiltInCategory, UnitUtils, ScheduleSheetInstance, DisplayUnitType

# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

# Unwrap the Revit elements
doc = DocumentManager.Instance.CurrentDBDocument

# Function to convert length value to millimeters
def convert_to_mm(length):
    return UnitUtils.ConvertFromInternalUnits(length, DisplayUnitType.DUT_MILLIMETERS)

# Function to get the size of the schedule
def get_schedule_size(schedule_instance):
    # Get the sheet containing the schedule
    sheet_id = schedule_instance.OwnerViewId
    sheet = doc.GetElement(sheet_id)

    # Get the bounding box of the schedule on the sheet
    bounding_box = schedule_instance.get_BoundingBox(sheet)

    # Check if the bounding box is available (schedule is visible on the sheet)
    if bounding_box:
        schedule_width = convert_to_mm(bounding_box.Max.X - bounding_box.Min.X)
        schedule_height = convert_to_mm(bounding_box.Max.Y - bounding_box.Min.Y)
        return schedule_width, schedule_height
    else:
        return None, None

# Main script
# Check if IN[0] is a list of elements
if isinstance(IN[0], list):
    schedule_elements = IN[0]
else:
    schedule_elements = [IN[0]]

# Process each element in the list and get the size
output_list = []
for element in schedule_elements:
    schedule_instance = UnwrapElement(element)
    if isinstance(schedule_instance, ScheduleSheetInstance):
        schedule_width, schedule_height = get_schedule_size(schedule_instance)
        if schedule_width and schedule_height:
            output_list.append("Schedule Width: {} mm, Schedule Height: {} mm".format(schedule_width, schedule_height))
        else:
            output_list.append("Schedule is not visible on the sheet.")
    else:
        output_list.append("Invalid element. Please select a ScheduleSheetInstance element.")

OUT = output_list


The ndoes are correct, but the schedule height from Python is the width of the bounding box, and the schedule width from Python is the length of the bounding box. My recollection is that these include the ‘buffer’ region when you select it. Try creating an annotation object on the sheet view to see if the drawn rectangle corresponds to the selected region.

I draw 2 lines in snapping points over the schedule vertexes on sheet and measured, I do not want to do that, I want dynamo to tell me:

not sure at all, but probably is possible get the rows width itself from the schedule, havent checked but archilab if i remember right have one there can set the width…

It seems to work pretty well if you use the ScheduleOnSheet.

If you are in metric, you might have to convert from decimal feet to mm to get the dimension you think it should be…

I don’t know why the ootb node doesn’t work for ScheduleSheetInstance but you can still get the bounding box via the API. From there it’s just unit conversion like Jacob said.

1 Like

Did you check my python script? I think i did it as mentioned but result still wrong, let me know if the schedule size on sheet that you can measure is the same than what you see in Dynamo

Was the same for me.

My Python code:

import clr

# Import ToDSType(bool) extension method
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)

# Import geometry conversion extension methods
clr.ImportExtensions(Revit.GeometryConversion)

# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *

# Imports Ilists module into python
clr.AddReference("System")
from System.Collections.Generic import List as cList

# Ilist Application
#New_List = cList[ElementId]("elements")

# Standard areas for Current Document, Active UI and application
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument

# Input and unwrapping 
sched = UnwrapElement(IN[0])
sheet = doc.GetElement(sched.OwnerViewId)
bb = sched.get_BoundingBox(sheet)
vect = bb.Max.Subtract(bb.Min)
half = vect.Divide(2)
cent = bb.Min.Add(half)
wInFeet = vect.X
hInFeet = vect.Y
wInMM = UnitUtils.ConvertFromInternalUnits(wInFeet, UnitTypeId.Millimeters)
hInMM = UnitUtils.ConvertFromInternalUnits(hInFeet, UnitTypeId.Millimeters)
# Start Transaction
TransactionManager.Instance.EnsureInTransaction(doc)

# End Transaction
TransactionManager.Instance.TransactionTaskDone()

OUT = cent.ToPoint(), wInMM, hInMM

Feeding that and a color into a code block containing this bit of design script:

crvs =
	Rectangle.ByWidthLength(
		Plane.ByOriginNormal(a[0],Vector.ZAxis()),
		a[1],
		a[2]
	).Explode();
detailLines =
	DetailCurve.ByCurve(
		Document.ActiveView(Document.Current),
		crvs
	);
overrides =
	Elements.Element.OverrideColorInView(
		detailLines,
		color
	);

I get a rectangle on the sheet where my schedule is. The top of that rectangle aligns to the top of my schedule’s header. The left, right, and bottom are slightly outside of the schedule. Looks like this:

And if you select the schedule, you see why, as it looks like this:

Not sure if the buffer around the schedule body can be modified, but this does confirm the math of the code in relation to the displayed graphics. It’s also likely that you don’t want anything inside that buffer as it’d make things quite tight on the page.

2 Likes

let say it is always the same, so if dynamo tells me DynamoLength=X, then RealLengthinSheet=X-Buffer*2, then if DynamoHeight=Y then RealHeightinSheet=Y-Buffer. So Buffer=2.1168749658811mm? :exploding_head:

please check this is constant in any sample, my sample is like this:
RealLengthinSheet=102mm
RealHeightinSheet=17.65mm
X=106.233333333mm
Y=19.76687mm

1 Like

Your math looks good, but I would be surprised if it were consistent, as it would depend on how your schedule is formatted. Best to not overthink it.

it is consistent in other tests, so whatever size indicates dynamo, reduce it by the buffer 2 times if the length and 1 time if the height of the schedule size. Buffer=2.1168749658811mm

3 Likes