Kean Walmsley

July 2009

Sun Mon Tue Wed Thu Fri Sat
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  

Twitter Updates

    follow me on Twitter



    « Updating a specific attribute inside an AutoCAD drawing using .NET | Main | YASA (Yet Another Simpsons Avatar) »

    July 25, 2007

    TrackBack

    TrackBack URL for this entry:
    http://www.typepad.com/services/trackback/6a00d83452464869e200e3932f72658834

    Listed below are links to weblogs that reference Updating a specific attribute inside a folder of AutoCAD drawings using .NET:

    Comments

    Kean,

    In VBA, autocad object document has "name" and "path" property, but in Autocad.Net, I only find "name" but not "path" for document,(Application.DocumentManager.MdiActiveDocument.Name)is that true? I also searched autodesk forum, but did not find an anwser.

    If that's true, is there any other way to get the path of current activated drawing?

    Thanks.

    Kean,
    Your example was great, but was not what I was hoping for. I need to be able to display a userform and be able to select a group of drawing files, perhaps from different locations and execute different routines in each one of them. What has me stuck is the "Execution Context". I know this is not a personal answering service, but if you ever write something that will show how to do this, I will very thankful.

    Yes - this is not a complete solution for someone wanting to run an arbitrary command against a list of files/folders. This isn't necessarily hard to build, but in any case there are out-of-the-box solutions you can use for just this - take a look at ScriptPro, for instance.

    My posts are more about helping people develop code to solve their own specific development issues, not providing a generic tool to solve them all myself.

    Regards,

    Kean

    Limin,

    The Name property on the Document object exposes AcApDocument::fileName(), which contains both the filename and the path:

    "Returns the full path and file name of the database being used by this AcApDocument."

    Kean

    Kean,
    funny enough, I did something nearly identical to this not more than about a couple weeks ago. I tried to incorporate the progress meter as you illustrated a while ago, and found that the (if I recall correctly) db.SaveAs() method seems to put its progress on the progress meter, and when the save is complete, my progress meter does not return. So, i get a meter in place for the first drawing processed, and then it just reverts to the default. Any insight on a way to maintain the progress meter through the entire process?

    Thanks. Kean.

    And I found for a drawing not saved yet, it only returns drawing name not path name, (even at that time it has a temparary file path). but for drawing that is saved, it returns both file name and path.

    Kean,
    I appreciate your response, but what I was look for is for something that AutoCAD users have been able to do since ever and it is being able to customized the application to suit our requirements. I have been able to create customizations that make our daily work much efficient. With the new .NET managed classes, the potential to create more sophisticated solutions has greatly expanded. Right now all our customizations (none of them commercially available) have been developed in LISP and VBA, both of which have been great in their times, excellent resources. I work for the precast industry and most of our jobs generate lots of drawings, hence the need to process batch of drawings. If I am not able to find a way of opening a list of drawings from a user form and solve the “Execution Context” problem, my future in .NET managed classes is dead. There is no information on the topic or I have been not able to find it.

    HJohn,

    I'd suggest submitting your question - with sample code to reproduce - via the ADN website, if you're a member, or otherwise posting it to the .NET Customization Discussion Group.

    Assuming you're talking about processing a number of open documents - which this post does not - then you will need to be careful. ObjectARX and .NET are inherently document-centric, unless you work to make sure they are working in the session/application context. There are various places you could be falling over - I now see you've posted to the discussion group, but haven't provided code. Unless you provide a minimal sample showing the problem you're having, it's hard for people to determine exactly where your problem is occurring.

    Regards,

    Kean

    M Schumacher,

    Yes - I see the problem. It also occurs if your drawing requires Autodesk Shape Manager to be loaded (the message "Loading Modeler DLLs" clears the progress meter in this case).

    The only way I can see around it would be to display your own dialog - it could be located wherever you like - with a progress meter to demonstrate overall progress through the operation.

    It would clearly have been nice to have used AutoCAD's, but this isn't really an option in this case, it seems.

    Regards,

    Kean

    Kean, thank you for your example. It demonstrates the idea very well.
    For the future:
    You mentioned "context" many times, will you give a review of them, their limitations, peculiarities, obligatory switching between them etc.? Now I know 3 contexts: application, document and (new) object.

    Hi Nikolay,

    Only two of these "contexts" are related: document and session/application. This previous post covers these fairly well (I hope).

    Object contexts are a separate concept and are currently only used for the annotation scaling feature. They're unrelated to the application execution contexts mentioned above.

    Then, of course, there are context menus, which are unrelated to both these areas. :-)

    Regards,

    Kean

    Kean,
    Thanks for pointing me to this great article! It really gave me what I needed. Is there any docmentation on the the BlockTable properties that are being exposed? I want to iterate thru more than 1 BlockTableRecord.PaperSpace object in each drawing file that I open and read. Is it possible to do that?
    Thanks again,
    John

    John,

    The documentation (such that it is) is currently included in the ObjectARX SDK (which you can download from http://www.autodesk.com/objectarx).

    You can certainly iterate through multiple layouts. Instead of just getting psId, you should be able to use foreach() on the BlockTable, taking each ObjectId and passing it to the UpdateAttributesInBlock() function. If you want to be slightly more efficient, you might want to open the block table record and check its IsLayout property, to skip the block definitions that are not layouts (this property is also true for the modelspace layout).

    Or you could just run the command on every block in the block table, and remove the recursion - that should also work.

    Cheers.

    Kean

    Kean,
    I appreciate your quick response and all these articles. They've been more informative and helpful than any "documentation" I've found so far (including the documentation downloaded with ObjectARX SDK). I'm assuming you're talking about in the UpdateAttributesInDatabase function. How do you type the foreach to iterate thru all ids in the blocktable and pass them into the UpdateAttributesInBlock function? That's giving me the most fits. It seems no matter how I type the variable for the foreach, it gives one error or another in the build.
    Thanks,
    John

    John,

    Try this (it compiles, but I haven't tested it, yet):

    private int UpdateAttributesInDatabase(
      Database db,
      string blockName,
      string attbName,
      string attbValue
    )
    {
      // Get the IDs of the spaces we want to process
      // and simply call a function to process each
    
    

    ObjectIdCollection layoutIds =
    new ObjectIdCollection();

    Transaction tr =
    db.TransactionManager.StartTransaction();
    using (tr)
    {
    BlockTable bt =
    (BlockTable)tr.GetObject(
    db.BlockTableId,
    OpenMode.ForRead
    );
    foreach (ObjectId id in bt)
    {
    BlockTableRecord btr =
    (BlockTableRecord)tr.GetObject(
    id,
    OpenMode.ForRead
    );
    if (btr.IsLayout)
    layoutIds.Add(id);
    }

    // Not needed, but quicker than aborting
    tr.Commit();
    }
    int updateCount = 0;
    foreach (ObjectId id in layoutIds)
    {
    updateCount +=
    UpdateAttributesInBlock(
    db,
    id,
    blockName,
    attbName,
    attbValue
    );
    }
    return updateCount;
    }

    Cheers,

    Kean

    Kean,
    You are the man!! That worked perfectly! Thanks so much for your time, help, and guidance!
    John

    Really interesting post!

    Never stop iterating and don’t fear failure. Choose well-understood conventions where they will do to the most good , shortcuts you might take will cost you more to fix later than to try to get right up-front today.

    Thanks , Zoli Juhasz

    Hi, Kean

    I'm luis again

    I take you code abut "Updating a specific attribute", Now when I to open file updated the attribute is not sichronized, so need to aply command "AttSync" but I can´t. how I do it in code VB, can you give me a tittle example to do it plase.


    Hi Luis,

    Have you tried SendStringToExecute, as in this post?

    Kean

    Yes kean, I tired that, but the problem is because I was opening the file by code:

    Dim doc As Document = Application.DocumentManager.MdiActiveDocument
    Dim ed As Editor = doc.Editor
    Dim db As New Database(False, True)
    Dim cadena As String = ruta
    Dim blk As BlockReference
    Try
    db.ReadDwgFile(cadena, System.IO.FileShare.ReadWrite, False, "")
    Catch ex As Exception
    MsgBox(ex.Message)
    Exit Sub
    End Try

    If I try use "SendStringToExecute" I need a drawing open (activedocumet), I just want to opening his database file but not open the file. I try this:

    Dim doc As Document = Application.DocumentManager.MdiActiveDocument
    Dim ed As Editor = doc.Editor
    Dim db As New Database(True, False)

    Dim cadena As String = RUTA
    Try
    db.ReadDwgFile(cadena, System.IO.FileShare.ReadWrite, False, "")
    Catch ex As Exception
    MsgBox(ex.Message)
    Exit Sub
    End Try
    Dim trn As Transaction = db.TransactionManager.StartTransaction
    Dim bt As BlockTable = trn.GetObject(db.BlockTableId, OpenMode.ForWrite)
    If bt.Has("PIE DE PLANO-" & ID_CLIENTE) Then
    doc.SendStringToExecute("attsync" & Chr(10) & "n" & Chr(10) & "PIE DE PLANO-597" & Chr(13), False, False, False)
    Else
    Exit Sub
    End If
    trn.Commit()
    Try
    db.SaveAs(RUTA, DwgVersion.Current)
    db.Dispose()
    db = Nothing
    Catch ex As Exception
    MsgBox("en archivo esta abierto" & ex.Message)
    ed.WriteMessage(vbCr + "\nError al Actualizar Archivo: " + db.Filename)
    End Try


    But it has an error (Buffertoosmal).How a do this (sichronize the atributtes) just open the database file:

    thank´s a lot kean. but I'm started to programing and a has so much errors.

    hi kean,I was tired but I'canto do this Help me please.

    Hi Luis,

    I'm sorry - I really don't have time to provide individual support (unless there's a problem with one of my posts).

    If you're an ADN member, please post it there - otherwise someone on the AutoCAD .NET Discussion Group may be able to help.

    Kean

    I'm sorry kean it wasn't my intesion. I'm started to programing and the best guide to do is your blog. Every day on the morning or on the bus in cel phone when I go to work I read an new example on you blog (you have many post).

    I hope you help if I will on problems abut someone your post.

    Many thanks for Update 2, that alignment problem plagued me for years in VBA and I'm glad to see there is a workaround on .NET.

    Keep up the good work, your a true hero to those of us learning .NET!

    Verify your Comment

    Previewing your Comment

    This is only a preview. Your comment has not yet been posted.

    Working...
    Your comment could not be posted. Error type:
    Your comment has been posted. Post another comment

    The letters and numbers you entered did not match the image. Please try again.

    As a final step before posting your comment, enter the letters and numbers you see in the image below. This prevents automated programs from posting comments.

    Having trouble reading this image? View an alternate.

    Working...

    Post a comment

    Feed & Share

    Search