Revit Macro to display warnings when Opening Project

Welcome back! I am feeling very grateful today, got a lot of pending tasks done and a few projects coming! Also, I have plenty of stuff to share during this year. So, I will start showing this useful Revit macro to populate the Start page, the page showed when opening the Revit project, with the number of warnings in the project.

Key takes

For those too busy to read everything, create an Application macro, copy and paste the code at the end of this post, build the macro, add a Project Parameter called Number of Warnings to the sheet you use as start page, and you are ready to go.

Now, for those that have some time to spare and want to follow me, you may learn something new, let’s get our hands dirty.

Setting up a parameter to store the number of warnings for the macro

The most efficient and organized way to retrieve the number of warnings in the model and display it for the user to view is to store it in a parameter. My preferred approach to set up a Start page is to use a sheet and a title clock especially created for the occasion. So, how do we move the information, number of warnings, contained in the project to a label contained in a sheet? With a shared parameter.

Inside the title block, the one to display as Start Page, create a Shared Parameter named Number of Warnings. Go to Manage > Shared Parameters and add it. Set the Type of Parameter as Integer, although you can use Text and cast it inside the macro. I will stick to Integer as it makes sense.

Create a label inside the title block and add the recently created Shared Parameter.

I made this one as an example, the number is the label described in the previous paragraph.

So, now we need to add the same Shared Parameter to the project (better to do this once in the template and not have to do it over and over). Go over the Manage tab and click on Project Parameters:

Create the Shared Parameter as follows:

Now the parameter is ready to transfer information from the project to the title block and vice-versa. Let’s go for the macro.

Creating an application macro

A brief introduction was released some time ago, like this one https://www.bimicon.com/create-revit-macro-in-c-1 and this one https://www.bimicon.com/number-doors-after-rooms-in-revit-using-a-macro. In our current post, I will expand on the topics introduced previously.

I have chosen an Application macro to develop this little program for a couple of reasons:

  • It is for internal use, only the firm where this is implemented should know that a background program has checked elements when the model was opened
  • No macro should be sent out, because no stakeholder should trust a program that comes from an external file, especially one that has the potential to wreck havoc in the organization’s network of computers.

To create an Application macro, go to the Manage tab, and click on the Macro Manager in the section Macros.

In the Macro Manager window, create a new Module under the Application tab.

After clicking OK, SharpDevelop will open:

Generally, all users code go after the line Revit Macros generated code, except Event listeners that have to be initialized when Revit opens. So, for the macro to detect when a document is opened, we need to start an event listener when the application starts. By the way, an Event listener is like Alexa or Siri, it is just stalking in the background waiting to hear the right word or command to start executing functions.

For the event listener, we need to add these two lines inside Module_Startup and Module_Shutdown. Line 24 adds an event listener that spies when a document is opened and executes a function called ThisApplication_DocumentOpened, which will be defined later. Line 29 removes the event listener if the application is closed.

Here is a list of the different event listeners:

https://www.revitapidocs.com/2015/54d437bf-87bb-1ba5-9357-8989c3da5ca7.htm

Afterwards, copy all the code that is the event handler:

A few comments, as usual, the GUID in line 74 is the GUID found inside the Share Parameters file, the txt where all shared parameter definitions are located.

Something to be careful when preparing a macro that is automatically launched when a document is opened is when an error happens, the macro suits silently. And as you have guessed, it is hard to debug. I have programmed things like this one as external commands, so I can track bugs, so would recommend it if you try to keep developing portable and scalable plugins.

Final look

Here you can check all the code from the macro:

using System;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Events;
using Autodesk.Revit.UI.Selection;
using System.Collections.Generic;
using System.Linq;

namespace BIMiconDocumentOpen
{
    [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
    [Autodesk.Revit.DB.Macros.AddInId("B9459AC0-EE99-40C3-877B-704063523CA9")]
	public partial class ThisApplication
	{
		private void Module_Startup(object sender, EventArgs e)
		{
			this.Application.DocumentOpened += new EventHandler<DocumentOpenedEventArgs>(ThisApplication_DocumentOpened);
		}

		private void Module_Shutdown(object sender, EventArgs e)
		{
			this.Application.DocumentOpened -= new EventHandler<DocumentOpenedEventArgs>(ThisApplication_DocumentOpened);
		}

		#region Revit Macros generated code
		private void InternalStartup()
		{
			this.Startup += new System.EventHandler(Module_Startup);
			this.Shutdown += new System.EventHandler(Module_Shutdown);
		}
		#endregion
		
		/// <summary>
        /// DocumentOpened event handler
        /// </summary>
        /// <param name="sender">sender</param>
        /// <param name="args">DocumentOpenedEventArgs</param>
        void ThisApplication_DocumentOpened(object sender, DocumentOpenedEventArgs args)
        {
        	// Retrieve active document
		    Document doc = this.ActiveUIDocument.Document;
		    
		    // Check if document is a project
		    bool isFamily = doc.IsFamilyDocument;
		    
		    if (isFamily != true)
		    {
		    	// Retrieve number of warnings in the project
				IList<FailureMessage> failureMessages = doc.GetWarnings();
				int numbWarnings = failureMessages.Count();
				
				// Retrieve the start page sheet
				FilteredElementCollector collectorSheets = new FilteredElementCollector(doc).OfClass(typeof(ViewSheet));
				ViewSheet sheet = null;
				foreach (var v in collectorSheets) 
				{
					ViewSheet vSheet = v as ViewSheet;
					
					if ( vSheet.SheetNumber == "000")
					{
						sheet = vSheet;
						break;
					}
				}
			    
				// Create a GUID with the guid of the shared parameter and retrieve parameter
				Guid sharedPramGUID = new Guid("943db437-7e9d-4efd-a1d8-4d332f07eb31");
				Parameter param = sheet.get_Parameter(sharedPramGUID);
				
				// Create transaction to assign the number of warnings to parameter
			    Transaction t = new Transaction(doc, "Set number of warnings on sheet");
			    t.Start();
				param.Set(numbWarnings);
			    t.Commit();
		    }
        }
	}
}

Leave a Reply

Your email address will not be published. Required fields are marked *