Click or drag to resize

ERPExportBaseExtraOptsWithProfileSettingsFIELDSETTINGSTYPE, EXPORTSETTINGSTYPE, PROFILESETTINGSTYPE Class

Export Base with custom Export Profile Field specific settings, custom Export Profile settings and Profile settings. Export profile and field settings can be accessed from GetExportSettings(CTExportProfile). Profile settings can be accessed from GetProfileSettings.
Inheritance Hierarchy
SystemObject
  CTExtensionsCTExtension
    CTBuiltInExtension
      CTExtensions.ExportCoreExportBaseFIELDSETTINGSTYPE, EXPORTSETTINGSTYPE, PROFILESETTINGSTYPE, Dummy
        CTExtensions.ExportCore.ExportBaseTypesERPExportBaseExtraOptsWithProfileSettingsFIELDSETTINGSTYPE, EXPORTSETTINGSTYPE, PROFILESETTINGSTYPE

Namespace:  CTExtensions.ExportCore.ExportBaseTypes
Assembly:  CTInterface (in CTInterface.dll)
Syntax
public abstract class ERPExportBaseExtraOptsWithProfileSettings<FIELDSETTINGSTYPE, EXPORTSETTINGSTYPE, PROFILESETTINGSTYPE> : ExportBase<FIELDSETTINGSTYPE, EXPORTSETTINGSTYPE, PROFILESETTINGSTYPE, Dummy>
where FIELDSETTINGSTYPE : new(), SettingsObject
where EXPORTSETTINGSTYPE : new(), ExportSettingsBase<FIELDSETTINGSTYPE>
where PROFILESETTINGSTYPE : new(), SettingsObject

Type Parameters

FIELDSETTINGSTYPE
Custom type derived from SettingsObject representing Export Profile Field settings.
EXPORTSETTINGSTYPE
Custom type derived from ExportSettingsBaseFIELDSETTINGSTYPE representing Export Profile settings.
PROFILESETTINGSTYPE
Custom type derived from SettingsObject representing Profile settings

The ERPExportBaseExtraOptsWithProfileSettingsFIELDSETTINGSTYPE, EXPORTSETTINGSTYPE, PROFILESETTINGSTYPE type exposes the following members.

Constructors
  NameDescription
Protected methodERPExportBaseExtraOptsWithProfileSettingsFIELDSETTINGSTYPE, EXPORTSETTINGSTYPE, PROFILESETTINGSTYPE
Initializes a new instance of the ERPExportBaseExtraOptsWithProfileSettingsFIELDSETTINGSTYPE, EXPORTSETTINGSTYPE, PROFILESETTINGSTYPE class
Top
Examples
This example shows how to utilize classes of CTExtensions.ExportCore, CTExtensions.ExportCore.Config, CTExtensions.ExportCore.ExportBaseTypes and CTExtensions.ExportCore.EXTs namespaces for creating a custom Export ERP integration that supports custom data storing on CT Profile, current User, Export Profile and Export Profile Field levels, as well as very powerful GenericExportHandlerT, E, I for the actual export process.

Language: C#
Class name: MyCustomErpIntegration
C#
// @AUTO-REFERENCE { [CT_INSTALL_PATH]\CTInterface.dll }
// @AUTO-REFERENCE { [CT_INSTALL_PATH]\Interop.CTEngineLib.dll }
// @AUTO-REFERENCE { [CT_INSTALL_PATH]\ATRControls2.dll }
// @AUTO-REFERENCE { [CT_INSTALL_PATH]\Interop.ATRControlsXLib.dll }
// @AUTO-REFERENCE { c:\Windows\Microsoft.NET\Framework64\v4.0.30319\System.Windows.Forms.dll }
// @AUTO-REFERENCE { c:\Windows\Microsoft.NET\Framework64\v4.0.30319\System.Drawing.dll }

using ATR.CT.CTInterface;
using CTEngineLib;
using CTExtensions.ExportCore.Config;           /* SettingsObject, ControlAdapter, StreamExtensions, PropertyGridAdapter */
using CTExtensions.ExportCore.EXTs;             /* EventExtension */
using CTExtensions.ExportCore.ExportBaseTypes;  /* ERPExportBaseExtraOptsWithUserSettings */
using System.Windows.Forms;                     /* MyExportSettingsGUI */
using System.IO;                                /* Stream */
using ATRControls2;                             /* MyUserSettingsGUI (GenericLoginCtrl) */
using System.Collections.Generic;               /* List */
using CTExtensions.ExportCore.ExportHandler;    /* GenericExportHandler */
using ATRControlsXLib;
using System.Linq;

/*
 * NOTE: This add-in requires CUSTOMTOOLS 2024 SP1 or newer to work properly.
 */ 

namespace CustomErpIntegrationDemo
{

  // THIS is the main class that ties it all together. In its simplicity,
  // it just defines the stong types for all custom objects and returns 
  // the MyExportHandler than handles the actual export.
  // All data is stored using IdentifyingName, so changing it will 
  // cause all previous data of this integration to be lost.
  // FriendlyName is shown all of the UI and messages related to this integration.
  public class MyCustomErpIntegration : ERPExportBaseExtraOptsWithUserAndProfileSettings<MyExportFieldSettings, MyExportSettings, MyUserSettings, MyProfileSettings>
  {
    public override string FriendlyName()
    {
      return "My Custom Integration"; // This is shown in the UI.
    }

    public override string IdentifyingName()
    {
      return "MY-CUSTOM-ERP-INTEGRATION-12345"; // Just something that is unique and constant.
    }

    public override List<EventExtension> GetEventExtensions()
    {
      return new List<EventExtension>() { new MyExportHandler() };
    }

    // Override to add PDM context support.
    protected override ExportTypeExt<MyExportSettings, MyExportFieldSettings> CreateExportType()
    {
      return new ExportWithFullPDMSupport();
    }

    // This class adds full PDM support, both 2-phased export (= export on client; conversions and writebacks on task host machine),
    // and silent execution (= completely on task host machine with no user interaction).
    // MyExportHandler should investigate MyExportHandler.CurrentExportCase variable to know the context.
    public class ExportWithFullPDMSupport : ExportTypeExt<MyExportSettings, MyExportFieldSettings>
    {
      public override bool AllowUseInSWPDM()
      {
        return true;
      }

      public override bool SupportsSilentExecution()
      {
        return true;
      }
    }
  }

  // This is the class that does all the magic in Export.
  public class MyExportHandler : GenericExportHandler<MyCustomErpIntegration, MyExportItem, MyRowItemizer>
  {

    // Do anything you like for the 'data' before it's being itemized by 'MyRowItemizer'. For example if you need to 
    // send PDM checkbox values as Yes/No instead of 1/0, or do some unit conversions, this is perfect place to do it.
    // But you need to known which fields you should handle. You could e.g. utilize MyExportFieldSettings.
    // Note that this is invoked for all exported configurations separately.
    protected override void ManipulateExportDataBeforeItemization(ICTExportProfile profile, ICTExportProfileData data, string conf, bool bLastConfiguration)
    {

      // As an example, lets assume "MyExportFieldSettings.MyFieldBoolData" is an option "To Uppercase".

      // Get the field settings from export settings
      MyExportSettings exportsettings = (GetParent() as MyCustomErpIntegration).GetExportSettings(profile as CTExportProfile);
      foreach (var fieldSettings in exportsettings.FieldSettings)
      {
        string field = fieldSettings.Key;
        MyExportFieldSettings settings = fieldSettings.Value;


        if (settings.MyFieldBoolData) // If the setting is on, convert the value in each row to uppercase.
        {
          for (int i = 0; i < data.Rows; i++)
            data.SetValue(i, field, data.GetValueByName(field, i).ToUpper());
        }
      }
    }

    // You might want to have some "control columns" that are hidden, or additional columns that hold e.g. status of the item.
    protected override void GetAdditionalColumnsSetup(IListViewEx oList, string configuration, out Dictionary<string, bool> oColsToAdd, out List<string> oColsToHide)
    {
      oColsToAdd = null;
      oColsToHide = null;

      // Lets add 'Item Status' column so we have a field to show the status for user.
      oColsToAdd = new Dictionary<string, bool>() { { "Item Status", true } };
    }


    // Do possible queries to target systems to map the items etc.
    // Supports setting field and bom field values, colors and everything even before
    // the actual list view items are added to the list.
    protected override void UpdateItemsPreFilling(List<MyExportItem> items)
    {
      // Get all the settings
      MyExportSettings exportsettings = (GetParent() as MyCustomErpIntegration).GetExportSettings(moExportProfile as CTExportProfile);
      MyUserSettings userSettings = (GetParent() as MyCustomErpIntegration).GetUserSettings();
      MyProfileSettings profileSettings = (GetParent() as MyCustomErpIntegration).GetProfileSettings();


      // It's important to know in which context you are and what you can do.
      // If you are outside SOLIDWORKS, then you cannot use SOLIDWORKS API. 
      if (CurrentExportCase == ExportCase.SOLIDWORKS)
      {
        // This Export is being called from SOLIDWORKS
        Log("This goes to %TEMP%\\MY-CUSTOM-ERP-INTEGRATION-12345.log"); // Log file name is IdentifyingName
      }
      else if (CurrentExportCase == ExportCase.PDM)
      {
        // This Export is being called (usually) from PDM

        Log("This goes to Task Details"); // Or to some other system that can do task-like executions in the future.
      }
      else if (CurrentExportCase == ExportCase.SOLIDWORKS_Silent)
      {
        // This Export started outside solidworks (usually from PDM) but is now being performed inside SOLIDWORKS
        // SILENTLY, which means user add-ins like this SHOULD NOT HAVE ANY USER INTERACTION!

        // It's not guaranteed that the files are open in SOLIDWORKS as that depends on the task settings.

        Log("This goes to Task Details and the operation is silent."); // Or to some other system that can do task-like executions in the future.
      }



      // TODO: item mapping to existing items & BOMs in target ERP.


      // As an example, lets assume all items except the first one are new after the mapping and we should indicate that for the user.
      if (items.Count > 0)
      {
        items.First().RowColorController.ClearColors();
        items.First().SetValue("Item Status", "EXISTING");
        items.First().RowColorController.SetFieldBGColor("Item Status", ExportItemColorController.COLOR_WHITE);


        items.First().WillGetItemNumberAfterExport = false; // let's also control our custom logic here.

      }

      foreach (var item in items.Skip(1))
      {
        item.RowColorController.ClearColors();
        item.SetValue("Item Status", "NEW");
        item.RowColorController.SetFieldBGColor("Item Status", ExportItemColorController.COLOR_NEW);

        item.WillGetItemNumberAfterExport = true; // let's also control our custom logic here.
      }

      // Lets also add "Ghost line" for the first item. Ghost lines can be used to show user that the BOM in target ERP
      // has items that are not present in the current structure.
      if (items.Count > 0)
      {

        var ghostItem = items.First().AddGhostItem<MyExportItem>("Item '12345' in target ERP");
        ghostItem.SetQuantityIn(items.First(), 1); // Must have quantity, otherwise it gets excluded.

        ghostItem.SetValue("Item Status", "Exists in ERP but not in CAD");
        ghostItem.RowColorController.SetRowFGColor(ExportItemColorController.COLOR_GHOST);
      }

    }

    // This is the actual export that happens after clicking that Export button in Export dialog.
    protected override bool Export(List<MyExportItem> items)
    {
      MyExportSettings exportsettings = (GetParent() as MyCustomErpIntegration).GetExportSettings(moExportProfile as CTExportProfile);
      MyUserSettings userSettings = (GetParent() as MyCustomErpIntegration).GetUserSettings();
      MyProfileSettings profileSettings = (GetParent() as MyCustomErpIntegration).GetProfileSettings();

      // Do the actual export.

      // Here we'd set the Writeback for all items that have 
      foreach (var item in items.Where(x => x.WillGetItemNumberAfterExport))
      {
        //item.CacheWriteBack("item number field", "item number from ERP");
        item.WillGetItemNumberAfterExport = false; // now there is actual writeback so remove the flag.
      }

      // As an example, let's fake success and just set the status here
      foreach (var item in items)
      {

        if (Itemizer.GetRowType(item.DataRows.First().Item1) == RowItemizer.RowType.Ghost)
          continue; // Skip ghost rows.


        item.RowColorController.ClearColors();
        item.SetValue("Item Status", "OK");
        item.RowColorController.SetFieldBGColor("Item Status", ExportItemColorController.COLOR_WHITE);

      }




      return true; // Success
    }


    /// This function is called during the second phase Export. At this point
    /// all conversions are done and collected, and writebacks are already done to files. This is mostly desined for
    /// sending converted documents to the target system, however, it is also possible to handle the whole Export Process
    /// silently within this function. 
    /// To write addtitional writebacks to files, call "PerformWritebacksWithCheckoutAndCheckin(...)" after
    /// caching the writebacks to items. Note that "PerformWritebacksWithCheckoutAndCheckin(...)" is already
    /// called once during "SecondPhaseInitialized(...)" so if there were writebacks added at the first
    /// export phase, some items might get multiple versions checked-in. You can override "SecondPhaseInitialized(...)"
    /// to not call.
    protected override bool SecondPhaseExport(List<MyExportItem> items)
    {
      // This ERP integration does nothing in "Second phase" or the Export that is usually
      // caused by PDM Task Add-in's run phase.

      return true; // Report success
    }

  }

  // ExportItem represents one or multiple rows in Export, and handles
  // all UI<->ExportData interaction as well as value writeback to files.
  // It support all Export options such as multiple configration export,
  // configuration grouping etc. and also conversions and writebacks in PDM context.
  // You'd normally add mapping information of the target ERP item to you Export Item.
  // And perform the mapping in MyExportHandler.UpdateItemsPreFilling.
  // You can also provide right-click menu actions for your items.
  public class MyExportItem : ExportItem
  {
    public bool WillGetItemNumberAfterExport { get; set; }

    public MyExportItem()
    {
      WillGetItemNumberAfterExport = false;
    }

    // We know this item requires writeback if it has writebacks
    // OR if it will get item number generated after the export (which is quite common).
    public override bool RequiresWriteBack()
    {
      return base.RequiresWriteBack() || WillGetItemNumberAfterExport;
    }
  }


  // This class allows you to override how rows in Export are itemized into
  // ExportItems (MyExportItems). For example, drawings, custom scopes and revision rows
  // are not recognized as items by default, so they will be collected in
  // parent items' "MyExportItem.Attachments".
  public class MyRowItemizer : RowItemizer
  {

  }

  // Object representing my custom settings (MyFieldStringData and MyFieldBoolData)
  // for Export Profile Fields of Export Profiles that are bound to my Erp Integration.
  public class MyExportFieldSettings : SettingsObject
  {

    // -- My data --
    public string MyFieldStringData { get; set; }
    public bool MyFieldBoolData { get; set; }
    // -- -- -- --


    // -- Serialization of my data
    protected override void Deserialize(Stream s)
    {
      MyFieldStringData = s.PopString();
      MyFieldBoolData = s.PopBool();
    }

    protected override void Serialize(Stream s)
    {
      s.PushString(MyFieldStringData);
      s.PushBool(MyFieldBoolData);
    }
    // -- -- -- --


    // -- return GUI control capable of showing and modifying my data
    //    when editing Export Profile Fields at Options.
    public override ControlAdapter CreateAdapter(ICTExtension parent)
    {
      // PropertyGridAdapter just utilizes System.Windows.Forms.PropertyGrid
      // to enable editing of data object values. It could be custom control too, 
      // but this is a quick solution.
      return new PropertyGridAdapter<MyExportFieldSettings>(parent);
    }
    // -- -- -- --

  }

  // Object representing my custom settings
  // for each individual CT user.
  public class MyUserSettings : SettingsObject
  {

    // -- My data --
    public bool Enabled { get; set; }
    public string UserName { get; set; }
    public string PassWord { get; set; }
    // -- -- -- --

    // -- Serialization of my data
    protected override void Serialize(Stream s)
    {
      s.PushBool(Enabled);
      s.PushString(UserName);
      s.PushString(PassWord);
    }

    protected override void Deserialize(Stream s)
    {
      Enabled = s.PopBool();
      UserName = s.PopString();
      PassWord = s.PopString();
    }
    // -- -- -- --

    // -- return GUI control capable of showing and modifying my data
    //    at User Options.
    public override ControlAdapter CreateAdapter(ICTExtension parent)
    {
      // Custom control "MyUserSettingsGUI" declared below
      return new MyUserSettingsGUI(parent);
    }
    // -- -- -- --
  }

  // Custom control that accesses "MyUserSettings", shown as
  // an individual page at User Options
  public class MyUserSettingsGUI : ControlAdapter<MyUserSettings>
  {

    // Utilizing generic login control from ATRControls2
    ATRControls2.WinForm.GenericLoginCtrl moCtrl;

    public MyUserSettingsGUI(ICTExtension parent) : base(parent)
    {
      // Load and configure the control.
      moCtrl = new ATRControls2.WinForm.GenericLoginCtrl();
      moCtrl.BackColor = System.Drawing.Color.White;
      moCtrl.ShowEnableCheck(true);
      moCtrl.ShowUsernameField(true);
      moCtrl.ShowPasswordField(true);

      moCtrl.ShowDatabaseField(false);
      moCtrl.ShowTestConnectionButton(false);
      moCtrl.ShowCommunicationPointField(false);

      moCtrl.Dock = System.Windows.Forms.DockStyle.Fill;
      Controls.Add(moCtrl);
    }

    // -- Couple the data object values with GUI elements
    //    back and forth.
    public override void LoadFrom(MyUserSettings settings)
    {
      moCtrl.LoginEnabled = settings.Enabled;
      moCtrl.Username = settings.UserName;
      moCtrl.Password = settings.PassWord;

    }
    public override void SaveTo(MyUserSettings settings)
    {
      settings.Enabled = moCtrl.LoginEnabled;
      settings.UserName = moCtrl.Username;
      settings.PassWord = moCtrl.Password;
    }
    // -- -- -- --
  }


  // Object representing my custom Export Profile specific settings.
  // Accessed from [...] button at Export Profile settings.
  // Internally, ExportSettingsBase holds also Export Profile Field
  // settings of our custom type (MyExportFieldSettings)
  public class MyExportSettings : ExportSettingsBase<MyExportFieldSettings>
  {

    // -- My data --
    public string TargetCompany { get; set; }
    // -- -- -- --

    // -- Serialization of my data
    protected override void Deserialize(Stream s)
    {
      base.Deserialize(s);  // Important to remember base object serialization!

      TargetCompany = s.PopString();
    }

    protected override void Serialize(Stream s)
    {
      base.Serialize(s); // Important to remember base object serialization!

      s.PushString(TargetCompany);
    }
    // -- -- -- --


    // -- return GUI control capable of showing and modifying
    //    TargetCompany Export Profile options.
    public override ControlAdapter CreateAdapter(ICTExtension extension)
    {
      return new MyExportSettingsGUI(extension);
    }
  }

  // GUI control that accesses "MyExportSettings", shown 
  // with [...] button at Export Profile settings
  // Just a simple text box.
  public class MyExportSettingsGUI : ControlAdapter<MyExportSettings>
  {
    System.Windows.Forms.TextBox tb;

    public MyExportSettingsGUI(ICTExtension ext) : base(ext)
    {
      tb = new System.Windows.Forms.TextBox();
      tb.Dock = System.Windows.Forms.DockStyle.Top;
      Controls.Add(tb);
    }

    // -- Couple the data object values with GUI elements
    //    back and forth.
    public override void LoadFrom(MyExportSettings settings)
    {
      tb.Text = settings.TargetCompany;
    }

    public override void SaveTo(MyExportSettings settings)
    {
      settings.TargetCompany = tb.Text;
    }
    // -- -- -- --
  }

  // Object representing my custom settings
  // in the scope of the current CT Profile
  public class MyProfileSettings : SettingsObject
  {

    // -- My data --
    public string ConnectionString { get; set; }
    // -- -- -- --


    // -- Serialization of my data
    protected override void Deserialize(Stream s)
    {
      ConnectionString = s.PopString();
    }

    protected override void Serialize(Stream s)
    {
      s.PushString(ConnectionString);
    }
    // -- -- -- --


    // -- return GUI control capable of showing and modifying my data
    //    when visiting this integration's page at Profile Options
    public override ControlAdapter CreateAdapter(ICTExtension parent)
    {
      // PropertyGridAdapter just utilizes System.Windows.Forms.PropertyGrid
      // to enable editing of data object values.
      return new PropertyGridAdapter<MyProfileSettings>(parent);
    }
    // -- -- -- --
  }

}
Availability

CUSTOMTOOLS 2022 SP0


See Also