So, much of what I post here is a rough cut, experimental before sitting down and have the users test, but here’s some final code.
For more details and background on the code, please see the previous incarnation.
https://potatoit.wordpress.com/2011/01/23/journal-importing-jscript-handling-of-error-messages/
This improved code will handle errors on panel E, it will also handle FAM Functions 100, 200, 300, 900.
I won’t bore you with long drawn out explanations of the code again, if you want a more detailed explanation, please refer to my previous posting on it and the comments in the code.
// V004 20110207 * completed // V005 20110207 * maximum row is now set to 10000 // * we will look for the word End to end our line processing // V006 20110212 * don't submit lines that have a 0 value // * truncate the decimals to two decimals import System; import System.Text; import System.Windows; import System.Windows.Controls; import System.Windows.Media; import System.Windows.Media.Media3D; import MForms; import Mango.UI.Core; import Mango.UI.Core.Util; import Mango.UI.Services; import Mango.Services; import Excel; import System.Reflection; package MForms.JScript { class GLS100_JournalImport_V06 { var giicInstanceController : IInstanceController = null; // this is where we will store the IInstanceController to make it available to the rest of the class var ggrdContentGrid : Grid = null; // this is the Grid that we get passed by the Init() var gexaApplication = null; // Excel.Application object var gbtnImportFromExcel : Button = null; // this is the button that we will put on to the panel that will kick off the whole import var glvListView : ListView = null; // this is the ListView on the panel var gwbWorkbook = null; // here we will store the Workbook object var giStartRow : int = 15; // the starting row in the Spreadsheet var giMaxRow : int = 10000; // the end row in the Spreadsheet var giCurrentRow : int = 15; // the current row in the Spreadsheet var gbLookForResponse = false; // should we be looking for a response? var gobjStatusJ1 = null; // the statusbar var gobjStatusE = null; var gbRequest : boolean = false; // the request event var gstrVoucherType : String = null; // the voucher type public function Init(element: Object, args: Object, controller : Object, debug : Object) { // lets make some of the controls and other // bits pieces available to other sections of our code ggrdContentGrid = controller.RenderEngine.Content; giicInstanceController = controller; glvListView = controller.RenderEngine.ListControl.ListView; try { // create the button for importing gbtnImportFromExcel = new Button(); gbtnImportFromExcel.Content = "Import"; Grid.SetColumnSpan(gbtnImportFromExcel, 10); Grid.SetColumn(gbtnImportFromExcel, 1); Grid.SetRow(gbtnImportFromExcel, 22); // finally add the control to the grid ggrdContentGrid.Children.Add(gbtnImportFromExcel); // ----- Events ----- gbtnImportFromExcel.add_Click(OnImportFromExcelClicked); gbtnImportFromExcel.add_Unloaded(OnImportFromExcelUnloaded); } catch(exException) { MessageBox.Show("Error: " + exException.Message + Environment.NewLine + exException.StackTrace); } } // find a specific control private function findControl() { var result = null; var objTopControl = goUp(ggrdContentGrid); // go up the visual tree to somewhere useful if(null != objTopControl) // we found 'somewhere useful' 😉 { result = findControlInner(objTopControl, 0, "labelStatus"); // search for a control with a name "labelStatus" } else MessageBox.Show("Went up without success"); return(result); } // check for errors, we need to check // for errors on BOTH the E panel // and J1 panel // We will go out and look for the status control if we // don't have it private function checkForError() { var strResult : String = null; var strStatusMessage : String = null; try { if(true == giicInstanceController.RenderEngine.PanelHeader.EndsWith("E")) { if(null == gobjStatusE) // have we found the status control, if not, try to find it { gobjStatusE = findControl(); // do the actual finding of the control } if(null != gobjStatusE) { // now we should extract the status strStatusMessage = gobjStatusE.Content.ToString(); if(false == String.IsNullOrEmpty(strStatusMessage)) { strResult = strStatusMessage; MessageBox.Show("There was an error, cannot continue! '" + gobjStatusE.Content.toString() + "'"); } } else { MessageBox.Show("Couldn't find the StatusBar"); } } else if(true == giicInstanceController.RenderEngine.PanelHeader.EndsWith("J1")) { if(null == gobjStatusJ1) // have we found the status control, if not, try to find it { gobjStatusJ1 = findControl(); // do the actual finding of the control } if(null != gobjStatusJ1) { // now we should extract the status strStatusMessage = gobjStatusJ1.Content.ToString(); if(false == String.IsNullOrEmpty(strStatusMessage)) { strResult = strStatusMessage; MessageBox.Show("There was an error, cannot continue! '" + gobjStatusJ1.Content.toString() + "'"); } } else { MessageBox.Show("Couldn't find the StatusBar"); } } } catch(ex) { MessageBox.Show("checkForError() exception: " + ex.message); } return(strResult); } // this function goes down the tree looking for a specific object private function findControlInner(parent : Object, depth : int, astrControlName : String) { var objResult = null; try { if(null != parent) { // get the type of our object, we do this // so we can check if the object inherits // from a DependencyObject var parentobjType : Type = parent.GetType(); if(parentobjType.IsSubclassOf(DependencyObject) == true) { for(var i=0; i < VisualTreeHelper.GetChildrenCount(parent);i++) { // retrieve the child object var current : Object = VisualTreeHelper.GetChild(parent,i); if(null != current) { // here we shall deterine the type of the new object var objType = current.GetType(); if(null != objType) { // we're looking for the Name property, because // this is what I am interested in var objPropertyName = objType.GetProperty("Name"); if(null != objPropertyName) { var strName = objPropertyName.GetValue(current); if(null != strName) { if(0 == String.Compare(strName, astrControlName)) { objResult = current; break; } // does the current object have any children? if(VisualTreeHelper.GetChildrenCount(current) >= 1) { // recurse down objResult = findControlInner(current, depth+1, astrControlName); if(null != objResult) { break; } } } } } } } } } } catch(ex) { //debug.WriteLine("!-! Exception: " + ex.Message + " " + ex.StackTrace); } return(objResult); } // go up the VisualTree until we get to PART_Window private function goUp(aContent : Object) { var parent : Object = aContent; var lastParent : Object = aContent; var result : Object = null; // here we will loop UP the VisualTree seeking the top while(null != (parent = VisualTreeHelper.GetParent(parent))) { lastParent = parent; var objType = lastParent.GetType(); var objPropertyName = objType.GetProperty("Name"); var strName : String = objPropertyName.GetValue(lastParent) if(null != strName) { // PART_ContentPanel if(String.Compare(strName,"PART_Window") == 0) { result = parent; break; } } } return(result); } // display an OpenFileDialog box // and extract the result private function retrieveImportFile() { var result : String = null; var ofdFile = new System.Windows.Forms.OpenFileDialog(); // we have to use the forms OpenFileDialog unfortunately if(null != ofdFile) { ofdFile.Multiselect = false; ofdFile.Filter = "Excel Files (*.xls;*.xlsx)|*.xls;*.xlsx|All Files (*.*)|*.*"; // filter on xls or xlsx files only if(true == ofdFile.ShowDialog()) { result = ofdFile.FileName; } } return(result); } // this is where we actually do the import private function OnImportFromExcelClicked(sender : Object, e : RoutedEventArgs) { gstrVoucherType = null; try { // here we do some initialisation of Excel InitialiseExcel(); var strFilename : String = retrieveImportFile(); // retrieve the filename of the Excel spreadsheet to open if((null != strFilename) && (null != gexaApplication)) // ensure that not only do we have a filename, but we also managed to initialise Excel { gwbWorkbook = gexaApplication.Workbooks.Open(strFilename); // open the spreadsheet if(null != gwbWorkbook) { giicInstanceController.add_RequestCompleted(OnRequestCompleted); giicInstanceController.add_RequestCompleted(OnRequested); gbRequest = true; gwbWorkbook.Saved = true; // get rid of those annoying save messages var strVoucherType : String = retrieveVoucherType(); // we want to get the voucher type from the spreadsheet (the GLS100 voucher) if(!String.IsNullOrEmpty(strVoucherType)) // we need to ensure that we have a voucher type { giicInstanceController.RenderEngine.SetFocusOnList(); selectFAMFunction(strVoucherType); // now we need to go out and select the function // from where on out, we start using the events } } else MessageBox.Show("Failed to Open Workbook"); } else MessageBox.Show("Filename or Excel doesn't exist: " + strFilename); } catch(exException) { MessageBox.Show("Error: " + exException.description); } } // set the VoucherText within GLS100/E private function setM3VoucherText(astrVoucherText : String) { var tbVoucherText : TextBox = ScriptUtil.FindChild(ggrdContentGrid, "WWGVTX"); if(null != tbVoucherText) { tbVoucherText.Text = astrVoucherText; } else MessageBox.Show("setM3VoucherText() - Child not found"); } // set the Year within GLS100/E private function setM3YEA4(astrYEA4Text : String) { var tbYEA4Text : TextBox = ScriptUtil.FindChild(ggrdContentGrid, "WWYEA4"); if(null != tbYEA4Text) { tbYEA4Text.Text = astrYEA4Text; } else MessageBox.Show("setM3VoucherText() - Child not found"); } // we need to set the reversal date private function setM3ReversalDate(astrReversalText : String) { var tbReversalText = ScriptUtil.FindChild(ggrdContentGrid, "WWSHDT"); if(null != tbReversalText) { try { var dtValue : DateTime = DateTime.FromOADate(Convert.ToDouble(astrReversalText)); tbReversalText.Value = dtValue; } catch(ex) { MessageBox.Show(ex.description); } } else MessageBox.Show("setM3ReversalDate() - Child not found"); } // set the accounting date within GLS100/E private function setM3AccountingDate(astrAccountingDate : String) { var tbITNO = ScriptUtil.FindChild(ggrdContentGrid, "WWACDT"); if(null != tbITNO) { try { var dtValue : DateTime = DateTime.FromOADate(Convert.ToDouble(astrAccountingDate)); tbITNO.Value = dtValue; } catch(ex) { MessageBox.Show(ex.description); } } else MessageBox.Show("Accounting Date not found"); } // retrieve the voucher text from the spreadsheet private function retrieveVoucherText() { return(gwbWorkbook.ActiveSheet.Range("E7").Value); } // retrieve the accounting date from the spreadsheet // we need to use Value2 in this instance to get // a value that we can actually use private function retrieveAccountingDate() { try { return(gwbWorkbook.ActiveSheet.Range("R5").Value2); } catch(ex) { MessageBox.Show("Exception: " + ex.message); } } // retrieve the voucher type from the Spreadsheet private function retrieveVoucherType() { gstrVoucherType = gwbWorkbook.ActiveSheet.Range("K5").Value; return(gstrVoucherType); } // retrieve the reversing date private function retrieveReversingDate() { try { return(gwbWorkbook.ActiveSheet.Range("R7").Value2); } catch(ex) { } } // GLS100/B set the FAM Function private function selectFAMFunction(astrFAMFunction : String) { var bFound : boolean = false; if(!String.IsNullOrEmpty(astrFAMFunction)) { // search through the ListView for the FAM function for(var iCount : int = 0; iCount < glvListView.Items.Count; iCount++) { var itmCurrentItem = glvListView.Items[iCount]; if(null != itmCurrentItem) { if(!String.IsNullOrEmpty(itmCurrentItem[0])) { var strCurrentString = itmCurrentItem[0].ToString(); if(0 == String.Compare(strCurrentString, astrFAMFunction)) { glvListView.SelectedItem = itmCurrentItem; bFound = true; break; } } } } } if(true == bFound) { // ok, we've found the FAM Function on the ListView // now we need to SELECT it giicInstanceController.ListOption("1"); // SELECT } } // our Import button is being unloaded, now's a good time to clean // everything up private function OnImportFromExcelUnloaded(sender : Object, e : RoutedEventArgs) { if(null != gbtnImportFromExcel) { gbtnImportFromExcel.remove_Click(OnImportFromExcelClicked); gbtnImportFromExcel.remove_Unloaded(OnImportFromExcelUnloaded); } } public function OnRequested(sender: Object, e: RequestEventArgs) { // we don't really use this at all at the moment } // set the error line against the spreadsheet private function setLineStatus(astrError : String) { if(null != gwbWorkbook) { gwbWorkbook.ActiveSheet.Range("S" + (giCurrentRow-1).ToString()).Value = astrError; } } public function OnRequestCompleted(sender: Object, e: RequestEventArgs) { var strError : String = null; try { if(e.CommandType == MNEProtocol.CommandTypeKey) // we're looking for a key event { if(e.CommandValue == MNEProtocol.KeyEnter) // specifically we're looking the enter key event { strError = checkForError(); if(true == String.IsNullOrEmpty(strError)) { if(true == giicInstanceController.RenderEngine.PanelHeader.EndsWith("E")) // are we on panel E? { handleEPanel(); // handle panel E strError = checkForError(); } else if(true == giicInstanceController.RenderEngine.PanelHeader.EndsWith("J1")) // are we on panel G1 (this should be GLS120/G1) { strError = checkForError(); if(true != String.IsNullOrEmpty(strError)) { giCurrentRow = giMaxRow + 1; } else { handleJ1Panel(); // handle panel j } } } else { setLineStatus(strError); } } } else if(e.CommandType == MNEProtocol.CommandTypeListOption) { if(e.CommandValue == MNEProtocol.OptionSelect) { if(true == String.IsNullOrEmpty(strError)) { handleEPanel(); } } } if(null != giicInstanceController.Response) { if(0 == String.Compare(giicInstanceController.Response.Request.RequestType.ToString(), "Panel")) { if((MNEProtocol.CommandTypeKey == giicInstanceController.Response.Request.CommandType) && (MNEProtocol.KeyF03 == giicInstanceController.Response.Request.CommandValue)) { CleanUp(); } } } } catch(ex) { MessageBox.Show(ex.message); } if(null != strError) { CleanUp(); } } // this is where we do the actual handling of the J1 Panel private function handleJ1Panel() { if(giCurrentRow <= giMaxRow) // the spreadsheet has a limited number of rows... { // extract the lines from the spreadsheet var strWWADIV : String = retrieveFromActiveSheet("H" + giCurrentRow); // division var strWXAIT1 : String = retrieveFromActiveSheet("B" + giCurrentRow); var strWXAIT2 : String = retrieveFromActiveSheet("C" + giCurrentRow); var strWXAIT3 : String = retrieveFromActiveSheet("D" + giCurrentRow); var strWXAIT4 : String = retrieveFromActiveSheet("E" + giCurrentRow); var strWXAIT5 : String = retrieveFromActiveSheet("F" + giCurrentRow); var strWXAIT6 : String = retrieveFromActiveSheet("G" + giCurrentRow); var strWWCUAMDebit : String = retrieveFromActiveSheet("I" + giCurrentRow); var strWWCUAMCredit : String = retrieveFromActiveSheet("L" + giCurrentRow); var strWWVTXT : String = retrieveFromActiveSheet("O" + giCurrentRow); var strWWVTCD : String = retrieveFromActiveSheet("N" + giCurrentRow); // this is the current row giCurrentRow = giCurrentRow + 1; if(!String.IsNullOrEmpty(strWXAIT1)) { if(0 != String.Compare(strWXAIT1,"undefined")) // verify that we actually have content { if(0 != String.Compare(strWXAIT1,"End", true)) { var bDoWeHaveAValue : boolean = false; if(!String.IsNullOrEmpty(strWWCUAMDebit)) { var dblDebit : double = strWWCUAMDebit; var strDebit : String = dblDebit.ToString("#.##"); // make sure that we are formatted to only 2 decimal places if(!String.IsNullOrEmpty(strDebit)) // ensure we actually have a value now that we have converted it { if(0 != String.Compare(strDebit, "0.00")) // ensure that the value isn't 0! { bDoWeHaveAValue = true; setM3TextField("WWCUAM", strDebit); // Value } } } else if(!String.IsNullOrEmpty(strWWCUAMCredit)) { var dblCredit : double = strWWCUAMCredit; var strCredit : String = dblCredit.ToString("#.##"); // make sure that we are formatted to only 2 decimal places if(!String.IsNullOrEmpty(strCredit)) // ensure we actually have a value now that we have converted it { if(0 != String.Compare(strCredit, "0.00")) // ensure that the value isn't 0! { bDoWeHaveAValue = true; setM3TextField("WWCUAM", "-" + strCredit); // Value } } } if(true == bDoWeHaveAValue) // if the value is 0, then we shouldn't submit it { // strWWADIV if(!String.IsNullOrEmpty(strWWADIV)) { setM3TextField("WWADIV", strWWADIV); // division } setM3TextField("WXAIT1", strWXAIT1); // account setM3TextField("WXAIT2", strWXAIT2); // Dept setM3TextField("WXAIT3", strWXAIT3); // Dim3 setM3TextField("WXAIT4", strWXAIT4); // Dim4 setM3TextField("WXAIT5", strWXAIT5); // Dim5 setM3TextField("WXAIT6", strWXAIT6); // Dim6 //setM3TextField("", retrieveFromActiveSheet("H" + giCurrentRow)); // Division setM3TextField("WWVTXT", strWWVTXT); // Voucher Text setM3TextField("WWVTCD", strWWVTCD); // VAT type giicInstanceController.PressKey("ENTER"); // press the enter key } else { // we need to go to the next line to process handleJ1Panel(); } } else { giCurrentRow = giMaxRow + 1; // 20110207 - end this loop CleanUp(); // and do our cleanup } } } } else { //MessageBox.Show("handleJ1Panel(): " + giCurrentRow + " - " + giMaxRow); CleanUp(); } } // a little wee helper function that will search for a TextBox name // and set the TextBox value private function setM3TextField(astrName : String, astrValue : String) { var tbTextBox : TextBox = ScriptUtil.FindChild(ggrdContentGrid, astrName); if(null != tbTextBox) { tbTextBox.Text = astrValue; } else MessageBox.Show("Can't find: " + tbTextBox.Text); } // retrieve some data from the active spreadsheet // at a specific location private function retrieveFromActiveSheet(astrPosition : String) { var strValue : String = gwbWorkbook.ActiveSheet.Range(astrPosition).Value; if(true == String.IsNullOrEmpty(strValue)) { strValue = ""; } else if(0 == String.Compare(strValue, "undefined")) { strValue = ""; } return(strValue); } // retrieveVoucherType // gstrVoucherType // handle the E Panel private function handleEPanel() { var strAccountingDate : String = retrieveAccountingDate(); // retrieve the accounting date from the Spreadsheet var strVoucherText : String = retrieveVoucherText(); // retroeve the voucher text from the Spreadsheet var strReversalDate : String = retrieveReversingDate(); // retrieve the reversal date var bHaveAllTheFields : Boolean = false; // do we have all the fields that we require? if( (0 == String.Compare(gstrVoucherType,"100")) || (0 == String.Compare(gstrVoucherType,"200")) || (0 == String.Compare(gstrVoucherType,"900"))) { if((!String.IsNullOrEmpty(strAccountingDate)) && (!String.IsNullOrEmpty(strVoucherText))) { if(0 == String.Compare(gstrVoucherType,"900")) { setM3YEA4(strAccountingDate); } else { setM3AccountingDate(strAccountingDate); // now we actually set the accounting date in the TextBox } setM3VoucherText(strVoucherText); // and the Voucher TextBox bHaveAllTheFields = true; } } else if(0 == String.Compare(gstrVoucherType,"300")) { if((!String.IsNullOrEmpty(strReversalDate)) && (!String.IsNullOrEmpty(strAccountingDate)) && (!String.IsNullOrEmpty(strVoucherText))) { setM3AccountingDate(strAccountingDate); // now we actually set the accounting date in the TextBox setM3VoucherText(strVoucherText); // and the Voucher TextBox setM3ReversalDate(strReversalDate); // now set the reversal date bHaveAllTheFields = true; } } else { MessageBox.Show("Sorry, but we can't handle the voucher type: " + gstrVoucherType); } // if((!String.IsNullOrEmpty(strAccountingDate)) && (!String.IsNullOrEmpty(strVoucherText))) if(true == bHaveAllTheFields) { giicInstanceController.PressKey("ENTER"); // now we press enter - this will fire off a Request event and should take us to GLS120/G1 } else MessageBox.Show("We require an Account Date and Voucher Text"); } private function CleanUp() { if(true == gbRequest) { giicInstanceController.remove_RequestCompleted(OnRequestCompleted); giicInstanceController.remove_RequestCompleted(OnRequested); } gbRequest = false; CleanUpExcel(); //MessageBox.Show("Cleaned up"); } private function CleanUpExcel() { // check to ensure we have a Workbook object // before we attempt to close the workbook if(null != gwbWorkbook) { gwbWorkbook.Close(); gwbWorkbook = null; } // make sure we have actually created // the Excel Application object before // we Quit if(null != gexaApplication) { gexaApplication.Quit(); gexaApplication = null; } } private function InitialiseExcel() { var result = null; try { gexaApplication = new ActiveXObject("Excel.Application"); gexaApplication.Visible = true; result = gexaApplication; } catch(exException) { MessageBox.Show("Error: " + exException.Message + Environment.NewLine + exException.StackTrace); } return(result); } // } }
Happy coding! 🙂