![]() | ERPExportBaseExtraOptsFIELDSETTINGSTYPE, EXPORTSETTINGSTYPE Class |
Namespace: CTExtensions.ExportCore.ExportBaseTypes
public abstract class ERPExportBaseExtraOpts<FIELDSETTINGSTYPE, EXPORTSETTINGSTYPE> : ExportBase<FIELDSETTINGSTYPE, EXPORTSETTINGSTYPE, Dummy, Dummy> where FIELDSETTINGSTYPE : new(), SettingsObject where EXPORTSETTINGSTYPE : new(), ExportSettingsBase<FIELDSETTINGSTYPE>
The ERPExportBaseExtraOptsFIELDSETTINGSTYPE, EXPORTSETTINGSTYPE type exposes the following members.
Name | Description | |
---|---|---|
![]() | ERPExportBaseExtraOptsFIELDSETTINGSTYPE, EXPORTSETTINGSTYPE | Initializes a new instance of the ERPExportBaseExtraOptsFIELDSETTINGSTYPE, EXPORTSETTINGSTYPE class |
// @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); } // -- -- -- -- } }
CUSTOMTOOLS 2022 SP0