Some ODB++ jobs have different variants for components. An easy way to find the variants is to check all attributes and list them in an overview dictionary, here is the code for a class who handles variants over strings. You have a list with all variants, it is possible to save the variant names and load them from a file. In the example there are two standard values included.
To find the variants, you have to call CreateVariantList and get the dictionary with all variants.
Here is the solution file as ZIP: Download
using PCBI.Automation;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace PCBVariantReport
{
public class VariantXMLClass
{
//list who contains all variant names
public List<string> VariantenTable = new List<string>() { "VARIANT_INSTANCE", "comp_variant_list" };
/// <summary>
/// The list is saved as simple xml and its possible to load it with an XmlSerializer.
/// </summary>
/// <param name="fullpath">The file path + filename</param>
/// <returns>ture if new list is loaded</returns>
internal bool LoadList(string fullpath)
{
if (!File.Exists(fullpath))
return false;
XmlSerializer x = new XmlSerializer(typeof(VariantXMLClass));
FileStream fs = null;
try
{
using (fs = new FileStream(fullpath, FileMode.Open))
{
XmlReader reader = new XmlTextReader(fs);
VariantXMLClass mainJobEntries = (VariantXMLClass)x.Deserialize(reader);
//add the loaded names to the standards, this can be change to replace if standard values not interesting
this.VariantenTable.AddRange( mainJobEntries.VariantenTable);
fs.Close();
}
return true;
}
catch (Exception ex)
{
Console.WriteLine("Error wihle loading xml "+ex.ToString());
if (fs != null) //get sure to close the files stream
fs.Close();
return false;
}
}
/// <summary>
/// Save custom setting of list, this is necessary if you have special attributes for variants.
/// </summary>
/// <param name="filename"></param>
internal void SaveFileEntries(string filename)
{
try
{
XmlSerializer x = new XmlSerializer(typeof(VariantXMLClass));
TextWriter writer = new StreamWriter(filename);
x.Serialize(writer, this);
writer.Close();
}
catch (Exception ex)
{
Console.WriteLine("Error while saving xml file " + ex.ToString());
}
}
/// <summary>
/// Check the complete step and sort variants in the list.
/// </summary>
/// <param name="parent">the current PCBI Window</param>
/// <returns>a list of variants for both component layers</returns>
internal Dictionary<string, VariantOverview> CreateVariantList(IPCBIWindow parent)
{
Dictionary<string, VariantOverview> PartList = new Dictionary<string, VariantOverview>();
IStep step = parent.GetCurrentStep(); //can be changed for all steps
if (step == null) return null;
ICMPLayer topLayer = step.GetCMPLayer(true);
ICMPLayer botLayer = step.GetCMPLayer(false);
if (topLayer != null)
{
AddCMPsForOneLayer(PartList, topLayer);
}
if (botLayer != null)
{
AddCMPsForOneLayer(PartList, botLayer);
}
return PartList;
}
/// <summary>
/// The actions for one cmp layer.
/// </summary>
/// <param name="PartList">List for variants</param>
/// <param name="relCMPLayer">the relevant component layer</param>
private void AddCMPsForOneLayer(Dictionary<string, VariantOverview> PartList, ICMPLayer relCMPLayer)
{
foreach (ICMPObject cmp in relCMPLayer.GetAllLayerObjects())
{
Hashtable attribs = cmp.GetComponentAttributeHashtable(); //get attributes
bool added = false;
foreach (string variant in VariantenTable)
{
if (attribs.ContainsKey(variant)) //check the variant is included?
{
#region variant element
VariantOverview overview;
if (!PartList.ContainsKey(variant))
{
overview = new VariantOverview();
overview.Variant = variant;
PartList.Add(variant, overview);
}
else
overview = PartList[variant];
//add to the correct list
if (overview.VariantValueAndList.ContainsKey((string)attribs[variant]))
overview.VariantValueAndList[(string)attribs[variant]].Add(cmp);
else
overview.VariantValueAndList.Add((string)attribs[variant], new List<ICMPObject>() { cmp });
added = true; //maybe there is no variant
#endregion
}
}
if (!added) //all cmps without variant
{
#region no variant
string noVariant = "no variant";
if (!PartList.ContainsKey(noVariant))
PartList.Add(noVariant, new VariantOverview() { Variant = noVariant });
if (PartList[noVariant].VariantValueAndList.ContainsKey(noVariant))
PartList[noVariant].VariantValueAndList[noVariant].Add(cmp);
else
PartList[noVariant].VariantValueAndList.Add(noVariant, new List<ICMPObject>() { cmp });
#endregion
}
}
}
/// <summary>
/// we have a simple class to sort the variants with lists
/// </summary>
internal class VariantOverview
{
public string Variant = "";
public Dictionary<string, List<ICMPObject>> VariantValueAndList = new Dictionary<string, List<ICMPObject>>();
}
}
}