August 2014

Sun Mon Tue Wed Thu Fri Sat
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31            








« Combining AutoCAD blocks in separate files into a single DWG using .NET | Main | Checking your application has enough memory for an operation using .NET »

January 10, 2011

Combining AutoCAD blocks in separate files into a single DWG using .NET – Take 2

Thanks for Chris, Dan and Dale for pointing out the obvious issue(s) with my last post. Let’s just blame it on a few holiday cobwebs needing brushing away during the first week back in the saddle. :-)

The main issue with my previous implementation was that I’d somehow forgotten that Database.Insert() allows you to insert into a named block definition. This simple function does all my previous, manual approach did and more.

The secondary issue – but still very important to those using annotation scaling – is that the previous code does not work for annotative blocks, as Dan very rightly pointed out. I’ve incorporated Dan’s approach into today’s post to make it more complete.

I’ve decided to leave the original post as it is – as the technique is somewhat interesting at a certain level – even if today’s post supercedes it.

Here’s the updated C# code:

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Runtime;

using System.IO;

using System;

 

namespace BlockImport

{

  public class BlockImportClass

  {

    [CommandMethod("CBL")]

    public void CombineBlocksIntoLibrary()

    {

      Document doc =

          Application.DocumentManager.MdiActiveDocument;

      Editor ed = doc.Editor;

      Database destDb = doc.Database;

 

      // Get name of folder from which to load and import blocks

 

      PromptResult pr =

        ed.GetString("\nEnter the folder of source drawings: ");

 

      if (pr.Status != PromptStatus.OK)

        return;

      string pathName = pr.StringResult;

 

      // Check the folder exists

 

      if (!Directory.Exists(pathName))

      {

        ed.WriteMessage(

          "\nDirectory does not exist: {0}", pathName

        );

        return;

      }

 

      // Get the names of our DWG files in that folder

 

      string[] fileNames = Directory.GetFiles(pathName, "*.dwg");

 

      // A counter for the files we've imported

 

      int imported = 0, failed = 0;

 

      // For each file in our list

 

      foreach (string fileName in fileNames)

      {

        // Double-check we have a DWG file (probably unnecessary)

 

        if (fileName.EndsWith(

              ".dwg",

              StringComparison.InvariantCultureIgnoreCase

            )

        )

        {

          // Catch exceptions at the file level to allow skipping

 

          try

          {

            // Suggestion from Thorsten Meinecke...

 

            string destName =

              SymbolUtilityServices.GetSymbolNameFromPathName(

                fileName, "dwg"

              );

 

            // And from Dan Glassman...

 

            destName =

              SymbolUtilityServices.RepairSymbolName(

                destName, false

              );

 

            // Create a source database to load the DWG into

 

            using (Database db = new Database(false, true))

            {

              // Read the DWG into our side database

 

              db.ReadDwgFile(fileName, FileShare.Read, true, "");

              bool isAnno = db.AnnotativeDwg;

 

              // Insert it into the destination database as

              // a named block definition

 

              ObjectId btrId = destDb.Insert(

                destName,

                db,

                false

              );

 

              if (isAnno)

              {

                // If an annotative block, open the resultant BTR

                // and set its annotative definition status

 

                Transaction tr =

                  destDb.TransactionManager.StartTransaction();

                using (tr)

                {

                  BlockTableRecord btr =

                    (BlockTableRecord)tr.GetObject(

                      btrId,

                      OpenMode.ForWrite

                    );

                  btr.Annotative = AnnotativeStates.True;

                  tr.Commit();

                }

              }

 

              // Print message and increment imported block counter

 

              ed.WriteMessage("\nImported from \"{0}\".", fileName);

              imported++;

            }

          }

          catch (System.Exception ex)

          {

            ed.WriteMessage(

              "\nProblem importing \"{0}\": {1} - file skipped.",

              fileName, ex.Message

            );

            failed++;

          }

        }

      }

 

      ed.WriteMessage(

        "\nImported block definitions from {0} files{1} in " +

        "\"{2}\" into the current drawing.",

        imported,

        failed > 0 ? " (" + failed + " failed)" : "",

        pathName

      );

    }

  }

}

The results are just as we saw with the previous code, so I won’t repeat them.

Update

I made a small update to the code, to make use of SymbolUtilityServices.GetSymbolNameFromPathName() rather than Path.GetFileNameWithoutExtension(). Thanks to Thorsten Meinecke for making this suggestion.

Update 2

Followed by a minor code update to fix simplify the post-edit of annotative block definitions as well as an additional call to SymbolUtilityServices.RepairSymbolName() recommended by Dan Glassman (thanks, Dan! :-).

blog comments powered by Disqus

Feed/Share

10 Random Posts