MFORMS Automation with Jscript.NET

I was requested to share some of my experience with MFORMS Automation and JScript.NET by Thibaud and here it is. MForms automation is simply a great alternative to perform data modification in M3, if you are left with no other option which was my case.

Problem

In our M3 implementation, we are using Std. Document Connect Media to deliver documents (example, Purchase orders) to our clients. These media entities like email addresses are setup in the program CRS945/949. This M3 program does not have an API implemented for data access. The alternative to using API was creating a Lawson Web service i.e. adding the customer to the program by simulating the panel sequence in LSO.

In CRS945, adding a document media control object involves the selection of document number (W1DONR). This step determines the kind of document selected and hence the other inputs (customer number, supplier ID or warehouse ID). In this example, document number 231 implies Order Confirmation document which requires a Customer number field which gets added to the panel.

Image

Since the Customer Number gets added to the A-panel dynamically after the document number selection, creating a Lawson web service is not a possibility. This is due to the fact that Lawson Web Services designer does not allow “A or B Panel with ENTER followed by panels A, B” which is the case here. So web service was eliminated as an option which would have allowed us to add all the documents en masse by calling it repeatedly which was our requirement.

Solution

This left us with one and only option which was MForms automation. We ended up creating the MForms automation steps which would accomplish the task on hand and it looks as follows:

Image

Note: Step command F3 which closes the panel is missing in this diagram. It is a critical step.

As you can see the sequence of steps are it easy to follow. Step one starts by running the program required which CRS945. In step two we end setting the value for the document number followed by an action step ‘ENTER’. Step 4 is another action which is to create the document connection. Finally we add the name and description for the connection and press ‘ENTER’. I have recreated these same steps using Jscript.NET and here it is:

Image

As you can see the inputs for my MForms automations are provided from an Excel document (column 1: Document number, column 2: Customer number). This allows us to input multiple rows in one attempt. Running this Jscript using LSO on CRS945 adds the document connection for all our customers.

Regards

Seth Subramanian.

23 thoughts on “MFORMS Automation with Jscript.NET”

  1. Hi, it is possible to do the “Add” operation via web service without any problem. But to do this, you must start in CRS027 and go via CRS945 to CRS949. Works as a charm. (But it is not possible to execute “Change”, “Delete” or “Display” in CRS949, because an invisible “Sequence” field is created in the background which cannot be set in the panel header, this field is set by selecting a record in the list -something what LWS/MWS can’t do.)

    This approach works often if a field is missing when a program is wrapped via LWS/MWS: Go back one step if it is possible.I.e., you can enter line charges in CRS277 directly in M3, with LWS/MWS you can’t. But it is possible to start in CRS275 and go to CRS277 as related option in LWS/MWS and you have the full functionality in CRS277.

    Like

  2. HI Seth, I m trying to work with my very first jscript on M3. I need to update Fixed Assets records (FAS001) to create a link with Equipment (MMS240) . However, Script Tools send me the following msg : error JS1135: Variable ‘MFormsAutomation’ has not been declared
    The “import MForms;” is included.
    None of my colleagues were able to solve this case…
    Thank you very much.
    Pat’

    Like

      1. HI, thank you . The following statements are added :
        import System;
        import System.Windows;
        import System.Windows.Controls;
        import MForms;
        import Mango.UI.Core;
        import Mango.UI.Core.util;
        import Mango.UI.Services;

        In fact, I just copy and paste the template created by Seth…
        Thank you.
        Pat’

        Like

  3. Thank you for your Template, Seth. I’m now able to create the link between Fixed Assets and equipement transferred from SAGE. However, the Excel file is now locked. I tried to clear the Script cache, without success. Is there a specific command to release the Excel file ? Thank you again for your help.
    Patrick

    Like

      1. Salut Thibaud, Merci pour ta réponse. J’avais autant de process Excel d’ouvert que de tentatives d’exécution du jscript . Comme je les ai tous arrêté depuis le Task manager, je ne sais pas si cela suffit. Je viens de lire la réponse de Heiko, je vais essayer cette méthode qui semble plus intégrée. Connais tu un bon guide pour débuter le JSCRIPT ?Merci. Patrick

        Like

          1. Be aware that a script, when running in productive mode = raised from a panel, behaves completely different compared to a script started in the script editor. Therefore a logging function which can be turned on and off from outside by setting a script start argument is crucial. Use the log4net libraray to achieve this. Here is more information: https://smartofficeblog.com/2012/07/23/improvements-in-jscript-logging/

            Even if you write compiled scripts in Visual Studio (C#-dll’s), logging remains important.

            Also, be aware that when your script starts with a M3 panel, rendering has not finished, you can’t access any control without delaying the execution by using a dispatcher. When you are not using extended logging, you will never be able to trace what your script really does in case of errors. This is one of the main reasons where people get surprised – everything worked fine in the script editor, outside it doesn’t.

            Like

            1. You can solve that problem with a delegate as explained by karinpb, like this:

              var controller : Object;
              var debug : Object;
              public function Init(element : Object, args : Object, controller : Object, debug : Object) {
                  this.controller = controller;
                  this.debug = debug;
                  var StartDelegate : VoidDelegate = Start;
                  // wait for UI to render
                  controller.RenderEngine.Content.Dispatcher.BeginInvoke(DispatcherPriority.Background, StartDelegate);
              }
              function Start() {
                  // ready
              }
              

              Like

    1. Hi Patgro,

      Excel as OLE object can be fully controlled from any external application. You can search the WWW for the objects workbook and excel.application.

      workbook.Close(null, null. null) will close you workbook without changes.
      Excel.Quit() will close the application.
      Then set workbbook = null and Excel = null to be sure that you have no more references.

      /Heiko

      Like

  4. HI, Many thanks for guiding us in many ways. I have tried following script for doing mforms automation to add the departure date in MWS410 via excel.
    I got MNS921 popup box, and from that point onwards i am not able to access the text/date filed in the pop up box. How can i proceed or what is the correct name for the MNS921 pop box text/date field(WWVAL1)?

    import System;
    import System.Windows;
    import System.Windows.Controls;
    import MForms;
    import Mango.UI.Core;
    import Mango.UI.Core.Util;
    import Mango.UI.Services;
    import System.Threading.Thread;
    package MForms.JScript {

    class InactiveItems {

    public function Init(element: Object, args: Object, controller : Object, debug : Object) {
    var fso, f1, ts, s, rline;
    var ForReading = 1;

    fso = new ActiveXObject(“Scripting.FileSystemObject”);

    ts = fso.OpenTextFile(“C:\Users\KesavanS\Desktop\OIS300 dep date\UpdateCO.csv”, ForReading);
    while( !ts.AtEndOfStream ){
    s = ts.ReadLine();
    rline = new Array();
    rline = s.split(“,”);
    if(!trim(rline[0])== “”){

                                           reclassify(debug, rline);
                                   }        
                                   else{
                                   }
    

    }

    ts.Close();
    MessageBox.Show(“done”);

    }

    public function reclassify(debug : Object, data : Object){

         try {
    
    
                var auto = new MFormsAutomation();
    
    
    
                auto.AddStep(ActionType.Run, 'MWS410');
                auto.AddStep(ActionType.Key, 'ENTER');
                auto.AddField('WWQTTP','7');
                auto.AddStep(ActionType.Key, 'ENTER');
                auto.AddField('W1OBKF',trim(data[0]));
                auto.AddStep(ActionType.Key, 'ENTER');
                auto.AddStep(ActionType.ListOption, '2');
                auto.AddStep(ActionType.Key, 'ENTER');
                auto.AddStep(ActionType.Key, 'ENTER');
                auto.AddStep(ActionType.Key, 'F16');
                auto.AddField('WWVAL1',trim(data[1]));
                auto.AddStep(ActionType.Key, 'F16');
    
    
                var uri = auto.ToUri();
                DashboardTaskService.Manager.LaunchTask(new Task(uri));
    
                } catch (e) {
                debug.WriteLine(e);
                }
    

    }

    function trim(stringToTrim) {
    return stringToTrim.replace(/^\s+|\s+$/g,””);
    }

    }
    }

    Like

    1. please find the correct code i used here with

      import System;
      import System.Windows;
      import System.Windows.Controls;
      import MForms;
      import Mango.UI.Core;
      import Mango.UI.Core.Util;
      import Mango.UI.Services;
      import System.Threading.Thread;

      package MForms.JScript {

      class InactiveItems {

      public function Init(element: Object, args: Object, controller : Object, debug : Object) {
      var fso, f1, ts, s, rline;
      var ForReading = 1;

      fso = new ActiveXObject(“Scripting.FileSystemObject”);

      ts = fso.OpenTextFile(“C:\Users\KesavanS\Desktop\OIS300 dep date\UpdateCO.csv”, ForReading);
      while( !ts.AtEndOfStream ){
      s = ts.ReadLine();
      rline = new Array();
      rline = s.split(“,”);
      if(!trim(rline[0])== “”){

                                             reclassify(debug, rline);
                                     }        
                                     else{
                                     }
      

      }

      ts.Close();
      MessageBox.Show(“done”);

      }

      public function reclassify(debug : Object, data : Object){

           try {
      
      
                  var auto = new MFormsAutomation();
      
      
      
                  auto.AddStep(ActionType.Run, 'MWS410');
                  auto.AddStep(ActionType.Key, 'ENTER');
                  auto.AddField('WWQTTP','7');
                  auto.AddStep(ActionType.Key, 'ENTER');
                  auto.AddField('W1OBKF',trim(data[0]));
                  auto.AddStep(ActionType.Key, 'ENTER');
                  auto.AddStep(ActionType.ListOption, '2');
                  auto.AddStep(ActionType.Key, 'ENTER');
                  auto.AddStep(ActionType.Key, 'ENTER');
                  auto.AddStep(ActionType.Key, 'F16');
                  auto.AddField('WWVAL1',trim(data[1]));
                  auto.AddStep(ActionType.Key, 'ENTER');
      
      
                  var uri = auto.ToUri();
                  DashboardTaskService.Manager.LaunchTask(new Task(uri));
      
                  } catch (e) {
                  debug.WriteLine(e);
                  }
      

      }

      function trim(stringToTrim) {
      return stringToTrim.replace(/^\s+|\s+$/g,””);
      }

      }
      }

      Like

      1. Hi Kesavan, I do not know if M3 popups are supported by MForms Automation. Karin/norpe on the Smart Office blog may know. Otherwise, try MForms Bookmarks. Otherwise, you will have to make a manual test of entering data in the popup and submit, and look at the resulting HTTP request to see where the data is going in the XML; then reverse engineer the MForms Automation assembly, and see if there’s a hack you can do. Worst case, add the data directly to the field (TextBox via .NET reflection if Smart Office, or input field via JavaScript if H5 Client). Sorry, I don’t have a better answer right now. –Thibaud

        Like

  5. Hi,

    I want to open OIS103 from OIS100 using MForms Automation, but as the OIS103 panel contains only read-only fields it doesn’t work. Is there is any way to use Automation on read-only fields?

                var auto = new MFormsAutomation();
                auto.AddStep(ActionType.Run, "OIS103");
                auto.AddStep(ActionType.Key, 'ENTER');
    
                auto.AddField('OKCUNO', this.cuno.Text);
                auto.AddField('ZZORNO', this.orno.Text);   
                auto.AddStep(ActionType.Key, 'ENTER');
    
                var uri = auto.ToUri();
                DashboardTaskService.Manager.LaunchTask(new Task(uri));
    

    Like

Leave a comment