Search This Blog

Friday, January 11, 2013

How to refresh NotesUIDocument from categorized embedded view

Hi guys

You may know that there is one limitation (bug, feature, I do not know how to call it properly) regarding calling of NotesUIDocument.Refresh() method from the action of embedded notes view with enabled single category.

If you do that you always get a crash of Lotus Notes.

I know that this limitation exists from Notes R5 and higher and it is still here, even with release 9.

Check my screens below

1) Here is a form with embedded view with "Show single category" enabled



2) Here is a view, that is embedded on the form with "Refresh" action. This view action calls NotesUIDocument.Refresh() method



3) Here is a result of the click on "Refresh" action


Enjoy Lotus Powa!

So my question is, if you ever had to handle that, how did you do that?

I found only one way and it works only for Window platforms - emulate a pressing of F9 key.
I replaced "call uidoc.refresh(false)" with "call F9" and it resolved this problem but I have suspicions that such solution is not very nice :-)

You may find the implementation of F9 function below

'F9/Crtl+S
'Declaration

Declare Function VkKeyScan Lib "User32.dll" Alias "VkKeyScanA" ( Byval char As Integer ) As Integer
Declare Function MapVirtualKey Lib "User32.dll" Alias "MapVirtualKeyA" ( Byval wCode As Long, Byval wMapType As Long ) As Long
Declare Sub keybd_event Lib "User32.dll" ( Byval Virtual As Integer, Byval OEMScan As Integer, Byval Flags As Long, Byval ExtrInfo As Long )
Const KE_KEYDOWN& = 0
Const KE_KEYUP& = 2

Sub F9
'*** Simulates a keypress and release.
  On Error Goto errorproc

Dim vk As Long
Dim sc As Integer

vk = &H78

sc = Cint( MapVirtualKey( vk&, 0 ) )

Call keybd_event( Cint( vk& ), sc%, KE_KEYDOWN&, 0 )
Yield
Call keybd_event( Cint( vk& ), sc%, KE_KEYUP&, 0 )
Yield

endofsub:
Exit Sub
errorproc:
Msgbox "Error #" & Err & " on line " & Erl & " in function " & Lsi_info(2) & " : " & Error, 48, "Runtime error"
Resume endofsub
End Sub


Updated on 01/18/2013

Hello

Just got a hint from Brent Henry about how to do it easier with support of all platforms.

The idea is to add two fields on the form and jump to them from the lotus script of embedded view action using NotesUiDocument.GotoField(). However you have to enable form property "Automatically refresh fields" to force form refreshing that I actually would like to avoid.

You can download my example from here to check it yourself. Just create a document using "Test" form via Create menu and click the buttons in the embedded view.



Updated on 24/05/2015

Hello

There is one more approach that lets you update embedded view with a single category enabled. Notice - this approach does not allow you to refresh a parent NotesUIDocument, it is only about refreshing an embedded view. I found it here (described by Ferdi Verlaan):

If you want an embedded view to refresh then please add the following code to a button, action or other component that triggers the refresh: 
       
Call ws.ViewRefresh 
       
Call uidoc.RefreshHideFormulas 
       
Call ws.ViewRefresh         
On the embedded view itself, make sure there is a hide-when formula. If there isn't any, give the embedded view the formula: 1=0.
 


Because this is never true, the embedded view will never be hidden, but it will be refreshed due to the "RefreshHideFormulas" command on the ui document.

8 comments:

  1. I've done this quite a few times by adding a couple of fields to the bottom of the form, such as FieldA and FieldB. If the document is in edit mode and automatically refresh fields is enabled then you can use the ui document methods to navigate into FieldA and then FieldB, which causes the form to refresh.

    You can also keep track of the current field and then move to FieldA, FieldB and back to the current field. This should work in both @Formulas and LotusScript and be cross platform.

    ReplyDelete
  2. This comment has been removed by a blog administrator.

    ReplyDelete
  3. I used the uidoc.RefreshHideFormulas on another application and it worked just fine, but trying it on another today, it wouldn't properly refresh. Here's something I tried that seems to work but hasn't been extensively tested. This is from memory, so sorry if I mess up something, but you should get the gist of it.

    In my agent that's called from the embedded view action button, I added the following:

    doc.DoRefresh = "1"
    Call uidoc.Save

    THEN, in my querySave, I added the following:

    If doc.DoRefresh(0) = "1" Then
    Call uidoc.Refresh
    doc.DoRefresh = ""
    Call doc.Save(True,True)
    End If

    This basically hands over control to the form, and from there, the QuerySave takes over, which has no problem calling the refresh. So far seems to work smoothly. If you have other code in the QuerySave that you don't want executing, you can add a Exit Sub inside the If statement, so that it will only be triggered by the embedded action button.

    If you don't want to actually save the doc yet, you could try:

    If doc.DoRefresh(0) = "1" Then
    Call uidoc.Refresh
    doc.DoRefresh = ""
    Continue = False
    Exit Sub
    End If

    ReplyDelete
  4. One correction... That doc.Save shouldn't be used for fear of a save conflict.

    ReplyDelete
  5. A simpler way: move LotusScript code (which uses NotesUIDocument.Refresh) to the agent and push it on that action through ToolsRunMacro.

    Best regards,
    VladSh

    ReplyDelete
  6. Create a lotusscript agent. Trigger as agent list selection. Target All selected documents. Use code:

    Dim ws As New NotesUIWorkspace
    Dim uiview As NotesUIView
    Set uiview = ws.Currentview
    Call uiview.View.Refresh()

    Then in an action button within the embedded view run the agent with:
    @Command([ToolsRunMacro]; "(EmbeddedViewRefresh)");

    ReplyDelete