Friday, July 19, 2013

Simple Civil 3D Report Customization

Everyone probably knows that Civil 3D comes with a host of built in reports which are available under Toolspace / Toolbox.  Some of these were developed in dotnet and others are simple XSL stylesheets.  Unfortunately, neither report type lends itself to customization by average end users.  The Edit Report Settings feature allows for some very minor customizations, but it is extremely limited.  For example, when using Imperial Units, the Parcel Inverse Report will report areas in Square Feet only.



This post will detail how to add Acres or a combination of Square Feet and Acres to the inverse report by adding a few lines of code.

The source files for all of the XSL reports can be found here:  C:\ProgramData\Autodesk\C3D 20xx\yourlanguage\Data\Reports\xsl   The filenames themselves are easy enough to decipher.  Before editing our file, Parcel_Inverse.xsl, I strongly suggest that you make a backup copy of the original Autodesk supplied file.  In practice, I would make a backup and name it Parcel_Inverse.xsl.ootb (ootb is an extension that I use to communicate to myself that this is an unaltered "out of the box" file).

[In a future post, I'll discuss a method for organizing custom reports without having to continually modify files on one or more C drives.  By using a little organization, we can make customization much more workgroup friendly and upgrade friendly.]

Once you've made a backup copy, let's open Parcel_Inverse.xsl.  This is a simple text file which can be edited with any text editor.  I prefer to use Notepad++ because it highlights code in virtually every language that I use.  If you don't want to install another text editor, Notepad will do just fine, albeit in all-black text.

Locate this line in two places: 

<td><xsl:value-of select="landUtils:FormatNumber(string($ParcelArea), string($SourceAreaUnit), 'squareFoot', string($Parcel.2D_Area.precision), string($Parcel.2D_Area.rounding))"/></td>


Immediately after each instance of the line above, paste the following:
<!--Custom Code 2013-07-18 (rs) START -->
<tr>
<td width="33%">&#160;</td>
<td>Acres</td>
<td> <xsl:value-of select="landUtils:FormatNumber(string($ParcelArea), string($SourceAreaUnit), 'acre', string($Parcel.2D_Area.precision), string($Parcel.2D_Area.rounding))"/></td>
</tr>
<!--Custom Code 2013-07-18 (rs) END -->

As I mentioned, you'll have to do this in two places.  Once to accommodate when your report settings are set to "Default," which inherits the DWG file's area unit , and then again to accommodate when your report settings are set explicitly to "Square Feet."

As of this post, using the Autodesk-supplied file that came with Civil 3D 2014, the  custom code above should be pasted immediately after line 68 and then again after line 78.

Once this is complete, save the file and reexecute the report from the toolbox.  Hopefully, you'll see Acres listed immediately below Square Feet.

Wednesday, July 10, 2013

Does AutoCAD seem slower than it used to be? It could be bloated DWG files. Be careful, it's very contagious.

Last fall, I started to receive a lot of calls from end users who were reporting that AutoCAD (various flavors) was acting sluggishly.  From looking over their shoulders, I could tell that it wasn't just their imagination.  In particular, executing copyclip caused the progress meter on the status bar to show that something was processing and it took several seconds before the user was able to paste.  At this point, sometimes the paste worked, and other times it did not.

Feeling confident in our hardware and software configuration, I started to examine the DWG files themselves, looking for anything out of the ordinary - dense hatch patterns, entities miles away from the project - the usual suspects.  As I weeded out groups of entities at a time looking for the culprit, I ended up with a completely empty drawing file that was still 7+ megabytes after a complete purge.

Upon closer examination, there were still thousands of unpurgable linetypes left behind in the drawing file as shown below.


It seems that, other than the names, many of these linetypes were duplicates.  After a little more digging, I discovered that these linetypes were all tied to the data dictionary called acad_dgnlinestylecomp.  This would seem to indicate that they came from a Microstation DGN file at some point in time.  While we do have some Microstation users, they don't share files with the department who first started reporting this problem to me.  Furthermore, the linetype/linestyle names were all unrecognizable to everyone in out office.  This suggests that that they came from somewhere else.

I quickly wrote a small command to eradicate the acad_dgnlinestylecomp dictionary from affected DWG files, and when run, performance was restored to expected levels for all of the end users who experienced this.  Unfortunately, it seemed like the problem kept reappearing in the same DWG files.

It was then that I started experimenting a little more with these linetypes and I discovered that they're extremely contagious from one DWG file to the next.  If a user copies any entity from a DWG that contains these linetypes into an otherwise clean DWG file, then the destination drawing inherits all of the excessive linetypes, regardless of the source entity's linetype, and regardless of whether or not a DGN file was ever imported directly into the problematic DWG file itself.

It was then that I realized that we had another compounding problem on our hands. If you've been using AutoCAD (or AutoCAD based verticals) for years, you might remember that named layer filters were just as contagious back in the 2000i / 2002 era.  More recently, scale lists were contagious from one DWG file to the next circa 2008.  As with the previous contagious bloat, it seems that if I have one DWG file with 1000 uniquely named DGN linestyle names, and I copy an entity from it into another DWG file with 2000 uniquely named DGN linestyle names, then I end up with 3000 unpurgable linetypes.  If I then get a polluted DWG file from an outside source and it contains another 5000 linestyles, and I happen to copy a single entity from it into my previously polluted DWG file, then I have 8000 linetypes, and so on.

Upon further examination, I determined that this problem has been going on for far longer than I've known about it.  It's likely that when it was just a few dozen linetypes per DWG file, the performance hit wasn't noticeable.  It wasn't until the problem started to snowball that it was brought to my attention.

I wrote a trigger into my company-wide acaddoc.lsp file that identifies the problem when anyone opens a drawing file and encourages end users to cleanse their DWG file.  This process is very reactive, though, and Autodesk should make an effort to make these linetypes less contagious, or at least purgable using the built in purge command.  As of AutoCAD 2014, though, we're still fighting the problem.

I've noticed that DWG files that are received from other firms are similarly polluted with excessive unpurgable linetypes and I have to wonder how they're handling it.  I would hope that nobody has gone as far as to buy new hardware to address the problem, but that possibility does exist.  After all, when it was initially reported to me, it was with the usual request of, "I need you to get me a new computer, watch how slow mine is."

Below is a sample of the code that I use to remove all DGN linestyles from the drawing.  Be advised, though, that it is brute force and it will remove the linetype even if it's used.  If one or more linetypes are used, then the linework doesn't get erased.  Rather, the used DGN based linetypes retain their name and revert to the appearance of continuous.  In our case, we never used the DGN linetypes anyway so I consider it to be fairly safe for us.

If you do use this code, please be aware that there is no warranty of any kind and I strongly suggest that you make a backup of you DWG file before you run it.

(defun c:cleandgnbloat (/)
  (if (dictremove (namedobjdict) "acad_dgnlinestylecomp")
    (progn
      (princ
 "\nClean DGN bloat complete.  Please check your file for any errors.  A purge is recommended."
      )
    )
    (princ
      "\nacad_dgnlinestylecomp not found.  This file will not benefit from cleandgnbloat."
    )
  )
  (princ)
)


Kean Walmsley has been kind enough to share a more elegant solution with the community on his blog.  If you use Kean's solution, then to stay ahead of the problem, you might want to identify the problem in your files by using something like this in your acaddoc.lsp:

(if (dictsearch (namedobjdict) "acad_dgnlinestylecomp")
  (call kean's command here)
)

Edit:  If you'd like to test this behavior for yourself, check out this file.  Merely copy the polyline out of it into a new blank DWG and then save the new file.  Notice how the new file contains almost 4 megabytes of unpurgeable linetype definitions.  Please be very careful with this file, though.  I wouldn't want it to begin to pollute your files.