TheSwamp

Code Red => .NET => Topic started by: T.Willey on August 29, 2006, 01:07:10 PM

Title: If statement, testing if Sub-routine call is true
Post by: T.Willey on August 29, 2006, 01:07:10 PM
How can I call this routine with and If statement?
Code: [Select]
public bool IsMember (string Str, string[] StrList) {
foreach (string str in StrList) {
if (Str == str) {
return true;
}
}
return false;
}
What I'm trying to do is test to see if the block that is currently selected within the code is in a string array.  I am trying to call it like
Code: [Select]
if (IsMember btr.Name, TbList) {
DocEd.WriteMessage ("\n Found [{0}]", btr.Name);
}
I have also tried
Code: [Select]
if ((IsMember btr.Name, TbList) == true) {
DocEd.WriteMessage ("\n Found [{0}]", btr.Name);
}
But that doesn't work either.

In case it matters, I make TbList like
Code: [Select]
string[] TbList = {"3M-BORDER-A", "3M-BORDER-B", "3M-BORDER-C", "3M-BORDER-D", "3M-BORDER-E", "3M-BORDER-E1"};

Any help/pointers is greatly appreciated.  Thanks.
Title: Re: If statement, testing if Sub-routine call is true
Post by: It's Alive! on August 29, 2006, 03:17:12 PM
Hi


I think your if statement might be formated incorrectly.
Code: [Select]
IsMember(btr.Name, TbList)

instead of

Code: [Select]
(IsMember btr.Name, TbList)

Code: [Select]
if (IsMember(btr.Name, TbList))
      {
        DocEd.WriteMessage("\n Found [{0}]", btr.Name);
      }
//
//
//
      if ((IsMember (btr.Name, TbList)) == true)
      {
       DocEd.WriteMessage ("\n Found [{0}]", btr.Name);
      }
Title: Re: If statement, testing if Sub-routine call is true
Post by: T.Willey on August 29, 2006, 03:32:46 PM
THANK YOU!!  It seemed so clear while reading your post, don't know why I didn't try it.  It works.
Title: Re: If statement, testing if Sub-routine call is true
Post by: T.Willey on August 29, 2006, 03:41:12 PM
New problem now.  Now it is saying that AttributeCollection doesn't have an Item method, which is a lie, unless my IDE is wrong.

Can anyone help me here?
Here is the code I'm trying to use, the commented out part works though.
Code: [Select]
if (IsMember (btr.Name, TbList)) {
DocEd.WriteMessage ("\n Found: [\"{0}\"]", btr.Name);
AttributeCollection AttCol = Blk.AttributeCollection;
ObjectId AttObj = AttCol.Item (0);
/*foreach (ObjectId AttObj in AttCol) {
AttributeReference AttRef = (AttributeReference) DbTrans.GetObject (AttObj, OpenMode.ForRead);
DocEd.WriteMessage ("\n  Tag: {0}, Value: {1}", AttRef.Tag, AttRef.TextString);
}*/
}
Title: Re: If statement, testing if Sub-routine call is true
Post by: Kerry on August 29, 2006, 05:01:40 PM
Tim, just a thought as I fly past ..
can you use the IndexOf() method on your array, to save writing your own ...
Title: Re: If statement, testing if Sub-routine call is true
Post by: T.Willey on August 29, 2006, 05:30:20 PM
Tim, just a thought as I fly past ..
can you use the IndexOf() method on your array, to save writing your own ...
I don't know, but in digging I found a way to do it.
Code: [Select]
AttributeReference AttRef = (AttributeReference) DbTrans.GetObject (AttCol[i], OpenMode.ForRead);
Where i = int.

Now I'm working on making the three revision attributes into an array that I can sort, and find the greatest one.  This is my attempt now, but not working so still looking.
Code: [Select]
if (IsMember (btr.Name, TbList)) {
//DocEd.WriteMessage ("\n Found: [\"{0}\"]", btr.Name);
AttributeCollection AttCol = Blk.AttributeCollection;
int[] AttLoc = {0, 6, 17};
string[] Revs;
int cnt = 0;
foreach (int i in AttLoc) {
AttributeReference AttRef = (AttributeReference) DbTrans.GetObject (AttCol[i], OpenMode.ForRead);
Revs[cnt] = AttRef.TextString;
}
}


EDIT: Code cleanup
Title: Re: If statement, testing if Sub-routine call is true
Post by: T.Willey on August 29, 2006, 05:49:24 PM
Here is how I got my attribute values, and put them into an array.
Code: [Select]
if (IsMember (btr.Name, TbList)) {
//DocEd.WriteMessage ("\n Found: [\"{0}\"]", btr.Name);
AttributeCollection AttCol = Blk.AttributeCollection;
/*for (int i = 0; i < AttCol.Count; ++i) {
AttributeReference AttRef = (AttributeReference) DbTrans.GetObject (AttCol[i], OpenMode.ForRead);
DocEd.WriteMessage ("\n Collection number: {0}  |  Tag name: {1}  |  Value: {2}", i.ToString(), AttRef.Tag, AttRef.TextString);
}*/
int[] AttLoc = {0, 6, 12};
string[] Revs = new string[3];
int cnt = 0;
foreach (int i in AttLoc)
AttributeReference AttRef = (AttributeReference) DbTrans.GetObject (AttCol[i], OpenMode.ForRead);
Revs [cnt] = AttRef.TextString;
++cnt;
}
foreach (string s in Revs) {
DocEd.WriteMessage ("\n Revision level: {0}", s);
}
}
With a little prompt to let me know it works.
Quote
Command: testing

 Revision level: O
 Revision level: P
 Revision level: R

I'm so happy now.  :evil:




EDIT: Code Cleanup
Edit: Is that what has been going on.  I will do that next time, sorry.
Title: Re: If statement, testing if Sub-routine call is true
Post by: T.Willey on August 30, 2006, 12:48:31 PM
What is wrong with this one?  If the layer isn't in the drawing it crashes, but it shouldn't, at least I don't think it should.

Thanks in advance.

Code: [Select]
private bool HasLayer (Document Doc, string LayName) {
Database DocDb = Doc.Database;
//LayerTableRecord Ltr;
using (Transaction DbTrans = DocDb.TransactionManager.StartTransaction()) {
LayerTable Lt = (LayerTable) DbTrans.GetObject (DocDb.LayerTableId, OpenMode.ForRead);
ObjectId Obj = Lt [LayName];
//LayerTableRecord Ltr = (LayerTableRecord) DbTrans.GetObject (Lt [LayName], OpenMode.ForRead);
//if (Ltr == null) {
if (Obj.IsNull) {
return false;
}
return true;
}
}
Title: Re: If statement, testing if Sub-routine call is true
Post by: Bobby C. Jones on August 30, 2006, 01:39:38 PM
What is wrong with this one? 

Hey Tim,

Code: [Select]
if Lt.Has(layerName)...
Title: Re: If statement, testing if Sub-routine call is true
Post by: T.Willey on August 30, 2006, 01:45:28 PM
What is wrong with this one? 

Hey Tim,

Code: [Select]
if Lt.Has(layerName)...
OMG!!  So simple!  Thank you so much Bobby!  I didn't even see that option in there.  Works great now.
Title: Re: If statement, testing if Sub-routine call is true
Post by: TonyT on September 01, 2006, 06:58:54 AM
OMG!!  So simple!  Thank you so much Bobby!  I didn't even see that option in there.  Works great now.

I wish it were that simple :-)

See the code I posted in the drag thread, to get the ID
of a block, given its name.  If you look at it, you may have
wondered why I was going through all of that, when I
could have just called Has() or the default indexer?

The reason is because of a problem in the SymbolTable
class, which is that both the default indexer and the Has()
member recognize erased symbol table record entires.

For example, if a given layer was deleted in the current editor
session, Has() will return true given its name. The default
indexer will return it, even though it's erased, and in most
cases, we don't want erased table records to be considered.

Hence, the code in that thread is what I generally use now
for testing for membership of, and accessing a non-erased
symbol table record (although I don't always remember to
use it in publicly posted sample code, mainly cause I'm too
lazy to find it, copy and paste... etc...).

Lately I've switched to a more generic version that works
for any type of symbol table:

Code: [Select]

public static ObjectId GetNonErasedTableRecordId( ObjectId TableId, string Name )
{
   ObjectId id = ObjectId.Null;
   using( Transaction tr = TableId.Database.TransactionManager.StartTransaction() )
   {
      SymbolTable table = (SymbolTable) tr.GetObject( TableId, OpenMode.ForRead );
      if( table.Has( Name ) )
      {
         id = table[Name];
         if( !id.IsErased )
            return id;
         foreach( ObjectId recId in table )
         {
            if( ! recId.IsErased )
            {
               SymbolTableRecord rec = (SymbolTableRecord) tr.GetObject( recId, OpenMode.ForRead );
               if( string.Compare( rec.Name, Name, true ) == 0 )
                  return recId;
            }
         }
      }
   }
   return id;
}


Title: Re: If statement, testing if Sub-routine call is true
Post by: T.Willey on September 01, 2006, 11:08:10 AM
Thanks Tony.  I read that, but that was at the very beginning of 'trying' to learn .Net, so most of the discussion was over my head, but I understand this now.  Thanks again, and I will use this method from now one, since I understand what you are doing here.
Title: Re: If statement, testing if Sub-routine call is true
Post by: mohnston on September 01, 2006, 01:28:51 PM
Tony,
Thanks very much for that valuable piece of information. That's just the kind of thing that can cause a lot of frustration and wasted effort if you don't know what's going on. Kind of like trying to create toolbars in 2007 VBA.
I'll definitely add that one to my new .NET collection.
Title: Re: If statement, testing if Sub-routine call is true
Post by: TonyT on September 02, 2006, 07:01:52 PM
Tony,
Thanks very much for that valuable piece of information. That's just the kind of thing that can cause a lot of frustration and wasted effort if you don't know what's going on. Kind of like trying to create toolbars in 2007 VBA.
I'll definitely add that one to my new .NET collection.

Thanks. I wasn't too happy with any of those solutions since
they involve opening each and every symbol table record to
find the non-erased one.

So, in R17 I decided to take another approach which is much
faster/better. It calls the AcDbSymbolTableRecord::getAt()
function directly from managed code. It also more generally
shows how to P/Invoke a method of an unmanaged native
C++ class from managed code, that can be used to address
many of the 'holes' in the managed API.

See http://www.caddzone.com/DBUtils.cs (http://www.caddzone.com/DBUtils.cs)

Title: Re: If statement, testing if Sub-routine call is true
Post by: Glenn R on February 02, 2007, 01:30:44 AM
Tony, I had occasion to use your implentation today for getAt.

I was setting a linetype on a layer and the linetypetablrecord was erased so the ObjectId was bogus and Acad choked.

Nicely done. Thanks.

Cheers,
Glenn.
Title: Re: If statement, testing if Sub-routine call is true
Post by: sinc on November 30, 2007, 08:05:23 PM
Thought I'd bump this topic, since I discovered this bug, too, and can be sort of nasty.  It's especially bad, since this bug means that some of the sample source code in the Labs provided by Autodesk is wrong.  It TELLS people to use default indexers, and fails to warn that it may return erased entities.

Tony's generic PInvoke solution works great.  Tony, do you mind if I include that in the source code download for the SincpacC3D (http://www.ejsurveying.com/sincpacc3d.htm)?  With attribution to you and a link to your website, of course.