AnsweredAssumed Answered

Programmatically "Unhiding" Columns in a BOM

Question asked by Erich Tisa on Dec 31, 2015
Latest reply on Mar 2, 2020 by Noah Sato

In brief, I am trying to programmatically "unhide" columns in a BOM (that is, a SldWorks.TableAnnotation object) in VBA. And then I am iterating over the columns and rows in the BOM and pushing the data to an Excel spreadsheet. I'm using SolidWorks 2015. The BOM types in question are indented BOMs (although hiding and unhiding columns should work on top-level BOMs and indented BOMs).


For background, I am unhiding hidden columns because I'm exporting the contents of the BOM table either to a text file or to Excel. If you use the API or the interface (i.e., right-click, Save As...) to export a BOM table, any content in hidden columns will not be exported. So, in order to export a complete BOM table, hidden columns and all, you have to unhide any hidden columns.


Let me just say that there is an apparently reliable set of operations that can be carried out in the UI that is more or less what I am trying to do programmatically. But my suspicion is that this operation cannot actually be implemented through the API, which would be a remarkable oversight. I'm hoping to be proven wrong.


The set of operations to unhide BOM columns in the UI comprises the following steps:


1. Right-click anywhere on a BOM table in a drawing document.

2. On the context menu that appears, click the "Show Row/Column" command. The mouse pointer will change to indicate, evidently, that you are in "show/hide" mode:


3. Click the column header of any blue-shaded (i.e., hidden) columns.

4. Click anywhere else in the SolidWorks window to exit the Show/Hide mode.

5. Note that the BOM "refreshes" and, if there was data in a given cell, the data becomes visible. Also note that when you are unhiding columns in this manner, a column may appear to be empty, but after clicking away, the data (if there is any) will populate the column.


This is the UI command on the context menu I'm referring to:




Now, I have done everything I can think of to carry out an analogue of these steps in the API. I imagine that anyone familiar with the API will of course tell me to iterate over the columns (using the TotalColumnCount) to set the ColumnHidden property of each column to false. Here is such a routine, which iterates over BOM features and then iterates over the table annotations associated with those features to unhide any hidden columns. (Note: This routine is pared-down to the basics (that is, it excludes exception handling, checks for nulls, etc. and it assumes swApp is global and a drawing doc is open, blah, blah.)



Private Sub UnhideBomColumns()

  Dim swDoc As SldWorks.ModelDoc2

  Dim swFeature As SldWorks.Feature

  Dim swTable As SldWorks.TableAnnotation

  Dim ColCount As Integer

  Dim c As Integer

  Dim TableArray As Variant

  Dim TableItem As Variant


  Set swApp = Application.SldWorks

  Set swDoc = swApp.ActiveDoc


  ' Get the annotation table from a feature or however else you prefer, say, by getting

  ' a BOM from a Feature using GetSpecificFeature2 and then getting annotations from

  ' the BOM using GetAnnotations or by using the GetTableAnnotations method of the View object.

  ' Using BOM features here.


  Set swFeature = swDoc.FirstFeature

  While Not swFeature Is Nothing

      If "BomFeat" = swFeature.GetTypeName2 Then

          Set swBOM = swFeature.GetSpecificFeature2

          TableArray = swBOM.GetTableAnnotations

          For Each TableItem In TableArray

              Set swTable = TableItem

              ColCount = swTable.TotalColumnCount

              For c = 0 To ColCount - 1

                  swTable.ColumnHidden(c) = False

              Next c

          Next TableItem

      End If

      Set swFeature = swFeature.GetNextFeature


End Sub



Now, when I see something that toggles visibility in an API, I would expect that visibility is actually toggled---that you can interact with the newly visible item. But, if you run this routine, the BOM table columns will APPEAR to be visible, but the previously hidden columns will not be populated with content. If you right-click a BOM and click Save As to export to Excel (or if you do this programmatically), the previously hidden columns will be posted to Excel but without any data. That is, a column in Excel will show up for the previously hidden column, but each cell will be empty.


HOWEVER: If, after running this routine, you right-click on a BOM and click the Show Row/Column command and then simply click AWAY from the BOM, you will see the data populate. It seems that this ColumnHidden property must be acting on some sort of phantom representation of the BOM.


So, it seems that something is being executed when you click that "Show Row/Column" command that is not executed when you programmatically unhide columns. The "refresh" that happens is essential. As I say, I've tried everything I can think of to generate this refresh behavior. I've toggled visibility on everything from dimensions to views to entire tables and features. I've iterated over configurations and layers. I've tried to invoke that "Show Row/Column" command using the RunCommand method (of both the ISldWorks and the IModelDocExtension interfaces) but there does not seem to be a command ID corresponding to the "Show Row/Column" command in the swCommands_e enumeration. (I've tried to invoke any command with "hide" or "show" or "visible" in its enumeration member name.)


But using RunCommand here, even if it were possible, would be a hack. Surely there is an API call that performs the functionality of the "Show Row/Column" command on a BOM. I've tried ForceRebuild3, GraphicsRedraw2, saving and reopening the drawing doc after unhiding columns---nothing invokes that refresh operation that seems to happen when you use the "Show Row/Column" command on the context menu.


The reason this baffles me is that normally an API is a SUPERSET of the functionality available in the UI. I simply can't believe that there is something so simple (and necessary) that can be done in the UI but that the same functionality is not available in the API. I must be missing something. I can't say I'm especially familiar with SolidWorks (although I've spent more time than I want to with its API now) but I've worked with many APIs, even interfaces more convoluted than that associated with SolidWorks. But maybe I'm going about this all wrong. Maybe I'm not operating within the proper SolidWorks paradigm. I'm not even sure what that "refresh" operation that the "Show Row/Column" command invokes is---is it a regeneration of the BOM from the model? Is it a visual redraw? If I knew what it was or could trace it, maybe I could find something in the API.


But surely someone has encountered this circumstance before. This seems like very remedial functionality and I expected to write the necessary code to get this working in an afternoon. Can anyone offer any suggestions?


One further note: I know I can insert a NEW BOM for a given drawing view using a template derived from an existing BOM but with all the columns displayed. This works to some degree, but it doesn't capture everything in the current BOM (for example, if someone has made in-place edits in the current BOM). There MUST be a programmatic way to unhide columns of a given BOM, refresh (or rebuild the BOM table) and then export the BOM.


I know this was long, but I wanted to be clear about what it is I'm after. And I wanted to forestall responses like "just right-click the BOM in the UI", etc., etc.


Any help or alternatives or workarounds or even some sort of definitive declaration that what I'm after is not possible would be greatly appreciated.


Thanks all. Be well.