Copy Sheets: Adventures in drawing numbering

Hi all - I’m new to pyRevit, and am curious to know if anyone has experienced this issue:

  • Revit 2024.3
  • Workshared Model File, BIM 360
  • “Copy Sheets to Open Documents”
    I’ve set up a ‘general details’ catalog file with drafting views of common details arranged & numbered on sheet layouts. Our goal is to utilize the ‘copy sheets’ feature to create import these ‘sheeted & numbered’ details to multiple building model files that will reference these details, via callouts in sections, elevations, plans, etc.

The copy function has worked in other past projects, but with our current project, this function seems hellbent on renumbering most of the details on each sheet. The viewports arrive in placed correctly in our 12-square grid (more or less - sometimes they’ve shifted slightly) on their respective sheets, but somehow the drawing numbering has changed; 3, 10, 2, 4, 6…random, no discernable order or logic. No matter what we try (“publish”, close out, restart, etc.), the result is exactly the same. We’ve been manually re-numbering them.

It seems that pyRevit might be relying on some kind of cache here, and it’s overriding the most recent drawing updates. Any theories or proposed fixes would be greatly appreciated.

Travis

Hi @wtravisl,

I’m a bit of a noob so this might sound silly, but could you not renumber the details via the script you’re using to place them? As in, do everything you’re currently doing, then iterate through all your sheets and then renumber the details on them, based on whatever logic you want?

This is a little bit of extra work, and it assumes that you want to number the details based on their positions on the sheet or some other calculable property, but it’s certainly the way I would go about handling this problem.

Let me know if any of that is unclear.

Benjamin

Hi Benjamin,
Thank you for your response. I understand what you’re proposing, but it sounds like a marginal improvement at best. It still represents extra time & potential for human error. The pyRevit “Sheets/Copy Sheets to Open Documents” command should get the numbering correct automatically, by default, without any manual workarounds - it’s obvious that something about our setup is throwing it for a loop, and it is generating sheet numbers from a bad info source. I need to keep poking around until I figure out what it is. It’s happening again, right now, with a completely different project to the one that generated my initial comment.

1 Like

Here’s the code for that function:
GItGub pyRevit,

I’m not seeing any reference io the code for sheet numbering - either applying or setting numbers. It doesn’t look like this function intends to deal with numbering.

Are you just copying views? Not the triblock? If so your position issue is probably an issue of the titleblocks in each view differing in placement. Users have a tendency to bump these or move them by accident when they move some other sheet element. Always reference the XYZ(0,0, 0) to the lower left corner for best practice. Sometimes people even change the lower left sheet corner in the wrong spot in the titleblock family. Very poor practice when editing titleblocks.

As for the numbering… Are there any error in the logger?

Are you using the same version of Revit as with past successful projects? More information would be needed to assist.

Just a thought… unverified…

Perhaps the viewports are getting renumbered in order of their ElementId (e.g. the order in which they were dragged onto the sheet)? Since you said it worked on previous projects, I’m inclined to think that the detail numbering in your catalog file has been manually changed since its creation, or the ElementIds of the original viewports may have been changed automatically by Revit.

When you say random, do you mean that it’s different every time the script is run? Or is it consistently the same screwed-up order each time? Can you try placing viewports on a sheet in order, without renumbering them, and see if order is preserved after copying?

I think I have run into something similar before when programmatically duplicating sheets. My script would collect all viewports on a sheet, then duplicate the views and position them on a new sheet at the same location. If I had renumbered the viewports at all, this change in numbering would not carry over to the new sheet. Instead, the duplicated viewports appeared to be numbered in the order they were created.

I suspect that this is because, when you collect elements from the DB, they tend to be returned in order of their ElementId, so when you iterate over a FilteredElementCollector, they are likely to be in the order of their creation, since ElementIds are assigned sequentially. (I am not sure if this is always necessarily the case, though, since ElementIds can sometimes change.)

Or, if the ordering is not based on viewport creation order, then it is probably due to iterating over an unordered collection. (I think either of these two options is more likely than an outdated cache of some kind.)

Either way, the solution probably involves recording the original detail number, then assigning that to the corresponding viewport after duplication. That would be better than trying to number them by x/y coordinates. I agree that this change should be integrated into the pyRevit code so that we don’t have to run a separate script after.

After reading through the pyRevit code, I think this issue could be fixed like so:

def match_detail_number(original_vport, nvport):
	nvport.get_Parameter(DB.BuiltInParameter.VIEWPORT_DETAIL_NUMBER)\
		  .Set(original_vport.get_Parameter(DB.BuiltInParameter.VIEWPORT_DETAIL_NUMBER).AsString())

def copy_sheet_viewports(activedoc, source_sheet, dest_doc, dest_sheet):
    existing_views = [dest_doc.GetElement(x).ViewId
                      for x in dest_sheet.GetAllViewports()]

    for vport_id in source_sheet.GetAllViewports():
        vport = activedoc.GetElement(vport_id)
        vport_view = activedoc.GetElement(vport.ViewId)

        print('\t\tCopying/updating view: {}'
              .format(revit.query.get_name(vport_view)))
        new_view = copy_view(activedoc, vport_view, dest_doc)
		
        if new_view:
            ref_info = revit.query.get_view_sheetrefinfo(new_view)
            if ref_info and ref_info.sheet_num != dest_sheet.SheetNumber:
                logger.error('View is already placed on sheet \"%s - %s\"',
                             ref_info.sheet_num, ref_info.sheet_name)
                continue

            if new_view.Id not in existing_views:
                print('\t\t\tPlacing copied view on sheet.')
                with revit.Transaction('Place View on Sheet', doc=dest_doc):
                    nvport = DB.Viewport.Create(dest_doc,
                                                dest_sheet.Id,
                                                new_view.Id,
                                                vport.GetBoxCenter())
					
					# Add this call to match detail number
					match_detail_number(vport, nvport)
					
                if nvport:
                    apply_viewport_type(activedoc, vport_id,
                                        dest_doc, nvport.Id)
			
            else:
                print('\t\t\tView already exists on the sheet.')

I just added the match_detail_number function, then called it during the transaction after viewport creation.

(code is completely untested)

1 Like

@Jean-Marc , I will submit a pull request for the above issue. I tested the code and made it a bit more robust. (I’m new to pull requests, so hopefully I do it correctly.)

Edit: the PR is now submitted.