Author Topic: Same Item Appears in Job.Items Multiple Times  (Read 2253 times)

0 Members and 1 Guest are viewing this topic.

Offline jaysomlamTopic starter

  • Senior Member
  • ****
  • Posts: 453
  • Country: us
  • Gender: Male
Same Item Appears in Job.Items Multiple Times
« on: Jan 15, 2021, 20:42:22 PM »
I have found cases where the same item appears in Job.Items 2 to 3 times.  In Job.Items, they show up in multiple entries.  But the properties of the items are exactly the same -- down to Item.Handle, and Item.UniqueId.  I believe they are pointing to the same duct item instead of multiple duct items.

This is like the index in the lobby of a high rise apartment building.  The index shows the persons living in which floor.  The index may show two Mr. Smith living in the building; one is living in 10th floor, and another one is living in 13rd floor.  In reality, the building doesn't have 13rd floor, and there is only one Mr. Smith living in the building.  This is like the problem that I have in Job.Items.

Seem like the problem is related to copying duct items from the main part of the drawing to the side of the drawing.  Not very sure.

I have tried PURGE command.  But this doesn't fix the problem.

I am wondering if there is a way to repair Job.Items in order to remove the phantom entries.  If not, if there is a way to tell if two items in Job.Items are actually pointing to the same item.

Jaysom

Offline jaysomlamTopic starter

  • Senior Member
  • ****
  • Posts: 453
  • Country: us
  • Gender: Male
Re: Same Item Appears in Job.Items Multiple Times
« Reply #1 on: Jan 18, 2021, 14:36:25 PM »
I dig a bit deeper into this problem.  And I have this finding:

In the case of duplicated entries in Job.Items mentioned in my question, the item entries in Job.Items can have the same Item.Handle.  Moreover, their Item.UniqueId are also the same.

On the other hand, if a drawing really has two _different_ duct items having the same Item.Handle, their Item.UniqueId are different.

Therefore, by checking the Item.UniqueId, I can tell if I am in the "duplicated entries in Job.Items" situation.  Then I can use this way to workaround this problem.

Having said this, this would be nice if there is a way to remove the duplicated entry from Job.Items -- without deleting them and redrawing them from scratch.

I consider this question as solved.

Jaysom
« Last Edit: Jan 18, 2021, 14:38:27 PM by jaysomlam »

Offline edsharp

  • Full Member
  • ***
  • Posts: 241
  • Country: us
  • Gender: Male
Re: Same Item Appears in Job.Items Multiple Times
« Reply #2 on: Jan 19, 2021, 13:04:02 PM »
Howdee

 just spitballing did you run  OVERKILL command ... it looks for identical objects in the same location this might not be what your looking for but its always a fun one to run

Offline jaysomlamTopic starter

  • Senior Member
  • ****
  • Posts: 453
  • Country: us
  • Gender: Male
Re: Same Item Appears in Job.Items Multiple Times
« Reply #3 on: Jan 21, 2021, 19:49:41 PM »
This is not it.  The OVERKILL command looks for items that are actually on the drawing.  The issue that I mentioned in this post is about multiple entries in Job.Items that point to the exact same item.  There is actually only one item on the drawing; but Job.Items list has multiple entries (two entries so far) about the same item.  In other words, one of the two entry is extra.

I have worked around the problem by not only checking Item.Handle, but also checking Item.UniqueId:

If two entries have the same Item.Handle but different Item.UniqueId, this means they are two different items; but somehow they are assigned the same Item.Handle.  In this case, I ask the draftsman to remove one of them and redraw it.  This works around this specific problem.  I have no idea how this problem can happen.  But this indeed happened.  Seem like CADmep may have lost track of the counter at some point.

On the other hand, if two entries have the same Item.Handle, _and_ the same Item.UniqueId, this means I am in the situation mentioned above (two entries in Job.Items pointing to the same item).  In this case, there is not much that I can do, and I just simply ignore one of the entry.  I have no idea how this problem can happen.  I have a feeling that this is related to someone copied-and-pasted the items around the drawing, or moving the items.

Jaysom

Offline DotNet

  • Senior Member
  • ****
  • Posts: 302
  • Country: us
  • Gender: Male
    • MICLOGIC
Re: Same Item Appears in Job.Items Multiple Times
« Reply #4 on: Jan 21, 2021, 20:44:20 PM »
It's a bug in the API specific to AutoCAD. Fairly certain this does not happen on the CAM/EST side. Iterating Job.Items is inconsistent in CADmep. A workaround is to iterate modelspace and pull the items out that way.
« Last Edit: Jan 21, 2021, 20:50:55 PM by DotNet »

Offline cadbob

  • Premier Member
  • *****
  • Posts: 2884
  • Country: us
  • Gender: Male
    • SMWIA Local 17
Re: Same Item Appears in Job.Items Multiple Times
« Reply #5 on: Jan 22, 2021, 11:59:35 AM »
Shot in the dark here see if SETQTYONE or UPDATEALLMAPTABLES works for the multiple items

When someone asks where you see yourself in 5 years... Buddy, I'm just trying to make it to Friday. :)

Offline jaysomlamTopic starter

  • Senior Member
  • ****
  • Posts: 453
  • Country: us
  • Gender: Male
Re: Same Item Appears in Job.Items Multiple Times
« Reply #6 on: Jan 22, 2021, 14:21:23 PM »
Thanks DotNet to confirm that I am not only one who has this "phantom items" problem.

Jaysom

Offline jaysomlamTopic starter

  • Senior Member
  • ****
  • Posts: 453
  • Country: us
  • Gender: Male
Re: Same Item Appears in Job.Items Multiple Times
« Reply #7 on: Jan 22, 2021, 16:13:29 PM »
Hello cadbob.  I have tried both SETQTYONE and UPDATEALLMAPTABLES commands.  I don't see anything changed.  May be I don't know how to use these two commands.

May be someone can try those 2 commands using my test drawing to see if those commands may work.  I have attached the test drawing that has this problem.

Any one interested can use the following C# routines to demonstrate the problem.

Code: [Select]
[CommandMethod("JayTest_FindDupHandleNotChkUniqueId")]
public void FindDupHandleNotChkUniqueId()
   // Find duct items in the drawing that have duplicated Item.Handle.
   // Here, we don't check Item.UniqueId.
   {
   Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;

   // Construct a list of Item.Handle of duct items on the drawing.
   List<int> lisHandle = new List<int>();
   foreach( Item itm in Job.Items )
      {
      lisHandle.Add( (int)itm.Handle );
      }

   // Sort the list of Item.Handle.
   lisHandle.Sort();

   // Find duplicated Item.Handle in the list.

   int nPrevHandle        = -1;
   int nCurDupHandleCount = 0;   // 0   - Not dealing with dup handle.
                                 // > 0 - Dealing with a dup handle.

   foreach( int nCurrHandle in lisHandle )
      {
      // Take care of the special case when we are in the first entry.
      if ( nPrevHandle == -1 )
         {
         nPrevHandle = nCurrHandle;  // No need to check.
         continue;
         }

      // Here, we know that we are after the first entry.
      if ( nPrevHandle == nCurrHandle )
         {
         if ( nCurDupHandleCount == 0 )
            nCurDupHandleCount = 2;    // 2 items have the same handle.
         else
            nCurDupHandleCount++;
         }
      else
         // Current handle is different from the handle in previous entry.
         {
         // Show the info about the duplicated handle (if any) that we
         // are dealing with before we reach the current one.
         if ( nCurDupHandleCount > 0 )
            {
            String sMsg = "\nError: " + nCurDupHandleCount.ToString() +
                          " items have the same Item.Handle " +
                          nPrevHandle.ToString();
            doc.Editor.WriteMessage( sMsg );

            nCurDupHandleCount = 0;
            }

         // No duplicated. Get ready to check next one.
         nPrevHandle = nCurrHandle;
         }
      } // foreach()

   // Show the info about the duplicated handle (if any) that we are
   // dealing with before we reach the current one. This means the last
   // handle in the list is a duplicated handle.
   if ( nCurDupHandleCount > 0 )
      {
      String sMsg = "\nError: " + nCurDupHandleCount.ToString() +
                    " items have the same Item.Handle " +
                    nPrevHandle.ToString();
      doc.Editor.WriteMessage( sMsg );

      nCurDupHandleCount = 0;
      }
   } // FindDupHandleNotChkUniqueId()

This C# routine (the JayTest_FindDupHandleNotChkUniqueId command) looks for items that have duplicated Item.Handle that may or may not have the exact same Item.UniqueId.  When I run this routine in the test drawing, I see this result:

Quote
Error: 2 items have the same Item.Handle 9361
Error: 3 items have the same Item.Handle 9371
Error: 2 items have the same Item.Handle 9386
Error: 2 items have the same Item.Handle 9413

We can use the following routines to select the items that have the Item.Handle found above:

Code: [Select]
[CommandMethod("JayTest_SelectDuctByHandle")]
public void SelectDuctByHandle()
   // Select duct by their Item.Handle. This program first asks the
   // user to enter a Item.Handle. Then this program will select the
   // items that have the specified Item.Handle.
   {
   Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
   Editor   ed  = doc.Editor;
   Autodesk.AutoCAD.DatabaseServices.Database db = doc.Database;

   // Prompt the user for an Item.Handle.
   String sHandleFromUser = this.sPromptUserForHandle();
   if ( sHandleFromUser.Length == 0 )
      return;

   // Select the items that have the specified Item.Handle.

   List<ObjectId> lisSelectObjId = new List<ObjectId>();

   foreach( Item itm in Job.Items )
      {
      // Save the ObjectId of the current item to the list if the
      // current item has the specified Item.Handle.
      String sCurItemHandle = ( (int)itm.Handle ).ToString();
      if ( sHandleFromUser.Equals( sCurItemHandle ) )
         {
         String sCurAcadHandle = Job.GetACADHandleFromItem( itm );
         if ( ! String.IsNullOrEmpty( sCurAcadHandle ) )
            {
            // Change the handle from a string into a 64-bit long integer.
            long lCurAcadHandle = Convert.ToInt64( sCurAcadHandle, 16 );

            // Convert the 64-bit long integer into a handle.
            Handle hCurItem = new Handle( lCurAcadHandle );

            // Get an ObjectId from the handle.
            // Note: false to indicate that we don't want to create a
            //       new object if there is no existing object that has
            //       the specified handle.
            // Note: 0 is placed there for future use by Autodesk.
            ObjectId idCurItemObj = db.GetObjectId( false, hCurItem, 0 );

            // Save the ObjectId of the current item to the list.
            lisSelectObjId.Add( idCurItemObj );
            }
         }
      } // foreach

   Autodesk.AutoCAD.Internal.Utils.SelectObjects( lisSelectObjId.ToArray() );
   } // SelectDuctByHandle()

private String sPromptUserForHandle()
   // Ask the user to enter an Item.Handle.
   {
   Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
   Editor   ed  = doc.Editor;

   // Get the Item.Handle from the user. Repeat until the user has
   // entered an valid Item.Handle or has decided not to enter any more.

   String sHandleFromUser = "";

   PromptStringOptions optPromptHandle = new PromptStringOptions( "\nEnter an Item.Handle: " );
   optPromptHandle.AllowSpaces = false;

   do {
      PromptResult resPromptHandle = ed.GetString( optPromptHandle );
      if ( resPromptHandle.Status != PromptStatus.OK )
         return( "" );           // The user decides not to enter. OK.

      sHandleFromUser = resPromptHandle.StringResult.Trim().ToUpper();
      if ( sHandleFromUser.Length == 0 )
         return( "" );           // The user decides not to enter. OK.

      // Make sure the Item.Handle is all numeric.
      // ...skipped...
      } while( sHandleFromUser.Length == 0 );

   // Return the Item.Handle to the calling program.
   return( sHandleFromUser );
   }

When I try this to select items with Item.Handle 6371 using my test drawing, I find that actually only one item is selected.  This seems to me that there is only one item with Item.Handle 6371 on the drawing.  But Item.Handle 6371 appears 3 times in Job.Items.

Jaysom

Offline DotNet

  • Senior Member
  • ****
  • Posts: 302
  • Country: us
  • Gender: Male
    • MICLOGIC
Re: Same Item Appears in Job.Items Multiple Times
« Reply #8 on: Jan 22, 2021, 17:01:35 PM »
When I try this to select items with Item.Handle 6371 using my test drawing, I find that actually only one item is selected.  This seems to me that there is only one item with Item.Handle 6371 on the drawing.  But Item.Handle 6371 appears 3 times in Job.Items.

This is consistent with the Job.Items CADmep bug. It has not worked properly since the Fabrication API was released. Without multiple sources reporting the same thing (or personally debugging the code), it is easy to pass us off as crazy :o. I'm linking a Fabrication API AU class from several years ago by Tim Catalano and Jubel Beren. They also mention this in one of their slides.

Fabrication API AU Class

There is a workaround, but it requires us to iterate ModelSpace and pull the Items out manually.

Iterating ModelSpace

Once this code is in place we can check the ObjectClass property of the ObjectIds to see if they belong to Fabrication Items:

Code: [Select]
        public static bool IsFabItem(ObjectId OID)
        {
            return OID.ObjectClass.Name == "MapsContainer";
        }

If the ObjectId belongs to a Fabrication Item we can then get a reference to the Item like this:

Code: [Select]
        public static Item GetItemFromObjectID(ObjectId OID)
        {
            return Job.GetFabricationItemFromACADHandle(OID.Handle.ToString());
        }

« Last Edit: Jan 22, 2021, 17:58:36 PM by DotNet »

Offline jaysomlamTopic starter

  • Senior Member
  • ****
  • Posts: 453
  • Country: us
  • Gender: Male
Re: Same Item Appears in Job.Items Multiple Times
« Reply #9 on: Jan 25, 2021, 15:14:03 PM »
Sorry for the bad news.  Seem like the solution is not to use Job.Items.  That is a tough pill to swallow.  I will have to continue using my workaround (check Item.UniqueId) to avoid this problem in a "as needed" basis.  I will keep your solution in mind if things get out of control.

Thanks.

Jaysom

Offline jaysomlamTopic starter

  • Senior Member
  • ****
  • Posts: 453
  • Country: us
  • Gender: Male
Re: Same Item Appears in Job.Items Multiple Times
« Reply #10 on: Jan 26, 2021, 14:11:10 PM »
I take this back.  My workaround doesn't always work.  My workaround won't work if the drawing has external references.  Seem like Job.Items contains the items in the external reference in addition to the items in the main drawing.  This messes up everything.  In this situation, many items in the external reference have the same Item.Handle as the items in the main drawing, but they have different Item.UniqueId.  Therefore, my workaround cannot tell if the drawing has items that have duplicated Item.Handle or not.

The bottom line is that I cannot depend on Job.Items.  I will have to try what DotNet has suggested and iterate the objects in the Model Space to look for Fabrication items.  Oh well...

Jaysom

Offline jaysomlamTopic starter

  • Senior Member
  • ****
  • Posts: 453
  • Country: us
  • Gender: Male
Re: Same Item Appears in Job.Items Multiple Times
« Reply #11 on: Jan 26, 2021, 19:44:34 PM »
Thanks the sample codes that DotNet has shared.  I use them to iterate the objects in Model Space and they work great!

Now, I can use this method to look for "real" Fabrication items instead of using Job.Items.  This avoids these two problems:

(1)  The phantom entries that can show up in Job.Items (duplicated entries that point to the same item).  This problem was the original reason why I posted this request.

(2)  Items that are in external references loaded with the drawing.

Now, I just need to use the same approach in many parts of my program.  I will have to "replace each as we go" instead of doing this in whole-sale fashion.

Jaysom