Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Any way to assign a lisp variable both its name and its value from a string?

41 REPLIES 41
Reply
Message 1 of 42
Anonymous
2388 Views, 41 Replies

Any way to assign a lisp variable both its name and its value from a string?

 

I.e. given a string "varname1:varval1,varname2:varval2" end up with the equivalent of calling this: (setq varname1 varval1 varname2 varval2) in a lisp routine

 

(I'm flexible as to exact structure of the string, characters used as connectors or spacers, etc.)

41 REPLIES 41
Message 21 of 42
dbroad
in reply to: Anonymous

Hmmm.  You should be able to (in Vlide) push help and type vla-setxdata and get a hit.  The link I pasted must be pasted into Microsoft's Internet Explorer browser to work. 

 

In any case, this is the documented example:  BTW, what AutoCAD version are you using?  If you are using a very early version, Vla-methods won't exist.  You can still however use entmod to add xdata

 

(vl-load-com)
(defun c:Example_SetXData()
    ;; This example creates a line and attaches extended data to that line.
    (setq acadObj (vlax-get-acad-object))
    (setq doc (vla-get-ActiveDocument acadObj))
    
    ;; Create the line
    (setq startPt (vlax-3d-point 1 1 0)
          endPt (vlax-3d-point 5 5 0))
    (setq modelSpace (vla-get-ModelSpace doc))
    (setq lineObj (vla-AddLine modelSpace startPt endPt))
    (vla-ZoomAll acadObj)

    ;; Initialize all the xdata values. Note that first data in the list should be
    ;; application name and first datatype code should be 1001
    (setq DataType (vlax-make-safearray vlax-vbInteger '(0 . 9)))
    (setq Data (vlax-make-safearray vlax-vbVariant '(0 . 9)))

    (vlax-safearray-put-element DataType 0 1001)
    (vlax-safearray-put-element Data 0 "Test_Application")

    (vlax-safearray-put-element DataType 1 1000)
    (vlax-safearray-put-element Data 1 "This is a test for xdata")

    ;; layer
    (vlax-safearray-put-element DataType 2 1003)
    (vlax-safearray-put-element Data 2 "0")

    ;; real
    (vlax-safearray-put-element DataType 3 1040)
    (vlax-safearray-put-element Data 3 1.23479137438413E+40)

    ;; distance
    (vlax-safearray-put-element DataType 4 1041)
    (vlax-safearray-put-element Data 4 1237324938)
  
    ;; 16 bit Integer
    (vlax-safearray-put-element DataType 5 1070)
    (vlax-safearray-put-element Data 5 32767)

    ;; 32 bit Integer
    (vlax-safearray-put-element DataType 6 1071)
    (vlax-safearray-put-element Data 6 32767)

    ;; scaleFactor
    (vlax-safearray-put-element DataType 7 1042)
    (vlax-safearray-put-element Data 7 10)

    ;; 3D point
    (setq reals3 (vlax-3d-point -2.95 100 -20))
    (vlax-safearray-put-element DataType 8 1010)
    (vlax-safearray-put-element Data 8 reals3)
    
    ;; world space position
    (setq worldPos (vlax-3d-point 4 400.99999999 2.798989))
    (vlax-safearray-put-element DataType 9 1011)
    (vlax-safearray-put-element Data 9 worldPos)
    
    ;; Attach the xdata to the line
    (vla-SetXData lineObj DataType Data)
    
    ;; Return the xdata for the line
    (vla-GetXData lineObj "" 'xtypeOut 'xdataOut)
)

 

Architect, Registered NC, VA, SC, & GA.
Message 22 of 42
Gary_J_Orr
in reply to: Anonymous

if VLIDE doesn't recognize the function then the VLxxx extensions have not yet been loaded into AutoCAD and, since VLIDE works within the AutoCAD namespace it doesn't recgonize it yet.
To initialize it type (vl-load-com) at your console prompt.
Also note that any routine that uses any VLxxx functions should include a call to load the extension library as it loads.
So many of us use the extensions so frequently that we have included the call in our startup functions so they are always available.

Also note that with his suggestions you will be entering the world of ActiveX interfaces as well as the Extension Dictionary stuff.
Gary J. Orr
(Your Friendly Neighborhood) CADD/BIM/VDC Applications Manager
http://www.linkedin.com/in/garyorr

aka (current and past user names):
Gary_J_Orr (GOMO Stuff 2008-Present); OrrG (Forum Studio 2005-2008); Gary J. Orr (LHB Inc 2002-2005); Orr, Gary J. (Gossen Livingston 1997-2002)
Message 23 of 42
Anonymous
in reply to: Gary_J_Orr

VL-load-com did it. The vl* functions are now recognized. Thanks.

I used to customize for r14 and earlier so I've always ignored the vl* functions. Now I'm on 2013, so there's no more reason to ignore the new functionality.

 

As for goose-chasing, I'm game for a bit of that.

Message 24 of 42
Anonymous
in reply to: dbroad

I called vl-load-com as per Gary, then used a VLIDE toolbar button for Help that I've always ignored and got the page in the ActiveX and VBA Reference.

 

(I was pulling down from the menu and typing F1 and getting the AutoCAD help that contains the helpfile for vanilla Vlisp.)

 

There's lots of detail in this document. Thanks. This will take a while...

Message 25 of 42
Gary_J_Orr
in reply to: Anonymous

if the references to Xdata (extended data) along with the activeX interface becomes too much to tackle at this time you can roll back to an easier methodology:

Dictionaries and xrecord objects...

Here is Dictionaries 101 for you to consider... simple expansions on examples directly out of the help files and using "basic" lisp functions that work with association lists and group codes (that you are familiar with given your previous mention to Assoc and list familiarity) that can be referenced in the DXF "Objects" section of help under "Dictionary" and "Xrecord". along with the lisp functions DictAdd, DictNext, DictSearch, DictRemove.

 

Might cut down on your learning curve perhaps if your starting point is something that you are familiar with. (you can dump the whole mess into a "scrap" lisp file and play around a bit if you want.

 

;this is an expansion of the lisp help file examples for:
;DictAdd, Dictnext, DictSearch, dictremove
;don't blame me for the values used, I kept them as they exist for cross reference
;you can add an extension dictionary to any acad object and/or database entity
;(I used to use this type of thing to coordinate drawing object info with excel spreadsheets)
;here we are using the master dictionary

;take a look at the existing Drawing dictionary
(entget (namedobjdict) (list "*"))

;create a data definition list for the dictionary
(setq dictionary (list '(0 . "DICTIONARY") '(100 . "AcDbDictionary")))
;create the dictionary
(setq xname (entmakex dictionary))
;add it to the main drwaing dictionary with a specified key name
(setq newdict (dictadd (namedobjdict) "MY_WAY_COOL_DICTIONARY" xname))

;create a data definition list for the dictionary record
(setq datalist (append (list '(0 . "XRECORD")'(100 . "AcDbXrecord")) '((1 . "This is my data") (10 1. 2. 3.) (70 . 33))))
;create the dictionary record
(setq xname (entmakex datalist))
;add the record to your dictionary with a specified key name
(dictadd newdict "DATA_RECORD_1" xname)

;create a second record
(setq datalist (append (list '(0 . "XRECORD")'(100 . "AcDbXrecord")) '((1 . "This is more of my data") (10 4. 5. 6.) (70 . 33))))
(setq xname (entmakex datalist))
(dictadd newdict "DATA_RECORD_2" xname)

;create a third record
(setq datalist (append (list '(0 . "XRECORD")'(100 . "AcDbXrecord")) '((1 . "This is the last of my data") (10 7. 8. 9.) (70 . 33))))
(setq xname (entmakex datalist))
(dictadd newdict "DATA_RECORD_3" xname)

;take a look at the new Drawing dictionary
(entget (namedobjdict) (list "*"))

;now let's imagine extracting saved data.
;We will ignore the fact that we already have variables referencing these items
;get your dictionary for reference, using the key that you created when you added it
(setq MyDict (dictsearch (namedobjdict) "MY_WAY_COOL_DICTIONARY"))
;note that dictsearch returns the entire association list for the dictionary
;enames are required for moving around so we will extract our main dict ename
;get the first data record in your dictionary
(setq MyDictRef (cdr (assoc -1 MyDict)))

;to do a loop on our dictionary
;get the first record
(setq record (dictnext MyDictRef T))
(while (/= nil record)
  (princ (strcat "\n" (cdr (assoc 1 record))))
  (setq record (dictnext MyDictRef))
  )

;to get a specific record from your dictionary,
;use the key value that you supplied when you created it
(setq record (dictsearch MyDictRef "DATA_RECORD_1"))
(princ (strcat "\n" (cdr (assoc 1 record))))

;combine the two retrieval methods to start at a specific spot for your loop
(setq record (dictsearch MyDictRef "DATA_RECORD_2" T))
(while (/= nil record)
  (princ (strcat "\n" (cdr (assoc 1 record))))
  (setq record (dictnext MyDictRef))
  )

;to stop at a specific point
(setq StopAt (cdr (assoc -1 (dictsearch MyDictRef "DATA_RECORD_3"))))
(setq record (dictnext MyDictRef T))
(while (and (/= nil record) (not (eq (cdr (assoc -1 record)) StopAt)))
  (princ (strcat "\n" (cdr (assoc 1 record))))
  (setq record (dictnext MyDictRef))
  )

;get rid of your dictionary
;first detach it from the main dictionary
(dictremove (namedobjdict) "MY_WAY_COOL_DICTIONARY")

;take a look at the Drawing dictionary again
(entget (namedobjdict) (list "*"))

;it is no longer in the dictionary, but... it still exists, only without an owner
;you can see this by entering our previously defined variable at the console:
(entget MyDictRef)
;to actually delete it you need to call entdel
(entdel MyDictRef)
;now check again
(entget MyDictRef)

;but, even if you do not have a var set for the ename of your dictionary,
;dictremove returns the ename if it's successful so you can use it for the entdel call:
(setq MyDictRef (dictremove (namedobjdict) "MY_WAY_COOL_DICTIONARY"))
(if MyDictRef (entdel MyDictRef))

 man... I must really be getting bored... I think I need a job... *ReallyBigGrin*

Gary J. Orr
(Your Friendly Neighborhood) CADD/BIM/VDC Applications Manager
http://www.linkedin.com/in/garyorr

aka (current and past user names):
Gary_J_Orr (GOMO Stuff 2008-Present); OrrG (Forum Studio 2005-2008); Gary J. Orr (LHB Inc 2002-2005); Orr, Gary J. (Gossen Livingston 1997-2002)
Message 26 of 42
Anonymous
in reply to: Gary_J_Orr

Thanks so much Gary. I've only been through it with one coffee, but it is pretty simple, given my experience, the datatype issue disappears, you can run through it, stop it, and start the sequence easily. I might put off submitting to the DOM for another day.

 

Can custom dictionaries can be nested?

 

I noticed this in the help:

 

"As a general rule, each object added to a dictionary must be unique to that dictionary. This is specifically a problem when adding group objects to the group dictionary. Adding the same group object using different key names results in duplicate group names, which can send the dictnext function into an infinite loop."

 

I sometimes reuse variables, ditching a previous value and datatype for another...<blushes>... usually based on the previous value in some way...<blushes>... to cut down on the number of variables I have to track. <blushes>

Message 27 of 42
Gary_J_Orr
in reply to: Anonymous

oh yes, they can be "nested".

 

After establishing your "master" dictionary in the "Named Object Dictionary" or NOD, which we aquired the entityname of by using (Namedobjdict) you can add new dictionaries to your master dictionary, each with it's own collection of xrecords.

 

simply <he says with a grin> retrieve your master dictionary from the NOD, get it's entity name from the assoc list, and pass that as the argument for creating your nested dictionaries instead of (NamedObjDict)

 

So:

(setq MyDict (dictsearch (namedobjdict) "MY_WAY_COOL_DICTIONARY"))

retrieves your Master dictionary.

(setq MyDictRef (cdr (assoc -1 MyDict)))

retrieves the entity name of your dict

 

then define and entmake  a new dictionary

then add it to yours with the same dictadd method that you added the master to the NOD

instead of:

(setq newdict (dictadd (namedobjdict) "MY_WAY_COOL_DICTIONARY" xname))

do this

(setq newdict (dictadd MyDictRef "MY_WAY_COOL_NESTED_DICTIONARY" xname))

... exactly like adding a record to the dictionary...

 

For your sanity I would recommend (if you choose to pursue this course, and since I don't have the specifics of what you are doing I don't know whether to recommend such a course of action or not) that: if you are going to use a master dictionary with nested dictionaries that the Master should only contain nested dictionaries and should never contain any direct records, all records should be kept in the nested dictionaries.

 

All of that being said... XData attached to specific objects may still be what you need, or possibly some combination of the two... I simply don't know.

Bright spot... XData can be added and retrieved without the ActiveX interface and all of the conversions and building of matched pairs of lists and the like... It can be done the "old-fashioned" way with entity association lists and the entmod function...

 

If you run the ActiveX example that you were provided you will have a line with XData attached to it.

pick it into a variable: (setq Line1 (car (entsel)))

if you then do the typical entget call on the line you will get it's data

(entget Line1)

but, to see the extended data that the example attached you can do an "extended Data" call in Entget

(entget Line1 (list "*"))

 

I used the wildcard in the Xdata list to get any and all Xdata, but you can replace the "*" with specific names (as many as you may need to search for)

(entget Line1 (list "Test_Application" "Some_Other_Application"))

 

Here's a little snippet modified from the help files in DXF reference...

 

(setq Line1 (car (entsel)))
(setq Line1EData (entget Line1))
; Gets the association ; list of definition data ; for the selected entity.
(setq AppName "GJO_Data")
(if (tblsearch "appid" AppName)
  (princ "\We have already Registered our App...")
  (regapp AppName)
  )
(setq exdata ; Sets the variable
       '((-3 ("GJO_Data")
		   (1000 . "This is a new thing!")
	      )))
      )
(setq newent  (append Line1EData exdata)) ; Appends new data list to  ; entity's list.
(entmod newent) ; Modifies the entity with the new  ; definition data.


(setq working_elist (entget line1 (list AppName)))
(if working_elist
  (progn
    ;modify desired values by reworking the list then call
    (entmod working_elist)
    )
  )

 ...

Time for a refill on my own cup 🙂

 

Gary J. Orr
(Your Friendly Neighborhood) CADD/BIM/VDC Applications Manager
http://www.linkedin.com/in/garyorr

aka (current and past user names):
Gary_J_Orr (GOMO Stuff 2008-Present); OrrG (Forum Studio 2005-2008); Gary J. Orr (LHB Inc 2002-2005); Orr, Gary J. (Gossen Livingston 1997-2002)
Message 28 of 42
Anonymous
in reply to: Gary_J_Orr

Right now, before writing a line, I think dictionaries alone should do it.

 

I'll write a little tester lisp mirroring the structure of my working routine, write some modules to write the values to dictionaries, retrieve them one at a time, and "replay" up to a chosen point.

 

It should be a lot smaller so I could post it, but should take a while. Thanks for holding my hand.

Message 29 of 42
Gary_J_Orr
in reply to: Anonymous

But we haven't even gotten to the fun part yet.... attaching dictionaries to objects instead of XData (to help remove some of the restrictions)...
*ReallyBigGrin*

BTW: there was an error in my XData reference:

(setq exdata ; Sets the variable
       '((-3 ("GJO_Data")
   (1000 . "This is a new thing!")
      )))
      )

should have been:

(setq exdata ; Sets the variable
       '((-3 ("GJO_Data"
    (1000 . "This is a new thing!")
      )))
      )


And no prob... my hand has been held a couple of times over the years so it's just "paying it forward"... I have the time so why not help out where I can.

Gary J. Orr
(Your Friendly Neighborhood) CADD/BIM/VDC Applications Manager
http://www.linkedin.com/in/garyorr

aka (current and past user names):
Gary_J_Orr (GOMO Stuff 2008-Present); OrrG (Forum Studio 2005-2008); Gary J. Orr (LHB Inc 2002-2005); Orr, Gary J. (Gossen Livingston 1997-2002)
Message 30 of 42
Anonymous
in reply to: Gary_J_Orr

Gary, in the following, is group code 1 the only place I can store data in the ent list?

 

;create a data definition list for the dictionary record
(setq datalist (append (list '(0 . "XRECORD")'(100 . "AcDbXrecord")) '((1 . "This is my data") (10 1. 2. 3.) (70 . 33))))
;create the dictionary record
(setq xname (entmakex datalist))
;add the record to your dictionary with a specified key name
(dictadd newdict "DATA_RECORD_1" xname)


The help page for XRECORD DXF says,

 

"1-369 (except 5 and 105) | These values can be used by an application in any way"

 

but so far every time I try to write to any other group code the list won't form. I was hoping to  geth three bits of data into each XRECORD: the variable name, it's value, and some flag I haven't devised yet telling me where in the prompt series it was stored. Will I have to pack all that into a single string and unpack it later?

Message 31 of 42
Gary_J_Orr
in reply to: Anonymous


@Anonymous wrote:

Gary, in the following, is group code 1 the only place I can store data in the ent list?

 


Nope... first you will have to "expand" the "quoted" definition list so you can actually work with it:

start by breaking down that long string to help you understand it (I also added a group code 11 which I'll explain in a minute):

(setq datalist (append
   (list '(0 . "XRECORD")'(100 . "AcDbXrecord"))
   '(
     (1 . "This is my data")
     (10 0.0 0.0 0.0)
     (11 10.0 10.0 0.0)
     (70 . 33)
     )
   )
      )

The section that I highlighted above in red is the typical single quote... everything that follows (within matching brackets) is taken exactly as it appears...

by calling functions to do what the quote is doing we can see exactly what is happening:

(setq datalist (append
   (list '(0 . "XRECORD")'(100 . "AcDbXrecord"))
   (list
     (cons 1 "This is my data")
     (list 10 0.0 0.0 0.0)
     (list 11 10.0 10.0 0.0)
     (cons 70 33)
     )
   )
      )

 

Notice how the groups for 10 and 11 are created using "List" while the rest use "cons"... Group codes that acad uses for points are not dotted pairs and must be treated "special"... there are also a few other "reserved" and "special" group codes, regardless of what the documentation says (back to that in a minute...

Also notice, now that I am constructing my datalist dynamically I can add variables instead of specific quoted strings/values:

(setq String1 "Some aquired value")

(setq Numb 33)

etc... then:

(setq datalist (append
   (list '(0 . "XRECORD")'(100 . "AcDbXrecord"))
   (list
     (cons 1 String1)
     (list 10 0.0 0.0 0.0)
     (list 11 10.0 10.0 0.0)
     (cons 70 Numb)
     )
   )
      )

 

Now, to the point of your question...

There are a few group codes within that range that you are suppossed to be able to freely add that are reserved. It can be tricky to understand the difference. The problem is that the documentation is a "mixed bag" of references. DXF itself as a language for storing information, and ACAD as an "Application" that has already reserved some of the codes that you are trying to use...

 

in the dxf reference for "Common Group Codes for Entities" you will find items that ACAD, being the application that you are working within, has already assigned to certain objects and types... Since you are actually working within those confines you really need to reference those "common..." for entities and for Objects.

DXF Reference -> DXF Format -> "Group Codes in Numerical Order" will show you more of what is expected.

Pay attention to the descriptions. Anything that says "APP: 3D point" will error out if you try to construct your list using a dotted pair. Anything else that has that "APP:..." needs special consideration, or will outright be rejected because ACAD wants control of that

 

Group codes 300-309 are probably your best and easiest targets. That gives you an easy 9 strings per Xrecord. After that you might need to get into some tricky stuff by subdividing using the 102 group with curly braces:

(cons 102 (strcat "{" SomeVarToIdentifyTheSubset)) ... nine more chunks of data... (cons 102 "}")

but all that is over and beyond... you already said 3 and 9 covers you well enough.

Gary J. Orr
(Your Friendly Neighborhood) CADD/BIM/VDC Applications Manager
http://www.linkedin.com/in/garyorr

aka (current and past user names):
Gary_J_Orr (GOMO Stuff 2008-Present); OrrG (Forum Studio 2005-2008); Gary J. Orr (LHB Inc 2002-2005); Orr, Gary J. (Gossen Livingston 1997-2002)
Message 32 of 42
Gary_J_Orr
in reply to: Gary_J_Orr

I probably could have explained one other thing before sending you off on your search for understanding...:
Yes (with the exception of certain "reserved" codes that can get tricky, see the last post for how to find most of those, and also look out for anything that says (fixed) in the description as well or ACAD may still try to reject it)... you can use any codes in the range indicated in the Xrecord group code range in any way that you want...
But you must use the correct "data type" for any given code.
The values can mean whatever you want them to mean but... 16 bit integers must be supplied if using the ranges designated for them, Floating point values in the ranges dedicated to such, Strings for strings, etc...

Also see "Group Code Value Types" for quick reference of those "ranges"
Gary J. Orr
(Your Friendly Neighborhood) CADD/BIM/VDC Applications Manager
http://www.linkedin.com/in/garyorr

aka (current and past user names):
Gary_J_Orr (GOMO Stuff 2008-Present); OrrG (Forum Studio 2005-2008); Gary J. Orr (LHB Inc 2002-2005); Orr, Gary J. (Gossen Livingston 1997-2002)
Message 33 of 42
Anonymous
in reply to: Gary_J_Orr

Lol. All the codes I was trying came with expectations. There are significant ranges of codes that aren't specified on that list. Others, like the one you mentioned are explicitly reserved for specifically "arbitrary" strings, still others for are reserved for data of a certain type. What's up with those?

 

I expect those not reserved for 'arbitrary' purposes could end up being reserved by AutoDesk at some point in the future. If I want to store reals or integers as well as strings, can/should I use some of the codes reserved for those types or convert all to strings and then convert back when retrieving?

 

(Have my dictionary maker module. Working on the record writer.)

Message 34 of 42
Gary_J_Orr
in reply to: Anonymous


@Anonymous wrote:

... still others for are reserved for data of a certain type. What's up with those?


As you have noticed by now, and in response to a line that I should have pointed out to you from an earlier post when you decided to ditch ActiveX (COM):
"...the datatype issue disappears..."

 

You still have to be concerned about the data type, you just don't have to convert the required Lisp data types into VB data types.

 


@Anonymous wrote:

I expect those not reserved for 'arbitrary' purposes could end up being reserved by AutoDesk at some point in the future. If I want to store reals or integers as well as strings, can/should I use some of the codes reserved for those types or convert all to strings and then convert back when retrieving?


freely use the "code groups" in any way that you want (within the guidelines of datatype defined within "Group Code Value Types" of course, and cross referencing by those labeled as '(fixed)" or with "APP:..." in the "Numerical Order" table).

If it's marked "Fixed" only use it for that purpose (such as GC 8 for "Layer Name" should always be used for the Layer Name of some object or perhaps a flag for a layer name that you want to track or reference) just to ensure fewer "oops's" as things roll along or you get to passing the dotted pair back and forth to/from objects/tables/dictionaries

 

But the "Data Type" is actually the most critical, followed by those flagged with "APP:..." , most critically are those that contain point lists due to the fact that they will be rejected if you try to pass a dotted pair to them.

 

 

And, of course, if it hasn't dawned on you yet (this from an earlier post):

 

"...and some flag I haven't devised yet telling me where in the prompt series it was stored..."

 

is easily addressed by using your "entry Point" as your key for the Xrecord.

 

(setq AppName "GJO_Data")
(setq dictionary (list '(0 . "DICTIONARY") '(100 . "AcDbDictionary")))
(setq DictEName (entmakex dictionary))
(setq DictKey (strcat AppName "_Dict"))
(setq newdict (dictadd (namedobjdict) DictKey DictEName))


(setq EntryMark 3)
(setq RecName "Entry_Point_3")
(setq datalist (list '(0 . "XRECORD")'(100 . "AcDbXrecord")
		     ;most commonly used for single text value
		     (cons 1 (strcat "My owner\'s key is: " DictKey))
		     ;often used for style names; good practice is to store the key here
		     (cons 2 RecName)
		     ;often used for descriptions
		     (cons 3 (strcat "I am Variable Storage for function " AppName))
		     ;often used for reference names
		     (cons 4 "My Entry Point is Stored in Group 90")
		     ;some associated point data
		     (list 10 0.0 0.0 0.0)
		     (cons 90 EntryMark)
		     (cons 300 "VarName1")
		     (cons 301 "Value for VarName1")
		     (cons 302 "VarName2")
		     (cons 303 "Value for VarName2")
		     (cons 304 "VarName3")
		     (cons 305 "Value for VarName3")
		     (cons 306 "VarName4")
		     (cons 307 "Value for VarName4")
		     (cons 308 "VarName5")
		     (cons 309 "Value for VarName5")
		     )
      )

(if (setq XRecEname (entmakex datalist))
  (dictadd newdict RecName XRecEname)
  (Princ (strcat "\nAddXrecord: " RecName " - Failed"))
  )

 


@Anonymous wrote:

(Have my dictionary maker module. Working on the record writer.)


Someone was up late... Think I'll start investing some money in coffee futures and "Monster" energy drinks 😉

Gary J. Orr
(Your Friendly Neighborhood) CADD/BIM/VDC Applications Manager
http://www.linkedin.com/in/garyorr

aka (current and past user names):
Gary_J_Orr (GOMO Stuff 2008-Present); OrrG (Forum Studio 2005-2008); Gary J. Orr (LHB Inc 2002-2005); Orr, Gary J. (Gossen Livingston 1997-2002)
Message 35 of 42
Anonymous
in reply to: Gary_J_Orr

So, bottom line, if the group code isn't one that's reserved, and my data type matches the requirement for it, I can use it? Looks like I can save booleans too. (Record writer module now seems to work.)

 

Because the flow of prompts forks and loops, and in subsequent iterations you might choose a different fork (at an if-then) or a different # of repetitions at a loop, addressing for the stored variable value needs to be flexible but unique. Address scheme might point to the correct dictionary for storage, and but the trip is less clear. Dictionaries seem to store alphabetically by key, and dictnext seems a handy function for getting the sequence right on replay, so it would be nice if the addressing scheme also stored the records in alpha order.

 

Was thinking of replacing all (most?) setq calls with calls to a setR module that would perform the setq but also write a record with the address as key to the approprate dictionary, after bumping the address. Would allow simple graft-on with find-replace except where I have (Setq a 1 b 2 ...) I'd have some typing there. Now- magic markers.

Message 36 of 42
Gary_J_Orr
in reply to: Anonymous

I've never paid any attention as to the "Dictionaries seem to store alphabetically by key", but I surely would not rely on that. DictAdd may have some such property that I'm not aware of that inserts a new dict in alpha order instead of simply appending but... I wouldn't bet my code on it...

As far as: "magic markers"...

My mommy still won't let me use those, I have to use washable crayons 😉
<Grins>
Gary J. Orr
(Your Friendly Neighborhood) CADD/BIM/VDC Applications Manager
http://www.linkedin.com/in/garyorr

aka (current and past user names):
Gary_J_Orr (GOMO Stuff 2008-Present); OrrG (Forum Studio 2005-2008); Gary J. Orr (LHB Inc 2002-2005); Orr, Gary J. (Gossen Livingston 1997-2002)
Message 37 of 42
Anonymous
in reply to: Gary_J_Orr

Xrecord keys do seem to store in a 'modified alphabetic order' in a dictionary. See watch window in the attached.

 

With significant exceptions among them, most punctuation marks over a number on a standard keyboard sort in numerical order of the numbers below them and they sort before numbers, but some come after numbers and some come last of all. Some puntuation marks are always rejected, including these | \ ? / < > = , : ;

 

An asterisk behaves differently than all other marks and actually modifies the key name that you enter if it is the first character. It replaces everything you type after the asterisk with an upper case letter A and an ascending sequence of consecutive natural numbers starting at 1, so you get *A1, *A2...*A9, *A10, *A12 and so on. Simple repeated assignments of anything starting with an asterisk as the key will assign an arbitrary sequence of keys that dictnext will return in the order of creation. If the asterisk comes after the first position, it is rejected.

 

Otherwise, numbers come before letters. Both behave as you'd think, and letters are not case sensitive. Spaces come before anything, except as the first or last character, which are rejected.

 

Dictnext calls retrieve xrecords in this same order.  It's independent of the order in which they are created. I think this is why they are called "dictionaries."

 

I feel confident enough in this to try exploiting this behavior to define xrecord keys so that they can be extracted in sequential order with serial dictnext calls. If anyone has better info on how this works, don't be shy. I'm still mulling over the wisdom of anonymous ordering with * vs deliberate 'modified alphabetic 'sequencing. Have to map out my sequences to decide.

Message 38 of 42
Anonymous
in reply to: Anonymous

sorry, here's the attachment

Message 39 of 42
martti.halminen
in reply to: Anonymous

I am wondering why you are fiddling with Xdata. Wouldn't Ldata be much simpler, with no type conversions etc. ?

See vlax-ldata-put, vlax-ldata-get.

 

--

Message 40 of 42
Anonymous
in reply to: martti.halminen

I moved away from DOM based because dictionaries were closer to my experience and looked like they would work. It does look like a few line less code in my record module, but that's done and working. I've now moved on to implementing a set of dictionary based methods in my application.

 

So far, it's been much easier than I thought. The real revelations to me in this exercise were READ and SET, which I have never used before. Thanks to everyone for their help. I'll post what I end up with shortly.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost