Hi All.
The code below is a combination of VBA code from CodeStack (thanks Artem)which has been converted to C# by GitHub Copilot and then modified further by GitHub Copilot to process all components within an assembly and map these properties to a part model. The code is mostly working as expected however the issue I'm having is that the GetCustomProperty2 method is not returning the evaluated values despite what the Solidworks documentation says.
If anyone could shed some light on why this is happening and what the solution might be it would be greatly appreciated.
public IEnumerable GetAllComponentCustomPropertiesRecursive(string assemblyPath)
{
const string swDocumentManagerKey = "LicenceKey";
var comps = new List();
SwDMClassFactory swClassFact = new SwDMClassFactory();
SwDMApplication5 swDmApp = (SwDMApplication5)swClassFact.GetApplication(swDocumentManagerKey);
if (swDmApp != null)
{
SwDmDocumentOpenError res;
SwDMDocument29 swDmDoc = (SwDMDocument29)swDmApp.GetDocument(assemblyPath, SwDmDocumentType.swDmDocumentAssembly, true, out res);
if (swDmDoc != null)
{
string activeConfName = swDmDoc.ConfigurationManager.GetActiveConfigurationName();
SwDMConfiguration18 swDmConf = (SwDMConfiguration18)swDmDoc.ConfigurationManager.GetConfigurationByName(activeConfName);
GetComponents(swDmConf, comps, true, activeConfName);
swDmDoc.CloseDoc();
}
else
{
throw new Exception("Failed to open the document");
}
}
else
{
throw new Exception("Failed to get Document Manager application");
}
return comps;
}
private void GetComponents(SwDMConfiguration18 conf, List coll, bool recursive, string confName)
{
// Use a dictionary to track unique components and their quantities across all recursion
var componentDict = coll.Count == 0
? new Dictionary(StringComparer.OrdinalIgnoreCase)
: coll.ToDictionary(
c => \$"{c.PartNo}|{c.BasePath}|{c.Configuration}",
c => c,
StringComparer.OrdinalIgnoreCase);
TraverseComponents(conf, componentDict, recursive, confName);
// Update the original collection with deduplicated components
coll.Clear();
coll.AddRange(componentDict.Values);
}
private void TraverseComponents(
SwDMConfiguration18 conf,
Dictionary componentDict,
bool recursive,
string confName)
{
object[] vComps = (object[])conf.GetComponents();
if (vComps != null)
{
foreach (object compObj in vComps)
{
SwDMComponent12 swDmComp = (SwDMComponent12)compObj;
string partNo = System.IO.Path.GetFileNameWithoutExtension(swDmComp.PathName);
string basePath = System.IO.Path.GetFileName(swDmComp.PathName);
string configuration = swDmComp.ConfigurationName;
string key = \$"{partNo}|{basePath}|{configuration}";
// Get configuration-specific properties
SWIPartsModel comp;
if (componentDict.TryGetValue(key, out SWIPartsModel existingComp))
{
comp = existingComp;
comp.Quantity++;
}
else
{
comp = new SWIPartsModel
{
BasePath = basePath,
PartNo = partNo,
Configuration = configuration,
TopLevelConfiguration = confName,
Quantity = 1
};
// Open the component's document to get its configuration properties
SwDmDocumentOpenError err;
SwDMDocument29 swDmChildDoc = (SwDMDocument29)swDmComp.GetDocument2(true, null, out err);
if (swDmChildDoc != null)
{
SwDMConfiguration18 swDmChildConf = (SwDMConfiguration18)swDmChildDoc.ConfigurationManager.GetConfigurationByName(configuration);
if (swDmChildConf != null)
{
object[] propNames = (object[])swDmChildConf.GetCustomPropertyNames();
if (propNames != null)
{
foreach (string propName in propNames)
{
string val = swDmChildConf.GetCustomProperty2(propName, out SwDmCustomInfoType type);
switch (propName.ToLowerInvariant())
{
case "part no": comp.PartNo = val; break;
case "description": comp.Description = val; break;
case "material": comp.Material = val; break;
case "stock size": comp.StockSize = val; break;
case "cutlength": comp.CutLength = val; break;
case "ismilled": comp.IsMilled = val == "Yes"; break;
case "isturned": comp.IsTurned = val == "Yes"; break;
case "machine time milling":
if (int.TryParse(val, out int millingTime))
comp.MillingTime = millingTime;
else
comp.MillingTime = 0;
break;
case "machine time turning":
if (int.TryParse(val, out int turningTime))
comp.TurningTime = turningTime;
else
comp.TurningTime = 0;
break;
case "isprofilecut": comp.IsProfileCut = val == "Yes"; break;
case "thickness":
if (decimal.TryParse(val, out decimal thicknessValue))
comp.Thickness = thicknessValue;
else
comp.Thickness = 0;
break;
case "prefix": comp.Prefix = val; break;
case "partno": comp.PartNo = val; break;
}
}
}
}
swDmChildDoc.CloseDoc();
}
componentDict[key] = comp;
}
// Recursively process subcomponents
if (recursive)
{
SwDmDocumentOpenError err;
SwDMDocument29 swDmChildDoc = (SwDMDocument29)swDmComp.GetDocument2(true, null, out err);
if (swDmChildDoc != null)
{
SwDMConfiguration18 swDmChildConf = (SwDMConfiguration18)swDmChildDoc.ConfigurationManager.GetConfigurationByName(configuration);
if (swDmChildConf != null)
{
TraverseComponents(swDmChildConf, componentDict, recursive, confName);
}
swDmChildDoc.CloseDoc();
}
}
}
}
}