Extracting a BoM using the Vault API

Extracting a BoM using the Vault API

waynehelley
Collaborator Collaborator
4,112 Views
7 Replies
Message 1 of 8

Extracting a BoM using the Vault API

waynehelley
Collaborator
Collaborator

Hi all,

 

I would like to export a BoM from Vault using the API.

 

Initially I found the function 'WebServiceManager.DocumentService.GetBOMByFileId', believing that I had hit the jackpot.  I then discovered, as discussed in some other forum posts, that this is just a template which the Item Master uses when it creates a BoM.

 

I then went down the road of extracting a BoM through the Item Master (ItemService.GetItemBOMByItemIdAndDate).  This seems to work great but the major problem is that you can only export a BoM for an Inventor assembly file if that assembly file already has items created for its entire BoM structure.

 

I did attempt to add in some logic which creates the items, if the items do not already exist, before extracting the BoM.  This method seemed to run into errors very frequently, which I believe was due to items getting locked, so I eventually gave up.  All my code is in the attached word document.

 

Has anybody else been down this road?  If so, what direction did you go in the end?

 

Right now, our system relies on using the Job Queue to open a session of Inventor and output the BoM to a CSV file.  I just find it very frustrating that all the data I need is sat within Vault, I just can't figure out how to extract it in a reliable way.

Wayne Helley
Inventor 2013 Certified Professional

Autodesk Inventor Professional 2023
Visual Studio 2022
Windows 10 Pro, 64-bit
0 Likes
Accepted solutions (3)
4,113 Views
7 Replies
Replies (7)
Message 2 of 8

Markus.Koechl
Autodesk
Autodesk
Accepted solution

Your approach to promoting files to items is the right one, but your option ItemAssignAll.Default might cause duplicates and item locks. The code below is not "production" ready but should provide a foundation to start over.

void m_AssignUpdateItem(object sender, long mFileId)
        {
            IWebService service = sender as IWebService;
            if (service == null)
                return;
            WebServiceCredentials cred = new WebServiceCredentials(service);
            using (WebServiceManager serviceManager = new WebServiceManager(cred))
            {
                long currentUserId = serviceManager.SecurityService.SecurityHeader.UserId;
                ItemService mItemSvc = serviceManager.ItemService;
                
                ItemsAndFiles promoteResult = null;
                Item[] updatedItems = null;
                bool m_PromoteFailed = false;
                try
                {
                    // in this case - we enforce to create/update an item by checkin; with that we must not cause the item creation "twice" in case an assembly's subcomponent also requires an item creation
                    // with that we have to set ItemAssignAll = No
                    mItemSvc.AddFilesToPromote(new long[] { mFileId }, ItemAssignAll.No, true);
                    DateTime timestamp;
                    GetPromoteOrderResults promoteOrderResults = mItemSvc.GetPromoteComponentOrder(out timestamp);
                    if (promoteOrderResults.PrimaryArray != null && promoteOrderResults.PrimaryArray.Any())
                        try
                        {
                            mItemSvc.PromoteComponents(timestamp, promoteOrderResults.PrimaryArray);
                        }
                        catch
                        {
                            m_PromoteFailed = true;
                            //create new restriction / message 
                        }
                    if (promoteOrderResults.NonPrimaryArray != null && promoteOrderResults.NonPrimaryArray.Any())
                        try
                        {
                            mItemSvc.PromoteComponentLinks(promoteOrderResults.NonPrimaryArray);
                        }
                        catch
                        {
                            m_PromoteFailed = true;
                            //create new restriction / message indicating that the item (unknown number here) linked to file e is probably locked by an editor
                        }
                    try
                    {
                        if (m_PromoteFailed != true)
                        {
                            promoteResult = mItemSvc.GetPromoteComponentsResults(timestamp);
                            //check the result for locked root item as we continue to update this
                            if (promoteResult.ItemRevArray[0].Locked != true)
                            {
                                updatedItems = promoteResult.ItemRevArray;
                                Item m_CurrentItem = promoteResult.ItemRevArray[0];
                                Item[] m_ItemToUpdateCommit = new Item[1];
                                m_ItemToUpdateCommit[0] = m_CurrentItem;
                                // commit the changes for the root element only; the reason is as stated before for ItemAssignAll = No
                                mItemSvc.UpdateAndCommitItems(m_ItemToUpdateCommit);
                            }
                            else
                            {
                                //create a restriction for file e and item promoteResult.ItemRevArray[0] Number / Title
                            }
                        }

                    }
                    catch
                    {
                        //still an unhandled situation?
                    }
                }
                catch
                {
                    if (updatedItems != null && updatedItems.Length > 0)
                    {
                        long[] itemIds = new long[updatedItems.Length];
                        for (int i = 0; i < updatedItems.Length; i++)
                        {
                            itemIds[i] = updatedItems[i].Id;
                        }
                        serviceManager.ItemService.UndoEditItems(itemIds);
                    }
                }
                finally
                {
                    if (promoteResult == null && m_PromoteFailed != true)
                    {
                        // clear out the promoted item
                        serviceManager.ItemService.DeleteUnusedItemNumbers(new long[] { promoteResult.ItemRevArray[0].MasterId });
                        serviceManager.ItemService.UndoEditItems(new long[] { promoteResult.ItemRevArray[0].Id });
                    }
                }
            }
        }

 



Markus Koechl

Solutions Engineer PDM, Autodesk Central Europe
Message 3 of 8

wayne.helleyY67EK
Enthusiast
Enthusiast
Accepted solution

Hi @Markus.Koechl 

 

Thanks a lot for your response.

 

I'm still not quite friends with the Item Master but this logic is working for me.

 

Wayne

Message 4 of 8

ron_m
Enthusiast
Enthusiast

I am lookup to pull bills from the vault without creating Items for all the components. Until upgrading to Vault 2022, I was getting good results using the un-document GetBomByFileID but now the file IDs in the saved bill don't match the file IDs in the vault. 

 

2 questions about the code sample you provided.

Does the code only create an Item for the top level assembly and none of the sub-assemblies and parts? 

Can I get the bill from the top level assembly Item without using the UpdateAndCommitItems step?

0 Likes
Message 5 of 8

ThomasRambach
Advisor
Advisor

@Markus.Koechl  I'm seeing some weird differences with this code between Vault 2021 and Vault 2023. The code works perfectly when I'm itemizing an AutoCAD file. But when the "AddFilesToPromote" AutoCAD file is also attached to an AutoCAD Electrical project file, the PromoteComponents function tries to promote the parent ACAD-E Project file and not the DWG file. It makes no sense to me. Any ideas?

0 Likes
Message 6 of 8

Markus.Koechl
Autodesk
Autodesk
Does the manual UI command match your findings?


Markus Koechl

Solutions Engineer PDM, Autodesk Central Europe
0 Likes
Message 7 of 8

ThomasRambach
Advisor
Advisor

Well, that's a tricky answer. So, the reason I'm using code to create the items is because we have AutoCAD Electrical schematics that are attached to the Inventor files and to each other. Vault out-of-the-box Item creation does not recognize file attachments. So, I'm basically using the code to create the parent item and then iterating through the Vault file attachments to create the associated item and add it to the parent items BOM.

 

It works for Inventor files with DWG attachments.

It works for DWG files with DWG attachment where the child DWG is not attached to an AutoCAD Electrical project file.

 

When it tries to create a DWG item where the DWG is attached to the WDP file, even with stepping through the code and it's clearly promoting just a single DWG file, it tries to promote the attached WDP file instead and causing lots of errors and issues.

 

So I'm not sure why the API is different when promoting a DWG with an attached WDP. I'm trying to find a workaround to accommodate it if I can't figure out the root cause.

0 Likes
Message 8 of 8

waynehelley
Collaborator
Collaborator
Accepted solution

Hi @Markus.Koechl,

 

I have returned to investigating BOM extraction using the Vault API.

 

Instead of using the item master, I decided to try using 'WebServiceManager.DocumentService.GetBOMByFileId'.  This was working fantastic for me (large BOMs exporting in less that 1 minute) but I am finding that as the day goes on, the time to export is increasing drastically (up to 10 minutes), possibly due to people being busy working on our Vault server.

 

I currently loop over the BOM recursively and execute GetBOMByFileId on every file (latest version) to ensure that I get the latest property data.

 

I was just wondering if you had any options on if this a better or worst method than pulling data from the Item Master?  The solution that we have been using, over the last few years, is to just open an Inventor/Apprentice session and extract a BOM from there.  I was hoping that the API might be significantly more efficient so I'm surprised that it's running slowly for me. Maybe I am doing something inefficient in my code.

 

Please ignore.  I discovered that the performance hit was coming from having coolOrange powerJobs/Events loaded.

 

Many thanks

 

Wayne Helley
Inventor 2013 Certified Professional

Autodesk Inventor Professional 2023
Visual Studio 2022
Windows 10 Pro, 64-bit
0 Likes