Cylis0509 Posted May 6, 2017 Posted May 6, 2017 Hi All, I have created this lisp and it works great but I need help with one thing. This will pull the hyperlinks from blocks and export them to a txt file in the order you select the blocks. Here is the problem I have. Apparently there are two ways to add hyperlinks to a block. You can go through the block editor and add it there in the properties pane (Image 1 ) or you can add it to outside of the block. (Image 2) Hope that makes sense. The routine below will work if the hyperlink is on the outside, and of course all the blocks I have, have the hyperlink on the inside. How do I modify this to extract the "nested" hyperlink? Also I noticed that if you cancel the txt save dialog the following error appears: ; error: bad argument type: stringp nil I'm not sure why... (defun c:test6 (/ ) (vl-load-com) (setq File1 (getfiled "Save File" (strcat "Export - "(menucmd "M=$(edtime,$(getvar,date),MO-DD-YYYY)")) "txt" 1)) (setq Fopen (open File1 "w")) (setq ss_mm (ssget (list (cons 0 "INSERT")))) (setq Ecount 0) (repeat (sslength ss_mm) (setq mm_obj (vlax-ename->vla-object (ssname ss_mm Ecount))) (setq mm_txt (vlax-get-property mm_obj 'Hyperlinks)) (progn (vlax-for each mm_txt (setq hyp_txt (strcat (vla-get-url each))) (write-line hyp_txt Fopen) (setq Ecount (1+ Ecount)) ) ) ) (close Fopen) (princ) ) Image 1 Image 2 Quote
Lee Mac Posted May 6, 2017 Posted May 6, 2017 (edited) This will pull the hyperlinks from blocks and export them to a txt file in the order you select the blocks. Note that when obtaining a selection using ssget, you cannot rely on the order of the entities within the set matching the order in which they were selected (consider window/crossing/polygon/group selections). Also I noticed that if you cancel the txt save dialog the following error appears: ; error: bad argument type: stringp nilI'm not sure why... Because you are not testing whether the getfiled function has returned a string value before supplying the value to the open function. If the user clicks 'Cancel' when prompted, getfiled will return nil and hence the open function will error when supplied with a null filename argument. I would suggest the following: ([color=BLUE]defun[/color] c:hypex ( [color=BLUE]/[/color] des ent hyp lst txt url ) ([color=BLUE]setq[/color] hyp ([color=BLUE]lambda[/color] ( ent ) ([color=BLUE]cdr[/color] ([color=BLUE]assoc[/color] 1000 ([color=BLUE]cdadr[/color] ([color=BLUE]assoc[/color] -3 ([color=BLUE]entget[/color] ent '([color=MAROON]"pe_url"[/color])))))))) ([color=BLUE]while[/color] ([color=BLUE]not[/color] ([color=BLUE]progn[/color] ([color=BLUE]setvar[/color] 'errno 0) ([color=BLUE]setq[/color] ent ([color=BLUE]car[/color] ([color=BLUE]entsel[/color] [color=MAROON]"\nSelect block <done>: "[/color]))) ([color=BLUE]cond[/color] ( ([color=BLUE]=[/color] 7 ([color=BLUE]getvar[/color] 'errno)) ([color=BLUE]prompt[/color] [color=MAROON]"\nMissed, try again."[/color]) ) ( ([color=BLUE]null[/color] ent)) ( ([color=BLUE]/=[/color] [color=MAROON]"INSERT"[/color] ([color=BLUE]cdr[/color] ([color=BLUE]assoc[/color] 0 ([color=BLUE]entget[/color] ent)))) ([color=BLUE]prompt[/color] [color=MAROON]"\nThe selected object is not a block."[/color]) ) ( ([color=BLUE]not[/color] ([color=BLUE]setq[/color] url ([color=BLUE]cond[/color] ((hyp ent)) ((hyp ([color=BLUE]cdr[/color] ([color=BLUE]assoc[/color] 330 ([color=BLUE]entget[/color] ([color=BLUE]tblobjname[/color] [color=MAROON]"block"[/color] (LM:name->effectivename ([color=BLUE]cdr[/color] ([color=BLUE]assoc[/color] 2 ([color=BLUE]entget[/color] ent))))))))))))) ([color=BLUE]prompt[/color] [color=MAROON]"\nThe selected block does not contain a hyperlink."[/color]) ) ( ([color=BLUE]=[/color] [color=MAROON]""[/color] url) ([color=BLUE]prompt[/color] [color=MAROON]"\nThe hyperlink for the selected block is linked to a view."[/color]) ) ( ([color=BLUE]setq[/color] lst ([color=BLUE]cons[/color] url lst)) ([color=BLUE]prompt[/color] ([color=BLUE]strcat[/color] [color=MAROON]"\nURL = "[/color] url)) ) ) ) ) ) ([color=BLUE]if[/color] ([color=BLUE]and[/color] lst ([color=BLUE]setq[/color] txt ([color=BLUE]getfiled[/color] [color=MAROON]""[/color] ([color=BLUE]strcat[/color] [color=MAROON]"Export - "[/color]([color=BLUE]menucmd[/color] [color=MAROON]"M=$(edtime,0,MO-DD-YYYY)"[/color])) [color=MAROON]"txt"[/color] 1))) ([color=BLUE]if[/color] ([color=BLUE]setq[/color] des ([color=BLUE]open[/color] txt [color=MAROON]"w"[/color])) ([color=BLUE]progn[/color] ([color=BLUE]foreach[/color] url ([color=BLUE]reverse[/color] lst) ([color=BLUE]write-line[/color] url des)) ([color=BLUE]close[/color] des) ) ([color=BLUE]princ[/color] ([color=BLUE]strcat[/color] [color=MAROON]"\nUnable to open "[/color] txt [color=MAROON]" for writing."[/color])) ) ) ([color=BLUE]princ[/color]) ) [color=GREEN];; Block Name -> Effective Block Name - Lee Mac[/color] [color=GREEN];; blk - [str] Block name[/color] ([color=BLUE]defun[/color] LM:name->effectivename ( blk [color=BLUE]/[/color] rep ) ([color=BLUE]if[/color] ([color=BLUE]and[/color] ([color=BLUE]wcmatch[/color] blk [color=MAROON]"`**"[/color]) ([color=BLUE]setq[/color] rep ([color=BLUE]cdadr[/color] ([color=BLUE]assoc[/color] -3 ([color=BLUE]entget[/color] ([color=BLUE]cdr[/color] ([color=BLUE]assoc[/color] 330 ([color=BLUE]entget[/color] ([color=BLUE]tblobjname[/color] [color=MAROON]"block"[/color] blk)))) '([color=MAROON]"AcDbBlockRepBTag"[/color]) ) ) ) ) ([color=BLUE]setq[/color] rep ([color=BLUE]handent[/color] ([color=BLUE]cdr[/color] ([color=BLUE]assoc[/color] 1005 rep)))) ) ([color=BLUE]cdr[/color] ([color=BLUE]assoc[/color] 2 ([color=BLUE]entget[/color] rep))) blk ) ) ([color=BLUE]princ[/color]) Edited May 8, 2017 by Lee Mac Code updated to account for dynamic blocks. Quote
Cylis0509 Posted May 7, 2017 Author Posted May 7, 2017 Hey Lee, Thank you so much. Your routine is great. But it still only pulls the outer hyperlink. Not the one nested in the block... any ideas? I can't seem to find anything on this. Thanks for all your help!!! Quote
Lee Mac Posted May 7, 2017 Posted May 7, 2017 It works fine in my testing - please upload a sample drawing. Quote
Cylis0509 Posted May 8, 2017 Author Posted May 8, 2017 Sure no problem, attached. I think I narrowed down where the problem lies... While creating the sample drawing I found that your routine worked, nested or on the outside. So I started looking into what was different. My blocks contain dynamic capabilities. As soon as I added some dynamic capabilities. Your routine no longer worked on nested hyperlinks. I believe this is tied to something I learned recently about dynamic blocks, the block name and the block true name. *U69 vs. HYPIN. Just guessing though. Thank you again. HyperlinkTest.dwg Quote
Grrr Posted May 8, 2017 Posted May 8, 2017 Thats why I don't rely on group code 2, cause of the dynamic block possibility: (if (wcmatch (setq n (cdr (assoc 2 (entget ent)))) "`*U*") (setq n (vla-get-EffectiveName (vlax-ename->vla-object ent))) ) Quote
Lee Mac Posted May 8, 2017 Posted May 8, 2017 As yes, dynamic blocks - I have now updated my above code. Quote
Cylis0509 Posted May 8, 2017 Author Posted May 8, 2017 Thank you Grrr and Lee, i really appreciate it. One last question... I know this goes against what Lee was saying about selection but just for my own edification; if I WERE to use Lee's LM:ssget, how would I incorporate your solutions of effective name into this: (setq ss_dtl (LM:ssget "\nSelect details in order for export or [Fence]: " (list "_:L" (append '((0 . "INSERT")) ((lambda ( / def lst )(while (setq def (tblnext "block" (null def))) (if (= 4 (logand 4 (cdr (assoc 70 def)))) (setq lst (vl-list* "," (cdr (assoc 2 def)) lst)))) (if lst (list '(-4 . "<NOT") (cons 2 (apply 'strcat (cdr lst))) '(-4 . "NOT>"))))) (if (= 1 (getvar 'cvport)) (list (cons 410 (getvar 'ctab))) '((410 . "Model")))))) ) Quote
Grrr Posted May 8, 2017 Posted May 8, 2017 I don't think that you can filter in/out dynamic blocks only with the ssget filter.. Yes you can find which block name definitions are dynamic and include them in the filter, but it won't select the dynamic block references with annonymous names. So I'd iterate over the selection set and remove the xref blocks.. (repeat (setq idx (sslength ss_dtl)) (setq e (ssname ss_dtl (setq idx (1- idx)))) (setq o (vlax-ename->vla-object e)) (and (eq :vlax-true (vla-get-IsXref o)) (ssdel ss_dtl e) ) ) Your question makes me ask Lee: How do/Can you determine if a block definition is dynamic, using vanilla ? Quote
Cylis0509 Posted May 8, 2017 Author Posted May 8, 2017 Grrr, So I would inject/replace were my Repeat is? (defun c:mcdldlf ( / ss_dtl dtl_export dtl_export_open dtl_count dtl_obj dtl_hyp each hyp_txt ) (if (and (setq ss_dtl (LM:ssget "\nSelect details in order for export or [Fence]: " (list "_:L" (append '((0 . "INSERT")) ( (lambda ( / def lst ) (while (setq def (tblnext "block" (null def))) (if (= 4 (logand 4 (cdr (assoc 70 def)))) (setq lst (vl-list* "," (cdr (assoc 2 def)) lst))) ) (if lst (list '(-4 . "<NOT") (cons 2 (apply 'strcat (cdr lst))) '(-4 . "NOT>"))) ) ) (if (= 1 (getvar 'cvport)) (list (cons 410 (getvar 'ctab))) '((410 . "Model"))) ) ) ) ) (setq dtl_export (getfiled "Save Export File" (strcat "Export - "(menucmd "M=$(edtime,$(getvar,date),MO-DD-YYYY)")) "txt" 1)) (setq dtl_export_open (open dtl_export "w")) ) (progn (setq dtl_count 0) (repeat (sslength ss_dtl) (setq dtl_obj (vlax-ename->vla-object (ssname ss_dtl dtl_count))) (setq dtl_hyp (vlax-get-property dtl_obj 'Hyperlinks)) (vlax-for each dtl_hyp (setq hyp_txt (strcat (vla-get-url each))) (write-line hyp_txt dtl_export_open) ) (setq dtl_count (1+ dtl_count)) ) (close dtl_export_open) (princ (strcat "\nA hyperlink from " (itoa dtl_count) " Detail(s) has been exported to a .txt file.")) ) ) (princ) ) (defun LM:ssget ( msg arg / sel ) (princ msg) (setvar 'nomutt 1) (setq sel (vl-catch-all-apply 'ssget arg)) (setvar 'nomutt 0) (if (not (vl-catch-all-error-p sel)) sel) ) Quote
Lee Mac Posted May 8, 2017 Posted May 8, 2017 I don't think that you can filter in/out dynamic blocks only with the ssget filter.. Yes you can find which block name definitions are dynamic and include them in the filter, but it won't select the dynamic block references with annonymous names. Slightly off-topic for this thread, but such a selection filter can be built using the methods I demonstrate here. Your question makes me ask Lee:How do/Can you determine if a block definition is dynamic, using vanilla ? I would test whether the block definition contains dynamic parameters, using the route I suggest in this thread. Quote
Grrr Posted May 8, 2017 Posted May 8, 2017 Thank you, Lee! You've been a huge help for me for the last few days! Quote
Cylis0509 Posted May 11, 2017 Author Posted May 11, 2017 Ok so I have been playing with this for days now and still cant figure it out. I have tried to incorporate Lee's code as posted to merge into what I have with no luck. I have scoured the internet for answers and found nothing. I did find Lee's LM:effectivename and obviously the one he's posted LM:name->effectivename. I am really curious how to do this with the code posted above. I would really like to use an ssget function; preferably Lee's since it's so nice. This would be used for selecting details in a drawing that all have unique names and the end users of this routine would be trained on how to use it; so I am not so worried about windows/crossings. I would love to be able to give the user the ability to use the fence command as other routines we have for details utilize this and the user's are used to it. Any help would be greatly appreciated. Edit: All the suggestion I have tried and the things on the internet will return the effective name but by that point the remainder of the routine sees it as a name string and not a block. Not sure how to do this. I cant use the hyperlink on the outside of the block because on insert into another drawing the hyperlink does not come with the block. I need to use the nested. Quote
Cylis0509 Posted May 11, 2017 Author Posted May 11, 2017 As yes, dynamic blocks - I have now updated my above code. Thank you, is there a way to get the selected block to be highlighted. I envision a user selecting 10-20 details at a time and not having them highlighted could cause confusion. Thanks again. Quote
Lee Mac Posted May 11, 2017 Posted May 11, 2017 I'm afraid I can't justify devoting any more voluntary time to this, but you're more than welcome to contact me through my site and I'll happily develop a program to meet your requirements. Quote
Cylis0509 Posted May 11, 2017 Author Posted May 11, 2017 (edited) I'm afraid I can't justify devoting any more voluntary time to this, but you're more than welcome to contact me through my site and I'll happily develop a program to meet your requirements. Fair enough. I will email you now. Thank you very much! Message Sent. Edited May 11, 2017 by Cylis0509 Quote
Recommended Posts
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.