About

This blog is for all the developers of Smart Office components, such as JScript solutions, Mashups or even full featured applications that uses the Smart Office framework to build new exciting applications. Administrators will also find useful information about Smart Office administration.

This blog is brought to you by the developers of Infor Smart Office (previously called Lawson Smart Office, Lawson Smart Client).

For developers – by developers.

Editors

Karin P (karinpb)

 

 


Peter K (norpe)

 

 


Rickard E (countzero42)

189 thoughts on “About

  1. Chen Liang

    hi, there,

    I was trying to build a link from a html page to a mash up in LSO. I use US demo server, therefore I added the server address, followed by “&task=mashup///?….”. But it proved that this is not working. I have tested to put “&task=mforms://CRS610” and it works. So the address is correct. The error message is: Url Url must be set on a mash up. Can you give me an instruction about what I did wrong?

    Leon

    Reply
    1. karinpb Post author

      Hi,
      Assuming the mashup uri is correct (the same uri as you have in the Navigator) you probably just need to URL encode the uri value. That is the complete mashup://?… Uri. Becasue it has paramets the value must be encoded or the paramets are consided to be part or the link to LSO installtion point. Encode the entire value (uri) you want to set the task to, but not task=.

      There are online encoders. Try this one online dencoder.

      Reply
  2. Daniel

    Hi!
    first of all thanks for this great page. The information helped me already in some cases.

    But is it not nice to have a also a forum to exchange knowledge with other LSO users?
    I think it will be great to post questions and answer questions from other users, post mashup ideas or maybe also source codes.

    As far as i know there is no other page at the moment.
    Why not to start here?

    I think many users will welcome that! 🙂

    Best regards!
    Daniel

    Reply
    1. karinpb Post author

      Hi Daniel,
      I think this is an excellent idea and I’ll push my manager and the product owner once more on this issue. I’ve been pushing for a public forum for quite some time but … nothing happend.

      That is the reason I started this blog. Becuase it is a great way to reach out not only to our service organisation and partners but also customers.

      The only public forum (independent) I know is here: http://www.lawsonguru.com/forums/ux/lso/

      Reply
  3. Daniel Johansson

    Hi!
    I´m new to Smart Office so perhaps this is an easy problem to solve.

    There is a widget for RSS feeds thats not working as I supposed. When I add an RSS-link like this http://www.yoursite.com/rss.xml it works perfect but when i try to use a rss-url to our intranet based on Sharepoint 2010 it doesn´t. It keeps telling me that the url is invalid.
    Have U seen this behaviour. Here is an example url from Sharepoint:

    http://portal.site.com/IT/Customer/M3/_layouts/listfeed.aspx?List=%7B0C0DFAFE%2D60F8%2D42AF%2D8874%2D03588BF18905%7D&Source=http%3A%2F%2Fportal%2Esite%2Ecom%2FIT%2FCustomer%2FM3%2FLists%2FM3%2520Announcements%2FLatest%2520news%2Easpx

    Thanks,
    Daniel

    Reply
    1. karinpb Post author

      Hi Daniel,
      I’m not sure. The RSS widget only supports RSS not Atom.
      Do you have a public URL for me to test or can you save the XML returned (in IE – view source for example) and share it either in a comment or a public link to your SkyDrive or some similar service?
      If you send me the XML I can have a look. I’ll also check if the URL gets corrupt somehow. To set log level (Settings for LSO) to debug might show some more info. Log is found from the About dialog or via internal://log.

      I’ll test when I’m back at the office. I’m at Microsoft today.

      Regards
      Karin

      Reply
    2. karinpb Post author

      Hi again,
      Did you say Sharepoint? I think the reason is that the page is secure and the news reader ony supports public RSS feeds. I definately think that you should contact support and add a requirement for supporting Sharepoint feeds. Sharepoint is probably using Windows classic authentication.

      Reply
      1. Daniel Johansson

        Hi Karin, Thanks for you reply. Yes, The Sharepoint-site use NTLM for login. So I will send a case to support. Thanks again,
        //Daniel

  4. yamakake

    Thank you very much for the page! It has been extremely useful in our mashup development (we’re not developers and we can still make sense of it, thanks to you guys!).

    One thing we have struggled with and still haven’t found an answer (on the Internet) is whether it’s possible to call up the Text functionality from a mashup. For example, an item in MMS001 may have Text (and Text Blocks) associated with it; our intention is to allow the user to directly jump to the Text based on an item selected, if text exists. Any thoughts and suggestions?

    Reply
    1. norpe

      When using the M3 Mashup ListPanel control there should be a Text option on the context menu for the list. If there is a text connected to the selected list row the M3 Test dialog should be opened when the Text menu item is clicked. There is a property called EnableTextOption on the ListPanel that can be used to turn this functionality on/off. The default value for the property is true.

      Unfortunately there is no way to know if there is a text connected to a list row. If no text is connected the Text dialog will not be displayed.

      Reply
      1. yamakake

        Thanks for the quick reply norpe!

        What you’ve described is exactly how we’ve currently implemented it right now, but the user would have to click on the Text option from the option menu. We were hoping to save one more click in the user experience by going directly to the text box instead of through that option menu but we haven’t found a way.

        Currently, we were indicate to the user that the item has text by grabbing the textID through an API (CRS980MI) and rendering appropriate confirmation text (via conditions) but we couldn’t connect it to any action (e.g., open up the Text box from CRS980). That would be the ultimate goal, but at least now the users don’t have to go into each Item to see if there’s text.

        If there are any ideas on this, that would be fabulous. 🙂

    2. norpe

      You can open the Text dialog in the same way as the context by using an event. The event name should be “ListOption” and there should be a parameter named “Option” with the value “Text”. See the XAML example below.

      <Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ui="clr-namespace:Mango.UI.Controls;assembly=Mango.UI" xmlns:mashup="clr-namespace:Mango.UI.Services.Mashup;assembly=Mango.UI" xmlns:m3="clr-namespace:MForms.Mashup;assembly=MForms">
         <Grid.Resources>
         </Grid.Resources>
      
         <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*" />
         </Grid.ColumnDefinitions>
         <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="1*" />
         </Grid.RowDefinitions>
      
         <Button Content="Open Text" Margin="8,8,8,0" HorizontalAlignment="Left" Name="TextButton">
            <Button.CommandParameter>
               <mashup:Events>
                  <mashup:Event TargetName="ItemList" SourceEventName="Click" TargetEventName="ListOption">
                     <mashup:Parameter TargetKey="Option" Value="Text" />
                  </mashup:Event>
               </mashup:Events>
            </Button.CommandParameter>
         </Button>
      
         <m3:ListPanel Name="ItemList" Grid.Row="1" Margin="4,16,4,8">
            <m3:ListPanel.Events>
               <mashup:Events>
                  <mashup:Event SourceEventName="Startup" TargetEventName="List">
                     <mashup:Parameter TargetKey="MMCONO" />
                     <mashup:Parameter TargetKey="MMITNO" />
                  </mashup:Event>
               </mashup:Events>
            </m3:ListPanel.Events>
            <m3:ListPanel.Bookmark>
               <m3:Bookmark Program="MMS001" Table="MITMAS" KeyNames="MMCONO,MMITNO" />
            </m3:ListPanel.Bookmark>
         </m3:ListPanel>
      
      </Grid>
      
      Reply
      1. yamakake

        Wow, that’s awesome! So very close… :\ What you described is exactly what I asked for…except I wasn’t specific enough (my bad). 😦

        Most of our users are not allowed to go into Change mode so they’ll result in an error “Failed to comply with your request.” Is there anyway to bring this Text option up in Display mode? I tried tinkering and applying to the detail panel to bring up F6 instead, but I couldn’t get it working. Thanks!

      2. yamakake

        So I guess there isn’t really a way to bring up the Text in Display mode?

        What we ended up doing was a workaround that wasn’t pretty (but it worked). We utilized three transactions from CRS980MI to bring back the Text ID in a TextBlock (GetTextID), get the text blocks with the right language into an MIComboBox (LstTxtBlocks), and displaying the text blocks in an MIListPanel (SltTxtBlock) depending on the text block selection from the MIComboBox.

        It would have been better if I could have displayed all the records concatenated in a text box, but I couldn’t figure that out. In any case, thank you very much for your help!

    3. norpe

      The option used to open the Text dialog is usually decided by the BE program depending on the option used for the detail panel. When showing the text dialog from the list there is no way to know what option to use. Currently the option used from the ListPanel is hardcorded to option 2 (change).

      It will be possible to use option 5 (display) for the text dialog in future versions. I will create a post when this is available.

      Reply
      1. Eric Wayker

        Is there a way to create an empty field in the MIComboBox? I am trying to get a list of companies as an argument however and argument could be null meaning that I would get all companies.

      2. karinpb Post author

        I’m afraid there is no standard way to get an empty value in the MIComboBox. I’ll add an enhancement request for this functionality.

  5. Joe Straight

    Hello, is it possible to create a shortcut in LSO to a Design Studio Portal Page? I can successfully create a shortcut to a DS form using similar syntax below but I am having difficulty with creating the shortcut to the portal page. Bookmark in portal to portal page LAWPAGE|file=abc.xml.

    net://auth?http://lsfserver.corpnet.lawson.com/lawson/portal/?_TKN=GL90.1&_RUNASTOP=0&_ID=MyCustomGL90

    Reply
    1. karinpb Post author

      I tested this myselft in the Utility program. Since the parameter has & when we create this Uri it will contain three parameters:
      http://lsfserver.corpnet.lawson.com/lawson/portal/?_TKN = GL90.1
      _RUNASTOP = 0
      _ID = MyCustomGL90
      This is not correct becuase the the last two are parameters of the lsf server URL not the net:// URL.

      The solution is URL encoding everything after the first ?.
      Try this: net://auth?http%3a%2f%2flsfserver.corpnet.lawson.com%2flawson%2fportal%2f%3f_TKN%3dGL90.1%26_RUNASTOP%3d0%26_ID%3dMyCustomGL90

      Reply
  6. Mikael H

    Hi. Sometimes you need to retrieve information with SQL-statements within LSO and Jscripts. There are several techniques for this but what is the recommended way from you ? Should we use Web service for this or what is the best way ? Thanks /mikael

    Reply
    1. norpe

      The M3 database should only be accessed using the M3 APIs. In JScript the MIAccess and MIWorker classes makes it easy to make MI calls. MDBREADMI can be used to define new transactions if necessary.

      Accessing any database directly from the client is generally a bad idea; there should be some kind of layer between the client and the database. The database could be exposed through web services or some kind of REST service. Calling REST services from JScript is easier than calling web services since they require stub code.

      It should be possible to use the Mango.Core.DynamicWs.WSDataService class to make web service calls since this class dynamically generates web service stubs. At the moment we don’t have examples of how to use this from JScript but there are examples for Mashups, see http://lawsonsmartoffice.com/2012/01/18/soap-mashup-with-bing-search/

      Reply
  7. Joe Straight

    Do you know if there is different syntax to be used to bring up the design studio portal page? My portal page contains both a form and data queries. The form portion of the portal page displays with the encoded URL, but the data queries are not displaying. The data queries are populated based on a key field in the form. Thanks, Joe

    Reply
    1. karinpb Post author

      I have to ask, how are you creating the link? net://auth?http://example?paramName1=Data. Is it in JScript? Link in the link manager? Is it _TKN that is not getting through?

      I don’t know the specifict of the parameters but in general those parameters have to be encoded and then the entire URL with the parameters has to be encoded if you set a parameter that is a URL like the net://auth?http://example?paramName=Data.

      That means first encode Data, then encode http://example?paramName=Data. Now ‘Data’ does not have to be encoded but if you have signs like &,space,=, those must be encoded.
      Give me some more specifics and I’ll check with the S3 team.

      Reply
  8. Joe Straight

    I am using syntax from a spreadsheet that a Lawson resource gave us to pull up embedded Design Studio forms. This syntax works with DS forms but not with DS portal pages. For example, my bookmark setup currently in Portal to call my DS portal page is as follows : LAWPAGE|file=emp_profile.xml. My bookmark setup to call a DS form in Portal is as follows : LAWFORM|TKN=AC42.1|ID=AC42.1_MOD.

    So I am not sure if the URL syntax in LSO was slightly different between displaying a DS form vx a DS portal page.

    Reply
    1. karinpb Post author

      Hi,
      This is what I have been able to find out. Seems to be something special about the way the & is encoded (see last URL).

      Using the url below on the browser command line does not work because S3 for Workspace is not loaded; what we are doing is loading index.htm from the pages directory and pages.js requires that a S3 Custom Page executes within S3 for Workspace.

      http://:/lawson/portal/pages/?FILE=cucodes.xml&VAR1=VALUE1&VAR2=VALUE2

      Using the same url from a Favorite or a Bookmark works as designed because the S3 Custom Page is loading and executing within S3 for Workspace. I find all the passed parameter values within the page.parameters collection.

      Inbasket.js works is because it is loaded and executed from within Lawson Portal and the Portal window reference can be found from the Portal Page.

      LPA Inbasket cannot use this url because it does not start S3 for Workspace, so it needs to use LAWPAGE, which will start S3 for Workspace and display the S3 Custom Page; the ampersands separating the name / value pairs need to be escaped so the name / value pairs can be placed into the page.parameters collection.

      http://:/lawson/portal/?_URL=LAWPAGE|FILE=cucodes.xml%26VAR1=VALUE1%26VAR2=VALUE2

      Reply
  9. Johan

    Hi! Is there any way to tile open programs on a canvas? Im looking for a script that sizes all open programs so that they appear on an equally large “square” on my Canvas. Kind regards, Johan

    Reply
    1. Johan

      Hi again….I think I found something on “Thibaud’s M3 ideas worth sharing”……I’ll try to make it work in my environment 🙂

      Reply
  10. Roger F

    I’ve installed LSO many times. On this new install of the LSO Grid, the LSO Grid is failing.to install each and every time, no matter what version of the grid is attempted to be installed. After filling in the information about the Grid (name, ports, etc.) it comes back and pops up an error message:
    “Failed to run script D:/LSO/LifeCycleManager/Server/products/Lawson_Grid_9.1.7.0/templates/GridNew.vm”

    … there is a log file produced but I can’t tell what specifically is the issue here.

    I’ve rebooted the server and all of the LCM Services. LCM starts up no problem (version 9.1.11.0).

    I’ve already got Infor support looking at it but they still don’t have any idea what’s going on.

    Any ideas or where to look at would be great.

    Thanks in advance,
    -R

    Reply
    1. Rickard Eklind

      Sorry, without any more information it is impossible to say what goes wrong. If the Infor support people does not know, they need to ask the developers.

      Reply
    2. karinpb Post author

      Hi,
      I asked around and got these general tips.

      The JDK should be JDK6, the update version shouldn’t affect the installation though we always recommend the latest of course.

      Key things to check from a grid perspective are: file system permissions, firewall settings, trying to overwrite existing broken installation, ports in use (somehow).

      Log file would be useful, but the version of Grid is old – the latest released is 10.1.9.0.14.

      Please consider using a newer version of the Grid. What version of Smart Office will you install?

      Make sure you get the updates if it is a 10.0.4, go directly to 10.0.4.1.

      Reply
      1. karinpb Post author

        Hi,
        I have not heard anything about this and it is Grid related and not Smart Office. Please turn to Infor Extreme support.

  11. Daniel

    Hi,

    is it possible to add a file viewer with a script?
    For example i have in APS112 the path of the PDF file in the database field WWPATH. I want to add a script that shows me the PDF in the form on the right side.
    It is no problem in a Mashup with the file viewer component but we want to have it directly in the Form.

    Can you help me? Maybe do you have a script snippet for this?

    Best regards
    Daniel

    Reply
    1. karinpb Post author

      Hi,
      Since it is code, anything is possible but we don’t have an example for it. One way would be to host the Mashup control. We will consider making an example.

      Regards
      Karin

      Reply
  12. Mikael H

    Hi,
    For example, if you have an XML-file that a jscript should read to validate user inputs. Where should be the best place to put the XML-file on the server so every user can access it ? Do you have a recommendation where it should be stored on the LSO-server ?
    Thanks !
    /mikael

    Reply
    1. karinpb Post author

      Hi, I would add a folder in the same folder that has the installation point.
      In my environment that is c:\SomePath\ISO_10.0.5.0.RC4\applications\LSO\Client\IP.

      This folder has three folders Application Files, features and OfficeAddIns. I would add a new folder called myconfig and place the XML file there. I would also make sure that I had a script that would take a backup becuase you never know what will happen to the files in an upgrade.

      An alternative is to create your own web app and place any content you like there. It can be RSS feeds, images or whatever. In that case you have full control because adding folders within our apps comes with a risk. We might change the security access policy or add our own folder with the same name or wipe everything before an upgrade.

      Then I would go to the JScript and make sure that it does not load the configuration file on the UI thread. I’ll bet you that it is currently doing that.

      Reply
  13. Joakim Bodin

    Hello,

    I’ve been looking at an issue that was presented to me by a solution consultant today where he is trying to present some data as a chart within a Mashup. It would seem that the ‘VisualizerPanel’ is not enough as the data is fetched by a SOAP Web Service and therefore uses a ‘DataListPanel’ (as far as I’m aware, the ‘VisualizerPanel’ only supports ‘ListPanels’).

    As an alternative, he’s been looking at the DataVisualization Toolkit ‘Chart’-control. The strange thing is that I can bind the data from the Web Service to a ‘DataGrid’ or ‘ListView’ without issue, but trying to bind the same data to the ‘Chart’-control does not work. I realize this is not much to go on, but: Do you see any reason that the data binding would work for a ‘DataGrid’ or ‘ListView’ but not the ‘Chart’-control? They should exist within the same DataContext.

    Using the SDK would solve our issue but it would be nice to be able to keep it Mashup-only.

    Thank you for your time,
    Jocke

    Reply
    1. karinpb Post author

      I’m not sure. You use the SOAP web service right? Becuase the values have to be objects and not strings becuase I guess there are numerical values. My recommendation would be to use the SDK and run it from within there to be able to read the output log in order to get more information on what is happending.

      Reply
  14. Heiko

    Hi,
    when working with the Mashup Designer, it happens from time to time that I cannot continue my work, I only retrieve a strange error message about invalid data, similar to an incorrect bookmark. But when I try to launch an interactive M3 program, I got an error message: “You may only have 20 tabs or windows open at a time. To change the limit, please contact your system administrator.” When I check the available programs in the Script editor, I see many open instances which are not visible on the screen. It seems that the Mashup designer does not close programs in some situations. Can you confirm ? The situation is very bad because sometimes I work an hour to detect the piece of code in the XAML which causes the problem, and then I see that I simply have to restart SmartOffice to get red of the lost program instances. As I can see in fiddler, the response from the M3 BE is clear, but the Mashup designer doesn’t display it. Do you have any idea what causes this lost instances, and what is the best way to deal with this situation
    /Heiko

    Reply
    1. norpe

      There have been at least one known bug where the Mashup Designer do not dispose the M3 Mashup panels and for list panels this means that the M3 program keeps running and you hit the max program limit. The bug should have been corrected in the latest service/fix packs for 10.0.5.x and 10.1.x.

      Until you get a Mashup Designer with the fix you might be able to minimize the issue by not using the Preview functionality in the Designer in the main window or in the settings dialogs (use Run instead to test). Not sure if this helps but it could be worth a try if an upgrade to the latest version is not possible at the moment.

      Reply
  15. Kim Pedersen

    Hello,

    We have tried to extend the functionality in the Smart Office (10.0.5) Mashups in order to do thinks like:

    * Automatically select the first row in a listview
    * Sort a listview upon data retrieval
    * Make the NumPad+ key work in mashups (as it does in the other programs)

    To do this we have developed a .NET 4.0 dll in Visual Studio 2012 Express (we have not looked into the Smart Office SDK yet).
    The dll is utilized in the mashups by declaring it as xml namespace:

    It is used in the same way as the other mashup namespaces, fx.:

    and

    ..

    The dll needs to reside together with the Smart Office executable, fx. in

    C:\Users\kpe\AppData\Local\Apps\2.0\69R5N71W.CYH\8CVJB1YZ.MHX\http..tion_7cc10bdd4091a528_000a.0000_f34d1ea4c3f95f95

    Our clients are starting Smart Office from a ClickOnce installer which downloads the installation if it hasn’t been done before.
    The installer generates a directory which looks like the above mentioned, and the dll will be deployed by the windows logon script which will
    find all directories containing LawsonClient.exe under C:\Users\USER and copy the file there.

    Do you think there’s a better approach to accomplish this? I don’t think we can do it the same way as we deploy the mashups and scripts.
    But of course this would be a bit more clean and transparent.

    Kim

    Reply
    1. karinpb Post author

      Hi Kim,
      The supported way would be to look at the Smart Office SDK and deploy your dll as part of a feature. You would need to add configuration for an application (even if you don’t use it) but then the dll would be automatically downloaded and loaded into the process.

      When you use the Smart Office SDK you create a project, add dependen dlls and then package it as an .lawsonapplication. The application is installed via Life Cycle Manager.

      Using the Smart Office SDK would make more sence to the clients becuase they install components like Mashup Designer or Process Flow the same way they would install your utility.

      If you deliver all mashups always together – I would package a .lawsonapp package that contains the mashups as well as this feature.

      But your current approach will still work since it will look for the dll in the same directory. I’m not sure if there can be any side effects from a pure Click-Once perspective.

      You can’t deploy it like you deploy scripts. You can deploy it like Mahsups if you mashups are installed via Life Cycle Manager.

      Reply
  16. Linda N A

    Hi!
    I’m building a jscript with automation where the customer wants to change the panel sequence in MMS100/P. When I look at the response XML in debug mode, I can see that the Panel sequence field is another type of field, not “EFld” like the rest but “PSeq”. I can’t change it using the usual functions like ScriptUtil.FindChild and the “.Text” property. Can you please tell me if there is a way to change this field?
    /Linda

    Reply
    1. norpe

      On a parameter panel like MMS100/P the panel sequence is displayed in a control called MForms.Controls.HelperControl. This control is just a subclass of TextBox so the Text property should work. You can also find the element using the ScriptUtil.FindChild method with the field name “WWDSEQ” for MMS100/P.

      See example code and debug output example below.

      var panelSequence = ScriptUtil.FindChild(content, “WWDSEQ”);
      debug.Info(“Current value: ” + panelSequence.Text);
      panelSequence.Text = “E”;
      debug.Info(“Value after change: ” + panelSequence.Text);

      Output:
      INFO: Current value: EF1
      INFO: Value after change: E

      Reply
      1. Linda N A

        When reading your response I realize my mistake. For some strange reason I’ve been using the field name WWPSEQ, and not WWDSEQ…. It works perfectly with the correct field name 🙂 So thank you for you time and my sincere apologies for the rookie mistake…

  17. Linda N A

    Hi!
    Can I access the WWOPT2 field with Jscript to use Related options on an A panel? I want to use option+11 in an automation from MMS100/A.

    Reply
    1. norpe

      Not sure exactly what you mean as you mention both JScript and Automation. To execute a list option from JScript on a list or detail panel you just use the ListOption method.

      Example:
      controller.ListOption(“11”);

      If you are using automation you use the LSTOPT command with the value “11”. The LSTOPT command is also used for both list and detail panels.

      Reply
      1. Linda N A

        I’m building the automation in a Jscript:

        var auto = new MFormsAutomation();
        auto.AddStep(ActionType.Run, “MMS100”);
        auto.AddStep(ActionType.Key, “F13”);
        auto.AddStep(ActionType.Set);
        auto.AddField(“WWSPIC”, “A”);
        auto.AddField(“WWDSEQ”, “1”);
        auto.AddStep(ActionType.Key, “ENTER”);
        auto.AddStep(ActionType.Set);
        auto.AddField(“WWFACI”, selFACI);
        auto.AddField(“WGTRNR”, selORNO);
        auto.AddField(“WGRORN”, fieldORNO);
        auto.AddField(“WGRORL”, fieldPONR);
        auto.AddField(“WGRORX”, fieldRIDS);
        auto.AddStep(ActionType.ListOption, “11”);
        var uri = auto.ToUri();
        DashboardTaskService.Manager.LaunchTask(new Task(uri));

        When I add the ListOption step, I recieve an error from the program that says “Option must be entered”, and the response XML show a relation to WWOPT2.

        ControlData>WGRORXWWOPT2http://10.253.1.13/mnehelp/GBOption must be enteredWOP0102

      2. norpe

        There is one “gotcha” with using options on detail panels in automations. The default behavior is to select the first list row so to avoid this on detail panels you must send a blank SELROWS parameter.

        The Set action should only be used on the last panel. When setting values for a normal Enter key the fields should be added to that step. If you use the ToXml method and checks the actual automation XML you can see the structure a bit more clearly.

        Modified example code:

        var auto = new MFormsAutomation();
        auto.AddStep(ActionType.Run, “MMS100”);
        auto.AddStep(ActionType.Key, “F13”);
        auto.AddStep(ActionType.Key, “ENTER”);
        auto.AddField(“WWSPIC”, “A”);
        auto.AddField(“WWDSEQ”, “E”);
        auto.AddStep(ActionType.ListOption, “5”);
        auto.AddField(“SELROWS”, “”);
        auto.AddField(“WWFACI”, “A01”);
        auto.AddField(“WGTRTP”, “POS”);
        auto.AddField(“WGTRNR”, “0000000002”);
        var uri = auto.ToUri();
        DashboardTaskService.Manager.LaunchTask(new Task(uri));

        You can check the XML using this method.
        debug.Debug(auto.ToXml());

  18. Linda N A

    Thank you, it’s working now with the SELROWS parameter. Do you have any documentation where things like these can be found? The trial and error method works most of the time to solve problems, but it’s hard when you have no knowledge at all about the “gotchas”.

    Reply
    1. norpe

      The Smart Office SDK contains a document called M3DevelopersGuide.pdf with information about MForms Automation. The SELROWS parameter is documented there but it is not obvious that a blank value must be sent for options on detail panels (since this was not part of the original design for automations).

      Reply
  19. Heiko

    Hi!

    In a Mashup, is there any way to bind to a filter field in a panel header of the M3 ListPanel? I can easily set the value of a filter field, but what about vice versa ? In my example I want to set filter values in the collapsed header from outside (a combox box) in order to save space on the panel; but the user may want to expand the panel header and set values there, then the combobox is out of sync; is there a way to link back the value to the combo box?

    Reply
    1. norpe

      I can’t think of a way to do this in pure XAML (no C# code) at the moment. We would have to make changes to the M3 Mashup panels to make this easy to do.

      Reply
  20. Linda N A

    Hi!
    I’m writing a jscript to change the panel sequence for certain order types when entering OIS101. I use controller.PressKey(“F13”) to enter the Settings. This works ok when I run my script in ScriptTool, but when I add the script under Tools/Personalize… the PressKey event is not launched. Other key presses with keybord or clicking with the mouse are working fine (I debug by using onRequested and e.CommandType/Value), but not the script. Do you have any ideas on how to solve this? I tried a MformsAutomation but it seems that you must begin with ActionType.Run (program) and I don’t want to launch a new instance but stay in the current one.

    Linda

    Reply
      1. norpe

        This should work but it hard to say what is wrong without more information. When the log level is set to debug you can see if the PressKey method is called, there should be a log entry like this: “Executing CMDTP=KEY CMDVAL=F13”. If a request is already executing this will be skipped, but then there should be a log entry like this: “Duplicate request skipped”.

        By using log statements in the script and matching these with log entries from the MForms code it should be possible to see what is happening.

        MForms Automation is not an option in this case since you can’t use that on a program that is already started.

  21. Linda N A

    There was in fact a “Duplicate request skipped” in the log file. I moved my keypress to the onRequestCompleted event instead of onRequested and then it worked.

    Reply
  22. Linda N A

    Is there a way in jscript to load the new controller instance when using ListOption to open a new program? I want to use controller.ListOption(“21”) on a row in MWS420, and then again in the opened row in MWS410 but the controller instance at hand is still focused on MWS420 so my script stops.

    Reply
    1. Joakim Bodin

      I don’t think JScripts can access another panel outside of the panel they’re connected to – I’m not sure.

      The easiest way to go about this would probably be to use an MForms Automation string from your JScript (these are described in the Smart Office Developers Guide) in combination with the DashboardTaskService from the Mango.UI.Services namespace. See below:

      DashboardTaskService.Manager.LaunchTask(uri);

      ..where “uri” is your MForms Automation string.

      Reply
      1. Linda N A

        I have also tried the automation option, and can get to the program I want. But when I try to close the window SmartOffice produces an error which seems to be connected to the same problem. When i use ListOption and a new controller instance is created LSO looses the connection to where it came from and therefor can’t find the originating ListRow.

        2014-02-17 14:28:18 ERROR MForms.InstanceController.HandleRenderException MFS0035 Failed to render
        System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. —> System.InvalidOperationException: AnchorItem ‘Mango.UI.Services.Lists.ListRow’ does not have a realized container and hence is invalid.
        at System.Windows.Controls.ListBox.set_AnchorItem(Object value)
        — End of inner exception stack trace —

      2. karinpb Post author

        Hi Linda,
        You can’t connect calls like this. With scripting and Automation there is no support for completing an entire flow like I guess you would like to do. As for the specific exception I’m not sure why you get it, probably you hold on to the list after the list was gone from the UI and that is not allowed.

    2. karinpb Post author

      Hi Linda,
      No there is no way to load the new controller. A script is local to that specific program and you should unregister as soon as the user has navigated away from the panel.

      Reply
  23. CAS

    First of all, a big thank you to all the hard work you’ve put into the blog so far, I’ve found your posts both very informative and incredibly helpful for some of the problems I’ve had in M3, that have had me tearing my hair out at times.

    One of the things I find a major headache sometimes when working with scripts and Mashups is identifying fields when trying to populate data. I use a mixture of the F1 help menu, debug menu ,script tool and personalisation window to try to identify the correct field name but at times I just don’t seem to be able to populate fields with data.

    One example being with ARS200 in a mashup where I’m trying to populate the WWPYNO (payer) field with data, I’ve added the WWPYNO field in the bookmark settings for ARS200 and added a target key entry in the event for WWPYNO/PYNO but I just don’t seem to be able to populate that specific field with any data,whether that’s using a source key, hard coded value, etc.

    The field name appears to be correct as I can set a value if using the Program property attribute and an apply event, but not with the bookmark.

    I was just wondering if it’s simply a case of that even if a page has been bookmarked and a valid filter exists on the standard panel there are some fields you just can’t populate on the event?

    Thanks

    System details M3 BE 15, Smart Office 10.05.4.10

    Reply
    1. norpe

      When setting values using a bookmark you can only set the values that the bookmark supports. For a detail panel this is usually just the keys. For a list panel it includes the keys and additional fields. The additional fields are specific for each bookmark and there is no guarantee that all fields can be set.

      I would recommend that you always test bookmarks using the MTS043 test program (mforms://mts043). In that program you can see which fields that can be set and also test that it actually works. If a bookmark does not work as expected in MTS043 it will not work in a Mashup either.

      Note that you must specify the names of the additional fields using the FieldNames property of the bookmark. See the documentation of MFroms.Mashup.Bookmark for more information.

      Reply
  24. Linda N A

    Is there a way in jscript to know how a program has been opened? For example, can I somehow retrieve the information that PCS200 has been opened from PDS001 or as a standalone program? Maybe get hold of the program stack in the Mforms toolbox or use some property in the renderEngine?

    Reply
  25. Nuno Monteiro

    Hi
    Some assistance would much appreciated. Newbie at Lawson Smart Office.
    Somehow, from few days ago, I can only run programs if I type mforms://
    For instance, MMS001 shows “Search not found”. I have to type mforms://MMS001.
    How can I solve this?
    Application version: 9.1.2.44.1 (seen on LawsonClient.log)
    Thanks

    Reply
    1. karinpb Post author

      Hi,
      Perhaps someone has set up a custom menu for you in MNS150 and MMS001 is not included?
      Do you have the full menu in the Navigator widget under M3 transactions? Can you search for MMS001 there?
      Any applied Microsoft updates applied recently that might affect SQL CE?

      Reply
      1. Nuno Monteiro

        Thanks for your answer, karinpb.
        MMS001 was just an example. It happens with all M3 programs.
        Navigator widget is empty!! And yes, few days ago I have applied Microsoft updates, upgrading from SQL 2008 to 2008 SP2 … Installed now SQL2012, but the problem remains…
        What can I do?

      2. Nuno Monteiro

        Hi Karin
        As you mentioned SQL CE, I did some reading and downloaded Microsoft SQL Server Compact 3.5 Service Pack 2 for Windows Desktop. In the installation I chose repair, and the problem is now solved! Thank you very much.

  26. Johan Lindström

    Hi!
    I am having trouble using the Link Manager in Smart Office to its full extent.
    I want to link to a document in Content Manager using a field as parameter. It’s all working fine when I create a link between an attribute in CM and for example ITNO (article no) in MMS001. However I would like to be able to put a condition in the search so that it searches for part of the ITNO
    Code for linking article no to my attribute in Content Manager (working):
    ca://da/search?QK_xquery=/ItemCM[@AttributeCM =]

    However the Attribute in CM is always the 5 first characters of ITNO so I would like to use substring but I can’t get the syntax to work:
    ca://da/search?QK_xquery=/ItemCM[@AttributeCM =SUBSTRING(,5)]

    Just to clarify I have 1 document in CM (no 12345) and multiple articles I want to link to that one document (12345A, 12345B, 12345C)
    Any help is appreciated

    Regards
    Johan Lindström

    Reply
    1. Johan Lindström

      I meant to include in the pseudocode:
      ca://da/search?QK_xquery=/ItemCM[@AttributeCM =SUBSTRING(,5)]

      I would like to be able to use the link in for example MMS001/B and part of ITNO should be used as a parameter to find a document in CM

      Reply
      1. norpe

        There is currently no way do do this.

        In Smart Office 10.2 it will be possible to use variable replacement expressions for Smart Links of type Web (which includes any Smart Office link) and in other places where variable replacement is supported. It will not be supported for Document Archive links however, unless you use a ca://da URI as a Web link with replacement variables. The expressions will support substring among other things.

        In that case the syntax would be something like this:
        ca://da/search?QK_xquery=/ItemCM[@AttributeCM={=Substring(GetVAlue(‘ITNO’), 0, 5)}]

        The variable replacement expression part of the URI above is:
        {=Substring(GetValue(‘ITNO’), 0, 5)}

        Smart Office 10.2 will be GA within a month.

  27. Linda N A

    I’m posting this question again since I have a new case when this could solve the issue.

    “Is there a way in jscript to know how a program has been opened? For example, can I somehow retrieve the information that PCS200 has been opened from PDS001 or as a standalone program? Maybe get hold of the program stack in the Mforms toolbox or use some property in the renderEngine?”

    Reply
    1. norpe

      The PanelState has a StartProgram property but unfortunately it is internal. You can still access it if you are willing to use reflection as in the example below. I will change this property to be public in future versions. The value returned by the StartProgram property is the program name converted from the the name of the panel that the program starts on. I guess that there could be some cases where this is not what is expected so it’s something to be aware of.

      import System;
      import System.Windows;
      import System.Windows.Controls;
      import System.Reflection;
      import MForms;
      
      package MForms.JScript {
         class StartProgramExample {
            public function Init(element : Object, args : Object, controller : Object, debug : Object) {
               var panelState : PanelState = controller.PanelState;
               debug.Debug("Start program: " + GetProperty(panelState, "StartProgram"));
               debug.Debug("Current program: " + panelState.ProgramName);
            }
      
            private function GetProperty(obj, propertyName) {
               var property = obj.GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
               return property != null ? property.GetValue(obj, null) : null;
            }
         }
      }
      
      Reply
  28. Heiko

    I am searching for a way to display a message in the StatusBar of a M3 panel from C#. In JScript .Net, it is easy – the type conversions and castings are handled automatically in the background. In C#, I can get the StatusBar control in similiar way. But I need to define the type of the StatusBar control in order to call the “SetMessage” method. But this piece of code doesn’t compile (variable “grid” has been set to the ContainerPanel control, statusBarType has been set via Type.GetType….):

    MForms.Controls.StatusBar statusBar;
    statusBar = (MForms.Controls.StatusBar)Helpers.FindElementsOfType(grid, statusBarType);

    The compiler tells me that it is not possible to convert System.Collections.Generic.List” into “MForms.Controls.StatusBar”:
    Is there a solution ?

    Reply
    1. Heiko

      I have found a solution, but don’t love it:

      var grid = Helpers.FindVisualElementUpInTree(Controller.RenderEngine.Content, “ContainerPanel”);
      var statusBarType = Type.GetType(“MForms.Controls.StatusBar,MForms”);
      if (grid != null)
      {
      for (int i = 0; i < VisualTreeHelper.GetChildrenCount(grid); i++)
      {
      if (VisualTreeHelper.GetChild(grid, i).GetType() == statusBarType)
      {
      MForms.Controls.StatusBar statusBar =
      VisualTreeHelper.GetChild(grid, i) as MForms.Controls.StatusBar;
      statusBar.SetMessage("TEST");
      break;
      }
      }
      }
      Any better way than to loop the visual children ?

      Reply
      1. Linda N A

        Hi, you can try
        controller.RenderEngine.ShowMessage(“TEST”);

        I don’t know if it suits you’re needs, but it’s an easy way to display messages.

      2. norpe

        The supported way to show a message in a MForms panel is to use the ShowMessage method on a RenderEngine instance (which you can get from a IInstanceController instance). This will show the message in the status bar or in a dialog depending on the users settings.

        The MForms.Controls.StatusBar class no longer exist in Smart Office 10.1.x, it has been replaced with Mango.UI.Controls.StatusBar, so accessing this class is not recommended and not supported. The StatusBar control is an internal implementation detail and not part of the public API.

        If you still want to do this it it possible.

        // Get status bar for 10.0.5.x or older
        var statusBar = Helpers.FindLogicalChild<MForms.Controls.StatusBar>(containerPanel);
        
        // Get status bar for 10.1.x and newer
        var statusBar = Helpers.FindLogicalChild<Mango.UI.Controls.StatusBar>(containerPanel);
        
        // Set message
        statusBar.AddMessage("Message text...");
        
  29. AmrDV

    thanks for that helpful blog ,,,
    i am new with Mashup .. i need something it may be simple but i don’t know.
    i want to know how to go back from Xaml file to the previous Opened Mashup with new values.
    i,e, i have First.xaml which has two fields and a button ,,, when i press the button i want to open Second.xaml file to select some values and with the close i want these values to be set in the First.xaml file ,, not to open a new instance of First.xaml ,, but to fill in the already opened instance .
    thanks alot

    Reply
    1. karinpb Post author

      Hi,
      There is an example that demonstrates how to do this in the Mashup Designer. It is called Dialog and found under Help -> Common Controls -> Dialog.

      Don’t get confused that the example uses the same XAML as the starting page as well as the page to be opened in a dialog.

      You use the Dialog XAML control. Add a button to trigger the dialog and then in your dialog XAML file you set as many targetkeys as you would like and call close.

      Start with applying the example to two simple XAML files.

      Reply
  30. Ed Kaufmnan

    We have published a lot of InforBrowsers and i wonder if there any way to create the custom folder under the Navigator and combine all those infor browsers by groups in different folders.
    Thank you

    Reply
    1. karinpb Post author

      Hi Ed,
      I’m sorry but there is no way to add a new category. I will take this up as a possible enhancement request to the predefined widget framework even though it does require a lot of development. Especially if the categories should be language controlled / translated.

      What you might consider (even though it is not what you are looking for) is to create a Startpad (from 10.0.5) with links to all widgets or a News Reader (pre 10.2) or a Menu Builder (10.2) that contains links that will add the widget instead.

      What we have added in 10.2 (or was it 10.1 – I’m not 100% sure) is the possibility to search both the title and the description so it will get easier to filter all the widget by searching in the library.

      All widgets can be added with a URI. And since you can create a menu widget you could do your own “widget library” as a widget. See my blog post on creating a simple menu with the News widget. In some cases using a web server for the Menu is the best choice becuase it means that you can update it and it will be pushed to all users.

      Below is the format for adding a widget:
      widget://add?scheme=&EnableSetting=false

      You can also add a link to the Widget Library as an URI if you feel like it. widget://library.

      Reply
  31. Sébastien REYNIER

    Hello,

    I’m working in a French company and we are implementing M3 V13.1 and we want to develop some mashups.
    We want to get the version number setuped in project’s properties field in order to display this information with a textblock (or other) in the screen of the mashup (in order to help us when user call us when he have an issue).

    Do you know if it’s possible to get this information ?

    Thanks a lot for your help

    Regards
    Sébastien

    Reply
    1. karinpb Post author

      Hi,
      This makes sence but I don’t know if you can get that information. If not we should add it. Anyway I have forwarded the questing and I’ll get back to you.

      Reply
    2. norpe

      The version can be accessed from code using methods but these that are not supported and I can’t see a way to get it from XAML.

      We should expose properties such as the version and other values from the Mashup manifest to the MashupContext or something similar.

      Reply
  32. ericwayker

    Hello. There is an MITEST program/transaction called EVS001MI. Within this program there are transactions to get the BE Version. FYI. I am on M3 and not S3. You could set up an MIPanel to call the program/transaction.

    Reply
    1. norpe

      I think he wanted to display the version of the Mashup.

      Access to the BE version is available in Smart Office 10.2.x and later using the MForms.BEEnvironment class which can be used after MForms has been initialized. The version is loaded using the MI transaction you mentioned.

      Example:
      BEEnvironment.Current.Version
      BEEnvironment.Current.VersionString

      Reply
  33. Alex

    Hi,

    I am working in an SE 9.0.1.13 environment on IE 11 and I am not having any luck with Design Studio. Getting “Half Menu” and I have played around with the Microsoft Emulator but without any luck, I am still missing my top menu bar. Has anyone had any luck???????????????

    Reply
    1. karinpb Post author

      Hi,
      If you are running the Design Studio from within Smart Office the default browser emulation mode for the browser control is IE7. You can open the Design studio in the external browser if the issue is within Smart Office. You can set the browser emulation manually in settings in newer versions of Smart Office. In your version you can still set it manually in the registry. See for example: Configuring emulation mode of IE. I’m not sure if that is what you mean with Microsoft Emulator- I have not tried the Design Studio myself. I asked around and I got this tip: Must have LSF 10x for IE 11 support. You could try compatibility mode to downgrade the render engine.

      Reply
  34. vmcgowaninfor

    As a former developer of Design Studio, I can provide a little more background. Initially developed 10-12 years ago, DS used an HTML technology for displaying the menu bar that Microsoft has long abandoned and does not support in IE beyond version 9. LSF 10.x provides a version of DS that supports IE 10+. I checked with the current development team and they say there is no way to run that version of DS with IE 11 even in compatibility view. One alternative might be to create a VM with an older version of IE installed.

    Reply
  35. Linda N A

    Is there some way to create a prompt dialog in jscript so the user can enter some values that are later used in the script?

    Reply
      1. Joakim Bodin

        Hi Linda,

        You can create a new HostWindow instance, and set the HostContent property of that HostWindow to a Grid instance. The grid could for example contain a text box where the user can enter a value, as well as a button to confirm and so on.

        To launch the HostWindow you can use DashboardService.Current.ShowDialog(yourHostWindow).

        Example below:

        var window = new HostWindow(true, true);
        window.Type = HostType.EmbeddedModal;
        window.Owner = ApplicationServices.MainWindow;
        window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
        window.HostTitle = “PIN Code”;

        var pinGrid = new Grid();
        pinGrid.Width = new GridLength(1, GridUnitType.Star);
        pinGrid.Height = new GridLength(1, GridUnitType.Star);
        pinGrid.HorizontalAlignment = HorizontalAlignment.Stretch;
        pinGrid.VerticalAlignment = VerticalAlignment.Stretch;

        // Define the columns
        var colDef1 : ColumnDefinition = new ColumnDefinition();
        var colDef2 : ColumnDefinition = new ColumnDefinition();
        var colDef3 : ColumnDefinition = new ColumnDefinition();
        var colDef4 : ColumnDefinition = new ColumnDefinition();

        // Set the Column Widths
        colDef1.Width = new GridLength(116, GridUnitType.Pixel);
        colDef2.Width = new GridLength(110, GridUnitType.Pixel);
        colDef3.Width = new GridLength(100, GridUnitType.Pixel);
        colDef4.Width = new GridLength(100, GridUnitType.Pixel);

        // Add the Columns to the Grid
        pinGrid.ColumnDefinitions.Add(colDef1);
        pinGrid.ColumnDefinitions.Add(colDef2);
        pinGrid.ColumnDefinitions.Add(colDef3);
        pinGrid.ColumnDefinitions.Add(colDef4);

        // Define the Rows
        var rowDef1 : RowDefinition = new RowDefinition();
        var rowDef2 : RowDefinition = new RowDefinition();
        var rowDef3 : RowDefinition = new RowDefinition();
        var rowDef4 : RowDefinition = new RowDefinition();
        var rowDef5 : RowDefinition = new RowDefinition();

        // Set the row heights
        rowDef1.Height = new GridLength(30, GridUnitType.Pixel);
        rowDef2.Height = new GridLength(30, GridUnitType.Pixel);
        rowDef3.Height = new GridLength(50, GridUnitType.Pixel);
        rowDef4.Height = new GridLength(30, GridUnitType.Pixel);
        rowDef5.Height = new GridLength(20, GridUnitType.Pixel);

        // Add the Rows to the Grid
        pinGrid.RowDefinitions.Add(rowDef1);
        pinGrid.RowDefinitions.Add(rowDef2);
        pinGrid.RowDefinitions.Add(rowDef3);
        pinGrid.RowDefinitions.Add(rowDef4);
        pinGrid.RowDefinitions.Add(rowDef5);

        // Passwordbox
        var pwdBox = new PasswordBox();
        pwdBox.Name = “passwordBox”;
        pwdBox.Margin = new Thickness(5,2,3,2);
        pwdBox.Height = pwdBox.MaxHeight = pwdBox.MinHeight = 18;
        pwdBox.Width = 130;
        pwdBox.HorizontalAlignment = HorizontalAlignment.Left;
        Grid.SetRow(pwdBox, 1);
        Grid.SetColumn(pwdBox, 0);
        Grid.SetColumnSpan(pwdBox, 2);
        pinGrid.Children.Add(pwdBox);

        // OK button
        var okButton = new Button();
        okButton.Width = 90;
        okButton.Name = “OkButton”;
        okButton.Content = “OK”;
        okButton.IsDefault = true;
        Grid.SetRow(okButton, 3);
        Grid.SetColumn(okButton, 2);
        pinGrid.Children.Add(okButton);

        // Add events
        okButton.add_Click(OnClickButton);

        window.HostContent = pinGrid;
        window.Width = window.MinWidth = window.MaxWidth = 440;
        window.Height = window.MinHeight = window.MaxHeight = 250;

        DashboardService.Current.ShowDialog(window);

    1. ericwayker

      For JScript above
      import Mango.Services; // copied in for HostType and ApplicationServices
      import Mango.UI.Services; // copied in for HostWindow and DashboardService

      I removed –
      pinGrid.Width = new GridLength(1, GridUnitType.Star);
      pinGrid.Height = new GridLength(1, GridUnitType.Star);

      I also added the on click button click event
      public function OnClickButton(sender: Object, e: RoutedEventArgs) {

      } // end of OnClickBtnCancel

      Reply
    1. Joakim Bodin

      Hi Linda,

      You can check the “AllowDrop” property of a TextBox control that you know is editable in “Change” mode but not editable in “Display” mode.

      If “AllowDrop” is true, you’re in “Change” mode.

      Reply
      1. Linda N A

        Thanks Joakim for the answer. I have previously used a check to see if field is tabable or not, seems like kind of the same principle. But why is there no setting for this, what determines the mode in Smart Office?

      2. karinpb Post author

        Hi,
        Unfortunately Smart Office does not have the Display/Edit mode on the client. It is only available on the M3 Adapter server and we could perhaps change that and add a method for it but it would only work in new versions of Smart Office in combination with a new M3 User Adapter. Until then you would have to do with these “work-arounds” that require you to know the behaviour of fields on the panel.

  36. Daniel

    Hi,
    Is there a documentation how to use a DataListPanel with web service in a mashup?
    I added a DataListPanel and I can see the result of the web service with the testing function. But when I start the mashup the DataListPanel stays empty even with static input for the web service. I just see a short loading circle and get the message “Completed NameofWebService”. Do I have to choose the columns I want to display or should all columns of the web service result come up?

    Reply
    1. karinpb Post author

      Hi, The Web Service test tool analyzes the data but you need to configure the DataListPanel manually to fit you data. The Web Service test tool will help you with the values for the data as well as for the columns. You can copy values from the out put in the test tool to the clipboard and then use those in the ListView to bind the columns. There is not much documentation except the API documentation and the examples on this blog.

      Reply
  37. Joakim Bodin

    @Linda N A, maybe there exists another variable we can look at somewhere. I haven’t found one yet! This is perhaps a question for the developers.

    Reply
  38. Harryliu

    Hi,everyone,when i use MForms Automation function ,but the script belong to (personalize ->scripts) seems taking no effect after MFormsAutomation windows closed .

    Reply
  39. Harryliu

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

    package MForms.JScript {
    class OIS812 {
    var controller;
    var debug;

    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;

    // TODO Add your code here
    this.debug = debug;
    this.controller = controller;
    var button = new Button();

    button.Content = ‘Test’;
    button.ToolTip = ‘Test Excel’;

    button.HorizontalAlignment = HorizontalAlignment.Left;
    Grid.SetColumn(button, 57);
    Grid.SetColumnSpan(button, 98);

    button.VerticalAlignment = VerticalAlignment.Top;
    Grid.SetRow(button, 4);
    Grid.SetRowSpan(button, 23);

    controller.RenderEngine.Content.Children.Add(button);

    button.add_Click(OnClick);
    button.add_Unloaded(OnUnloaded);

    }

    function OnClick(sender: Object, e: RoutedEventArgs) {
    try {
    var data = new Array();
    data[’11’] = [“CRC”, “2” ,”122303″ ,”2″ ,”CH2701″ ,”015001002″ ,”CH63″ ,”4″ ,”0″ ,”0″];
    data[’12’] = [“CRC”, “2” ,”122303″ ,”2″ ,”CH2701″ ,”015001003″ ,”CH63″ ,”7″ ,”0″ ,”0″];

    for (var x in data) {

    var auto = new MFormsAutomation();
    auto.AddStep(ActionType.Run, ‘OIS811’);
    auto.AddStep(ActionType.Key, ‘ENTER’);
    auto.AddField(‘WWDISY’, data[x][0]);
    auto.AddField(‘WWDIPO’, data[x][1]);
    auto.AddField(‘WWFVDT’, data[x][2]);
    auto.AddField(‘WWPREX’, data[x][3]);
    auto.AddStep(ActionType.Key, ‘ENTER’);
    auto.AddField(‘WWOBV1’, data[x][4]);
    auto.AddField(‘WWOBV2’, data[x][5]);
    auto.AddStep(ActionType.Key, ‘ENTER’);
    auto.AddStep(ActionType.ListOption, ’11’);
    auto.AddStep(ActionType.Key,’ENTER’);
    auto.AddField(‘W1CMPN’,data[x][6]);
    auto.AddStep(ActionType.ListOption, “-1”);
    /*
    there is OIS811
    */
    auto.AddStep(ActionType.Key, ‘F3’);
    auto.AddStep(ActionType.Key, ‘F3’);
    var uri = auto.ToUri();
    var flag = DashboardTaskService.Manager.LaunchTask(new Task(uri));
    }
    } catch (ex : Exception) {
    debug.WriteLine(ex);

    }
    }

    function OnUnloaded(sender: Object, e: RoutedEventArgs) {
    sender.remove_Unloaded(OnUnloaded);
    sender.remove_Click(OnClick);
    }
    }

    }

    Reply
    1. karinpb Post author

      Hi,
      I’m not an expert at Automation scripts and we are very busy so I don’t have time to try this out or ask Peter who is the expert in this. Can you test the automation separately? There is an MNE automation build tool that can build a link that you can try and run directly. I think it is delivered in the Smart Office SDK. It’s called the automation builder. But I do see a few issues. You start the program but why add a ENTER step? ENTER is only needed to go from one panel to another. So don’t have enter after a ListOption – only when pressing enter to go to the next panel. Then I’m not sure -1 would ever be a valid listoption?

      Reply
      1. Harryliu

        hi,
        I use MFormsAutomationBuilder and test ,but it seems no effect. In other way , I try use personal ->shortcuts link the jscript. When I click the shortcut , it take effective. But how can I launch this shortcut by using script.

      2. karinpb Post author

        No you shouldn’t try and work around and launch a shortcut. If you log the URL that you get from the MNE automation helper class that you pass in to launchTask – does it really look the same as the link you can launch as a shortcut? You have a difference in the way you apply the steps.

  40. CAS

    Hi everyone, I’ve been having a search through quite a few of the articles both on here and some of the other related blogs and I’m getting quite close to my answer but just can’t quite get there. I’m trying to retrieve the current Division from the System Profile in a JScript, but I’m not sure the property I should be looking for.

    I’ve made use of the var profile = ApplicationServices.SystemProfile; and can bring back the Profile name using var text = “Profile: ” + profile.Name; but I’ve not been able to figure out what the Division property is called in the System Profile.

    I’ve been able to use the var user = ApplicationServices.UserContext; and var text = “Division: ” + UserContext.Division; to bring back the user’s record in MNS150 but found that as we have a few users that operate in multiple divisions and as I’m trying to use the JScript to validate the division the user is logged into against a division of a warehouse on a Listview line, it’s causing me some problems.

    Any assistance of advise would be greatly appreciated, if it would help to show my entire script for reference just let me know and I’ll post it up. Thanks Chris

    Reply
    1. karinpb Post author

      Hi,
      It’s not in the profile becuase it is dynamic data and not something you can edit in the profile editor. It is in the UserContext and you are close, the properties are:
      UserContext.CurrentDivision
      UserContext.CurrentCompany
      debug.WriteLine("Current company: "+UserContext.CurrentCompany+", Current division:" +UserContext.CurrentDivision);

      Reply
      1. CAS

        Ah haaaa I knew I was close to the answer, thank you so so much Karin P, it was really bugging me yesterday, your help is very much appreciated. Happy Holidays!

  41. Mikael

    Hi
    Is it possible to change the layout in a dialog? For example ConfirmDialog.ShowAttentionDialog.
    I would have some fields in BOLD or change the FONT. Is it possible ?

    Thanks
    /mikael

    Reply
  42. karinpb Post author

    It’s not possible to change the font etc in the ConfirmDialog. You can create your own dialog if you like to but then you would need to set the widowheader, title, buttons etc.

    Reply
    1. Mikael

      Hi
      Thanks for the answer. The following question is of course where I could find a good example for creating my own dialog. Thanks !

      Reply
  43. karinpb Post author

    It depends on the minimum version of Smart Office that you need to support. There are better utility methods in newer versions. What is the Smart Office version you are targeting?

    Reply
  44. Mikael

    We will go live this weekend so it should be a new version. Smart office version 10.2.0.0.49 and MBE = 13.2. Thanks /mikael

    Reply
    1. Mikael

      I solved the problem with dialog box. I create my own dialog box (as you suggested) with HostWindow and Grid/TextBlock. Best regards Mikael

      Reply
  45. CAS

    Hi there, I’m trying to make a jscript conditional based on the content of a specific field, in this case it’s the Order Type field in MMS101/F (MGTRTP). If the order type used is equal to X or Y I’d like the script to proceed, but if the order type is equal to A,B,C,D,E, etc.then I’d like the script to exit. The part I seem to be having a problem with is getting the script to search for both the X and Y order types. I’ve tried a number of things but the script seems to either just look for one of the order types or just ignores the order type altogether and just proceeds with the script whatever the order type is.

    What would be the recommended way in terms of scripting to search through a list of criteria (X or Y order type) to find a matching value and continue or exit the script?

    Thanks!

    Reply
    1. karinpb Post author

      Hi,
      Make sure you use logs in your script as you probably have a bug in there. If it is just a field that you would like to compare to a number of values you can do an if/else approach. Just be sure to use compareIgnoreCase() when comparing strings (or always compare with a lowercase value). An ArrayList of strings and a contains check would work as well but you need to use the same case – for example lowercase.

      Reply
  46. Mikael

    Hi
    A question about MIWorker and output fields with data type DATE. In MRS003 we set a field (output) with data type D (for Date). When we call the transaction with MIWorker and read the field, it is in format UTC. Why ? Should not SetDateFormat not be enough to use before we call the transaction.

    For example when we read the output field it says: MON Feb 23:00:00 UTC+1 2015.

    What is the common practice here. How should we convert the UTC-format ? Could we use common methods for this ? Which ?

    Of course if we change the format in MRS003 from D to N (numeric) and it will work,

    Thanks a lot !

    Reply
    1. karinpb Post author

      Dates that are configured to D in metadata will be automatically transformed to DateTime objects in .Net using MIAccess. The Date object can be formatted on many different ways. With standard .Net methods and Smart Office specific converters like M3DataConverter. When you say that you “read” the outputfield what method do you use? This is output so you will get a DateTime object – how do you use it in the next step in you application?

      Reply
  47. Linda N A

    Hi,

    when calling MI Worker a couple of times in a row I get this error message:
    Error when running API. Apierror:System.InvalidOperationException: The username is not provided. Specify username in ClientCredentials.
    Server stack trace: at System.ServiceModel.ClientCredentialsSecurityTokenManager. CreateSecurityTokenProvider(SecurityTokenRequriement tokenRequrirement, Boolean disableInfoCard).

    Even though I get this error the API is working as it should and saves data in database. Why do I get this error? Is there some setting that could prevent this in SmartOffice? I only get this with one customer.

    /Linda

    Reply
    1. karinpb Post author

      Hi Linda,
      I’m not sure why you would get this error message since we always have the username and we always set the ClientCredentials. Isn’t there any more information in the stacktrace? I think you should report this so that we can have a look at MIAccess becuase it seems strange that it should work when there is an invalidOperationException (or at least email me the full log file in debug). In some cases (depending on version of Smart Office) we will also send a cookie container so you might already have a valid cookie for the API server.

      Reply
      1. Linda N A

        Hi, I have a new example now when the MI worker returns this error. What’s your email address where I can send the log file?

      2. Mikael

        Hi
        Actually I got the same error message. Not always but sometimes. It will occurr when we call for MI worker several times (in this case for every row in a display list). Not everytime the user opens the program but now and then. They are running BE 13.2.
        Best regards

        Mikael

      3. Mikael

        Hi
        We got this error now and then when we are calling MI Worker. Is this something you have encountered ? (M3 BE = 13.2)
        /mikael

      4. karinpb Post author

        Hi, As for this warning just make sure that you are only calling this method once. It might be related to threading. I’ve only seen this when there are multiple calls to the same API caused by eventhandlers that are not disconnected. So even if the solution works there are multiple calls to the API after for example a page down or a function call that – especially when manipulating a list. You must disconnect all event handlers on all event except page down. It is very important not to flip the condition around since there might always be scenarios that you down think of and then you’ll have attached events running in parallel. Check if page down is called – add a debug line and then an else branch that will remove the event listeners.

        So I think it is related to threading but there has been no fixes in this area since it seems like the issue is in Microsoft code. Please verify (with Fiddler and code review) that you will always detach events.

  48. Daniel

    Hi,
    as mashup designer is based on WPF, is it also possible in the mashup designer to create a background script and link some functions to objects?

    Reply
  49. karinpb Post author

    It is not possible to use scripts in Mashups. The only exception is if you have a M3list since you can run a script in that program. To be able to run code in a Mashup you would have to build a SDK feature with XAML extension methods or with a custom Mashup control. It’s possible to have a Mashup control with just code and no UI. It’s a good requirement.

    Reply
  50. olaborde2015

    Hi there !

    It is possible to close a screen on a startup script ?

    I tried with 2 possibilities :

    1-
    var auto = new MFormsAutomation();
    auto.AddStep(ActionType.Key, “F3”);
    var uriF3 = auto.ToUri();
    DashboardTaskService.Manager.LaunchTask(new Task(uriF3));

    2-
    controller.PressButton(“F3”);
    With a shorcut this solution works but not with a startup script.

    Have you an idea ?

    Reply
    1. karinpb Post author

      Hi,
      I’m not sure what you mean with startup script.
      1) The automation URI will not work beacuase you are launching a new instrance of a program when you call launchTask (without the program in the Uri so it will just fail).
      2) I guess the controller isn’t ready to submit any button actions in init. Have you tried dispatching the call so that it is done at a later time on the UIThread or listening to the onRequestCompleted event and then unregister the eventhandler and then call controller.PressButton(“F3”).

      Reply
      1. olaborde2015

        It works ! Thank you !

        […]
        var instanceController : Object;

        public function Init(element: Object, args: Object, controller : Object, debug : Object) {
        instanceController = controller;
        instanceController.add_RequestCompleted(OnRequestCompleted);
        }

        public function OnRequestCompleted(sender : Object, e : RequestEventArgs) {
        instanceController.remove_RequestCompleted(OnRequestCompleted);
        instanceController.PressKey(“F3”);
        }

        Best regards

  51. Amy

    I am looking for a “type ahead” solution to tie into Mashup Search fields or IES search. Any suggestions?

    Reply
    1. karinpb Post author

      Hi Amy, No suggestion except that it would require writing a new control. We have similar functionality but our control (TypeAheadControl) that we use for start and search for example is not intended for external use. It also requires you to write code so you wouldn’t be able to use it in a Mashup but it can act as inspiration if you write your own control.

      Reply
  52. Steve Arnone

    Hi. I have attached a handler to the RequestCompleted event. When the event fires I check the CommandType and CommandValue to make sure it was part of the panel submittal. Is there a way to determine if an M3 validation error has occurred on the page? I have tried looking at the ResultCode and Result values but that didn’t seem to work.

    Thanks.

    Reply
  53. Daniel

    Hello,
    can you explain how to fill a filter of a list view and then press create with a jscript?
    I think it is a simple thing but somehow I´m a bit lost with this and I cannot find a good example.
    Thank you in advance!

    Br
    Daniel

    Reply
    1. norpe

      The function below is part of a larger example but it shows how to set position field values and triggering the create option.

      Note that more checking would be required if the number of position fields could be different depending on the selected view etc. This example was for the OIS002/B panel.

      private function CreateAddress() {
          debug.WriteLine("CreateAddress()");
      
          var listControl = controller.RenderEngine.ListControl;
          listControl.PositionFields[0].Text = "1" // WRADRT
          listControl.PositionFields[1].Text = "1" // WRADID
      
          expectedPanel = "OIA002E0";
          controller.ListOption(MNEProtocol.OptionCreate);
      }
      
      Reply
  54. Heiko

    Hi,

    I have a JScript problem … my Code uses the DynamicWS class to execute SQL over Web Services. The SQL is a stored procedure, which takes only 2 input variables: 1. The company number; 2. The complete SQL statement which is constructed at runtime in the code with the company number as a variable parameter.

    It works fine in general, but I have one statement which does not work in the JScript.

    In the WSTEST tool, everything is fine. I get a collection. But in my JScript in the CallBackDelegate, I got an error message, and my result is “undefined”:

    SQL0087 Function CallBackDelegate : Exception : System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. —> System.ServiceModel.FaultException: An error occured during execution of the database query: Variable cannot be NULL.

    This SQL code is working fine in the script:

    SELECT MMITNO, MMITDS, MMFUDS, MMRGDT, MMLMDT, MMLMTS FROM MITMAS WHERE MMCONO = ? AND MMITNO IN ()

    This SQL code does not work (it works in WSTEST!):
    SELECT POPLPN, POPLPS, POPLP2, POITNO, POPITD, POPITT, MMITDS, MMFUDS, MMRGDT, MMLMDT, MMLMTS FROM MPOPLP JOIN MITMAS ON POCONO = MMCONO AND POITNO = MMITNO WHERE POCONO = ? AND POPLPN IN ()

    Any hint ?

    The 2 SQLs are separate methods in the Web Service as they return different result sets. I am using only Numeric and Char data types. Some Char fields can be blank in the resultset, but not null, as M3 doesn’t allow null values in the db tables.

    SQL0087 is an error message from the iSeries DB2 – but this should not be the reason as WSTEST is displaying the correct result. I can also call my SP manually in any SQL tool with the parameters above, and it works fine.

    The SP is a simple SQL stored procedure created on the IBM i with the IBM i Navigator SQL tool.

    Reply
    1. karinpb Post author

      Hi,
      I suggest that you use Fiddler and compare the response/request you get from the WSTest tool and when running the jscript. There might be something different that would explain the issue you have when calling via jscript.

      In general the solution works in both jscript and ws test, it is just that a specific statement – the one with the join – does not work in the script?

      Reply
      1. Heiko

        Hi Karin,

        You are right 😦

        Fiddler told me that I don’t pass the parameters to the Web Service, and the reason was very simple.

        When setting the input parameters to the Web Service, the method name is part of the input parameters for DynamicWS:

        p.Add(“GetByList1.CONO”, UserContext.CurrentCompany.ToString());
        p.Add(“GetByList1.SQLSTMT”, sql.ToString());

        Of course, for my second method, “GetByList” must be changed to the name of the method which is “GetByLines” .

        Thanks for the quick response.

  55. Heiko

    Hi,

    I get a strange error message in the Script editor. I moved some re-usable code to a feature. Now, when I try to compile, I get an error message “Failed to get type object for the script”.
    The script is correctly loaded from my local script path. At the end of the main script, two additional classes are added; but that compiled well before I moved the code. The new classes are outside the “MForms.JScript” namespace. Is that the reason ? Any other hint ?

    Reply
    1. karinpb Post author

      Hi Sudharshan, this blog is about Smart Office development. I suggest that you contact Infor Support since your request is bit too generic for this forum and there are differentent approaches depending on your requirements. If you are building a Smart Office application you should use M3 APIs.

      Reply
  56. Mikael Malmberg

    Hi,

    I am currentley developing a mashup, when I select a line in the list I want the button that I have created to execute a related option, how can I do that? All help is greatley appreciated.

    Mikael

    Reply
  57. jonathansanjuan

    Hi,

    In Jscript, has anyone tried creating a non-modal window brought up by a jscript button from an M3 Panel? A client wants to be able to access the quicknotes widget while using the jscript window. But since HostWindow and ShowDialog makes it modal, it’s not possible.

    // Wire up the host-window and show it.
    var content = masterGrid;
    host = new HostWindow(true);
    host.HostContent = content;
    host.HostTitle = title;
    DashboardService.Current.ShowDialog(host);

    Thanks,
    Jonathan

    Reply
    1. norpe

      If you don’t want to have modality to the new window you can create a window that shows up in the task bar using an overload of the LaunchTask method. The script below shows examples of how to launch a modal window and a non-modal window.

      import System;
      import System.Windows;
      import System.Windows.Controls;
      import MForms;
      import Mango.UI.Core;
      import Mango.Services;
      import Mango.UI.Services;
      
      package MForms.JScript {
         class NewWindowTest {
            var controller, content, debug, host;
            var buttonOpen, buttomOpenModal, buttonClose;
              
            public function Init(element: Object, args: Object, controller : Object, debug : Object) {         
               this.controller = controller;
               this.debug = debug;
               var content : Object = controller.RenderEngine.Content;
      
               var stackPanel = new StackPanel();
               stackPanel.VerticalAlignment = VerticalAlignment.Center;
               stackPanel.HorizontalAlignment = HorizontalAlignment.Center;
      
               buttonOpen = new Button();
               buttonOpen.Content = "Open New Window";
               buttonOpen.Width = "160";
               stackPanel.Children.Add(buttonOpen);
               
               buttomOpenModal = new Button();
               buttomOpenModal.Content = "Open New Modal Window";
               buttomOpenModal.Width = "160";
               buttomOpenModal.Margin = new Thickness(0,8,0,0);
               stackPanel.Children.Add(buttomOpenModal);
               
               Grid.SetRowSpan(stackPanel, 100);         
               Grid.SetColumnSpan(stackPanel, 100);
               content.Children.Add(stackPanel);
      
               buttonOpen.add_Click(OnClickOpen);
               buttomOpenModal.add_Click(OnClickOpenModal);
               controller.add_Requested(OnRequested);                  
            }
            
            public function OnClickOpen(sender: Object, e: RoutedEventArgs) {         
               try {
                  var title = "New Window Test";
                  var task = new Task(new Uri("notused://")); // The uri is not important (but must be valid) when shortcut are not allowed
                  task.AllowAsShortcut = false;
                  task.VisibleName = title;
                  task.ToolTipInfo = title;
                  task.UseVisibleShortName = false;
                  
                  var runner = DashboardTaskService.Current.LaunchTask(task, HostType.Default);
                  host = runner.Host;
                  
                  host.HostContent = CreateWindowContent("Window Content");  
                  
                  host.HostTitle = title;
                  host.Width = 640;
                  host.Height = 480;
                  runner.Status = RunnerStatus.Running;
                  host.Show();
               } catch(ex) {
                  Log(ex);         
               }
            }
            
            public function OnClickOpenModal(sender: Object, e: RoutedEventArgs) {         
               try {
                  var content = CreateWindowContent("Modal Window Content");  
                  content.Width = 640;
                  content.Height = 480;
                  
                  var title = "New Modal Window Test";
                  host = new HostWindow(true);
                  host.HostContent = content;
                  host.HostTitle = title;
                  DashboardService.Current.ShowDialog(host); // Use DashboardService to get modal "shake".
               } catch(ex) {
                  Log(ex);         
               }
            }
            
            public function CreateWindowContent(text : String)
            {
               var grid = new Grid();
               var textBlock = new TextBlock();
               textBlock.Text = text;
               textBlock.VerticalAlignment = VerticalAlignment.Center;
               textBlock.HorizontalAlignment = HorizontalAlignment.Center;
               textBlock.FontSize = 48;
               grid.Children.Add(textBlock);
               
               buttonClose = new Button();
               buttonClose.Content = "Close";
               buttonClose.Width = "120";
               buttonClose.VerticalAlignment = VerticalAlignment.Bottom;
               buttonClose.HorizontalAlignment = HorizontalAlignment.Right;
               buttonClose.Margin = new Thickness(0,0,8,8);
               buttonClose.add_Click(OnClickClose);
               grid.Children.Add(buttonClose);
               
               return grid;
            }
            
            public function OnClickClose(sender: Object, e: RoutedEventArgs) {         
               if(host != null) {
                  host.Close();
                  host = null;
               }
            }
            
            public function OnRequested(sender: Object, e: RequestEventArgs) {
               buttonOpen.remove_Click(OnClickOpen);
               buttomOpenModal.remove_Click(OnClickOpenModal);
               controller.remove_Requested(OnRequested);
               if(buttonClose != null) {
                  buttonClose.remove_Click(OnClickClose);
               }
            }
            
            function Log(text : String)
            {
               debug.WriteLine(text);
            }
         }
      }
      
      
      Reply
      1. jonathansanjuan

        Thank you Norpe!

        I was able to assign the contents of my modal window
        var masterGrid = new Grid();
        :
        masterGrid.Children.Add(mainGroupBox);
        :
        var content = masterGrid
        :
        var runner = DashboardTaskService.Current.LaunchTask(task, HostType.Default);
        :
        host.HostContent = content;
        runner.Status = RunnerStatus.Running;
        host.Show();

  58. Ted Chong

    First of all, greatly appreciate this blog page. Lots of info… I am new to mashup. And we have M3 for just only one year. There is a page that i try to create in Mashup but i found it is not bookmarked. It is ARS112 using FSLEDG and other files. Can someone please suggest how to create a bookmark or where to look for this info. All i need is to add a column from ARS112 to show a field in additional info (FSLEDX).
    any suggestion/help greatly appreciated.

    Reply
    1. karinpb Post author

      Hi,
      I would recommend you to contact Infor Extreme support. I think they can answer if it is possible to get the source for a bookmarked version of the program. It would be a customer modification to add it but the source might already exist.

      Regards
      Karin

      Reply
  59. Denis

    Hi there,

    I am new to mashup and I try to do one with the following 3 parts :
    1 – List Panels : Customers (CRS610/B)
    2 – Detail Panel for customer (showing discount Model DISY and some other fields)
    3 – Custom list based on OGDMTX
    The goal is to show all records of discount model table OGDMTX corresponding to the customers discount model (OKDISY) and to the customer itself (field OBV1=OKCUNO).
    What I need to do is a search/query on my custom list based on the customer number and discount model.

    If I use the following, I select on customer number
    Parameter TargetKey=”Query” Value=”{Binding ElementName=CustomerDetails, Path=CurrentItem[CUNO]}”
    If I use the following, I select on discount model
    Parameter TargetKey=”Query” Value=”{Binding ElementName=CustomerDetails, Path=CurrentItem[DISY]}”

    What I want to achieve is the following with parameters and no hardcoded values.
    Parameter TargetKey=”Query” Value=”OBV1:900112 AND DISY:901_XXX”

    Is there a way to specify both parameters in the value ?
    Or have I designed this the wrong way ?

    Best regards,
    Denis

    Reply
    1. karinpb Post author

      Hi,
      The way you do when you want to have multiple values in one parameter is to introduce new parameters and then use variable substitution syntax in the Query. You select two new names for the variables for example company and model assuming 900112 should be fixed).

      Parameter TargetKey=”company” Value=”{Binding ElementName=CustomerDetails, Path=CurrentItem[CUNO]}”
      Parameter TargetKey=”model” Value=”{Binding ElementName=CustomerDetails, Path=CurrentItem[DISY]}”
      Parameter TargetKey=”Query” Value=”OBV1:900112 AND DISY:{company}_{model}”
      
      Alternaive:
      Parameter TargetKey=”model” SourceKey="DISY"
      

      Replacement variables to the rescue 🙂
      I just introduced two new variables and used them in the creation of the Query string.

      Reply
  60. Denis

    It works perfect with this solution. Thanks a lot !

    Next question 🙂
    To retrieve DISY from customer, I found 2 different solutions :
    1 – Have a detail panel containing DISY, updated when a customer is selected in My customer list panel
    2 – In stead of using a standard list panel+detail, I created a custom list panel for customers where I have DISY as a column.
    Is there a way to retrieve the value of field DISY directly from a standard List Panel CRS610 (use a field whithout showing it)?

    Then I have some troubles with the custom list panel fo customers.
    When I define it, it works fine and pass both CUNO and DISY as parameters. Then it works for while and at some time it stops sending DISY (can see that using Debug) but still show it in the list. Even if I haven’t changed my mashup. I then delete column DISY from my custom list and readd it, then it works again. Until next time. Any idea of is going on ?

    Reply
    1. karinpb Post author

      Hi,
      You can only get parameters from a list that are part of the list. They don’t have to be visible but they have to exist on the selected row. So check with Debug on the event. I don’t think it’s in the standard list. Then to my understand your approach is to create a custom list with the fields you would like as input to the second list? If you have issues with events “losing values” you should report that to support but we have not received any indication that this should be an issue with the custom list. If it is visble in the list and you see that the focus is moved to a new row they should be passed in the event.

      But instead of using bindings in your events to adding SourceKey=”DISY” instead. Bindings are more for complext scenarios in most cases the field name is enough as SourceKey.

      If this is an issue that can be verified then you should report it to support. One way to test this without the debug dialog would be to add a TextBox that will bind to the DISY value or use an event to set the property Text on the TextBox (See example of how to set a property with an event in the Designer).

      Reply
      1. Denis

        Hi again Karin,
        My issue “loosing values” has been solved by following your recommendation using SourceKey in stead of Bindings. Thanks a lot for that.
        Then I had another issue with the second part of the mashup getting an error tipically first time of the day. I had then to open the Mashup editor, go to the custom list then out again, then it worked.
        Having a colleague using debug, we found out that CMS100 was not run when using only an event “Search” on my second custom list, then the mashup dumped. By going in Mashup Editor, M3 probably saved the bookmark in a cache and could reuse it (guessing).
        I worked around this adding an event “List” that is run just before the search.
        It works fine but I was wondering if there is another smart way.

  61. Denis

    Thank you very much again for your answer. I’ll experiment further to find out if the bug is in M3 or in my head. 🙂

    Reply
  62. Johannes Schwartzer

    Hi,
    i have a problem with the correct transfer of date values from a datepicker to a ListPanel.
    After i transfered the date values via an event to the list panel the result of the list is not limited on basis of the date values.
    Could you please help me out on this issue ?

    Thanks
    Johannes

    Reply
    1. karinpb Post author

      Hi,
      Please see https://smartofficeblog.com/2012/07/09/using-date-bookmark-keys-in-m3-mashups/ and https://smartofficeblog.com/2011/10/14/formatting-dates-and-numbers-in-a-mashup/. If that does not provide you with enough information we need more background information. Eg. Does the field expect the database format in a user based format or in the database format? In a date picker you have a .Net Date object so it will need to be converted.
      Do you have a binding to an event parameter?

      Reply
  63. cs

    Good Afternoon,

    We have developed a Mashup with contains a MIPanel with an UPDATE transaction, this then returns a status as the MI output. A subsequent MI transaction then runs on the UpdateComplete event, this second API transaction is conditional based on the status returned by the first MI transaction.

    The problem we seem to be encountering is that if we run the UPDATE transaction successfully for a record, the status is returned as expected and the secondary MI runs. However if we then run another record through the transaction, which is not able to UPDATE successfully (for example if one of the input fields contains invalid data) then the result from the first record is retained in the Output field of the UPDATE transaction and the secondary API runs as it has a valid condition, even though in truth it doesn’t.

    The problem seems to be that the result of the UPDATE transaction does not clear, when a new transaction is run. We have tried using a Clear event, forcing a blank value into the output filed when there is a current item change on the source list as well as also disabling then enabling the panel on current item change .

    We have encountered some similar problems before when using some M3ListsPanels but we were able to get round this problem using the CloseProgram event, however this event does not seem to be available for MIPanels.

    We were just wondering if there was anyway to trigger the MIPanel to close then reopen on something like a current item change event or if there was a better way of clearing the Update transaction output field.

    We’re currently using M3 BE14.1.1 and Smart Office v 10.2.1.0.77

    Thanks

    Reply
    1. karinpb Post author

      Hi,
      It seems like you have tried pretty much everything. For me to be able to understand the scenario in detail I would need a smaller reproduction of the mashup that you are trying to build. It is possible that we need to add some new configuration to the MIPanel to get your scenario working – or it might be that a fix is needed. I recommend that you put together a word document and a small mashup that clearly shows how you would like to set up your datasources and submit it to Infor support. You need to be clear that the issue is “Output fields are not cleared after secondary failed output” or similar. There are two more events coming for the MIPanel in the next fix for 10.2.1.x, CompletedSuccessfully and CompletedWithErrors that might help to simplify your scenario but not if the Clear event isn’t clearing what you expect it to clear. Perhaps the Clear Event isn’t implemented correctly in this control. Please contact support and inform them to contact Karin in the Smart Office team. A log in debug when you run your full mashup might also help.

      Reply
  64. Denis

    Hello

    I am trying to make a mashup showing, for each production work center, the ressource load per day (sum per day of lines in RCS105) and the capacity per day (PDS016).

    Actually I would like to get the same result as the following SQL.
    select PDDATE, PDCPT1, sum(RDBRLO)
    from m3fdbtst.MRCSPE
    left outer join m3fdbtst.CSYCAL on CDCONO = RDCONO and CDDIVI = ” and CDYWD5 = RDCYW7 – 2000000
    left outer join m3fdbtst.MPDCAD on pdcono = rdcono and pdfaci = RDFACI and PDPLGR = RDRCID and PDDATE = CDYMD8
    where RDCONO = 1 and RDFACI = ? and RDRCVR = ? and RDRCID = ? and
    PDDATE >= replace(char(current date,ISO),’-‘,”)
    group by PDDATE, PDCPT1
    order by PDDATE, PDCPT1

    I started a mashup with a custom list based on MRCSPE and with CSYCAL and MPDCAD as related tables.
    And here are my issues :
    1 – When I am in the custom list designer, I can define aggregation (to get a load per day) and selection fields. And it works fine. But I can’t get this back to my mashup. Is it possible ? (most important issue is the aggregation)
    2 – The date in field MRCSPE/RDCYW7 is in format YYYYWWD, while the date in MPDCAD/PDDATE is in standard YYYYMMDD. I thought about using CSYCAL to link these 2 but the week date in file CSYCAL is in format YYWWD. I defined then a virtual field to convert RDCYW7 to format YYWWD. But when defining the link between CSYCAL and MRCSPE (CMS011/F), I am not allowed to use this field (field &YWD5 is invalid). How could I link these 2 files (or link MRCSPE and MPDCAD without using CSYCAL).

    Last but not least, if you think that I am completely wrong in solving this that way, I will be glad if you indicate me another way.

    Thanks in advance.

    Reply
    1. karinpb Post author

      Hi Denis,

      I heard back from M3 dev:
      For related tables to work the correct data needs to exist in the table and in this case it doesn’t so it can’t be solved.

      Seems like nr 2 can’t be done like that. We have another tool that is called MDBRead that can be used to create MITransactions but I think it has similar limitations so I’m afraid I don’t know how to assist.

      Reply
    2. Heiko

      Hi,

      put your SQL into a Web Service and then consume the Web Service in the Mashup. Has better performance then API etc if you carefully design your SQL statement – are you following the existing LF’S? Then you’re fine. Sometimes it makes sense to build nested queries – limiting the records first which match existing LF’s, then do the last operations / selections on a higher level based on the selected records.

      Reply
      1. karinpb Post author

        According to M3 Architects it’s never a good idea to use SQL against live M3 data. Perhaps if you have a read only replica but there is a Knowledge base article (1647745 ) that states that event reads has proven to be problematic. “Even external select/read SQL statements have, depending on isolation level, proven to lock the database and can actually cause the same problems as invalid external updates.”

  65. karinpb Post author

    Hi Denis,
    1. Aggregation should work but all settings must be correct with filter and sorting and so on. If there are issues you should report it to support so that they can have a look at this specific case. Please provide as detailed information as possible:
    – Step by step instruction of set-up
    – Simple XAML / mashup file
    – Smart Office client log in debug
    – Fiddler log/capture when running the mashup in Smart Office (really nice to have to see exactly what BE is returning to Smart Office) http://www.fiddler2.com or Fiddler Cap for a more non-technical user http://www.telerik.com/fiddler/fiddlercap

    I don’t know enough about the specific programs to be able to do a quick look.

    2. I don’t have knowledge in these M3 specific tables but I have tried to reach out to my colleagues to see if they have any tips for you. I’ll get back when I get a reply.

    Reply
  66. Nuno Monteiro

    Hi all. Great blog!
    Trying to find some help. I’m new to Jscript. I’ve done this jscript for OIS0101: It disables for input discount 4 if there’s a promotion; otherwise, discount 4 is enabled for input. This is working ok.
    But I also want to set focus on the discount 4 field when it is enabled. The script works fine when run in mforms://jscript, but fails to activate focus when deployed to LCM.
    I know it is running because it is enabling and disabling discount 4 correctly… How can I solve this?
    Thanks in advance…

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

    package MForms.JScript {
    class OIS101E_DesativaDesconto4 {
    public function Init(element: Object, args: Object, controller : Object, debug : Object) {

    if(element != null) {
    debug.WriteLine(“Connected element: ” + element.Name);
    }
    var content : Object = controller.RenderEngine.Content;

    var OBPIDE : Object = ScriptUtil.FindChild(content, “OBPIDE”);
    var WBDIP4 : Object = ScriptUtil.FindChild(content, “WBDIP4″);
    if (OBPIDE.Text==””) {
    WBDIP4.IsEnabled = true;
    WBDIP4.Focus();
    }
    else {
    WBDIP4.IsEnabled = false;
    }
    }
    }
    }

    Reply
    1. karinpb Post author

      Hi,
      Focus can be tricky and setting the focus directly in init will not work as the program itself tries and set focus becuase M3 tells us where the focus should be and the control might not be loaded. What you can try is to delay calling Focus.
      Try adding:
      import Mango.UI

      Instead of Focus() use. our extension method called FocusAsync()
      WBDIP4.FocusAsync();
      This method will dispatch the Focus call on the UI-thread at a specific priority which means that it will be done at a later time as the method is added to the UI-queue.

      Reply
      1. Nuno Monteiro

        Hi, thanks for your quick answer. Just tried, but it didn´t work.
        Maybe using a script just for the focus and assigning it on a later event would be the solution, but don’t know how to do this.

      2. karinpb Post author

        So I checked some more and since we use FocusAsync() internally to work around some issues with WPF you can try the same approach but on a lower priority than the FocusAsync() method. Or you can dispatch a call to the UI thread and then call FocusAsync() in that way forcing your call to be put on the queue two times…

        I did try around and it seems that there has to be a cleaner way to do this but below is a suggestion that you can play around with. Double try so to say…

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

        package MForms.JScript {
        class SetFocus {
        var focusElement;

        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;

        var textBox : Object = ScriptUtil.FindChild(content, "MMFUDS");
        if (textBox != null) {
        focusElement = textBox;
        debug.WriteLine("Dispatching focus " + textBox.GetType());
        var setFocusDelayed : Action = SetFocusOnElement;
        textBox.Dispatcher.BeginInvoke(DispatcherPriority.Background, setFocusDelayed);
        }

        }

        private function SetFocusDelayed() {
        if (focusElement != null) {
        var isFocused = focusElement.Focus();
        if(!isFocused){
        var setFocusOnElement : Action = SetFocusOnElement;
        focusElement.Dispatcher.BeginInvoke(DispatcherPriority.Background, setFocusOnElement);
        }
        }
        }

        private function SetFocusOnElement(){
        if (focusElement != null) {
        focusElement.Focus();
        }
        }

        }
        }

      3. Heiko

        I think this is the “minimum” solution:

        import System;
        import System.Windows;
        import System.Windows.Controls;
        import MForms;
        import System.Windows.Input;
        import System.Windows.Threading;

        package MForms.JScript
        {
        class TestFocus
        {

        var content;

        public function Init(element: Object, args: Object, controller : Object, debug : Object) {

        this.content = controller.RenderEngine.Content;
        var setFocusDelegate : Action = setFocus;
        Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, setFocusDelegate);
        }
        private function setFocus()
        {
        var TXFUDS : Object = ScriptUtil.FindChild(content, “MMFUDS”);
        Keyboard.Focus(TXFUDS);
        }
        }

  67. Daniel

    Hi,

    I do this and get a type mismatch for the “load” line.
    Any tip?

    var viewer;
    var uri = new Uri(“http://www.google.com”);
    this.viewer = new Mango.UI.Services.Mashup.WebBrowser();
    this.viewer.Load(uri);

    Thanks!

    Reply
  68. johan wibjer

    Hi,
    Do you have any suggestions on how to make a datepicker input field in Jscript.
    I want to look like WARLDT on OIS100/E.
    Thank you for answers,

    Reply
    1. karinpb Post author

      Hi Johan,
      You need to user the DataPicker in Mango.UI.Controls. I’m afraid I did not have a ready example of this but perhaps one of our readers can help you 🙂

      var datePicker = new Mango.UI.Controls.DatePicker();

      You need to set the date format to M3Format.DateTimeFormat

      datePicker.DateFormat = M3Format.DateTimeFormatM3Format.DateTimeFormat

      datePicker.Value can be used to set a .Net date. It also has support for a setting the date as text. I’m not sure if this class is included in the API documentation for the Mashup Designer but you can check there if you have the Designer. If you have the Mashup SDK it contains an API documentation for all public classes that you are allowed to use.

      Reply
  69. John

    Hello,
    Trying to find out how to make Mforms Automation run silently. So far i haven’t been able to find anything.
    To make more sense on what i am trying to do is run ARS260 Enter the customer name,Press enter, Get Textbox data using VisualTreeHelper.
    If i can somehow run this in the background it would be fantastic.
    Thanks

    Reply
    1. karinpb Post author

      Automation is not for running silently. It’s for getting to the correct panel and then showing the UI. This should be an API call. Perhaps the MDBREAD tool (create API transactions from M3 tables) can be used in this case. If not you need to develop an MI API for it.

      Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s