Jump to content


  • Content count

  • Joined

  • Last visited

Community Reputation

10 Good

About JackStone

  • Rank

My Software

  • Main CAD Product
  • Current Product Version
  • First AutoCAD Version
    AutoCAD 2004
  1. Good evening, everyone. When manually creating table styles you can create custom cell styles and set, for each of them, a horizontal and a vertical margin. I'm trying to change an existing table style via LISP. I need to check each cell style, extract the values of its horizontal and vertical margins, multiply those values by a factor and then set these new products as the horizontal and vertical margins of that cell style. My problem is that I don't seem to find reference to cell styles anywhere. I can't find them using entget and I can't find them listed in vlax-dump-object. Is there a way to get the names of all the cell styles defined in a table style? And then is there a way to change the properties of such cell styles (namely the horizontal and vertical cell margins)? The most promising thing I've found so far is the GetCellStyles method (which is supposed to list by name the defined cell styles), but I can't seem to be able to use it correctly. No matter which arguments I supply to it I always get nil. Does anyone know how to use the GetCellStyles method? I thank you all in advance. PS.: there are a HorzCellMargin and a VertCellMargin methods (40 and 41 groups in the tablestyle entity list), but the values there apply only to the standard cell styles ("Data", "Header" and "Title").
  2. Thank you for your assistance, SuperCAD, but that approach still didn't work for me.
  3. Jarr, thank you very much for your contribution. But I'm afraid I haven't explained my situation very well. First of all, that file I attached contains a block that exemplifies my problem, but it is not the actual block I'm interested in. I used that block because it's simpler than the actual one, which would add unnecessary complexity to the problem. I'm only interested in learning the concepts, so I used a surrogate block because I figured that once I understood what I was doing wrong I could fix my actual block. The text behaviour I want is exactly the one displayed by the block FlagBlock3. A reference point attached to the text must rotate along with the remaining entities, so in the end the position of the text with relation to the remaining entities would not change. That's not exactly what happens in FlagBlock3 because I defined the reference point carelessly, so the text moves a bit. But that doesn't matter, it's just to get the idea across. In short: as I rotate the block I wish the text to follow along but remain at 0 degrees (horizontal). I also want all the grips to rotate with the block, none being left behind. Moving the text manually definitely doesn't help me. I hope this is not too complicated. Please let me know if I still haven't explained myself clearly. I once again thank you for your assistance.
  4. Good evening. After some extensive reasearch I could not find a way to solve my problem, so I have come here hoping you guys can save me yet again. I've spent the past three days trying to create this block and at the moment I'm quite frustrated. I'm trying to create a dynamic block with multiple actions. I need a flip, a stretch, a visibility and a rotation parameter and a basepoint. Everything works just fine until I add the rotation action. I need certain entities to rotate but the text to remain at 0 degrees. I learned that you can do that by assigning point parameter to move the text and then include only the point parameter in the rotate action selection set. The problem happens when I try to do that and also add a basepoint. With the basepoint the behaviour of the attributes (or text entities) becomes erratic. Sometimes they even spin in an opposite direction when compared to the other entities. I don't know why that is happening. If I do not include a basepoint explicitly AutoCAD automatically creates a grip that works as a basepoint. In this case the rotation of the attributes and the other entities works just fine, but the new basepoint grip is left behind when I use the rotate action. I have attached a file containing three slightly different blocks. The first one is without any tinkering; on the second one I made the rotation action "Independent" (sometimes that helps, but it didn't work here); on the third one I deleted the explicit basepoint and you will notice the behaviour I described above. I thank you all in advance for your time and expertise. FlagBlocks.dwg
  5. Fantastic! Works like a charm, Lee! A two hundred-line table was created in two seconds, literally. Yet again you have saved my sloppy programs! Thank you very much! This topic may be closed now.
  6. Good afternoon. In my line of work it is necessary for me to create tables (bills of materials) and I have automated this process with some AutoLISP programs. The problem is that when I'm done collecting and organizing the data and it is time to actually draw the table the program takes forever to finish the task. One table, for example, has 6 columns and a variable number of rows. If I create it with, say, 10 rows the program will run quite fast, taking only a couple of seconds to draw the table. If, however, I try to create this table with 100 (one hundred) rows then it takes the program 40 (forty) minutes to finish the task! That depends a bit on the computer hardware, but not so significantly. The method I'm using to create the table is vla-AddTable etc. I start by creating an empty table with the final number of rows and columns and then proceed to set the contents of each cell (always a string) and the type of the cell ("Data", "Header" or "Title"). I may post the code here if necessary, but it's a bit long and I feel the explanation above should make things clear enough. So my question is this: why is AutoCAD taking so long to draw the table? The time elapsed does not scale linearly with the size of the table. Why would that be? I know there are some workarounds to this problem (such as drawing the table as exploded text and lines or dividing a 100-row table into twenty 5-row tables, which are quick to draw individually), but I wanted to get a better understanding of the problem before I attempted to solve it in another way. So, has anyone encountered such difficulty before? Any tips for me? I thank you all in advance for your time and interest!
  7. Very interesting solution, Lee. I especially liked the screen size idea. However the problem persists. Why won't a hatch be shown while inside the grread loop? Am I doing it wrong? Is it a bug? Is there a way around it? Thanks again for all the information!
  8. Oh, sorry, I should have explained myself better. I know some of the work-arounds (though I didn't know about the nomutt system variable - thanks for that!) and this is by no means a fundamental program. See it more as an useful exercise. I wanted to create a subroutine that would behave like ssget. That is, when you click on the screen to create a selection it should display that blue hatched rectangle (window mode of ssget) or that green hatched rectangle (crossing mode of ssget). See it as the getcorner procedure, except that the rectangle it displays is not hatched. Have I managed to put it a little better now? Please say so if I should explain something further. Thank you for your assistance!
  9. I have been attempting to recreate the ssget function to, among other things, allow for custom messages to be displayed on the command prompt. To closely imitate the original ssget function I'm trying to create a hatched rectangle that is changed dynamically as the user moves the mouse. To achieve that I'm using grread. But when I create the polyline and then the hatch associated to it the hatch will not be displayed until the routine is finished and I've exited the grread loop. Why won't my hatch be displayed while still in the grread-while loop? The whole code is a bit too long thus far and most of it would be, I believe, useless to this problem. Here, however, are the subroutine I'm using to create hatches and the structure of the loop in question: (defun dynamic-rectangle (#StartPoint / *DynInp* *DynType* *DynVal* *RectangleObject* *HatchObject* *OldTransparencyDisplay* *ConcatenatedString*) (setq *OldTransparencyDisplay* (getvar 'TransparencyDisplay)) (setvar 'TransparencyDisplay 1) (while (not (setq *Answer* (progn (setq *DynInp* (grread 't 15 1) *DynType* (car *DynInp*) *DynVal* (cadr *DynInp*)) (cond ((= 5 *DynType*) (if (equal *DynVal* #StartPoint) nil (if (and *RectangleObject* *HatchObject*) (reposition-rectangle *RectangleObject* *HatchObject* #StartPoint *DynVal*) (mapcar 'set '(*RectangleObject* *HatchObject*) (if (> (car *DynVal*) (car #StartPoint)) (draw-window-rectangle #StartPoint *DynVal*) (draw-crossing-rectangle #StartPoint *DynVal*))))) nil) ((= 3 *DynType*) (list #StartPoint *DynVal*)) ((= 2 *DynType*) (princ (chr *DynVal*)) (if (member *DynVal* '(32 13)) (if (stringp-n *ConcatenatedString*) *ConcatenatedString* nil) (progn (if (= *DynVal* (setq *ConcatenatedString* (str-RemoveLast *ConcatenatedString*)) (setq *ConcatenatedString* (strcat (cond (*ConcatenatedString*) ("")) (chr *DynVal*)))) nil))) (T nil)))))) (setvar 'TransparencyDisplay *OldTransparencyDisplay*)) (defun make-SolidHatch (#PolylineObject / *HatchObject*) (if (objectp #PolylineObject) (progn (if (not (objectp modelspace)) (init)) (setq *HatchObject* (vla-addHatch modelspace acHatchPatternTypePreDefined "SOLID" :vlax-true)) (vla-appendouterloop *HatchObject* (vlax-safearray-fill (vlax-make-safearray vlax-vbobject '(0 . 0)) (list #PolylineObject))) (vla-evaluate *HatchObject*) *HatchObject*) (progn (princ "\nMAKE-SOLIDHATCH error: invalid argument.") (exit)))) The code above will not work because (I assume) you do not have many of the subroutines required. If it is necessary I can post them here, I just didn't want to exagerate on too many code lines that would not actually be useful. Thank you all for your help!
  10. JackStone

    Make-Counter: Common Lisp?

    Gentlemen, Thank you for your assitance. However, I was left unsatisfied with the use of global variables (other than the name of the counter function itself) to make this counter possible. I left this problem alone for some time but just yesterday I found out about the functions defun-q, defun-q-list-ref and defun-q-list-set and the make-counter routine seemed possible again in my mind. After a few hours of working with these functions I finally managed to do what I wanted. My code looks nothing like the Abelson-Sussman one, that is for sure, but I believe I have managed to simulate a frame by rewriting the functions c1 and c2 every time they are called. (defun-q make-counter (N) (set 'N (1+ N))) (defun boot-c1 () (defun-q c1 () (defun-q-list-set 'c1 (cons nil (cons (cadr c1) (list (cons 'make-counter (list (last c1))))))) (make-counter 0))) (defun boot-c2 () (defun-q c2 () (defun-q-list-set 'c2 (cons nil (cons (cadr c2) (list (cons 'make-counter (list (last c2))))))) (make-counter 0))) Every time you need to reset the counter you call boot-*CounterName*. From then on, every time you call the counter (such as (c1), for example) it will be incremented and the c1 function itself will be rewritten. The counters c1 and c2 (and any other you would like to create) work independently. I posted the code here so I could get your opinion on it. I have never written something like this before, so I need to know if it's buggy or something. Thank you all for your time and collaboration. Edit: slight improvements. (defun-q [b]make-counter[/b] (N) (set 'N (1+ N))) (defun-q [b]boot-CounterX[/b] () (defun-q [b]CounterX[/b] () (defun-q-list-set '[b]CounterX[/b] (cons nil (cons (cadr [b]CounterX[/b]) (list (cons '[b]make-counter[/b] (list (last [b]CounterX[/b]))))))) ([b]make-counter[/b] 0))) (defun [b]replace-instances[/b] (#Searched #Placed #List) (if (listp #List) (mapcar '(lambda (@Element) (if ([b]match[/b] @Element 'LIST) ([b]replace-instances[/b] #Searched #Placed @Element) (if (equal @Element #Searched) #Placed @Element))) #List) (progn (princ "\nREPLACE-INSTANCES error: invalid argument.") (exit)))) (defun [b]boot-counter[/b] (#Name) (if ([b]match[/b] #Name 'SYM) (progn (defun-q-list-set #Name ([b]replace-instances[/b] '[b]CounterX[/b] #Name (defun-q-list-ref '[b]boot-CounterX[/b]))) ((eval #Name)) (princ (strcat "Counter " (vl-symbol-name #Name) " set.")) (princ)) (progn (princ "\nBOOT-COUNTER error: invalid argument.") (exit)))) With such routines you can create a counter and reboot with any name using boot-counter. I didn't add any options to start from any number different from zero, but that can be easily done.
  11. Good evening, everyone. I've recently started to watch the Abelson-Sussman MIT lectures on computer science (mostly because I find them very interesting, not because they have much to do with what I do) and I've ran across this piece of code to create a counter: (define make-counter (lambda (N) (lambda () (set! N (1+ N)) N))) (define c1 (make-counter 1)) (define c2 (make-counter 10)) The explanation concerning the mentioned code starts at around the 48 minute mark. The syntax is not that of AutoLISP and neither that of Common Lisp, I believe, mostly because it's a fragment taken from the middle of a lecture and there's a good reason for the way the code above is written. Anyway, what is supposed to happen is that when you run (c1) for the first time you get a 2; for the second time you get a 3 etc.; when you run (c2) you get (regardless of when you run (c1)) 11; the next time you get 12 etc. I attempted to translate it to AutoLISP: (defun make-counter (N) (lambda () (setq N (1+ N)) N) ) (defun c1 () ((make-counter 1)) ) (defun c2 () ((make-counter 10)) ) The problem is that this does not work. When I attempt to evaluate this with N being nil I get an error. If N is preset to some integer/real then it will be incremented, regardless of calling c1 or c2. I'd like to know if I'm doing something wrong or if this is something that I simply cannot do in AutoLISP. Can this piece of code run the way Sussman shows it in his lecture? Is there a catch here? This is not a matter of life or death, obviously, and I'm not interested in another piece of code that works as a counter (though I'd be delighted to see whichever ones you guys came up withd) since this is something I can easily get around. All I wanted is to know if this can work in AutoLISP and, if so, how. Thank you all!
  12. Thanks for that code, Lee! Exactly as it is it returns the fieldcode but the object Id is nowhere to be found. I don't understand exactly the meaning of "\\_FldIdx 0" that seems to be there in place of the Id. I have made some changes to obtain the object the field is associated with. I'll post it here so that you can comment on it if you wish (and guide me in case I'm doing everything wrong ): (if (not (vl-catch-all-error-p (vl-catch-all-apply '(lambda (enlist) (setq ename (cdr (assoc 331 (entget (cdr (assoc 360 (entget (cdr (assoc 360 (dictsearch (cdr (assoc -1 (dictsearch (cdr (assoc 360 enlist ) ) "ACAD_FIELD" ) ) ) "TEXT" ) ) ) ) ) ) ) ) ) ) ) (list (setq enlist (entget (car (entsel))))) ) ) ) (progn (if (= 'ENAME (type ename)) (setq object (vlax-ename->vla-object ename)) ) ) ) Thank you all for your help once again!
  13. Well, thank you very much! I shall try that out. I don't know much about dictionaries. I see there seems to be a dictionary "inside" the entity which in turn stores other dictionaries (like "ACAD_FIELD"). Is that the correct perception? Where can I learn more about dictionaries? Thank you again for your help!
  14. Hello again. I have made a lisp routine that creates multilines with text of the following format: 15NB%%C8.0c.20-356 The last number (after the dash) is a field linked to a polyline (object length divided by 10). I need to extract the object id from the field code. In the past I used single-line text and I managed to extract the field code through vla-fieldcode, but that method is not available for multileaders and I can't find one to do the same. So here is the problem: how do I extract the field code and, more specifically, the object id stored inside of it from a multileader text? Thank you all for your time.