JScript Feedback

This page has been closed for comments. Please use the Infor Community for feedback and questions.

We would like to get feedback from all JScript developers.

What kind of utility methods have you developed? What kind of information do you need from the M3 panels?
If you are looking for stuff in the visual tree, what are you looking for, can we provide you with an API since accessing stuff in the visual tree is not supported and might brake in coming releases?

How can we help you be more productive?
Please describe the scenario and what you would like to do with the JScript. Reply by entering a comment.

173 thoughts on “JScript Feedback

  1. José Ramon

    Hi,
    I’m trying to program a script that changes the looks of a row in a listview.
    In panel MWS060 I want to make easier for the user see the different warehouses for the same item, i.e. changing the color of the row, or the font…
    I’m obtaining the Container Generator and then changing properties:

     
    listViewItem = listView.ItemContainerGenerator.ContainerFromIndex(i);
    listViewItem.Background = color;
    

    But seems a lot of programming, I have to control when the ContainerFromIndex can be applied, control the scrolling on the listview, keeping temp values for the warehouses to compare them with the rest of the rows… and not sure if that’s the best way to do it (if possible).

    Thanks.

    1. Joshua

      Hello, I currently learning about of Smart Office for M3 and I would like to know how is a code change, such as the one you wrote above, migrated into the production instance of M3.

      1. karinpb Post author

        Hi, There are two steps that needs to be performed. You need to be a H5 Administrator (M3-UI- Administrator)
        1. The script is uploaded in H5 Admin tool (web client) in the Data Files tool. It’s a tool for uploading different types of files, for example JScript but also JavaScript (for the H5 client)
        2. You connect the script to a program/panel by adding a script personalization

        This is true for the newer versions. In earlier versions the files were just placed on disk.

  2. Jose Ramón

    Hi again :).
    It’s clear now how to change the looks of the row but in the script I’m working I need to set different templates according to values for the previous row.
    Can I set different templates depending on values of the previous row?, like if previous row has column[2] = ‘some_string’ then the template is templateGreen, otherwise templateRed?.

    Thanks.

    1. karinpb Post author

      In the SelectTemplate method you can use the name property on the item to get the Row name of the current row.

      var rowName = item.Name; // r1, r2 etc. To get the row index substring the name to get the number eg, r3->3-1=2-> current row index.

      Then get the previous row:
      var previousRow = listView.Items[currentRowIndex-1] (don’t forget checks if you are on the first row).

  3. Lode Vlaeminck

    Hi, I would like to know how i can acces the browse popup when you press F4 on a field to limit the value that can be selected

    1. Lode Vlaeminck

      I found it, but now my script is running in an other program. how do i end the script and keep it inside 1 program ?

      1. karinpb Post author

        I’m afraid there is not enough information for us to help you. You should be very careful when running scripts to make sure the script is unloaded and all event handles are removed, once you leave the program.

  4. Jim Stewart

    Currently planning an upgrade from 7.1 to 13.2(3). I am trying to avoid recreating extension tables and modifications to the Java source. I’m thinking JScript is the way to go but can’t find a great example that does this, or even if its possible. I am basically trying to replace the code in PEDSP,PECHK,PEPMT,PEUPD. I’m trying to update CUGEX1 using apis AddFieldValue and ChgFieldValue. For instance I have a custom table with “Assignment Type” and “Bank for Season”. Assignment type is a field I need to prompt 4 (or have in a list view as I only have a few), Bank for Season is a check box. I’d need to protect the fields in Display mode. I do not own Mashups which may make the F4 tricky from what I’ve found so far. Any awesome great examples would be appreciated, or am I trying to take this one step too far.

    1. karinpb Post author

      Hi, I would think that trying to replace code in PEDSP,PECHK,PEPMT,PEUPD is taking it too far but perhaps not it applies to only showing a field or two in one panel. But as you mention that you would need to Browse(F4) for it – then it requires validation as well – probably with an API. For the F4 you would need a Mashup (possibly with enterprise search).

      Even if you don’t have Mashups (so you can’t build new ones – perhaps there is an existing Mashup that you can use or perhaps a partner can help?). You can use the Mashup runtime without having the Mashup Designer at least as far as I understand. Mashups are great and you should definately consider adding it. We don’t have a full example like that and it depends on all the available functions and the specific program as well. There is one about validation that would help and one that has the custom browse example.

  5. Mark

    Hi,

    I am working on a custom screen using Jscript in M3 and I am having trouble with the text validation.

    Here is my problem:

    I am validating two parameter fields in a custom form using JSCRIPT and the error should be ” Input parameter 1 is missing, please fill value” and Input Parameter 2 is missing, please fill value”

    It seems that the program is validating all fields even if the input parameter 1 field is not yet filled. What I want in my program is to validate my first parameter. Once I have the provided a value on that parameter, then that is the only time the 2nd validation will be processed.
    Basically, I dont want my program to proceed to another validation or action until my 1st parameter has been validated.

    I am sorry. I am just newbie in Jscript and M3. I Hope you can help

    Mark

    1. karinpb Post author

      I’m not sure I fully understand your scenario. As it involves validation I’m assuming that you would like to do the validation as the user press next to go to the next screen. Thus the request is already submitted so you would need to always cancel that request – perform your jscript validation – and then trigger the “next/enter/submit” action in the background if both input1 and input2 is valid. This kind of script that spans requests is complex as in most cases you will end up not detaching events correctly with the script running in multiple instances on the same panel as a consequence. I would not recommend this to a newbie wihout assistance from an experienced jscript developer. Check the validation example since you don’t need to call an MI program your scenario would be easier that this one.

      1. Mark

        Hi,

        Thanks for the reply but I already saw the solution from the same link. Cool!

        Can I ask you another question?

        I am working on this particular custom screen using jscript via Smart office that will trigger a flow. The custom screen contains 20 parameter/input fields and will be used by PFI (thru service variable definition) when the flow is triggered from custom form.

        Unfortunately, I am encountering an internal server error and it seems that PFI doesn’t allow us to process more than 15 service variables names.

        Have you encounter this issue before? If yes, what alternative solution do you propose if we have more than 15 service variables needed in the flow?

        Error:
        TEST Master Setup %26varName[0]=Company%26varValue[0]=1%26varName[1]=Division%26varValue[1]=010%26varName[2]=UserId%26varValue[2]=test%26varName[3]=RequestedBy%26varValue[3]=DEV%26varValue[3]=TEST TEST%26varName[4]=CurDate%26varValue[4]=Mon Mar 2 16:37:49 EST 2015%26varName[5]=VendorRequest%26varValue[5]=%26varName[6]=VendorName%26varValue[6]=%26varName[7]=Address1%26varValue[7]=%26varName[8]=Address2%26varValue[8]=%26varName[9]=TelNum%26varValue[9]=%26varName[10]=FaxNum%26varValue[10]]=%26varName[11]=ContactDtl%26varValue[11]=%26varName[12]=ProdDtl%26varValue[12]=%26varName[13]=DateDtl%26varValue[13]=%26varName[14]=AmountDtl%26varValue[14]=%26varName[15]=AnnTranDtl%26varValue[15]=test
        Error: The remote server returned an error: (500) Internal Server Error

        And last question, how do you validate the checkbox if its checked or unchecked in jscript?

        Thanks again!

  6. Maxric

    Hi to all,

    I would like to submit you a problem i am not able to solve on a script running in a single panel A (no list).
    The panel is used to create packages in a customer order by flashing bar codes; the data red by the mobile device (data acquisition) is written into an input field on the panel and the device adds the ENTER key at the end. So each time we flash something, the javex program validates the data.
    – if the data is correct, we can continue (the input field is cleared and the cursor has focus on it so that the next flash will fill up the input field with new data)
    – if the data is incorrect, the error message is displayed in a classic errorTextBox. The problem is that the user is not always in front of the screen and he is not aware of the error if there is one : here comes the script.

    On the next ENTER (i.e. on the next OnRequesting event), if the errorTextBox.Text is not blank, then the screen is changed in red, the error message is enlarged in a bigger textBox and a sound is provided to alert the user. The curor focus is not any more on the input textBox and any new flash will block the user. The only possibility he has to continue is to come in front of the M3 panel and press Fxx key.

    The main complaint of the user is that he has to wait the next ENTER key (so the next flash) to be alerted fron an error on the previous flash. I don’t know how to catch immediately the content of the errorTextBox when the javex program displays the panel after the control; i tried to use TextChanged event on the errorTextBox but without success.

    Do you have any idea about how to catch the content of a TextBox without using OnRequesting event ?

    Thanks!

    1. Maxric

      Hi again,

      In fact i have just found what to do : use the RequestCompleted event ! 🙂

  7. EB

    Hello,
    Until the last update, everything worked fine.
    But in the last update , we have a problem to reffer to LABELS.

    when I use the method ScriptUtil.FindChild(controller.RenderEngine.Content,ControlName), So if it is text box, check box etc. etc. – then it work good.

    BUT when it is a Label (part of System.Windows.Controls.TextBlock) – So we get an Error : Object Requiered.

    I need to know, what changed in the last version regarding to this issue, and how to fix it.
    It is VERY IMPORTANT. Please reply me ASAP.
    Thanks & regards
    EB

    1. karinpb Post author

      Hi, I have forwarded this question to Norpe.

      Reply:
      We had to change the Labels to use TextBlock instead of text to show the text. The reason is that some labels had underscore which would turn to accellerator keys. A label is a content control so it can have any content. In the last version the content is a TextBlock and not a string. You can get the content and check if it is of type TextBlock an in that case you need to get the Text() property to get the text.

  8. Jose R.

    Hi,
    I’m working on this mashup that shows customer information.
    I have to retrieve the CUNO from data that comes from another program being executed on the pc.
    I don’t know how to send information from this program to the mashup inside Smart Office, and I don’t know where to start looking into, JScript, Extensions, Smart Office SDK…
    is there a way, with an url, to call a mashup from outside Smart Office?, and even to set data into it?.

    Thanks for your time.

    1. karinpb Post author

      This “other program on the PC” is this a program you can develop/modify?
      There are two communication options (if the install is ClickOnce).
      1. Launch a new Smart Office with a URL that has a TASK parameter. The task parameter would startwith mashup://xxxx. The mashup can have default parameters. There is one example covering that in the Mashup Designer examples. I would need to check a shortcut to a deployed mashup to get a real example (I’ll add the full example URL later)
      2. Use a local port and submit a message to it – but then the “other program” must be able to detect the port – and only programs launched from SmartOffice would know the port
      3. Named pipe integration. This is standard Microsoft technology but requires coding.

      If you can get the other program to launch an URL (and IE is the default browser) you should be able to calculate the task. BUT CUNO must be valid as a URL paramter without special characters- eg “arla” is OK but not “skånemejerier” – as it will give you a URL with bad encoding. Or you must be able to encode parts of the URL after adding the CUNO part.

      1. Jose R.

        Hi,
        I could modify the code of the ‘other app’, and open the mashup with a link like the one on the example in the designer, but I had to encode the uri, otherwise I get an error.

        Thanks!

  9. Jose R.

    Hi,

    At this stage I’m not sure how much I would change the code of the other software.
    But I think I can try the first option, calling the mashup and encoding the URL parameters.
    Then in the mashup I will have to find a way to refresh the information shown depending on the parameter.

    Tack.

  10. Linda N A

    Hi,
    when the script is running in a mashup – is there a way to get hold of the runner.Host for the mashup so that you can access the HostContent, say for example a textbox and write some values to it?

    1. karinpb Post author

      Hi,
      When you are running a script you can access anything in the visual tree. I would recommend using Snoop to check the visual tree and then the class called VisualTreeHelper to first find a parent of a specific type and then search for the textbox using the name. We have our own util built on top of that standard class – but I need to check if it is public. If you have a more specific scenario that would help as you will only find the textbox if it has a specific name. But navigating the visual tree is not fully supported as the structure might change between versions. But navigating for a specific name or class type is usually never changed.

      I would need to have a quick look into the code to be sure I give you the correct classes to search for but some more info would be nice. Is the textbox in a M3 detail / MI detail or why would you set it in script and not by an event?

      1. Linda N A

        Hi!
        My script is intended to give the user a possibility to delete multiple rows at once from a customlist and imitate normal M3 behaviour. I have successfully used the Visualtreehelper to find my mashup textbox and placed the key values for the rows to be deleted in there. So when a delete button is clicked, a loop in the script can send the selected row data into a bookmark string and execute it.

        But there is a big problem that I’m hoping you have the solution for. If I don’t enable the listview somehow in the mashup (opening and closing the filter works) and then do a manual refresh of the mashup, I can’t go up the visual tree to the top parent that I find when using Snoop on the mashup window. It’s like the visual tree doesn’t know that it’s currently in a mashup (with extra content) instead of the M3 program unless I do this, and therefor the visual tree stops at GridContent and I never get to the content that’s in the mashup.

        I hope I have described the problem so you understand it. Is there any way you can think of that this can be fixed, or am I doing something wrong in my code?

  11. Angelos Arampatzis

    Hello! I am building a script that needs to read information from a database external to M3 and then display this information in a panel. The problem I have is that the JScript Tool refuses to recognize the declaration of SqlConnection. I am importing both System.Data and System.Data.SQLClient, but when I am trying to declare a variable of type SqlConnection I get an error when compiling:
    var aDbConnection = new SqlConnection(‘server=T-M3DB;database=M3FDBTST;uid=username;pwd=password’);

    Variable ‘SqlConnection’ has not been declared

    I have copied the script from https://thibaudatwork.wordpress.com/2011/09/09/sql-to-xml-in-a-script/ and it compiles just fine.

    Thanks in advance for your time.

    1. karinpb Post author

      Hi,
      Did the example compile and run for you? Becuase there must be a typo or something in the script and the variable in the example was called connection and not var aDBConnection so you have done modifications so I would need the entire script and the exact error information. I had not seen this example before and I have to inform you that it is very unsecure to have the user and password in the connection string like this. It has to be a user that has very limited access to the databse, only read access and you have to be fine with everyone being able to get the user and password as the script files are loaded with http and which means that they are visible in plain text and the connection string pattern is an easy partter to search for. I’m just saying that it is a very unsecure and I would recommend using a web service (like Infor Web Service that can create web services from a stored procedure) instead of exposing the connection string. It’s easy I know just a big security risk. Even if access is correct and very strict to start with you never know if someone will give that user more rights to the DB in the future.

      1. Angelos Arampatzis

        Karin thank you for your reply and all the security-related issues you pointed out. I am well aware of those, and the plan is to use a WS to supply the information to the script. For now I am building a just proof-of-concept to allow the users to evaluate the solution.

    2. Angelos Arampatzis

      I found what the problem was: System.Data.SQLClient needs to be System.Data.SqlClient.

  12. Jose R.

    Hi, is there a way to read/write messages that appear on the bottom of a panel (status bar) from JScript?.
    I tried:
    WriteProperty(“Message “, panelState.Message);
    WriteProperty(“MessageId “, panelState.MessageId);
    But is not working.

    Thanks.

    1. karinpb Post author

      Hi,
      There is a method to read the message from M3 and a way to add a message. But if the message appears in the statusbar or in a dialog depends on a user setting. You have no control of that.
      The following methods should be available if you are on 10.0.5.x or later.

      controller.RenderEngine.ShowMessage("Message text");
      
      // To read the message. Note! Read-only property
      controller.PanelState.Message
      controller.PanelState.MessageId
      
  13. Mikael

    Hi,

    I am building mashup that merges that product information from PDS001/PDS002 etc in a mashup. However I have encountred a problem (small). I would like to have search-button that is displayed in the detail panel, which should diplay item related information when clicked on. I tried to do this using a button which call MMS200MI – Get (MIPanel). But I don’t konw how to configure the button to search? The information I have is the product number (PHPRNO) from MPDHED.

    Br,
    Mikae

  14. Jose R.

    You can try to trigger the API call to MMS200MI/Get to fill a detail panel.
    On the click event of ths button you can retrieve the PHPRNO from the list (PDS001/002).

  15. Suraj

    Hi,

    We have build a number of Smart Office personalisation’s based on Jscript to enhance the usability of some of the screens. These scripts utilize calls to M3API and Some custom REST services that we have written and hosted within the Network.

    The client has just informed that they want to start providing their users the ability to use H5 client.

    My question is
    1. Can the scripts be ported to the H5 Client?
    2. If not what are the options available on H5 client to do something similar?

    Thanks,
    Suraj

  16. Jose R.

    Hi,

    In InforXtreme there is a guide called: “H5 Development Guide”. Its a good start.

  17. Jose R.

    When adding a colunm to a List Panel in Smart Office through scripting, is there a way to add a personalization (Conditional Style) to that new column?.
    I tried editing the personalization xml, adding the name of the new column, with no success…

    Thanks,
    Jose

  18. Shawn VS.

    Lawson S3 jscript help to access a tab area defined in a detail area.

    I am attempting to add a new tab to the Infor delivered PO20 screen in S3 via jscript. The form contains the main form grid. On that is a detail area which contains 5 detail lines. On each detail line is a set of 6 tabs. I am attempting to add a 7th tab to the detail area. However, when I try to use any of the Infor defined helper functions none of them seem to be able to access the tab area under the detail area.
    I tried using both of the code examples below to either access or update the tab area and both of the objects are coming back as undefined.
    var aa = formGrid.GetTabPageContainer(“TF0-0”);
    console.WriteLine(“GetTabPageContainer: ” + aa);

    var bb = formGrid.AddTabPage(“TR0”, “TF0-6”, “NewTab”, “”);
    console.WriteLine(“AddTabPage: ” + bb);

    Any help is appreciated.
    Thanks,
    Shawn

    1. karinpb Post author

      Comments from S3 Developer:
      I see a couple problems with the script provided:
      1) formGrid is a global variable, but it does not have a method of GetTabPageContainer. The method is available on the other global variable named form.
      2) When working with detail areas, such as adding tab pages or other visual elements, you must use of on the static methods in ControlsUtil. For tab pages the method is named, AddDetailTabPage.

      The Object Browser, available from the Help menu of the Script Tool provides documentation and sample code that can be quite useful.
      Also, look to the code insertion helpers in the upper right corner of the tool. If you use that, it would have inserted:

      var count = ControlsUtil.AddDetailTabPage(form, detailName, tabPageName, text);

      Then you would fill in necessary parameter names:

      var count = ControlsUtil.AddDetailTabPage(form, “DT0”, “TF0_6”, “New Tab”);

      If the count is greater than zero, the method succeeded and you could add controls to the tab:

      if (count > 0)
      {
      // add controls to the tab pages
      ControlsUtil.AddDetailLabel(form, “DT0”, “TF0_6”, “MyLabel”, 3, 5, 20, “Label content”);

      }

      This is one of the code examples found in the Object Browser.

  19. Martin Stephens

    Hi,

    We are upgrading M3 from modified 7.1 to vanilla 13.3. We are using Jscripts to get around some of the old modifications. One of these maintains records in CUGEX1 using ChgFieldValueEx.

    This updates the new part of the record that holds dates and check boxes.

    My script writes and updates dates ok, but I am having trouble clearing a date value using the API. I have tried using a zero length string “”, a string containg 0 (“0”), and various other permutations of “00000000”, “0000/00/00″ etc. but all return ” an “Incorrect date” error.

    Do you know how to do this?

    Regards,

    Martin

    1. karinpb Post author

      Hi,
      Is this a standard API? What is the program name and is the transaction ChgFieldValueEx? Perhaps if you can change the metadata for the field in the transaction and try and pass in “” (blank) it might work. If a field is a date then I don’t know how to pass in a blank date when using the rest-end point. But I don’t know if this is a valid scenario. The position based API uses ‘?’ to indicate “no value / clear value” but this should be wrapped in the REST call. But if the metadata says it has to be a date – it don’t know how to clear the date since we would validate and transform. It’s an interesting question and if this is a standard API I need to know more details so that I can ask the M3 Development Organisation.

      1. Martin Stephens

        Hi Karin,

        It is a new standard transaction in the CUSEXTMI API. The customer extension table has a new section to store check boxes and dates. I reported it to the xtreme helpdesk yesterday as well. I tried blank “”, and ? etc nothing seems to work.

        Regards,

        Martin

      2. Martin Stephens

        Hi Karin, Just to let you know this has gone to development to get the API fixed.

        Regards,

        Martin

  20. Joe Walker

    Hi – I am trying to write a script that opens OSS415 in M3 and populates the order number in the field that is an entry field in the part of the B panel. I can get it to populate the header fields fine but can not find a way to get it to populate this field. It is an entry box but part of the list panel rather than a header field. The script is below but I can’t get the ORNO.Text field I have picked up to go into this box. I can get it into the WWUFLD field that is at the top but this is not where it needs to go.

    Any ideas whether this is possible or how to resolve it?

    Thanks,
    Joe

    var auto = new MFormsAutomation();
    auto.AddStep(ActionType.Run, “OSS415”);

    auto.AddStep(ActionType.Set, String.Empty);

    auto.AddField(‘WHRPID’, ‘LSALE2’);
    auto.AddField(‘WASBRL’, ‘2’);
    auto.AddField(‘WBACPE’, ‘1510’);
    //auto.AddField(‘UCORNO’, ORNO);
    //auto.AddField(‘XJSBFA’, ORNO);
    auto.AddField(‘WWUFLD’, ORNO.Text);

    //auto.AddStep(ActionType.Key, ‘ENTER’);

    var uri = auto.ToUri();
    DashboardTaskService.Manager.LaunchTask(new Task(uri));

  21. Colm Hayes

    // Hi. I’m wondering if anyone can help out. I’m trying to develop a script to create records in PCS260 using data stored in an excel file. When the form loads a button is added and on click of that button the first record is created and the instance Cache increments up so the second time the form loads there is if statement to get more data from the excel file without the need for the user to click the button.

    //Everything works fine with the button but the next time the form loads after cycling through Panel E and back to Panel A the excel information is not added and the “System.Windows.Forms.SendKeys.SendWait(“^1″);” doesn’t create a new record.

    //Any help would be much appreciated

    import System;
    import System.Windows;
    import System.Windows.Controls;
    import MForms;
    import System.Windows.Forms;
    import Excel;
    import System.Reflection

    package MForms.JScript {
    class PCS260_A_Loop {

    var debug, button, content, gcontroller;
    var giStep;
    var gITNO;
    var bRemoved;

    public function Init(element: Object, args: Object, controller : Object, debug : Object)
    {
    //Create An Instance Cache and a Counter
    var counterInstanceCache = 0;
    var key = “TestCounterInstanceCache”;

    //Check if Instance Cache Already Exists and if so set the counter value
    if(InstanceCache.ContainsKey(controller, key))
    {
    counterInstanceCache = InstanceCache.Get(controller, key);
    }

    // Increment the Instance Cache Counter
    counterInstanceCache++;

    InstanceCache.Add(controller, key, counterInstanceCache);
    MessageBox.Show(“Instance Cache Counter: = ” + counterInstanceCache);

    //Create a Controler for the Mform
    this.gcontroller = controller;
    content = controller.RenderEngine.Content;

    //Add A Button
    button = new Button();
    button.Content = “Import”;
    Grid.SetColumnSpan(button, 10);
    Grid.SetColumn(button, 26);
    Grid.SetRow(button, 12);
    content.Children.Add(button);
    button.add_Click(OnClick);
    button.add_Unloaded(OnUnloaded);

    //IF STATMENT TO CHECK IF THE CODE HAS AREADY RAN AND IF SO RUN AGAIN WITHOUT NEED OF THE BUTTON
    if (counterInstanceCache>1)
    {
    if (counterInstanceCache<15)
    {
    MessageBox.Show("In The Loop");
    try
    {
    // Create an Excel Instance
    var exExcel = new ActiveXObject("Excel.Application");
    // Set the Work book to not show
    exExcel.Visible = false;
    // Set the Workbook Address and Open The Workbook
    var wbBook = exExcel.Workbooks.Open("C:\\Users\\colm.hayes\\Desktop\\PCS260 upload.xlsm");
    // Get Values from the Workbook
    var Item_Number = wbBook.Worksheets(1).Cells(2,1).Value
    var Cost_type = wbBook.Worksheets(1).Cells(2,8).Value
    var Cost_Date = wbBook.Worksheets(1).Cells(2,7).Text
    var Date_Offset = wbBook.Worksheets(1).Cells(2,9).Text
    // Save and Close the Workbook
    wbBook.Save();
    wbBook.Close();
    //Find the fields on the Mform
    var W1ITNO = ScriptUtil.FindChild(content, "W1ITNO"); // Item Number
    var W1STRT = ScriptUtil.FindChild(content, "W1STRT"); // Structure Type
    var W1PCTP = ScriptUtil.FindChild(content, "W1PCTP"); // Costing Type
    var W1PCDT = ScriptUtil.FindChild(content, "W1PCDT"); // Costing Date
    //Calculate the Date for the Costing Date
    var dtCurrent : DateTime = DateTime.Now;
    var dtCurrent = dtCurrent.AddDays(Date_Offset); // Today + 1 day
    //Add the Values from the Excell Workbook to the Mform Fields
    W1PCDT.Value = dtCurrent ;
    W1ITNO.Text = Item_Number;
    W1PCTP.Text = Cost_type;
    W1STRT.Text = "001";
    //Set the focas back on the MForm and send the keyboard shortcut CTLR + 1
    MessageBox.Show("Send Wait");
    W1PCTP.Focus();
    System.Windows.Forms.SendKeys.SendWait("^1");

    //Catch errors
    }
    catch(ex)
    {
    debug.WriteLine(ex.Message);
    }

    }
    }

    }

    public function OnClick(sender: Object, e: RoutedEventArgs)
    {
    try
    {
    // Create an Excel Instance
    var exExcel = new ActiveXObject("Excel.Application");
    // Set the Work book to not show
    exExcel.Visible = false;
    // Set the Workbook Address and Open The Workbook
    var wbBook = exExcel.Workbooks.Open("C:\\Users\\colm.hayes\\Desktop\\PCS260 upload.xlsm");
    // Get Values from th Workbook
    var Item_Number = wbBook.Worksheets(1).Cells(2,1).Value
    var Cost_type = wbBook.Worksheets(1).Cells(2,8).Value
    var Cost_Date = wbBook.Worksheets(1).Cells(2,7).Text
    var Date_Offset = wbBook.Worksheets(1).Cells(2,9).Text
    // Save and Close the Workbook
    wbBook.Save();
    wbBook.Close();
    //Find the fields on the Mform
    var W1ITNO = ScriptUtil.FindChild(content, "W1ITNO"); // Item Number
    var W1STRT = ScriptUtil.FindChild(content, "W1STRT"); // Structure Type
    var W1PCTP = ScriptUtil.FindChild(content, "W1PCTP"); // Costing Type
    var W1PCDT = ScriptUtil.FindChild(content, "W1PCDT"); // Costing Date
    //Calculate the Date for the Costing Date
    var dtCurrent : DateTime = DateTime.Now;
    var dtCurrent = dtCurrent.AddDays(Date_Offset); // Today + 1 day
    //Add the Values from the Excell Workbook to the Mform Fields
    W1PCDT.Value = dtCurrent ;
    W1ITNO.Text = Item_Number;
    W1PCTP.Text = Cost_type;
    W1STRT.Text = "001";
    //Set the focas back on the MForm and send the keyboard shortcut CTLR + 1
    W1PCTP.Focus();
    System.Windows.Forms.SendKeys.SendWait("^1");

    //Catch errors
    }
    catch(ex)
    {
    debug.WriteLine(ex.Message);
    }
    }
    // Remove the button from Memory
    public function OnUnloaded(sender: Object, e: RoutedEventArgs)
    {
    button.remove_Click(OnClick);
    button.remove_Unloaded(OnUnloaded);
    }

    }
    }

    1. norpe

      I’m not sure exactly why the script does not work as expected but here are a couple of things I noticed.

      You should never rely on the Unloaded event to disconnect events. This event is might not fire in all cases which can cause incorrect behaviors with multiple active event handlers. Always use the Requesting event on the controller instance and disconnect all events there (including the Requesting event). There should be lots of examples of this in the scripts examples in the blog.

      The create list option can be triggered by a method on the controller instead of using SendKeys.SendWait.

      Examples with constant and hardcoded option (option -1 is used internally for create compared to option 1 for select):

      controller.ListOption(MForms.MNEProtocol.OptionCreate);
      controller.ListOption("-1");
      

      I’m not sure why the Excel document is loaded for each panel? It seems like it just gets the same values each time so the values could be cached. If the Excel document must be loaded each time I would create a function for that to avoid duplicating the code.

      Is it necessary to Save the Excel document? It does not seem like the content is modified.

  22. Dirk Deperz

    Hi, I am searching for an example of a mforms automation uri which is launched within a mashup (example through a button)
    mashup:Event SourceEventName=”Click” LinkUri=”mforms://automation….

    the pgm that I want to launch has no bookmarks and in this way I want to prefill the fields with a value from the mashup

    1. karinpb Post author

      Hi,
      You should check the Smart Office SDK. The M3 Developers guide included in the download zip has a few examples and the zip also contains MFormsAutomationBuilder.exe (External\M3\Tools) that is a program that will help you build the xml template. I think the syntax you have for the button if fine the trick is building the XML with the values as well as understanding the limitations with automation. If you have the MFormsAutomationBuilder tool you can get a launch URL that you can try in Smart Office. But keep in mind that automation only works for a specific view etc.

  23. Raul

    Hello,
    I have two questions that I’m sure you can answer (I’m not very experienced jscript developer):

    1. I’m trying to develop a jscript to add a column to a list. Your scripts have been very useful and I did it but, when I use “Display” option on a row, my news column for that row is empty and I don’t know how to refresh again the information for it.

    I’ve been trying to add a routine on OnRequested function, but no success. Any idea?

    2. I saw that the OnRequested or OnRequestCompleted functions seems that they are removing themselves or other functions. That means that the removed functions will not work anymore? I mean, when I double click a row on a program with a script, the function OnRequested is running and its removing itself. Then, the second time that I double click another row, nothing happens because the function doesn’t exists. Is this normal?

    function OnRequestCompleted(sender: Object, e: RequestEventArgs) {
    try {
    var controller: MForms.InstanceController = sender;
    if (controller.RenderEngine == null) {
    scrollViewer.remove_ScrollChanged(OnScrollChanged);
    controller.remove_RequestCompleted(OnRequestCompleted);
    }
    } catch (ex: Exception) {
    debug.WriteLine(“OnRequestCompleted: ” + ex);
    }
    }

    Thank you in advance.

    1. norpe

      Most of the times when you get back from to a list panel to a detail panel the BE program will return updated list rows. Any local modification such as added columns will be list and have to be reapplied again.

      A script that modifies list columns must check which list rows that needs to be updated each time the script loads.

      The script should always disconnect all events when the panel is reloaded (when the Requested event is triggered) to avoid memory leaks and multiple instances of a script executing at the same time.

      1. Raul

        Thank you very much for you reply.
        I know the selected row and I tried to update, but no success. The program is entering within the routine, but the row is not updated.
        Any idea?

        Thank you in advance

  24. Angelos Arampatzis

    I am building an MForms automation script that changes the Warehouse From field in DPS170/E, but so far all my efforts have failed. For reason unknown, I can change none of the panel’s fields. A very simple script that demonstrates the problem is this:

    import MForms;
    import Mango.UI;
    import Mango.UI.Core;
    import Mango.UI.Core.Util;
    import Mango.UI.Services;

    package MForms.JScript {
    class Test {
    public function Init(element: Object, args: Object, controller : Object, debug : Object) {
    var auto = new MFormsAutomation();

    // Start DPS170
    auto.AddStep(ActionType.Run, “DPS170”);
    auto.AddStep(ActionType.Key, “ENTER”);

    // Set the sorting order
    auto.AddField(“WWQTTP”, “15”);
    auto.AddStep(ActionType.Key, “ENTER”);

    // Specify the planned order number
    auto.AddField(“W1OBKV”, “3017892”);
    auto.AddStep(ActionType.Key, “ENTER”);

    // Call the Edit option
    auto.AddStep(ActionType.ListOption, “2”)

    // Specify the desired value for the Warehouse From field
    auto.AddField(“WEFWHL”, “133”);

    // For testing pusrposes
    auto.AddField(“WEPRIP”, “4”);
    auto.AddField(“WEPTXT”, “Test text editing…”);

    // This is commented out to demonstrate that we are indeed in edit mode in DPS170/E
    //auto.AddStep(ActionType.Key, “ENTER”);

    var uri = auto.ToUri();
    DashboardTaskService.Manager.LaunchTask(new Task(uri));
    }
    }
    }

    The script successfully changes the sorting order, specifies the planner order number and calls Change (option 2), thus entering DPS170/E in edit mode. But all calls to AddField accomplish nothing.

    Does anyone have any ideas about what might be causing the problem I am facing?

    Thanks!

    1. norpe

      First of all you should always add a step first and then add the fields that you want to set for that step. In your example it seems a bit mixed up and there were some unnecessary Enter steps. I have modified your example to make it easier to see which step a field belongs to.

      If you want to set values on a panel without committing the panel with Enter you need to use a step with ActionType.Set. This will set values on the last panel in an automation but it is up to the user to actually commit the values. Note that ActionType.Set can only be used on the last panel in an automation.

      import MForms;
      import Mango.UI;
      import Mango.UI.Core;
      import Mango.UI.Core.Util;
      import Mango.UI.Services;
      
      package MForms.JScript {
          class AutomationRepro {
              public function Init(element : Object, args : Object, controller : Object, debug : Object) {
                  var auto = new MFormsAutomation();
      
                  // Start DPS170
                  auto.AddStep(ActionType.Run, "DPS170");
      
                  // Set the sorting order
                  auto.AddStep(ActionType.Key, "ENTER");
                  auto.AddField("WWQTTP", "15");
      
                  // Specify the planned order number
                  auto.AddStep(ActionType.Key, "ENTER");
                  auto.AddField("W1OBKV", "3017892");
      
                  // Call the Edit option
                  auto.AddStep(ActionType.ListOption, "2")
      
                  // Set values without committing the panel with ENTER
                  auto.AddStep(ActionType.Set);
                  auto.AddField("WEFWHL", "133");
                  auto.AddField("WEPRIP", "4");
                  auto.AddField("WEPTXT", "Test text editing…");
      
                  // Set values and commit the panel with ENTER
                  //auto.AddStep(ActionType.Key, "ENTER");
                  //auto.AddField("WEFWHL", "133");
                  //auto.AddField("WEPRIP", "4");
                  //auto.AddField("WEPTXT", "Test text editing…");
      
                  var uri = auto.ToUri();
                  DashboardTaskService.Manager.LaunchTask(new Task(uri));
              }
          }
      }
      
  25. Daniel

    Hi,
    I try to get a text out of a text panel in PMS101. The idea is to have kind of marco that opens the text panel, takes the text, modifies the text, paste it back in and press next. All without having complicated “select” and “update” web services or using APIs.

    The problem is that the window of the text panel is somehow out of everything.

    ScriptUtil.FindChild(content, “TX60”) does not work.
    So I tried with copy and past the text with keyboard commands and work with the clipboard in the script.
    this.controller.PressKey(“F6”); works to open the text panel. But with “PressKey()” I cannot do key combinations; as far as I know.
    System.Windows.Forms.SendKeys.SendWait(“^a”); will mark all text but as it is a “SendWait” it does wait until the window gets closed by the user.
    Forms.SendKeys.Send(“^a”); does not work; error that it cannot run inside this application because the application is not handling Windows messages.

    Any idea to that?

    Br
    Daniel

    1. karinpb Post author

      Hi Daniel,
      I discussed this with *norpe* since he is the expert and it should be possible just that there are many bits and pieces and they are all complex and it could take as long as one day for us to write an example on this.

      There are a few different parts:
      1. Leave the script running and do not unload on onRequestedCompleted if the panel the text panel is loaded. Dispatch to the UI thread to look for the text panel dialog – possible with a small delay so you don’t try and access the dialog before it has opened.
      2. The text can have multiple lines so you would need to handle that as well
      3. Check if you can find the text panel dialog using System.Application.Windows collection over windows. To get the text field you can search the WPF visual tree using System.Windows.Media.VisualTreeHelper or our Mango.UI.Helpers. If that does not work there might be some native APIs that can be used to get the current window. It’s a modal dialog.

      I would use Snoop to investigate what to search for in the visual tree but first you need to find the modal dialog and I’m not sure how to do that so that would require some research. I wish I could be more specific but this is not an easy task.

  26. Amy

    I am looking to somehow have some validation at entry on OIS100/A so that if the order type is DIR the facility is updated to A08, OR that it warns the user to change the facility to A08.

    1. karinpb Post author

      Hi,
      I don’t have such a script but I might create one as this would be a rather easy task. You need to add an event handler to the OnRequesting event and then if the facility and order types does not match you can cancel the request and change the facility. I don’t think you should do this automatically since it will be more complicated.

  27. Len Lim

    Hi,
    I’m just starting to learn H5 client scripting. How can we get the user Role of the user who is currently login? In ISO, we use
    var userRole : String = UserContext.Roles[0].Role;
    How do I do that in H5 client? And also how can I get the text value from a label?
    In ISO, I use this
    var content = controller.RenderEngine.Content;
    var tmpOrderNum : String = ScriptUtil.FindChild(content, ‘OAORNO’).Text;

    Thanks,
    Len

    1. gsmarquez

      Hi Len,

      If you are starting with H5 scripting, I would recommend looking into Infor M3 H5 Development Guide.

      Regarding your questions:

      1) The user roles are not yet available in H5 client but it is on its way. For now you can retrieve UserContext values by using ScriptUtil.GetUserContext(contextProp).
      2) To get the text values, you can use the function ScriptUtil.GetFieldValue(fieldName).

      Here is a sample code.

      var Test = new function () {
          this.Init = function (scriptArgs) {
             
              // get a specific property from the UserContext
              console.log(ScriptUtil.GetUserContext("CONO"));
      
              // get field value from detail panel
              console.log(ScriptUtil.GetFieldValue("WFSLCT"));
          }
      }
      
      1. Len Lim

        Hi,
        Thanks for the reply. I have another question. Is there a conversion for H5 script of OnRequesting and OnRequested function?

        Here is a sample :

        public function OnRequesting(sender : Object, e : CancelRequestEventArgs)
        {
        if ((e.CommandType == “KEY” && e.CommandValue == “ENTER”) || (e.CommandType == “LSTOPT” && e.CommandValue == “2”) || (e.CommandType == “LSTOPT” && e.CommandValue == “4”) )
        {
        if (datestring == tmpOrderDate)
        {
        debug.WriteLine(“same date”);
        }
        else
        {
        e.Cancel = true;
        ConfirmDialog.ShowWarningDialog(“Change Not Permitted”, “”, null);
        }
        }

        }

        public function OnRequested(sender : Object, e : RequestEventArgs)
        {
        controller.remove_Requesting(OnRequesting);
        controller.remove_Requested(OnRequested);
        debug.WriteLine(“Script unloaded”);
        }

      2. karinpb Post author

        Hi,
        For H5 questions please use the new H5 Scripting page to submit comments.
        The example is JScript and not JavaScript (H5). I thought the question was if there was a “convention” – of how to best use the events. In you case you are detaching the events just fine and the same pattern applies to Javascript.
        But as for as if there is a conversion of H5 script? Do you mean if you can convert a JScript to a H5 Script? No. There are two different languages and technologies. Some of the MForms objects are the same and the architecture with the events are the same (if you are on one of the latest of H5 – 10.3.0.x) but they are different.

      3. Len Lim

        Hi,
        The sample script was used in Jscript for ISO. I’m trying to convert this script to work on H5. I have read the developer’s guide, I’m just not sure how to convert it.

      4. gsmarquez

        Hi Len,

        Here is a sample script for H5 that contains OnRequesting, OnRequested and OnRequestCompleted event handlers. You can use this as reference for your conversion.

        var H5SampleRequestTracer = (function () {
            function H5SampleRequestTracer(args) {
                this.scriptName = "H5SampleRequestTracer";
                this.controller = args.controller;
                this.log = args.log;
            }
            H5SampleRequestTracer.prototype.logEvent = function (eventName, args) {
                this.log.Info("Event: " + eventName + " Command type: " + args.commandType + " Command value: " + args.commandValue);
            };
            H5SampleRequestTracer.prototype.attachEvents = function (controller) {
                var _this = this;
                controller.Requesting.On(function (e) {
                    _this.onRequesting(e);
                });
                controller.Requested.On(function (e) {
                    _this.onRequested(e);
                });
                controller.RequestCompleted.On(function (e) {
                    _this.onRequestCompleted(e);
                });
            };
            H5SampleRequestTracer.prototype.onRequesting = function (args) {
                this.logEvent("Requesting", args);
            };
            H5SampleRequestTracer.prototype.onRequested = function (args) {
                this.logEvent("Requested", args);
            };
            H5SampleRequestTracer.prototype.onRequestCompleted = function (args) {
                this.logEvent("RequestCompleted", args);
            };
            H5SampleRequestTracer.prototype.run = function () {
                var controller = this.controller;
                var key = this.scriptName;
                var cache = InstanceCache;
                // Check the instace cache to see if this script has already attached to this program instance.
                if (cache.ContainsKey(controller, key)) {
                    // The script is already attached to this instance.
                    return;
                }
                this.log.Info("Running...");
                // Add a key to the instance cache to prevent other instances of this script on the same program instance.
                cache.Add(controller, key, true);
                // Attach events.
                this.attachEvents(controller);
            };
            /**
             * Script initialization function.
             */
            H5SampleRequestTracer.Init = function (args) {
                new H5SampleRequestTracer(args).run();
            };
            return H5SampleRequestTracer;
        }());
        

        Regards,
        Gerard

      5. Len Lim

        Hi,
        Based on your sample code in event handlers. What if I want to cancel the request because it didn’t meet my condition, where should I put the cancel code and how should I do it?

        Thanks,
        Len

      6. gsmarquez

        Hi Len,

        You can put it in the H5SampleRequestTracer.prototype.onRequesting method. You can cancel the request by setting the args.cancel to “true”.

            H5SampleRequestTracer.prototype.onRequesting = function (args) {
                this.logEvent("Requesting", args);
        
        	// set conditions here
                args.cancel = true;
            };
        

        Regards,
        Gerard

      7. Len Lim

        Hi Gerard,
        The script you gave me work. Right now I have another problem. the cancellation doesn’t work when I put a condition inside another condition. The request will just proceed the command. Here’s my code.

        H5SampleRequestTracer3.prototype.onRequesting = function (args) {
        this.logEvent(“Requesting”, args);

        if ((args.commandType == “LSTOPT” && args.commandValue == “4”) || (args.commandType == “LSTOPT” && args.commandValue == “2”) || (args.commandType == “KEY” && args.commandValue == “ENTER”))
        {
        debug.WriteLine(“change is ” + permit);
        if (permit == false)
        {
        args.cancel = true;
        this.log.Info(“CANCEL!”);
        }
        else
        {
        this.log.Info(“APPROVE!”);
        }
        }
        else
        {
        this.log.Info(“PROCEED”);
        }
        };

      8. Len Lim

        It does work when it is triggered for the first time. After that, when I test it to another transaction, it won’t work anymore. I’m thinking i think I’m missing the
        controller.add_Requesting(OnRequesting);
        controller.add_Requested(OnRequested);
        controller.remove_Requesting(OnRequesting);
        controller.remove_Requested(OnRequested);

        Not sure how do you do that in H5?

      9. gsmarquez

        Hi Len,
        We have tried your sample code with the conditions and it works on our side.

        H5SampleRequestTracer3.prototype.onRequesting = function (args) {
         this.logEvent(“Requesting”, args);
        
        if ((args.commandType == “LSTOPT” && args.commandValue == “4”) || (args.commandType == “LSTOPT” && args.commandValue == “2”) || (args.commandType == “KEY” && args.commandValue == “ENTER”))
         {
        debug.WriteLine(“change is ” + permit);
         if (permit == false)
         {
         args.cancel = true;
         this.log.Info(“CANCEL!”);
         }
        else
         {
         this.log.Info(“APPROVE!”);
         }
         }
        else
         {
         this.log.Info(“PROCEED”);
         }
         };
        

        We’ve tried pressing enter(Key/Enter) on a position field and it canceled the request. We tried it several times and the request was always canceled. Please the check the permit variable, your code should work as long as permit is false.

        Regards,
        Gerard

      10. Len Lim

        Hi, it is working when the script is trigger for the first time. when I tried it in a different transaction it won’t work anymore. Example : I test it to CO#1, the script works perfectly. Then I test it in CO#2 to test the 2nd condition in the code. That’s the time when it won’t wont work anymore. It is still showing the result from the CO#1

      11. Len Lim

        What I noticed is that I put the script in OIS101. But even go back to OIS300, the script in OIS101 is still running.

      12. gsmarquez

        Hi Len,

        For future posts about H5 scripting, please use our new H5 Scripting page (https://smartofficeblog.com/h5-scripting/).

        Based on your jscript, you need to detach the requesting and requested event when a request has been completed, would that be correct?

        When attaching the requesting/requested event handler using the method On(), it returns a function that you can use to detach the event handler. Here is how the requeting/requested event handler can be detached.

            H5SampleRequestTracer.prototype.attachEvents = function (controller) {
                var _this = this;
                this.detachRequesting = controller.Requesting.On(function (e) {
                    _this.onRequesting(e);
                });
                this.detachRequested = controller.Requested.On(function (e) {
                    _this.onRequested(e);
                });
            };
            ...
            H5SampleRequestTracer.prototype.onRequested = function (args) {
                this.logEvent("Requested", args);
                this.detachRequesting();
                this.detachRequested();
            };
        

        All event handlers can also be removed by using the method Clear().

        	...
        	controller.Requesting.Clear();
        	controller.Requested.Clear();
        

        Also please take note of the InstanceCache on the sample H5 script that I have provided. Line 6 makes sure that the script’s event handlers are attached only once even if the form is refreshed which may not exist on your jscript.

            H5SampleRequestTracer.prototype.run = function () {
                var controller = this.controller;
                var key = this.scriptName;
                var cache = InstanceCache;
                // Check the instace cache to see if this script has already attached to this program instance.
                if (cache.ContainsKey(controller, key)) {
                    // The script is already attached to this instance.
                    return;
                }
                this.log.Info("Running...");
                // Add a key to the instance cache to prevent other instances of this script on the same program instance.
                cache.Add(controller, key, true);
                // Attach events.
                this.attachEvents(controller);
            };
        

        Regards,
        Gerard

  28. Linda

    Hi,

    is it possible to get a sample code of how to retrieve values from a list row in H5 Scripts?

    Thanks,
    Linda

    1. rdespiritu

      Hi,

      This function returns the selected row/s in the list.

      ListControl.ListView.SelectedItem();
      

      These functions collect all the selected item(s) then get the value relative to the column name/index.

      ListControl.ListView.SelectedItem();
      ListControl.ListView.GetValueByColumnIndex(parseInt(textFieldValue, 10));
      ListControl.ListView.GetValueByColumnName(textFieldValue.toUpperCase());
      

      Thanks,
      Reah

  29. Greg Wiers

    Hi,

    I’m new to the JScript/Mashup development, and thanks to some information on your blog have successfully implemented a button to launch another internal website, and manipulate the DOM of the resulting page with data from selected items in a list.

    What I am looking for is a way to determine in JScript which M3 environment I am connected to so I can alter the URL to point the proper environment of the website I am calling. Do you know of a way to handle this?

    Thanks,
    Greg

    1. karinpb Post author

      Hi,
      An M3 environment does not have a name. What you can get is the runtime URL from the profile. Then you would need to know what environment that URL matches within your code.
      Below is an example on how to get the URL from the profile. The API is documented in the API documentation if you need more information. The parameters are all just strings but my example uses the constants from MForms.

      Include the following namespaces:
      Mango.Services
      MForms

      If ProfileDefinition isn’t public in your version the strings are: “RuntimeUrl”, “RuntimeUrlLogon”. From the ApplicationServices.SystemProfile you can get any value that is in the profile using the group, application and key values of the elements in the profile xml. Please note that if the application is not in the profile at all it will throw a KeyNotFoundException.

      var profile = ApplicationServices.SystemProfile;
      var runtimeUrl = profile.GetProperty(ApplicationGroupType.M3, "MForms", ProfileDefinition.RuntimeUrl);
      var runtimeUrlLogon = profile.GetProperty(ApplicationGroupType.M3, "MForms", ProfileDefinition.RuntimeUrlLogon)

  30. potatoit

    What is the recommend location to store per environment settings for your scripts?

    Traditional I’ve followed what an Infor partner did and have a separate text configuration file which is read during the scripts Init(), but with the newer versions of the MUA this has become troublesome.

    I know we can store settings in the Profile – and ideally I’d like to create my own group, rather than lump the settings under M3, SmartClient or External, but if I can’t which group would be recommended?

    1. karinpb Post author

      Hi,
      If you can use the script parameters for passing the values that is the preffered way.
      You can greate your own group but for applications that have a dependency to M3 it’s ok to add it to M3. You still need to add an application group for the values, eg the name of the script or something unique. Perhaps you have all jscript configuration under a single application name like JscriptConfiguration.

      I would say the recommended way is to add the values you need as parameters to the script if that is possible. If not then add an application under the M3 group.

  31. Len

    Hi,
    Is there a way to disable a field using jscript? for example in PPS300, I don’t want the user to be able to change the Trans date field.

    Thanks,
    Len

    1. karinpb Post author

      Hi Len,
      I’m on vacation so I can’t check the details but a disabled field has a specific style applied and I think it would be enough to set the style on the field. Below is an example for a textbox.
      The way to check is a field is enabled or not is to check the style of the TextBox. If the style is styleTextBoxDisabled the field is disabled. All disabled TextBoxes have this style.
      var isEnabled = true;
      If (yourTextBox.Style == Mango.UI.Core.StyleManager.StyleTextBoxDisabled){
      isEnabled=false;
      }

      For a DatePicker I would guess that the name of the style is: StyleDatePickerDisabled
      But I can’t verify it. But please try.

  32. Tom Bateup

    Are there any methods or utils that can be called to copy data from the windows clipboard into a variable in a JScript?

    1. karinpb Post author

      Hi,
      No, we have no utils for that. Is there a specific data structure that Smart Office stores in the clipboard that you are interested in? If not see MSDN

      1. Tom Bateup

        Hej Karin,
        The inquiry I received from my colleague was whether we could copy a number of cells from an Excel spreadsheet and paste them directly into the corresponding fields within M3. The specific example being copying data from 7 fields in an Excel spreadsheet and then having a JScript within GLS120 paste that data into the New Accounting Line fields WXAIT1 to WXAIT7.
        KR,
        Tom.

  33. karinpb Post author

    Hi Tom,
    Yes it is possible. I don’t know the details of a GLS120 but the following StackOverflow question should get you started on what to look for:

    http://stackoverflow.com/questions/8614910/paste-from-excel-into-c-sharp-app-retaining-full-precision

    or some simpler approach to get the clipboard values as texts:

    http://stackoverflow.com/questions/1679778/is-it-possible-to-paste-excel-csv-data-from-clipboard-to-datagridview-in-c

    http://stackoverflow.com/questions/31238873/copy-paste-from-excel

    I wouldn’t use any third party but instead just parse the text or XML depending on what is easiest. If this is a tricky script to write I would write is as a dll using the Mashup SDK so that I could debug in Visual Studio and write anything in C#. Then the script can be the dll if it follows naming convention as described in https://smartofficeblog.com/2013/06/20/script-assemblies-in-mforms/

    Don’t forget to localize the solution to support . / or , or whatever number format you might need to support.

  34. Linda

    Hi,

    is there a folder on ISO server where you can place a textfile and use the URL to retrieve the data via xmlhttp.open in a jscript? I’m building a popup with a listview and the customer would like to populate it using a web request rather than open the textfile using a path to the folder.

    Thanks,
    Linda

    1. karinpb Post author

      Hi,
      There is no folder on the ISO server where you can place a file. There is the web application which has the download page and it might be possible to pace something next to that index.html file. BUT when Smart Office is upgraded the file will be lost. I would recommend placing the file in a IIS web root somewhere else.

  35. Amrinder

    HI,
    I want to auto close a message box /pop up box/ dialog box after say 5 seconds.
    Could you help me with that.

  36. Amrinder

    I want to auto close a message box/dialog box after 5 seconds.
    Possible to do so? Could you help me with that.

    1. karinpb Post author

      Hi,
      If it is your own dialog you can add a timer and then close the dialog or click the button. If it is a standard message box (which you shouldn’t use) or a Smart Office dialogs there is no API for that and I can’t help you with it. Consider other options.

  37. Joeerg

    Hi All,
    I’ve a problem in MWS420 with focussing on field WCPLRI when I connect my script via personalization. It does not focus !!! When I test my script with the ISO-script-tool ist works !
    Could someone help me please ?
    BR Jörg

  38. Joerg

    Hi All,
    I’ve a problem in MWS420 with focussing on field WCPLRI when I connect my script via personalization. It does not focus !!! When I test my script with the ISO-script-tool ist works !
    Could someone help me please ?
    BR Jörg

    1. karinpb Post author

      Hi,
      In the init method controls aren’t rendered yet. Please try and dispatch before making the call or include Mango.Core.Util and use FocusAsync() instead of Async() as it is an extension method that will dispatch before trying to set focus.

  39. Jörg Wanning

    Hi All,
    I’ve a problem in MWS420 with focussing on field WCPLRI when I connect my script via personalization. It does not focus !!! When I test my script with the ISO-script-tool ist works !
    Could someone help me please ?
    BR Jörg

    1. Jose Ramon

      Hi,
      Maybe is a problem of timing (when the script is executed and when the control can receive the focus).
      You can try to use the Application.Current.Dispatcher funtion:

      public function Init(element : Object, args : Object, controller : Object, debug : Object) {
      this.controller = controller;
      var action : Action = ChangeTemplate;
      Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Input, action);
      }

      https://smartofficeblog.com/2014/08/21/custom-data-templates-in-m3-lists-with-jscript/

    2. Joerg

      import System;
      import System.Windows;
      import System.Windows.Controls;
      import MForms;

      package MForms.JScript {
      class MWS420JW {

      var content,controller,debug,gElement,argumente,gArgs;
      var hasValues = false;
      var valueField;
      var fields = new Array(“WCPLRI”);
      var butText : String;
      var col : int;
      var row : int;

      public function Init(element: Object, args: Object, controller : Object, debug : Object)
      {
      debug.WriteLine(“Script Initializing.”);
      this.controller = controller;
      this.content = controller.RenderEngine.Content;
      this.debug = debug;

      var panelState = controller.PanelState;
      var fieldName = “WWQTTP”;
      var valueQTTP = panelState[fieldName];

      debug.WriteLine(“Start-qttp: “+valueQTTP);
      debug.Info(“” + valueQTTP);

      if (valueQTTP == “88”)
      {
      debug.Info(“SortingOrder88 selected !”);
      valueField = ScriptUtil.FindChild(content,fields[0]);
      valueField.Focus();
      }

      controller.add_Requested(OnRequested);
      controller.add_Requesting(OnRequesting);
      }

      public function OnRequesting(sender: Object,e: CancelRequestEventArgs) {
      debug.Info(“OnRequesting”);
      valueField = ScriptUtil.FindChild(content,fields[0]);
      valueField.Focus();

      }

      public function OnRequested(sender: Object, e: RequestEventArgs) {
      debug.Info(“OnRequested”);
      var listControl = controller.RenderEngine.ListControl;
      var listView = listControl.ListView;
      listView.SelectedItems.Clear();
      controller.remove_Requesting(OnRequesting);
      controller.remove_Requested(OnRequested);
      }
      }
      }

      1. karinpb Post author

        Hi,
        As pointed out by our readers this is a timing issue. There are lots of factors controlling the focus, like tab order etc. and in the init method the controls are not guaranteed to be rendered. (Which they will always be when you debug in the tool because the panel is already running. Try adding Mango.Core.Util and use the FocusAsync() method (it uses the dispatcher behind the scenes). Or dispatch once with a really low priority. If that does not work dispatch once and then use FocusAsync. This is a standard trick for render issues and there are many different sources for setting focus in a standard M3 panel so you need to be sure that your code is run last.

    3. Jörg Wanning

      **** Below the script ********************************************************
      import System;
      import System.Windows;
      import System.Windows.Controls;
      import MForms;

      package MForms.JScript {
      class MWS420JW {

      var content,controller,debug,gElement,argumente,gArgs;
      var hasValues = false;
      var valueField;
      var fields = new Array(“WCPLRI”);
      var butText : String;
      var col : int;
      var row : int;

      public function Init(element: Object, args: Object, controller : Object, debug : Object)
      {
      debug.WriteLine(“Script Initializing.”);
      this.controller = controller;
      this.content = controller.RenderEngine.Content;
      this.debug = debug;

      var panelState = controller.PanelState;
      var fieldName = “WWQTTP”;
      var valueQTTP = panelState[fieldName];

      debug.WriteLine(“Start-qttp: “+valueQTTP);
      debug.Info(“” + valueQTTP);

      if (valueQTTP == “88”)
      {
      debug.Info(“SortingOrder88 selected !”);
      valueField = ScriptUtil.FindChild(content,fields[0]);
      valueField.Focus();
      }

      controller.add_Requested(OnRequested);
      controller.add_Requesting(OnRequesting);
      }

      public function OnRequesting(sender: Object,e: CancelRequestEventArgs) {
      debug.Info(“OnRequesting”);
      valueField = ScriptUtil.FindChild(content,fields[0]);
      valueField.Focus();

      }

      public function OnRequested(sender: Object, e: RequestEventArgs) {
      debug.Info(“OnRequested”);
      var listControl = controller.RenderEngine.ListControl;
      var listView = listControl.ListView;
      listView.SelectedItems.Clear();
      controller.remove_Requesting(OnRequesting);
      controller.remove_Requested(OnRequested);
      }
      }
      }

  40. joseramoncll

    Hi,
    Maybe using this method: Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Input, action) solves the problem.

    public function Init(element : Object, args : Object, controller : Object, debug : Object) {
    this.controller = controller;
    var action : Action = ChangeTemplate;
    Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Input, action);
    }

    Fro this post: https://smartofficeblog.com/2014/08/21/custom-data-templates-in-m3-lists-with-jscript/

  41. Jasper

    Hi Len,

    Can I please ask a quick question about the H5 Requesting event?
    I had a read of the H5 developer guide but that doesn’t mention anything about Requesting, Requested and Requested Completed event.
    I’m on M3 H5 v10.2.2.0.
    When I run your script H5SampleRequestTracer.
    I’ve got exception Uncaught TypeError: Cannot read property ‘On’ of undefined(…)
    This is the code.
    controller.Requested.On(function(args){
    console.log(“Requesting triggered”);
    });
    Thanks for your help.

  42. PrabodhA

    Hi

    These days im developing Smart office SDK application in which i wanted to display Current Company and the current division name in form header as standard M3 programs . I m using UserContext.CurrentDivisionName to get division name.

    The problem is that when user logged to the smart office and once changed the default division using mforms://cmp100110 command it does not get reflected to the UserContext.CurrentDivisionName until manually run what ever M3 program.(Mform).

    What could be the possible reason for that .

    1. karinpb Post author

      Hi,
      Smart Office supports many versions of MUA and M3 in parallell. This is originally by design since we did not receive the new information when executing the change company / Division command. This has been changed if you use M3 User Adapter (MUA) 10.3 or later. In that case we can automatically change the display names. I have created an enhancement ticket to add support for this when using MUA 10.3 or later. If you would like to follow this ticket you would have to report the issue to support and then ask them to track UID-23557 (Jira identifier) for you.

      1. PrabodhaA

        Hi Karin
        Thanks for the response .

        How should I track UID-23557 ? Do I need to report this to the infor extreme

      2. karinpb Post author

        Hi,
        Yes, you would need to report this to Infor extreme and give them the ID to say that a Jira ticket exists but you want to connect your report to that ticket. That way support will track when the ticket is completed and resolved. That is the process for bugs and I think it will apply to the enhancement as well. The other option is to wait for the next two fixes (we release one each month). I don’t think it will make it to HF19 because that is submitted to test tomorrow but perhaps the next one. You can always check the release notes upon each fix to see if this enhancement is included.

  43. SamanJ

    Hi

    I m developing JScript Smart assembly script for PPS200/E. My required functionality is that to update a table when user changed date filed in the E panel .

    So OnRequesting i event i did the update logic. But my concern is when WARNNING or BE error occurred how do i avoid the execution of my update logic ?

    1. karinpb Post author

      Hi,
      OnRequesting is before the request is made. If you need to wait for a successful change of panel you need to use RequestCompleted instead and check if you are on the next panel or not.

  44. PrabodhaA

    Hi,

    Is there way to access SDK application via smart office navigator ? . Currenlty im accessing it via typing name in the search bar,
    I have tried with showInMenu=”true” in application manifest .But it seems does not worked for me .

    Is that possible ?
    Thanks
    Prabodha

    1. karinpb Post author

      Hi,
      You need to implement IClientApplicationTasks or use the MenuExtensionService. This is documented in the developers guide and I also think that we have the two approaches as samples. I know for sure that we have the MenuExtensionService in the samples but I think that we have the IClientApplicationTasks as well. With IClientApplicationTasks you will have your own root node and with the MenuExtensionService you will have a node under “Other”. There is no way to get into another applications menu.

  45. PrabodhaA

    Hi

    I am developing smart office mashup for display some PO lines . In which i have a requirement to change the row color based on value of the ROW .(some conditional style- if status is 45 etc ).

    How can i do this ?

    Any idea appreciated .

    1. karinpb Post author

      Hi, If you are using a M3 program to display the lines (eg ListPanel) you use personlizations to color the lines. Please note that these personlizations needs to be managed separately and will also be the same as in the PO program in M3. You can also create local personalizations in the Mashup, called inline personalizations.
      See: https://smartofficeblog.com/2013/04/15/inline-personalizations-in-m3-mashups/

      If the lines are from an MIProgram you need to use standard WPF DataTemplates.

  46. Patrik

    Hi Karin,
    I’ve been looking for the syntax in jscript, xaml, mformsautomation, etc that corresponds to
    the well known commands: CTRL-A (Mark), CTRL-C (Copy) and CTRL-V (Paste).
    Example: I wan’t to open an M3 program, Tab, Enter etc and move to a certain field/information that I wan’t to copy, and recycle downstream the process.
    Since I write to you I’ve not found any help anywhere…
    Hope I’m not completely out in the blue here, thx in advance.
    Regards
    Patrik

    1. karinpb Post author

      Hi Patrik,
      Are you sure that you would like to add text to the computers clipboard? Because that is what those commands do.
      It seems like a really strange way to solve a requirement when you are writing code and can save the value in a variable and then update a field with that value using JScript.
      What is the requirement?
      The only reason to involve the clipboard would be to later paste it in another Windows application.

      To access the clipboard? System.Windows.Clipboard.SetText(“”);

      Links:
      https://msdn.microsoft.com/en-us/library/system.windows.clipboard(v=vs.110).aspx
      How to: Add Data to the Clipboard

  47. Patrik

    Hi Karin,
    first, thx for the reply!

    Well I understand that it sounds weird but let me rephrase:
    I work a lot with mformsautomation, either as is or hidden behind a button in a Mashup, and
    consider it a really easy and powerful tool. And sometimes when I develop a “process” (=several
    M3 steps consolidated to one or fewer) I might wan’t to go in to one program and retrieve information (ex copy) and recycle that information somewhere downstream (ex paste).
    Does this “example” make it more understandable?
    (I’ve many years experience of Movex/M3 and even though I’ve done development
    in RPG, Java, jscripts and whatever, I always start from the application perspective…)
    Regards
    Patrik

    1. karinpb Post author

      Hi Patrik,
      I understand your scenario but we don’t have that kind of support when you mix-in automation with scripts. But you could do with scripts more or less what automation does but it would be visible to the end-user. Add an overlay and take it away, get the data you need and store it and do whatever you like because JScript is a powerful tool. But we have not added any advanced methods to call automation and retrieve data from it or reuse data in one step in another and so on. There are no plans to add that kind if stuff either but if we get a lot of requests we might reconsider but that is not currently the case.

      It is great that you have a big toolbox to use but automation will only take you so far.

  48. Jacob Fierro

    Hello,

    I am trying to developing a script that is capable of change supplier number on several Purchase order proposals (PPS170 / B). The idea is:
    1.The user select all lines on B panel where he wants the supplier to be changed
    2.Press the button (script). The new supplier number is asked
    3. Supplier is changed for all selected lines.

    Every time you change supplier on a proposal a pop up window is shown asking for a confirmation on a Purchase Price Update. I can not handle that message in the script (by using automation at least) and im getting an error message: “Failed to render panel”.

    This is the automation I’m using:
    Try {
    Var listViewControl = gController.RenderEngine.ListViewControl;
    Var tmpBaseUrl = ‘mforms: // _ automation /? Data = ‘
    + ‘ ‘
    + ”
    + ” + sorting_order + ”
    + ”
    + ”
    + ” + IN_1 + ”
    + ” + IN_2 + ”
    + ” + empty + ”
    + ”
    + ”
    + ” + first_row + ”
    + ”
    + ”
    + ” + valueSupplier + ”
    + ”
    + ” // Make Sure to save changes HERE COMES THE ERROR
    + ”
    + ” // Make sure to close PPS170 (Avoid PPS913 when some orders are released)
    + ”;

    I get purchase order proposal number and line number on variables IN_1 and IN_2 respectively. Then I set sorting order where i can sort by those values, and finally enter on the first listed row on change mode.
    After entering new supplier number I press ENTER twice and get the mentioned error.

    I would be tremendously grateful if you could give me any idea here.
    Regards.
    Jacob.

    1. Jacob Fierro

      var auto = new MFormsAutomation();
      auto.AddStep(ActionType.Run,”PPS170″);
      auto.AddStep(ActionType.Key,”ENTER”);
      auto.AddField(“WWQTTP”,sorting_order);
      auto.AddStep(ActionType.Key,”ENTER”);
      auto.AddField(“W1OBKV”,IN_1);
      auto.AddField(“W2OBKV”,IN_2);
      auto.AddField(“W3OBKV”,empty);
      auto.AddStep(ActionType.ListOption,”2″);
      auto.AddStep(ActionType.Key,”ENTER”);
      auto.AddField(“WESUNO”,valueSupplier);
      auto.AddStep(ActionType.Key,”ENTER”); //To accept Price/date validation
      auto.AddStep(ActionType.Key,”ENTER”); //HERE COMES THE ERROR
      auto.AddStep(ActionType.Key,”F3″);
      auto.AddStep(ActionType.Key,”F3″); //To avoid PPS913 when released proposals exists.

      var uri = auto.ToUri();
      DashboardTaskService.Manager.LaunchTask(new Task(uri));

  49. Prabodha

    Hi
    I am developing SDK application in which I need get some data from iseries . There is no inbuilt APIs for retrieve that particular set of data . I cannot create new APIs since my customer wants to keep M3 as vanilla.
    Furthermore I cannot use web service as my query contains dynamic where clauses and query returns huge amount of data set .

    So I wrote a query and try to all that query using “IBM.Data.DB2.iSeries.dll” driver . This approach did not worked for me because , this required to install Iseries driver in client machines .

    What would be the best possible way to call iseries queries inside the SDK applications .

    1. karinpb Post author

      Hi,
      Sorry I have never had to connect to a DB2 from .Net and this is not specific to Smart Office development. I would however recommend that you don’t add a connection string to a setting or profile value because it is NOT secure. The only scenario that would be secure is to ask the user for the DB user and password in a dialog and store it using Mango.Core.Security.CredentialStorage that will store it encrypted on the local machine.

      I suggest that you try with:
      Forum: .NET Development with DB2 and IDS

      Connect to IBM DB2 only using .dll reference

  50. Angelos Arampatzis

    Hello! I am creating a script that should change a text box’ contents when the user selects a new value from a combo box (on MOS057/E). I do not know though how to assign a handler to the combo box’ OnSelectedIndexChanged event (or whatever event JScript has). In effect, I am looking for the corresponding of the Button’s add_Click method which assigns a handler to the button’s OnClick event.

    Thank you in advance for your time.

      1. Angelos Arampatzis

        Thank you for your quick and to the point reply Karin! Indeed, there is a add_SelectionChanged method.

  51. Martin Stephens

    Hi,

    I have a script that validates an E panel in the OnRequesting event, then if something is invalid cancels the operation (e.Cancel). What I would like to do as well, is under some conditions, force the user to go to the F panel even if the F panel isn’t in the users panel sequence. Searching for examples, I can’t see a way of doing this. Is this possible?

    Regards,

    Martin

    1. karinpb Post author

      Hi,
      The client can only change the panel sequence on the B panel. So no, that it not possible with script. The M3 program can tell the client to show a specific panel in a flow, but not the other way around.

  52. Daniel Henningsver

    If I add a datepicker on a panel with script in Smart Office in order to store data into the custom defined fields, is it possible to include this field in the tab order somehow? At the moment this field is skipped when tabbing around the elements on the panel.

  53. Bhumika Lekurwale

    Hi, I want to develope a JScript for Infor Smart office. First a button has created on OIS300 panel. Onclick of this button , want to show a form/window where need to write some data from M3 API transaction in the column and row form.
    Can someone help me in creating a form/window on click of button and write data in Column and row format, from where I should be able to read data again.

  54. Bhumika Lekurwale

    Hi Lode Vlaeminck, Thanks for the answer.

    Just to clarify, I can now popup the modal window using the link you attached above. But May I know how to write the data received from M3 API transaction on this window in row and column format.

    Thanks,
    Bhumika

    1. Lode Vlaeminck

      Just make sure the controls on the popup are accesible (declare them as private attributes of the class) and use the method that handles the response to update the controls.

  55. Prabodha

    According to current set up in MMS100/E panel when user is pressed next button, Dialog box is being displayed with Yes, No and Cancel buttons and always Yes button is focused. This dialog box is from M3BE side validation .Not using a JScript .So I wanted to focus No button or Press the No or Cancel button of the Dialog box automatically when Dialog is emerged.
    . I tried with Key press tab and enter and It didn’t work. (To focus No and press Enter)

    1. norpe

      First I should say that scripting of the M3 dialogs is not officially supported but technically possible. If you do script the dialogs it is probably easier to just call the PressKey method on the controller instead of setting focus to buttons etc.

      Example for cancel:
      controller.PressKey(“F12”);

      All keys for the confirm dialog:
      OK = “ENTER”
      Yes = “1”
      No = “0”
      Cancel = “F12”

      1. Jacob Fierro

        Hi Norpe,

        I have the same problem on PPS170/E. Every time i change supplier on a planned Purchase order, a “pop-up” Windows shows up asking for a Price recalculate confirmation. I’m not able to handle this kind of message. Can you help me?

  56. Jonatan Stenbacka

    I know there’s a “controller.RenderEngine.ShowMessage” function to show a message in the “status bar” of a panel, but as far as I can tell there’s no way to check the message in the status bar.

    using “controller.RenderEngine.messageHistory” somehow works, but it only contains the latest shown message, and doesn’t mean that that message is shown any more.

    Am I missing something?

  57. Jonatan Stenbacka

    Is there a way to programmatically refresh a program (the same functionality as pressing F5).

    One obvious way is to invoke an F5 key press using controller.PressKey(“F5”). But if you want to do it in a mashup for instance, where you can have several programs loaded at the same time, invoking F5 is not sufficient since you don’t know which program has focus, hence will execute the F5. Or am I thinking wrong? What is the best approach in this scenario?

    On another note: Is this the best place to ask JScript questions, or is there another forum I’m not aware of?

    1. Karin Portillo Post author

      Hi,
      Let’s start with the last question. There are some forums on the infor developer community but they are more general and I personally do not monitor those.

      As for refreshing a program you should use controller.PressKey(“F5”). The script executes in the context of a program, that is the controller is for one of the M3 programs within a Mashup and it will refresh it’s own program. If you would like to refresh the entire Mashup that is another question and I would set that up with events, perhaps there is a normal flow where you can refresh only one program and the other panels will react to that.

  58. Jonatan Stenbacka

    Hi!

    Is there a way to find out the column indexes (by name) of a ListView when you only have the System.Windows.Controls.ListView object? I don’t have the ListControl object and therefore I can’t use ListControl.GetColumnIndexByName as I’d normally do.

    The reason I’m asking is because I have a mashup with several lists. And I get each list by looking through each child node in the panel containing each list, and finding the ListView object. Sometimes the different lists in the mashup will have different sorting orders, and therefore I need to know in which order the columns are sorted in each list. Hence, I need to find the ListControl object. (At least that’s my approach to it, feel free to steer me in another direction.)

    The problem is that if I try to find the ListControl object by looking through all of the nodes in the panel, like I do to find ListView, it doesn’t work. I can’t find any ListControl object in the panel.

    I’ve tried a few alternative approaches. Since you usually get the ListView by doing controller.RenderEngine.ListControl.ListView in the init method, I thought I would find the ListControl by looking at the parents of the ListView using VisualTreeHelper.GetParent(). But there is no parent ListControl it seems like.

    I’ve also tried to look for the ListViewControl object that you can also retrieve from controller.RenderEngine. But I can’t find that object either.

    Is there any way to do this? Can you find out the indexes of different columns in a list by only having the System.Windows.Controls.ListView object?

    Thank you!

    Jonatan Stenbacka

    1. petergrew

      Hi Jonatan,
      If you have the System.Windows.Controls.ListView object you need to get the GridView to obtain the column headers.

      /Peter

      Try to do something like this:

      var content : Object = controller.RenderEngine.Content;

      var listView = ScriptUtil.FindChild(controller.RenderEngine.Content, “List”);
      debug.WriteLine(listView.GetType().FullName);

      var gridView = element.View;
      debug.WriteLine(gridView.GetType().FullName);

      var count : int = gridView.Columns.Count;
      for(var index=0; index<count; index++)
      {
      var gridViewColumn = gridView.Columns[index];
      var header = gridViewColumn.Header;
      debug.WriteLine(header);
      }

  59. dirkhoag Hoag

    I have a simple concern but can’t find the answer to it so I’m hoping you can help me. I’m creating a script to blank out certain fields in PPS200/A when a user launches the panel, and it works fine at launch but then it also executes each time the panel is refreshed or a call is executed, and I don’t want that. What is the best way to restrict my script to the initial load of a panel only?

    1. Karin Portillo Post author

      No, there is no notion on initial load. The script should unload when you leave the panel, but then it gets loaded again if you are back on that panel. It’s M3 that decides which panel to view in the next step, the client only reacts to it.

  60. dirkhoag

    How does one make sure a script runs only on the initial load of a panel, and not at every refresh or update? I have a simple script to clear out some fields when users go into PPS200/A, but it continues to clear them each time the user hits Enter/Next or F5, which doesn’t help.

    1. Karin Portillo Post author

      Hi,
      This is a tricky one that we basically has no support for. The script will just execute in a stateless manner. It does not have information about the steps that were taken before you got to that screen.

      What you can try is to use the instance cache, save a simple value like “pps200Clear” set to true, then the script would check for the existence of the value in the cache and if a value exist then it will not clear the values. But depending on the scenario this might not be enough as you can come to that program in the same instance flow multiple times.

      InstanceCache.Add(controller, key, value)
      InstanceCache.Get(controller, key);
      InstanceCache.ContainsKey(controller, key)
      
      1. Doms Molina

        Hi,

        Putting this in a different context. If I have a screen with a button and I want to prevent multiple execution while it’s running the usual approach we take is to set the cursor to busy status. However, I have come to know that you can still press the button even though it’s in busy state. If I disable(I assume we can) the button and enable it only after completion is that enough? And is this approach a recommended one?

        Second question if I may. Is it recommended to block the refresh of a panel by using a flag to be set to true on the onrequesting and setting it to false in the completed event. If yes where should I put the flag validation considering the refresh might create a new instance of the script?

      2. Karin Portillo Post author

        Doms Molina, I’m afraid if you comment on a comment there is no way for me to reply to that comment, so I’m answering here.

        Busy is just an indication, it will not lock the UI. Disabling the buttons should be done, but keyboard can also be used so you need to do all that and then also actually cancelling the request (if there is one). That leads to the second question.

        Yes you are describing the recommended approach. Cancel the request and then on the completed event on the request you are doing you set it to false.

  61. Calum

    Hi,

    Is it possible to set a default value in an M3 pop up using JScript?

    I need to select “No” by default each time a certain pop up appears.

    Thanks!

    1. norpe

      There are some parts missing in the API to make this simple but it is still possible using the RequestCompleted event and the Windows array in the Application object. The script example below checks if a ConfirmDialog is opened and automatically clicks the No button (PressKey with “0” for No, “1” for Yes). The user will still see the dialog but the No button will be pressed as soon as the dialog is opened. There is currently no way to do this without displaying the dialog.

      Note that you have to be careful with these types of scripts and only use them on panels where you are sure that the users do not have to be able to select another option.

      import System;
      import System.Windows;
      import System.Windows.Controls;
      import MForms;
      import Mango.UI.Services;
      
      package MForms.JScript {
          class ConfirmDialogAutomaticNo {
              var controller;
              var debug;
      
              public function Init(element: Object, args: Object, controller: Object, debug: Object) {
                  debug.WriteLine("Initializing script ConfirmDialogAutomaticNo");
      
                  this.controller = controller;
                  this.debug = debug;
                  controller.add_RequestCompleted(OnRequestCompleted);
              }
      
              public function OnRequestCompleted(sender: Object, e: RequestEventArgs) {
                  try {
                      controller.remove_RequestCompleted(OnRequestCompleted);
                      if (IsConfirmDialog()) {
                          debug.WriteLine("ConfirmDialog opened, automatically selecting No");
                          controller.PressKey("0"); // "0" = No, "1" = Yes
                      }
                  } catch (ex) {
                      debug.WriteLine("Failed to handle event " + ex);
                  }
              }
      
              private function IsConfirmDialog() {
                  if (!controller.Response.IsDialog) {
                      return false;
                  }
      
                  var content: Panel = GetDialogContent();
                  return content != null && content.GetType().Name == "ConfirmDialog";
              }
      
              private function GetDialogContent() {
                  var window: HostWindow = Application.Current.Windows[Application.Current.Windows.Count - 1];
                  return window.HostContent;
              }
          }
      }
      
  62. deepanalyticsblog

    I am running an instance of MFormAutomation on FAS001 which, MFormAutomation then opens up a new FAS145 via the command AddStep(ActionType.Run, “FAS145”).

    I need to read the error message from generated in FAS145, but unable to do via the controller.PanelState.Message since this returns the message from FAS001 as this is the host that runs the script. Is there a way i can read error message not from the host instance (FAS001) but from the instance started by MFormautomation ( AddStep(ActionType.Run, “FAS145”) )

    Thanks And Best Regards

    1. Karin Portillo Post author

      Hi,
      No they only way would be to actually have another script that is started in FAS145. Before starting the automation you can place an object in the session cache with for example a time and then in FAS145 you always check the session cache and if that object is there you can perhaps call a method on that object or perform other type of logic but they are unfortunately NOT connected. That is why you need another script in FAS145 to take over and to the checks. Kind of complex, but possible.

  63. Maxime

    Hi,
    I hope I will not bother you.

    Here is my issue :

    I work on a mashup with some event handlers from a Jscript.
    All is working fine excepted when users try to use “mini-mode” or detached mode.
    When this mode is enabled, all programs are out of the canvas therefore my mashup is not an “EmbeddedHostWindow” anymore and become an “HostWindow”.
    According to my research, I understand that these objects are different and inherits from differents objects.
    My mashup is crashing when handlers are set up and user swaps into the mini-mode. Indeed, handlers are no longer linked to the host.

    My question is : How to trigger and manage the swaping between these modes?

    I tried :
    – To manage the code depending on the host. This method is crap; as I said, both objects (EmbeddedHostWindow & HostWindow) don’t inherit from the same object (At least, I think so).

    – To handle the click on the detach button.
    ** Unfortunately I can’t attach an event on this button, I can’t even get the button’s instance :
    —-> buttonDetach.add_Click(function) is not working.

    ** I tried to do same but on the host directly :
    —-> host.onClickDetachButton(handler) but it’s not triggered.
    —-> host.AttachEvent(hostEvent, handler) but i don’t know how to create a “Delegate” handler

    The deeper I search, the more I think it can not be managed. But I believe in you 🙂

    For context and your information, its a request from a customer. Some users use this mini-mode and we have to manage this feature on our mashup.
    I’m learning JScript following this request, so I must miss some details.

    Sorry for my English (I’m French).

    Thanks for your time (And all the good stuff here) !

    Maxime

    1. Karin Portillo Post author

      Hi Maxime,
      You have a mashup running some M3 form and on the M3 form there is a JScript attached. Is the JScript hooking up to window events or what? It’s going outside of the M3 panel in the visual tree and adding an event listener? To what and why? What is the functionality the script is used for? Preventing the mashup to be closed? The different type of windows are different and when exactly is the issue? Always in mini-mode or in the transition when the mashup is already open and we switch from one type of window to another? There are different implementations simply because they have to be different implementations but both are IInstanceHosts.

  64. Jonatan Stenbacka

    Hi! Is it possible to map a drive from Smart Office using a JScript?

    I’ve tried the following:

    Process.Start(“C:/WINDOWS/System32/net.exe”, “net use V: \\server\folder”);

    But it doesn’t do anything. A command prompt is flashing, but it doesn’t have any effect. I’ve also tried using ProcessStartInfo:

    var si = new ProcessStartInfo();
    si.FileName = “C:/WINDOWS/System32/net.exe”;
    si.Arguments = “net use V: \\server\folder”;
    var p = new Process();
    p.StartInfo = si;
    p.Start();

    Am I doing something wrong, or is this not even possible?

    // Jonatan

  65. Peter Grew

    HI Jonatan,
    Try to skip the program name “net” in the argument list.
    Like this Process.Start(“net.exe”, “use V: \\server\folder”);

    1. Jonatan Stenbacka

      Hi Peter. Thank you for your reply!

      Sadly I have tried that before, and that doesn’t work either. But if I write the same command in the command prompt it maps the drive without any issues. Does this mean that this is simply not possible from inside ISO?

      1. Peter Grew

        Hi Jonatan,
        Here is a full example:

        import System;
        import System.Windows;
        import System.Windows.Controls;
        import System.Diagnostics;
        import MForms;

        package MForms.JScript {
        class openfolder {

        public function Init(element: Object, args: Object, controller : Object, debug : Object) {
        debug.WriteLine(“Script Initializing.”);
        if(element != null) {
        debug.WriteLine(“Connected element: ” + element.Name);
        }

        var content : Object = controller.RenderEngine.Content;

        try {
        debug.WriteLine(“START”);

        var p = new Process();
        p.StartInfo.FileName = “cmd.exe”;
        // The flag /K leave the command window open after execution (debug friendly), replace with /C flag to close window
        p.StartInfo.Arguments = “/K net use V: \\\\host.acme.com\\SharedFolder”;
        p.StartInfo.Verb = “open”; // available verbs {open, runas, runasuser}
        debug.WriteLine(p.StartInfo.Verbs.toString());
        p.Start();

        debug.WriteLine(“DONE”);
        }
        catch(e){
        debug.WriteLine(“Exception ” + e.Message);
        }
        }
        }
        }

      2. Jonatan Stenbacka

        Hi Peter. It works! Thank you so much for this. Our customer will be pleased :). Enjoy your day!

  66. Jonatan Stenbacka

    Hi! Is it possible to map a drive from Smart Office using a JScript? Or would that be considered as a security breach or something?

    I tried to post this question a few weeks ago, but didn’t get any definite answer. Would be great if somebody from Infor could take a look at this. We have a customer who has this request.

    See my previous question for more information.

    // Jonatan

    1. Karin Portillo Post author

      Hi,
      Just answering here for completeness.The answer is some posts up.
      Yes, it’s possible. But I would not say that it is recommended. It’s not a security breach if it is intended and requested by the customer and documented. But you need to be careful and not store any sensitive information i scripts that can be missused.

Comments are closed.