Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Loop through sheets - generating graphics

13 REPLIES 13
SOLVED
Reply
Message 1 of 14
ATassera
1893 Views, 13 Replies

Loop through sheets - generating graphics

Hey folks!

 

My program loops through all the sheets in a document (open in the background - no UI) to get some info such as name, number, "approved by" etc.

 

Why does Revit, during the looping, say "Generating graphics for Sheet: -nameofsheet-" with a loading bar, at the very bottom-left corner of the Revit window? (image below) What is it doing?

image.png

 

It seems to me like it's more time consuming than simply accessing the sheets in the document (as it does for, for example, model elements, etc.)

 

Is it possible to avoid this and just get the info I need without "generating graphics"?

 

Thanks!

 

Andrea

13 REPLIES 13
Message 2 of 14
jeremytammik
in reply to: ATassera

Can you share the code that is looping through the sheets? 

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 3 of 14
ATassera
in reply to: jeremytammik

Sure! Sorry I didn't put it here straight away!

 

 

// Sheets
foreach (Element sheetElement in CollectSheetElements(currentDoc))
{
    ViewSheet sheet = sheetElement as ViewSheet;

    // Get titleblock
    FilteredElementCollector titleblock =
        new FilteredElementCollector(currentDoc, sheet.Id)
        .OfCategory(BuiltInCategory.OST_TitleBlocks);

    Element titleblockElement = titleblock.First();

    // Get id of titlebloc type
    int? titleblockDbId = GetTypeIdDb(currentDoc, titleblockElement, types);

    RevitSheet revitSheet = new RevitSheet(
        file.FileId,
        sheet.ViewName,
        sheet.SheetNumber,
        GetParameterValueByName(sheetElement, "Approved By"),
        GetParameterValueByName(sheetElement, "Designed By"),
        GetParameterValueByName(sheetElement, "Checked By"),
        GetParameterValueByName(sheetElement, "Drawn By"),
        GetParameterValueByName(sheetElement, "Sheet Issue Date"),
        titleblockDbId);

    // Write sheets
    connection.Execute(DbSqlCommands.sheetsSql, revitSheet, transaction: transaction);
}

where RevitSheet is a custom class that I created to write into a db. And there a few other custom method but I don't think they would matter here (but happy to copy them too if they do)

 

And this is how I collect the sheets:

        internal static List<Element> CollectSheetElements(Document doc)
        {
            FilteredElementCollector views
                = new FilteredElementCollector(doc)
                .OfCategory(BuiltInCategory.OST_Sheets);

            return views.ToElements().ToList();
        }

 

Thanks,

 

Andrea

 

Message 4 of 14
jeremytammik
in reply to: ATassera

First of all, a small comment on enhancing performance:

 

You can completely eliminate two expensive method calls from CollectSheetElements; both ToElements and ToList serve no purpose whatsoever. Change the return type from List<Element> to IEnumerable<Element> and eliminate those two calls. That will save you time and space, twice over.

 

Unfortunately, I have no idea what could be causing the graphics regeneration.

 

I'll ask the development team about that for you.

 

Cheers,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 5 of 14
ATassera
in reply to: jeremytammik

Thank you so much for your advice @jeremytammik ! That's really appreciated!

In regards to the regeneration: Could it be due to the bit of code where I'm taking the titleblock assigned to the sheet?

new FilteredElementCollector(currentDoc, sheet.Id).OfCategory(BuiltInCategory.OST_TitleBlocks);

 Where I do this? (it still wouldn't explain the regeneration of the graphics to me...) 

 

Thank you for passing my question on to the dev team.

 

Please let me know if they can figure out why.

 

Andrea

Message 6 of 14
jeremytammik
in reply to: ATassera

My initial reaction was 'no'...

 

However, maybe the sheet is indeed regenerated to determine which elements to return for that collector, since the view id is specified... ?

  

I asked the devteam and hope they will be able to reply fast.

  



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 7 of 14
ATassera
in reply to: jeremytammik

That was my same train of thought.

 

Yeah hopefully they will reply soon! That would help a lot as I'm really curious to understand what's going on there now!

 

Please let me know.

 

Thanks,

 

Andrea

Message 8 of 14
jeremytammik
in reply to: ATassera

They have replied and share a really good idea for an alternative approach which will hopefully solve the problem. The reason is exactly what we thought it was: This is not regeneration, it is generating the view. In order to iterate elements in the view, it needs to be generated (even if non-visible). So the FilteredElementCollector(doc, viewId) is causing that. Trying to think of another option: perhaps you could visit all Titleblock instances in the document, and ask it for its view id, rather than visiting elements in the view? Cheers, Jeremy


Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 9 of 14
ATassera
in reply to: jeremytammik

Thank you Jeremy for following up!!

 

Now that's a great solution and it works great!

If I get all the titleblocks from the document and then take the one with the same OwnerViewId property as the Id of the sheet it doesn't generate the sheet!

snippet here:

FilteredElementCollector allTitleBlocks = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_TitleBlocks);

foreach (Element sheetElement in CollectSheetElements(currentDoc))
{
    // Get sheet's titleblock
    Element titleblock = allTitleblocks.Where(t => t.OwnerViewId == sheet.Id).First();
}

Unfortunately that doesn't speed up the process as much as I thought, weirdly enough. The script was taking 6.77 minutes with the old method and takes now 6.32 minutes now.

Although, it needs to be considered that the program doesn't only taking into account the sheets.

 

Thanks again,

 

Andrea

Message 10 of 14
jeremytammik
in reply to: ATassera

... and you suppress the annoying regeneration message  🙂

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 11 of 14
jeremytammik
in reply to: ATassera

You could improve this by implementing a dictionary inverting the relationship:

 

  FilteredElementCollector allTitleBlocks 
    = new FilteredElementCollector(doc)
      .OfCategory(BuiltInCategory.OST_TitleBlocks);

  // Map sheet to title block:

  Dictionary<ElementId, ElementId> map_sheet_to_title_block ...

  for each title block t in allTitleBlocks:
    map_sheet_to_title_block.Add( t.OwnerId, t.Id )

 

After that, use map_sheet_to_title_block(sheet.Id, t.Id) to get the title block.

 

No more need for a call to Where in each loop iteration.

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 12 of 14
ATassera
in reply to: jeremytammik

Yeah that's actually a great idea!

 

Thanks for all the advice @jeremytammik !!

 

I'll use this same strategy for when I extract the parameters too! Should make it better too!

Message 13 of 14
jeremytammik
in reply to: ATassera

My pleasure entirely.

 

Yes.

 

Seven minutes is a long time.

 

You should definitely benchmark your entire add-in to discover what is taking so much time.

 

It could be built-in Revit operations. However, with obvious optimisation possibilities like that, you may be able to speed it up a lot.

 

Good luck!

 

Cheers,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 14 of 14
ATassera
in reply to: jeremytammik

Yes, I actually benchmarked the process and the thing that takes 80% of the processing time (5 min of the total 6 and a bit) is extracting all the instance parameters of the model elements...I guess it makes sense, a few thousands elements with 20/30 parameters each makes it a lot of parameters 😄

 

I'll probably write another question here on the forum at some point to see if anyone sees a faster way to do that.

 

Thanks again!

 

Andrea

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Rail Community