Page 1 of 2 12 LastLast
Results 1 to 10 of 14

Thread: Change attribute based on another attribute? Over multiple instances of the same block?

  1. #1
    Design Visualization Moderator stusic's Avatar
    Join Date
    2004-10
    Location
    Denver, Colorado
    Posts
    1,515
    Login to Give a bone
    0

    Default Change attribute based on another attribute? Over multiple instances of the same block?

    Okay, I've searched around and seen some things that are *kinda* like what I want to do, but can't seem to figure out enough from those examples to put it all together, especially the iteration through the blocks.

    I need to run SQL queries based on the page number of wiring diagrams (each page contains different information). There is a "PAGE_NO" attribute in each border block, with as many as 6 or 8 pages per drawing. What I need is to iterate through the title blocks and run the query for each page, with the PAGE_NO attribute value being applied to it's particular query string. Once that's done, I'll need to update the REV attribute based on the results of the query.

    I think I need to:

    1. Create a list of the relevant blocks in the drawing.

    Code:
    (if (setq ss (ssget "_X"
                  (list (cons 0 "INSERT")
                    (cons 2 "*BORDER*")
                    (cons 66 1)
                  )
               )
          )
    (OTHER CODE HERE)
        (princ "\n<!> No Block Found <!>")
      )
    2. Dig down into each one and get the value of the "PAGE_NO" attribute.
    I don't know how to do this without applying it to the whole list.
    3. Apply the value found to the SQL statement.

    Code:
    (setq wdpg1 (strcat "SELECT level FROM revisions WHERE (item = '"fld1"') AND (document = 'Wiring Diagram>pg 1')"))
    4. Apply query results to the "REV" attribute.
    I know how to apply the results to a variable, but I don't know how to apply the variable to the REV attribute to the border of that particular PAGE_NO.

    5. Repeat for remaining pages.
    Code:
    (foreach x ... something or another...

    Any guidance would be greatly appreciated.

    Thanks

  2. #2
    Administrator BlackBox's Avatar
    Join Date
    2009-11
    Posts
    5,714
    Login to Give a bone
    0

    Default Re: Change attribute based on another attribute? Over multiple instances of the same block?

    I don't do much with SQL for our requirements, but I believe I already have some source-code that I can tweak for your needs.

    Rather than guessing, would you be willing/able to post a sample drawing that I can test before posting back? If you don't want your drawing made public, you can PM me to email.

    In short, the user is prompted to specify a directory, and then an ObjectDBX wrapper will be used to iterate a valid vl-Directory-Files call for DWGs, and successively iterate each DBX Drawing Document, subsequently iterating each Layout Object for a matching Title Block, if found query the attributes.

    ... Wash, rinse, repeat.

    The only snag I can see that would force this initiative to be less than efficient, is if the Rev Attribute Tag is encountered prior to the Page Attribute Tag... Or do you want the Rev changed regardless? My interpretation was that Rev is only changed based on the result of the Page query, no?

    ** Edit - If the former, then this will (potentially) require iterating the (Title) Block's Attributes twice... For each (Title) Block Object.

    Lastly, you just need to decide how you'd like the output... Perhaps to a temporary CSV file with appropriate column data (i.e., Source Drawing Location, Layout Tab, Page, Current Revision, etc.)?

    HTH
    "How we think determines what we do, and what we do determines what we get."

    Sincpac C3D ~ Autodesk Exchange Apps

    Computer Specs:
    Dell Precision 3660, Core i9-12900K 5.2GHz, 64GB DDR5 RAM, PCIe 4.0 M.2 SSD (RAID 0), 16GB NVIDIA RTX A4000

  3. #3
    Design Visualization Moderator stusic's Avatar
    Join Date
    2004-10
    Location
    Denver, Colorado
    Posts
    1,515
    Login to Give a bone
    0

    Default Re: Change attribute based on another attribute? Over multiple instances of the same block?

    Sorry Renderman, I neglected to say I've already got the communication with the sql server established. I just need help in gathering the information from the blocks to build my query statement.

    Code:
    (strcat "SELECT level FROM revisions WHERE (item = '"fld1"') AND (document = 'Wiring Diagram>pg 1')")
    This is the statement I need to build from my title blocks. There may be as may as 10 pages per dwg (a mixed bag between modelspace and paperspace, if it makes a difference), so I need to be able to go through each one, read it's PAGE_NO value, modify the above statement (in red), send the query and apply the resulting variable (from the ADOLisp thread, thanks again) back into the same block. I don't know how to run through the blocks, do something, do something else, then move on to the next block. And there may be a faster/better way to do it than the way I'm approaching it. I think the things I'm missing from my method is the way to iterate through a selection of blocks one by one, and a way to read and write attribute values. I didn't know if there was a way I could just define the statement and the resulting variable once, then just update them for each block.

    I'm going to fiddle with it a bit more tomorrow and see what I can figure out, but as always, any direction would be great. I've attached an example if you want to play.

    Thanks
    Attached Files Attached Files

  4. #4
    Administrator BlackBox's Avatar
    Join Date
    2009-11
    Posts
    5,714
    Login to Give a bone
    0

    Default Re: Change attribute based on another attribute? Over multiple instances of the same block?

    I haven't looked at the drawing yet, but as you've already identified the attributes involved, iterating the Blocks and Getting, and Putting their TextString Property is the easy part. Since you're wanting to process a directory of drawings in one go, my thought was to use ObjectDBX which does not support Selection Sets. Instead we will be iterating the Block Object for each Layout Object, in each DBX Document Object (sounds more confusing than it really is).
    "How we think determines what we do, and what we do determines what we get."

    Sincpac C3D ~ Autodesk Exchange Apps

    Computer Specs:
    Dell Precision 3660, Core i9-12900K 5.2GHz, 64GB DDR5 RAM, PCIe 4.0 M.2 SSD (RAID 0), 16GB NVIDIA RTX A4000

  5. #5
    Design Visualization Moderator stusic's Avatar
    Join Date
    2004-10
    Location
    Denver, Colorado
    Posts
    1,515
    Login to Give a bone
    0

    Default Re: Change attribute based on another attribute? Over multiple instances of the same block?

    I don't need to process an entire directory, just the open/active drawing. The multiple title blocks are all in one dwg file... but I am glad to hear that the stuff I can't figure out is the easy part.

  6. #6
    Administrator BlackBox's Avatar
    Join Date
    2009-11
    Posts
    5,714
    Login to Give a bone
    0

    Default Re: Change attribute based on another attribute? Over multiple instances of the same block?

    This worked well with the drawing you provided, even after copying all four 'Title Blocks' to each tab (including Model Space; 12 total).

    Since I do not have your database, nor ADOLisp query code, I simply used a list of grouped pairs to represent the query results... Associating the PAGE_NO value with the REV value:

    Code:
    (defun c:FOO (/ *error* adoResults ss pageNo data)
    
      (defun *error* (msg)
        (if (and ss (= 'VLA-OBJECT (type ss)))
          (vla-delete ss)
        )
        (if acDoc
          (vla-endundomark acDoc)
        )
        (cond ((not msg))                                                   ; Normal exit
              ((member msg '("Function cancelled" "quit / exit abort")))    ; <esc> or (quit)
              ((princ (strcat "\n** Error: " msg " ** ")))                  ; Fatal error, display it
        )
        (princ)
      )
    
      ;; Represents the dataset for the ADOLisp results for each pageNo
      (setq adoResults '((1 . "6") (2 . "10") (3 . "5") (4 . "7")))
    
      ;; Main code
      (if (setq
            ss (ssget "_x" '((0 . "INSERT") (2 . "TITLE_BLOCK") (66 . 1)))
          )
        (progn
    
          ;; Get page_no attribute values from blocks
          (vlax-for x (setq ss (setq acDoc
                                      (vla-get-activeselectionset
                                        (vla-get-activedocument
                                          (vlax-get-acad-object)
                                        )
                                      )
                               )
                      )
            (foreach att (vlax-invoke x 'getattributes)
              (if (= "PAGE_NO" (vla-get-tagstring att))
                (progn
                  (setq pageNo (atoi (vla-get-textstring att)))
                  (setq data (cons (cons x pageNo) data))
                )
              )
            )
          )
    
          ;; Put revision attribute values into blocks
          (foreach item data
            (foreach att (vlax-invoke (car item) 'getattributes)
              (if (= "REV" (vla-get-tagstring att))
                (vla-put-textstring
                  att
                  
                  ;; This is a pseudo ADO query
                  (cdr (assoc (cdr item) adoResults))
                )
              )
            )
          )
          (*error* nil)
        )
      )
    )
    "How we think determines what we do, and what we do determines what we get."

    Sincpac C3D ~ Autodesk Exchange Apps

    Computer Specs:
    Dell Precision 3660, Core i9-12900K 5.2GHz, 64GB DDR5 RAM, PCIe 4.0 M.2 SSD (RAID 0), 16GB NVIDIA RTX A4000

  7. #7
    Design Visualization Moderator stusic's Avatar
    Join Date
    2004-10
    Location
    Denver, Colorado
    Posts
    1,515
    Login to Give a bone
    0

    Default Re: Change attribute based on another attribute? Over multiple instances of the same block?

    I'm not great at Vlisp, but I understand most of it. The one part I really don't get is the use of the "data" variable in the foreach statements. Can you expand a little on how that works? I can't figure out how to query the sql server to get a list of the latest revs for all the drawings, so I'd like to try to embed each query inside the code by using the SSLENGTH function and wrapping the following code in a REPEAT function, repeating as many times as the value of SSLENGTH. Would this work?

    Code:
    (setq ssl (sslength ss)
    (setq cntr 1)
    (while (< cntr ss)
    (foreach att (vlax-invoke x 'getattributes)
              (if (= "PAGE_NO" (vla-get-tagstring att))
                (progn
                  (setq pageNo (atoi (vla-get-textstring att)))
                  (setq data (cons (cons x pageNo) data))
    
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;; somewhere in here, add the SQL statement:
    (setq fld2 (strcat "SELECT level FROM revisions WHERE (item = '"fld1"') AND (document = 'Wiring Diagram>pg "pageNo"') ORDER BY level DESC"))
    
    
          (setq
    	SQL2 fld2
          )
          (if (setq result2 (car (cdr (ADOLISP_DoSQL ConnectionObject SQL2))))
            (progn
              (setq str2 (vl-string-trim "()" (vl-princ-to-string result2)))
              (print str2)
    ;; result2 is the variable that holds the page number result from the server, str2 is after i cut out all the unnecessary stuff
            )
            (progn
              (prompt "\nFailed!")
              (ADOLISP_ErrorPrinter)
            )
          )
                )
              )
            )
          )
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    
          ;; Put revision attribute values into blocks
          (foreach item data
            (foreach att (vlax-invoke (car item) 'getattributes)
              (if (= "REV" (vla-get-tagstring att))
                (vla-put-textstring
                  str2
                  
                  ;; This is a pseudo ADO query
                  (cdr (assoc (cdr item) adoResults))
                )
              )
            )
          )
    
    (setq cntr(+ cntr 1))
    
            )
    Once you get done laughing, let me know what you think

    Thanks for your help

  8. #8
    Administrator BlackBox's Avatar
    Join Date
    2009-11
    Posts
    5,714
    Login to Give a bone
    0

    Default Re: Change attribute based on another attribute? Over multiple instances of the same block?

    Quote Originally Posted by stusic View Post
    The one part I really don't get is the use of the "data" variable in the foreach statements. Can you expand a little on how that works?
    The Data variable in my offering is a list of grouped pairs, where the each list item, is a grouped pair, where the first element is the vla-Object for a "TITLE_BLOCK", and the second element is the "PAGE_NO" TextString Property (i.e., the value for which you're wanting to look up using ADO).

    We could instead simply iterate the vla-Object stored within the SS variable, as an alternative to the Foreach call on the Data (List) variable. The latter, the option I used, simply saves the step of iterating the SS Object again, and goes straight to the Data list, iterating it's (the TITLE_BLOCK Object's) Attributes, then querying the REV value, given the PAGE_NO value (the second element of the Item variable), thus populating the REV Attribute Object's TextString Property with the value returned from the query.

    Giving this another look, I should probably account for a Nill value from the query, using vl-catch-all-apply... But still.

    Quote Originally Posted by stusic View Post
    I can't figure out how to query the sql server to get a list of the latest revs for all the drawings
    ... Simply feed the second element of the Item variable (the PAGE_NO TextString Property, as String) to your query expression (converting from string to any data type you need, if necessary)... Then supply the returned, non-Nill value from your query to the TextString Property of the REV Attirbute Object's TextString Property. Lemon squeezy.
    "How we think determines what we do, and what we do determines what we get."

    Sincpac C3D ~ Autodesk Exchange Apps

    Computer Specs:
    Dell Precision 3660, Core i9-12900K 5.2GHz, 64GB DDR5 RAM, PCIe 4.0 M.2 SSD (RAID 0), 16GB NVIDIA RTX A4000

  9. #9
    Design Visualization Moderator stusic's Avatar
    Join Date
    2004-10
    Location
    Denver, Colorado
    Posts
    1,515
    Login to Give a bone
    0

    Default Re: Change attribute based on another attribute? Over multiple instances of the same block?

    Quote Originally Posted by RenderMan View Post
    The Data variable in my offering is a list of grouped pairs, where the each list item, is a grouped pair, where the first element is the vla-Object for a "TITLE_BLOCK", and the second element is the "PAGE_NO" TextString Property (i.e., the value for which you're wanting to look up using ADO).

    We could instead simply iterate the vla-Object stored within the SS variable, as an alternative to the Foreach call on the Data (List) variable. The latter, the option I used, simply saves the step of iterating the SS Object again, and goes straight to the Data list, iterating it's (the TITLE_BLOCK Object's) Attributes, then querying the REV value, given the PAGE_NO value (the second element of the Item variable), thus populating the REV Attribute Object's TextString Property with the value returned from the query.
    Haha, you totally lost me. It's Friday, after a long week - I'm going to look at this again in the morning over a cup of coffee on the back porch.

  10. #10
    Administrator BlackBox's Avatar
    Join Date
    2009-11
    Posts
    5,714
    Login to Give a bone
    0

    Default Re: Change attribute based on another attribute? Over multiple instances of the same block?

    Here's another try, using the code you posted here to pull the ADO calls you show... Note there are several comments used as place holders for where additional calls are needed (i.e., to ConnectionObject, fld1, etc.) that must be added for this code to actually work.

    No need for the vl-Catch-All-Apply block, as we're using an IF statement here to test for a valid AdoValue:

    Code:
    (defun c:FOO (/ *error* adoResults ss ConnectionObject pageNo data fld1
                  fld2 adoValue
                 )
    
      (defun *error* (msg)
        (if (and ss (= 'VLA-OBJECT (type ss)))
          (vla-delete ss)
        )
        ;; <-- Release ConnectionObject here?
        (if acDoc
          (vla-endundomark acDoc)
        )
        (cond ((not msg))                                                   ; Normal exit
              ((member msg '("Function cancelled" "quit / exit abort")))    ; <esc> or (quit)
              ((princ (strcat "\n** Error: " msg " ** ")))                  ; Fatal error, display it
        )
        (princ)
      )
    
      ;; Main code
      (if
        (and
          (setq
            ss (ssget "_x" '((0 . "INSERT") (2 . "TITLE_BLOCK") (66 . 1)))
          )
          ;; <-- Set ConnectionObject here
        )
         (progn
    
           ;; Get page_no attribute values from blocks
           (vlax-for x (setq ss (setq acDoc
                                       (vla-get-activeselectionset
                                         (vla-get-activedocument
                                           (vlax-get-acad-object)
                                         )
                                       )
                                )
                       )
             (foreach att (vlax-invoke x 'getattributes)
               (if (= "PAGE_NO" (vla-get-tagstring att))
                 (progn
                   (setq pageNo (atoi (vla-get-textstring att)))
                   (setq data (cons (cons x pageNo) data))
                 )
               )
             )
           )
    
           ;; Put revision attribute values into blocks
           (foreach item data
    
             ;; Not sure where to set fld1?
    
             (setq fld2 (strcat
                          "SELECT level FROM revisions WHERE (item = '"
                          fld1
                          "') AND (document = 'Wiring Diagram>pg "
                          (cdr item)
                          "') ORDER BY level DESC"
                        )
             )
             (if (setq adoValue (caadr (ADOLISP_DoSQL ConnectionObject fld2)))
               (foreach att (vlax-invoke (car item) 'getattributes)
                 (if (= "REV" (vla-get-tagstring att))
                   (vla-put-textstring att adoValue)
                 )
               )
             )
           )
           (*error* nil)
         )
      )
    )
    HTH
    "How we think determines what we do, and what we do determines what we get."

    Sincpac C3D ~ Autodesk Exchange Apps

    Computer Specs:
    Dell Precision 3660, Core i9-12900K 5.2GHz, 64GB DDR5 RAM, PCIe 4.0 M.2 SSD (RAID 0), 16GB NVIDIA RTX A4000

Page 1 of 2 12 LastLast

Similar Threads

  1. How to change dynamic block attribute default values based on block selected?
    By zeirz109180 in forum Dynamic Blocks - Technical
    Replies: 2
    Last Post: 2013-12-13, 02:20 PM
  2. Change the layer of a block using the attribute value
    By lee.harte.166277 in forum AutoLISP
    Replies: 0
    Last Post: 2012-09-20, 09:51 AM
  3. Block attribute change within a table...
    By seneb in forum AutoCAD General
    Replies: 2
    Last Post: 2009-01-29, 07:45 PM
  4. Change multiple instances of a block into xref?
    By n1659 in forum AutoCAD General
    Replies: 1
    Last Post: 2007-02-03, 01:20 AM
  5. Replies: 27
    Last Post: 2006-10-06, 01:04 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •