Jeremy Tammik blogging on the Revit API

March 11, 2013

Export Wall Parts Individually to DXF

I am back from my vacation.
It was a wonderful break, and I feel ready and happy to get back to grips with everyday life and work again.

A query from a colleague caught up with me already on the way back, on exporting a whole bunch of selected wall panel parts to individual DXF files.
That gave me something nice and interesting to fiddle with during the nightly train ride up from Napoli to Milano and led to the following issues:

Before getting to that, though, here are a few final notes on my last vacation day in Napoli.

Last Day in Napoli

I had some wonderful pastry in the
Gran Bar Riviera pasticceria
on the Riviera di Chiaia.
Incidentally, an old palazzo partially collapsed there last week, just a few hundred meters away from where I was staying.

Further, I took a pair of old shoes to Gabriele, an extremely sweet and happy 86 years old shoemaker in the Spanish quarter.
He repaired them and they look better than new now.
He also invited us to coffee and told me his life story.
If you ever need a pair of shoes fixed, be sure to look him up in Vico Lungo del Gelso, 108, I-80134 Napoli :-)

Two final parting pictures capturing some of the decrepit charm of Naples...

Anyway, now I am back at work now again, and we return to the Revit API and my nocturnal dabbling on the train.

Exporting Individual Compound Wall Gyp Wallboard Parts

This query came in from my colleague William Spier, MEP & Design to Fabrication SME at Autodesk
(YouTube,
Revit Family Jewels).
He says:

Question: I would like to customise two pretty easy things.

The scenario is a compound wall on which I divide the gyp wallboard into standard (4’x8’) sheet size parts.
I need to export each of those sheets/parts to DXF format, but even though I have divided them into parts, Revit still groups them and exports them as one single DXF file – not as separate ones, like I need.
The only way around this is to isolate each part one at a time and export each one individually, which is WAY too laborious.

So I need to customize the export process so that:

Each part exports as a separate part, even though I globally selected them.

Each part exports named by its own unique code/identifier – whatever coding keeps each one distinct in the parts schedule.

Here is a snapshot from a simple sample project:

Answer: A first search for related API methods turn up the following potentially useful items:

The IsolateElementTemporary method requires a transaction, so even though the whole operation is theoretically read-only, we still need to specify manual transaction mode for this command.
We encapsulate the isolate and export method in a transaction that is later rolled back, so the model ends up unchanged after all.

Handling and Dismissing a Warning Message

However, a complication arises:

Calling the Export method with an isolated element in the current view displays a task dialogue warning message:

I repeatedly discussed how to automatically handle messages like this in the past, e.g. to
detach a workset.

To be notified of this message, we subscribe to the DialogShowing event:

Initially, I did not yet know exactly which dialogue id to use to identify this specific message.
I therefore first implemented a dummy DialogBoxShowing event handler, triggered the event, and determined the dialogue id to use by re-running the command and looking at the event handler argument in the debugger.

As it turns out, the required dialogue id in our case is "TaskDialog_Really_Print_Or_Export_Temp_View_Modes".
We wish to retain the temporary isolate mode and export, i.e. select the second command link option.
Therefore, the final dialogue box showing event handler implementation becomes:

Adding Support for both Pre- and Post- Part Selection

In the initial implementation, I just went ahead and used the pre-selected set of parts defined by the user before launching the external command, accessible via the uidoc.Selection.Elements collection.

However, it is much more user friendly to also support post-selection.
For that case, it is also useful to implement a selection filter to simplify easy mass selection of the parts.

In order to handle the elements identically regardless of whether they were pre- or post-selected, I convert the selection set to a list of element ids in both cases.

For the pre-selection, I iterate over the pre-selected elements and test each one as follows:

Here is
ExportWallboard03.zip including
the complete source code, Visual Studio solution and add-in manifest of the current state of this external command.

There are obviously still some implementation details to iron out.

Handling Temporary Transactions and Regeneration

Luckily, I took a closer look at the generated DXF output files before letting this command loose on humanity.

To my horror, I discovered that all files generated except the first one contain no geometry.

As it turns out, there is an issue with the regeneration and view settings in my original implementation.

After quite a bit of experimentation, I found out that I can successfully generate the individual files if I add the following steps:

Add code to switch off the first temporary isolation before applying the next one.

Commit the transaction to temporaily isolate each part before calling Export.

This requires encapsulating all the temporary transactions in a group and rolling back the entire group instead of the individual transactions, as described for the
temporary transaction trick touchup.

Separate the code to switch off the last temporary isolation and applying the new one into separate transactions.

Here is
ExportWallboard04.zip including
the source code, Visual Studio solution and add-in manifest of the updated version.

I certainly expect more implementation details to crop up that need ironing out.

For instance, I could imagine adding some code to delete the PCP files that are generated together with the DXF output.
Or is there any reason to keep them?

I can also imagine that the part identification needs improving.
Currently, the command simply uses the part and its source element ids.
Maybe the part unique id would be better, or the parent element id needs checking, or is unnecessary snd can be completely removed.

Anyway, for a first stab, this implementation now looks pretty good to me.