Jump to content

repeat insert block - while loop


mestar

Recommended Posts

Hi everybody!

 

This is my first post ever, I hope of some feedback...

 

I am not an expert in lisp, but with a lot of searching I can manage to find and modify what I need.

 

But in this case I don understand why in this code (which repeats inserting one block until user hits enter) the block is not visible on crosshair:

 

(defun c:MyBlock (/ pt)

(while (setq pt (getpoint "\nPick Insertion point."))

(command "-insert" "BlockName" "_non" pt "" pause)

)

(princ)

)

 

I have made also one with repeat, and then is the block visible on crosshair:

 

(repeat 3000

(princ "\nPick Insertion point.")

(command "insert" "BlockName" pause "" "" "")

 

);end repeat

 

But I would prefer not to use ESC to break repeat (before it makes the same 3000 times), as an user.

 

Thanks very much,

and have a nice day!

Link to comment
Share on other sites

  • Replies 37
  • Created
  • Last Reply

Top Posters In This Topic

  • The Buzzard

    10

  • mestar

    10

  • Lee Mac

    7

  • gile

    6

Hi,

 

the block isn't visible on the crosshair because the point is specified in the (getpoint ...) expression which is evaluated before the (command "_insert"... ) statement.

Link to comment
Share on other sites

Hi,

 

the block isn't visible on the crosshair because the point is specified in the (getpoint ...) expression which is evaluated before the (command "_insert"... ) statement.

 

Hi Gile,

 

Thanks!

So there is no other way to see the block except with "repeat"? :unsure:

Link to comment
Share on other sites

Here's a way using grread. Inconvenient: you can't use osnaps.

 

(defun c:MyBlock (/ InsertBlock elst gr loop)
 (defun InsertBlock ()
   (entmake
     '((0 . "INSERT")
       (10 0.0 0.0 0.0)
       (2 . "BlockName")
      )
   )
 )
 (InsertBlock)
 (setq elst (entget (entlast)) loop T)
 (while (and (setq gr (grread T 4 0)) loop)
   (cond
     ((= (car gr) 5)
      (entmod (subst (cons 10 (cadr gr)) (assoc 10 elst) elst))
     )
     ((= 3 (car gr))
      (InsertBlock)
      (setq elst (entget (entlast)))
     )
     (T (entdel (entlast)) (setq loop nil))
   )
 )
 (princ)
)

Link to comment
Share on other sites

Still have to hit escape to exit...

 

(defun c:Test (/)
 (while t
   (command "_.-insert" "BlockName" "_s" 1.)
   (princ "\nSpecify insertion point: ")
   (command PAUSE)
   (princ "\nSpecify rotation: ")
   (command PAUSE)
 )
 (princ)
)

Link to comment
Share on other sites

Here's a .NET solution:

Command: MULTINSERT

Prompt the user for a block name (or a dwg name, have to specify the full path if the the file isn't in AutoCAD search path),

displays the bloc during insert,

allows osnaps using,

hit Enter or Space or right click to break the loop.

 

C# code

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

namespace MultiInsertSample
{
   public class MyBlockClass
   {
       class BlockJig : EntityJig
       {
           BlockReference m_blkRef;
           Point3d m_insPt;

           public BlockJig(BlockReference br)
               : base(br)
           {
               m_insPt = br.Position;
               m_blkRef = br;
           }

           protected override SamplerStatus Sampler(JigPrompts prompts)
           {
               JigPromptPointOptions jigOpts = new JigPromptPointOptions();
               jigOpts.UserInputControls =
                 (UserInputControls.Accept3dCoordinates | UserInputControls.NullResponseAccepted);
               jigOpts.Message = "\nEnter insert point: ";
               PromptPointResult ppr = prompts.AcquirePoint(jigOpts);
               if (m_insPt == ppr.Value)
                   return SamplerStatus.NoChange;
               else
                   m_insPt = ppr.Value;
               return SamplerStatus.OK;
           }

           protected override bool Update()
           {
               m_blkRef.Position = m_insPt;
               return true;
           }
       }

       [CommandMethod("MULTINSERT")]
       public void MultiInsert()
       {
           Document doc = Application.DocumentManager.MdiActiveDocument;
           Database db = doc.Database;
           Editor ed = doc.Editor;
           PromptStringOptions opts = new PromptStringOptions("\nEnter block name: ");
           PromptResult pr = ed.GetString(opts);
           if (pr.Status != PromptStatus.OK)
               return;
           Transaction tr = doc.TransactionManager.StartTransaction();
           using (tr)
           {
               BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
               ObjectId blockId = ObjectId.Null;
               string name = pr.StringResult;
               if (bt.Has(name))
                   blockId = bt[name];
               else
               {
                   try
                   {
                       string filename = HostApplicationServices.Current.FindFile(
                           name.EndsWith(".dwg") ? name : name + ".dwg",
                           db,
                           FindFileHint.Default);
                       using (Database source = new Database(false, true))
                       {
                           source.ReadDwgFile(filename, System.IO.FileShare.None, false, null);
                           blockId = db.Insert(name, source, false);
                       }
                   }
                   catch
                   {
                       ed.WriteMessage("\nBlock not found.");
                       return;
                   }
               }
               while (pr.Status == PromptStatus.OK)
               {
                   Point3d pt = new Point3d(0, 0, 0);
                   using (BlockReference br = new BlockReference(pt, blockId))
                   {
                       BlockJig entJig = new BlockJig(br);
                       pr = ed.Drag(entJig);
                       if (pr.Status == PromptStatus.OK)
                       {
                           BlockTableRecord btr =
                               (BlockTableRecord)tr.GetObject(bt[blockTableRecord.ModelSpace], OpenMode.ForWrite);
                           btr.AppendEntity(br);
                           tr.AddNewlyCreatedDBObject(br, true);
                           doc.TransactionManager.QueueForGraphicsFlush();
                       }
                   }
               }
               tr.Commit();
           }
       }
   }
}

MultInsert.zip

Edited by gile
Corrected error handling if the block (or file) is not found
Link to comment
Share on other sites

Thanks Alan,

 

For your time too, I have to consider ESC as a slolution.

 

Have a nice day!

You're welcome. It's about the best you can get, using LISP.

 

Here's a .NET solution:

Command: MULTINSERT

Prompt the user for a block name (or a dwg name, have to specify the full path if the the file isn't in AutoCAD search path),

displays the bloc during insert,

allows osnaps using,

hit Enter or Space or right click to break the loop.

 

C# code

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

namespace MultiInsertSample
{
   public class MyBlockClass
   {
       class BlockJig : EntityJig
       {
           BlockReference m_blkRef;
           Point3d m_insPt;

           public BlockJig(BlockReference br)
               : base(br)
           {
               m_insPt = br.Position;
               m_blkRef = br;
           }

           protected override SamplerStatus Sampler(JigPrompts prompts)
           {
               JigPromptPointOptions jigOpts = new JigPromptPointOptions();
               jigOpts.UserInputControls =
                 (UserInputControls.Accept3dCoordinates | UserInputControls.NullResponseAccepted);
               jigOpts.Message = "\nEnter insert point: ";
               PromptPointResult ppr = prompts.AcquirePoint(jigOpts);
               if (m_insPt == ppr.Value)
                   return SamplerStatus.NoChange;
               else
                   m_insPt = ppr.Value;
               return SamplerStatus.OK;
           }

           protected override bool Update()
           {
               m_blkRef.Position = m_insPt;
               return true;
           }
       }

       [CommandMethod("MULTINSERT")]
       public void MultiInsert()
       {
           Document doc = Application.DocumentManager.MdiActiveDocument;
           Database db = doc.Database;
           Editor ed = doc.Editor;
           PromptStringOptions opts = new PromptStringOptions("\nEnter block name: ");
           PromptResult pr = ed.GetString(opts);
           if (pr.Status != PromptStatus.OK)
               return;
           Transaction tr = doc.TransactionManager.StartTransaction();
           using (tr)
           {
               BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
               ObjectId blockId = ObjectId.Null;
               string name = pr.StringResult;
               if (bt.Has(name))
                   blockId = bt[name];
               else
               {
                   string filename = HostApplicationServices.Current.FindFile(
                       name.EndsWith(".dwg") ? name : name + ".dwg",
                       db,
                       FindFileHint.Default);
                   if (filename == string.Empty)
                   {
                       ed.WriteMessage("\nBlock not found.");
                       return;
                   }
                   using (Database source = new Database(false, true))
                   {
                       source.ReadDwgFile(filename, System.IO.FileShare.None, false, null);
                       blockId = db.Insert(name, source, false);
                   }
               }
               while (pr.Status == PromptStatus.OK)
               {
                   Point3d pt = new Point3d(0, 0, 0);
                   using (BlockReference br = new BlockReference(pt, blockId))
                   {
                       BlockJig entJig = new BlockJig(br);
                       pr = ed.Drag(entJig);
                       if (pr.Status == PromptStatus.OK)
                       {
                           BlockTableRecord btr =
                               (BlockTableRecord)tr.GetObject(bt[blockTableRecord.ModelSpace], OpenMode.ForWrite);
                           btr.AppendEntity(br);
                           tr.AddNewlyCreatedDBObject(br, true);
                           doc.TransactionManager.QueueForGraphicsFlush();
                       }
                   }
               }
               tr.Commit();
           }
       }
   }
}

Nice work, Gile!

Link to comment
Share on other sites

Thanks Gile,

 

But how can I start it? What shall I do with "MultiInsertSample.dll" ? :o

I am not so good, guys! I have never seen something like that!

Link to comment
Share on other sites

I corrected the error handling when the block (or file) is not found, so reload the new version.

 

To use it, load the DLL from AutoCAD with the NETLOAD command (the DLL is loaded for the whole session) and type MULTINSERT.

Link to comment
Share on other sites

I corrected the error handling when the block (or file) is not found, so reload the new version.

 

To use it, load the DLL from AutoCAD with the NETLOAD command (the DLL is loaded for the whole session) and type MULTINSERT.

 

All right men! Excellent stuff!!!

I owe you a beer! :)

 

By the way, where is the new version?

 

Thanks!

"France 10 Points!"

Link to comment
Share on other sites

mestar,

 

Here is a looping method that I use. Some might frown on it, But its really not bad. I have seen well known programmers use this method before. I create a function for the loop instead of using while allowing prompting of two choices, R or Enter for repeating insertion or E for program Exit.

 

Give this a try. You will also see the block on insertion.

 

The block name must be called MyBlock.dwg and must be in the ACAD Search Support Path or you can use findfile and specify the path. I included a line for this if you decide to use it. It is commented out temporary for now. I indicate instructions for this.

 

See the attached Zip file.

Sorry about that, But I am having trouble posting this code with code brackets.

MyBlock.zip

Edited by The Buzzard
Link to comment
Share on other sites

tharwhat313,

 

This DLL is compiled from a .NET (C#) code, not LISP.

And yes, "it's better than vlx" because .NET is more powerfull than LISP (this example shows it).

Edited by gile
Link to comment
Share on other sites

mestar,

 

Here is a looping method that I use. Some might frown on it, But its really not bad. I have seen well known programmers use this method before. I create a function for the loop instead of using while allowing prompting of two choices, R or Enter for repeating insertion or E for program Exit.

 

Give this a try. You will also see the block on insertion.

 

The block name must be called MyBlock.dwg and must be in the ACAD Search Support Path or you can use findfile and specify the path. I included a line for this if you decide to use it. It is commented out temporary for now. I indicate instructions for this.

 

See the attached Zip file.

Sorry about that, But I am having trouble posting this code with code brackets.

 

Thanks Buzzard,

 

It's OK, but there is a one klick too much (for my user who is to be my boss, and does not know anything about it...) I supose "repeat" could not be a default option and ESC as an exit?

 

Thanks for your time!

Link to comment
Share on other sites

Thanks Buzzard,

 

It's OK, but there is a one klick too much (for my user who is to be my boss, and does not know anything about it...) I supose "repeat" could not be a default option and ESC as an exit?

 

Thanks for your time!

 

Thats Ok, I just want to put another option out there for you. I did setup R (Repeat) as a default so all you needed to do was right click the mouse for enter. You do not need to enter R each time, And when you were done click E for (Exit). As I mentioned not everyone cares for this method. If you are changing settings in the program it would pay to have an error trap so that ESC will not screw the settings up. I think the program works cleaner this way than using ESC.

Link to comment
Share on other sites

I modified MyBlock.lsp to MyBlock2.lsp. I used you suggestion looping the insert command and allowing you to use ESC to exit. Its up to you, But as I said its sort of tacky. I would prefer the first lisp better.

 

By the way, I had retested the first code comparing the amount of steps required to operate. There are no extra steps. You must hit enter to finish out the insert command in any event. So what is the difference between hitting enter in the loop or at the end of each insert which is the same thing. I mentioned before that you do not have to hit the R for Repeat, But right click for enter as this is set as default or enter. The E for Exit is no different than hitting ESC except that E for Exit is a cleaner way to exit as it does not show an error.

The amount of steps required will depend upon the insert command input such as Block Scale and rotation.

I will make one more code and post to show you the difference in speed of insertion by supply default values for these as well.

You need to move away from those rogue code habits.

MyBlock2.lsp

Edited by The Buzzard
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...