External Link VBScript to Update Bitmap of Button that Called it

SOLVED

I created a button that runs a simple VBScript that checks if a customer is set up on paperless or not. The problem is that while I am modestly proficient at VBS, I don't know anything about the Sage Object model.

I first attempted to have the script display a MsgBox, but received an Access Denied error when I attempted to run it. So now I am wanting to try something else (which would be better anyways as the user will not have to close a dialog box when the script runs). Once the script determines a True/False value, I am wanting to add a bitmap to that same button that called the script. For example:

  • If the result is True, then I want to update the button with the "Checkmark" bitmap
  • If the result if False, then I want it to update the button with the "Delete" bitmap:


The name of the button/link is BT_LINK_1. I am just wanting to know the proper syntax to update the button's Bitmap selection from within the script. This is my pseudocode for further illustration:

If RetVal Then
BT_LINK_1.Bitmap = "Checkmark"
Else
BT_LINK_1.Bitmap = "Delete"
End If
  • +1
    verified answer

    Pop-up will be much easier.  Changing UI elements dynamically is always hard to get working properly.

    VBScript's MsgBox won't work with client / server versions of Sage 100, so there is a MessageBox method to use which solves that problem:

    retVal = oSession.AsObject(oSession.UI).MessageBox("", sStringVarWithWhatYouWantToSay)

  • 0 in reply to Kevin M

    Oh, and button scripts that require access to Business Objects must be set to run on the Server, not the workstation.

  • +1
    verified answer

    Since this is a button script, you can use the following.

    oUIObj.SetControlProperty "control name", "Text$", "{!bitmap name}Text"

    Here is what my sample looks like by default.

    And this is after using the above code but with the control name being BT_Link_1 and the last argument being {!Checkmark}Link 1.

    This does not modify the library, it just modifies the control on the fly.

    Get your control name and bitmap name to use by editing the control.

    You can position the bitmap on the left or right of your text by changing its position in the string passed as the third argument.  In the above example, the bitmap is on the left.  The bitmap name you get from customizer should be prefixed with "{!" and it should have the "}" suffix, then place your button text before or after it.

    EDIT:

    Just for fun, here are three different routes for a button script set to execute on the server that I tested in Item Maintenance with.  The value in the nMode variable determines the route taken. 

    1. The first one uses InStr and Replace to toggle the bitmaps, this was more about testing being able to toggle between two different bitmaps. 
    2. The second one checks if the current item code is equal to "1001-HON-252" and depending on the boolean result which gets converted to an integer and then multiplied by -1 so the evaluation should always return 0 if false or 1 if true.  The result is used to get a value from the array by using it to reference the array's index.  So your bitmap for false should be the first element in the array and the bitmap for true should be the second element in the array. 
    3. The third one is very similar to the second except it doesn't use an array and just uses CBool on the nRetVal variable to branch into setting the value in the sBitmap variable to one value if true and another if false.

    nMode = 3
    Select Case nMode
    	Case 1
    		sCurrentControlName = "" : sCurrentControlName = MAS_SCR_OBJ
    		If sCurrentControlName <> "" Then
    			sCurrentControlText = "" : oUIObj.GetControlProperty sCurrentControlName, "Text$", sCurrentControlText
    			If sCurrentControlText <> "" Then
    				Select Case True
    					Case InStr(UCase(sCurrentControlText), UCase("Checkmark")) > 0 
    						sCurrentControlText = Replace(sCurrentControlText, "Checkmark", "Delete")
    					Case InStr(UCase(sCurrentControlText), UCase("Delete")) > 0 
    						sCurrentControlText = Replace(sCurrentControlText, "Delete", "Checkmark")
    				End Select
    				oUIObj.SetControlProperty sCurrentControlName, "Text$", sCurrentControlText
    			End If
    		End If
    	Case 2
    		aBitmaps = Array("Delete", "Checkmark")
    		sCurrentControlName = "" : sCurrentControlName = MAS_SCR_OBJ
    		If sCurrentControlName <> "" Then
    			sCurrentControlText = "" : oUIObj.GetControlProperty sCurrentControlName, "Text$", sCurrentControlText
    			If sCurrentControlText <> "" Then
    				If InStr(sCurrentControlText, "{!") > 0 And InStr(sCurrentControlText, "}") > 0 Then
    					If Left(sCurrentControlText, 2) = "{!" Then
    						sCurrentControlText = "{!}" & Mid(sCurrentControlText, InStr(sCurrentControlText, "}") + 1, Len(sCurrentControlText))
    					Else
    						sCurrentControlText = Left(sCurrentControlText, InStr(sCurrentControlText, "{!") - 1) & "{!}"
    					End If
    				End If
    			End If
    			sItemCode = "" : oBusObj.GetValue "ItemCode$", sItemCode
    			nRetVal = UCase(sItemCode) = UCase("1001-HON-H252")
    			sCurrentControlText = Replace(sCurrentControlText, "{!}", "{!" & aBitmaps(CInt(nRetVal) * -1) & "}")
    			oUIObj.SetControlProperty sCurrentControlName, "Text$", sCurrentControlText
    		End If
    		If IsArray(aBitmaps) Then Erase aBitmaps
    	Case 3
    		sCurrentControlName = "" : sCurrentControlName = MAS_SCR_OBJ
    		If sCurrentControlName <> "" Then
    			sCurrentControlText = "" : oUIObj.GetControlProperty sCurrentControlName, "Text$", sCurrentControlText
    			If sCurrentControlText <> "" Then
    				If InStr(sCurrentControlText, "{!") > 0 And InStr(sCurrentControlText, "}") > 0 Then
    					If Left(sCurrentControlText, 2) = "{!" Then
    						sCurrentControlText = "{!}" & Mid(sCurrentControlText, InStr(sCurrentControlText, "}") + 1, Len(sCurrentControlText))
    					Else
    						sCurrentControlText = Left(sCurrentControlText, InStr(sCurrentControlText, "{!") - 1) & "{!}"
    					End If
    				End If
    			End If
    			sItemCode = "" : oBusObj.GetValue "ItemCode$", sItemCode
    			nRetVal = UCase(sItemCode) = UCase("1001-HON-H252")
    			sBitmap = ""
    			If CBool(nRetVal) Then
    				sBitmap = "Checkmark"
    			Else
    				sBitmap = "Delete"
    			End If
    			sCurrentControlText = Replace(sCurrentControlText, "{!}", "{!" & sBitmap & "}")
    			oUIObj.SetControlProperty sCurrentControlName, "Text$", sCurrentControlText
    		End If
    End Select

    Because it is a button script, it is able to use the MAS_SCR_OBJ variable to determine the control name that gets passed to GetControlProperty and SetControlProperty.  Now I don't where you intend to put this button script, I'm guessing either Customer Maintenance, Sales Order Entry, or SO Invoice Data Entry but you could instead use a table event script, i.e. post read on AR_Customer filtered to the correct library using the script object's uUI object's GetScreenName method, or you could have it on the post validate event on the CustomerNo column on SO_SalesOrderHeader and/or SO_InvoiceHeader.  This would allow you to bypass the need for the user to click the button.  You would just need to know the control name.  So in Customer Maintenance, you could add a custom button that is locked and doesn't actually do anything and place it somewhere with or without text, then whenever a customer record is selected, you could toggle the bitmap of the button.

  • 0 in reply to David Speck

    Ah wonderful. I actually got somewhat close last night after I posted the question, just couldn't find any documentation that explains the .SetControlProperty method in detail.

    This was my failed attempt:

    Yeah to answer your question I am placing on SO Invoice Data Entry next to the email text box. If the customer has the "Use E-mail Address in Data Entry" selected, this would need to return True and present the Checkmark.

    What I was really hoping for originally was to just add a simple field and bypass the scripting altogether, but it doesn't appear to have a reference to AR_CustomerDocument table that I would have needed.

    But appreciate the the details you provided as this should also help with future projects I will be working on once we get the details ironed out.

  • 0 in reply to SoonerFan21

    In short, the first argument is the control name without the ".ctl" suffix, the second argument is the property, and the third argument is value you want to set into the property.

    To be ableto fully utilize the SetControlProperty method, you need to know what properties a given control type supports and how to use the properties.  For this, you would need to reference the ProvideX documentation.

    Based on your intended usage, I would put the script on the post validation event of the CustomerNo column in SO_InvoiceHeader.  Have it evaluate your criteria and then set the Text$ property of the button appropriately.  If you don't want the button to do anything and instead just be a placeholder for the bitmap, then don't give it anything in the Text field and on the Link Settings tab, just have it point to a placeholder script with a single apostrophe in it to indicate a commented line, this will cause the button to not perform any action.  Alternatively, you could have the button launch the paperless configuration window for the current customer.

    If you are not going to treat the button as an actual button, you could also override the BackColor$ property and set it to something like "LIGHT GRAY" if using the standard background color.  Without any text, it will look like this.

    You could also try using whatever color the system is currently using for the background but because the bitmaps all use "LIGHT GRAY" as the background (the background is not transparent), it will look like this if using any other background color besides "LIGHT GRAY" and the "Flat" property is set to 1.

    If "Flat" defaulted to 0, then it would look like this.

    To really get good results, it would probably be best to either draw a new button or replace the existing button with a new button using the "fT" options.  This would be best done in a UI post load event script that would be triggered on the pHeader panel of the SO_SalesOrder.M4L library.  This is really only applicable if you just want to treat the button as a placeholder for the bitmap though (no text and no action when clicked).