Modal/non-modal dialog

I have been working on translating a VBA suite to LO. In VBA I can load a spreadsheet AND display a ‘dialog’ on top with working controls while still being able to scroll around the spreadsheet.

In LO, it seems that if I place a modal dialog on top, I lose access to the spreadsheet and if I use a non-modal dialog the controls do not work!

Is this something that I can do in LO?

John - I already have routine events for each button on the dialog - they work fine if modal but just do not trigger the event when non-modal.

This is very odd. I can indeed run a simple non-modal or modal dialog on its own with the controls working normally. In my module, however, I open a spreadsheet and then a dialog on top of that. With the spreadsheet loaded, the controls on the dialog will not function. If I do not load the spreadsheet, the controls on the dialog work normally. Somehow the spreadsheet is taking control away from the dialog. How do I stop that?

Post a sample containing the problem.

FWIW at this stage of description, I cannot replicate the unexpected behavior as stated with LO 7.3.2.2 on Windows 10. I can open another copy of the same ODS from within the dialogue open event or load another ODS, either way, all functionality remains. This is true even if I launch another instance of the same dialogue from within the loaded copy of the ODS. However, since my example doesn’t implement a semaphore, I do have to close the last-opened dialogue first if the same ODS has been loaded. If a different ODS has been loaded (even though it uses the same dialogue nominally), then everything works exactly as one would expect…both dialogues are truly independent.

OK - I have made up a new small ods and spreadsheet. Not sure how to write the ‘openfile’ in the module for you, but here are the files. When I run it, the spreadsheet opens with the dialog on top but although the command button changes colour on mouse it does not run my routine. Hope I got the upload right!

LOForum.ods (10.3 KB)
LOForumdata.ods (13.5 KB)

EDITED TO ADD: If I comment out the loading of the LOForumdata.ods the dialog works correctly.

Yes you are right. And if you put the text of the CommandButton1_click() procedure in LOForumdata.ods, then the button will also call MsgBox(). Why do you think this is happening?

Very difficult for a beginner to work out! Not a lot of ‘easy’ help available. Is it because the LOForumdata has focus or is modal? How would I be able to load other spreadsheets for processing without placing that routine on each?

It’s not very difficult. Place everything related to the project not in a separate spreadsheet, but directly in the office: create a library in My Macros, create modules with code and dialogs there - they will be available for any documents you open.

What exactly is “everything related to the project” in my samples? I have over 2200 lines of code in the project, John. do they ALL have to go in the library?

Is there any clue about this in any documentation, John? I cannot find any reference in any to linking to a library event. If you can recommend such I would be grateful. Why am I offered the option of linking the dialog to a routine in the main macro when it apparently should go in the library, and why does the linked event work when only the dialog is active but not with the worksheet loaded?

I don’t know. You know your project, you know what all these two thousand lines are supposed to do, you have to decide if all this code is needed. By the way, what should the program do? What user actions will be facilitated or eliminated by the code? Could most of these actions be left to existing built-in office tools?

Try starting from this page, or Chapter 5.29. Macro libraries

I will try to explain in simple terms (not sure if I can do it).

When you installed the ggCalendar or Bugeera extensions libraries were created in My Macros that contained several modules with code and dialogs. They were created automatically by the extension installer. I suggest that you do the same for your project, but create a library manually and put everything that is needed for the project there. When the work on the project is finished, you can easily save this program for other people to use.

Yes. Simple to change. Instead of loading the dialog in LOForum, load it using LOForumdata event when opening the document.
LOForum.ods (10.1 KB)
LOForumdata.ods (16.9 KB)

In my opinion this is a bug that should be reported. This macro does not work (in LoForum.ods):

Sub Main
  Dim oDialog
  StarDeskTop.loadComponentFromUrl ("private:factory/scalc", "_blank", 0, Array())
  DialogLibraries.loadLibrary("Standard")   
  oDialog = CreateUnoDialog(DialogLibraries.Standard.Dialog1)
  oDialog.execute
End Sub

This macro is OK:

Sub Main2
  Dim oDialog
  DialogLibraries.loadLibrary("Standard")   
  oDialog = CreateUnoDialog(DialogLibraries.Standard.Dialog1)
  StarDeskTop.loadComponentFromUrl ("private:factory/scalc", "_blank", 0, Array())  
  oDialog.execute
End Sub

Sorry, ratslinger - I do not understand. The sheet is loaded from LOForum.ods as you can plainly see. Are you now saying I should run the module in LOForumdata.ods on opening it and not in LOForum.ods - ie scrap LOForum.ods?

This is all very confusing. From where I sit I understand LO Basic allows the loading of a worksheet (there is established code for this), and also allows a routine to be tied to a dialog (there is an established procedure for this). Now it appears I have to create a library item to run this instead?

Is there anyone on this forum who can explain SIMPLY how LO Basic works in a simple programme?

Perhaps someone could tell me EXACTLY what I need to put into a library item from my sample code?

@nigelb1
Possibly do not understand what it is you are attempting. From what I have read thus far, you want to open, from LOForum.ods, LOForumdata.ods and there have a dialog open which is non modal.
.
If not the case please explain the process in more detail.

Exactly, although, for simplicity, my samples create a modal dialog. I want to be able to call the CommandButton1 routine from the dialog, which I can do with the worksheet not loaded. Re non-modal, yes, the aim is to be able to scroll the worksheet and use the dialog (which requires selections in the worksheet)

@nigelb1
The sample I posted does just what you stated, including the dialog as non modal. As for the code it can be placed in MyMacros as @JohnSUN has already presented and can be used by other files being opened without duplicating code (just tested this). Just need the Open Document event set for each.

OK, thanks - I can see the way forward now.

At first I thought @sokol92 was just missing that some context switched when a new spreadsheet opened. Not so. There is an unexpected difference given the event order:

Sub Main3
  Dim Caller
  Dim Spawn
  Dim oDialog
  
  Caller = ThisComponent
  Caller.DialogLibraries.loadLibrary("Standard")   
  Spawn = StarDeskTop.loadComponentFromUrl ("private:factory/scalc", "_blank", 0, Array())
  oDialog = CreateUnoDialog(Caller.DialogLibraries.Standard.Dialog1)
  oDialog.Controls(1).Text = Caller.Title
  oDialog.Controls(2).Text = Spawn.Title
  oDialog.execute
End Sub

creates a dialog that does not launch the button press event but otherwise seems fine, even though everything is exactly specified.

I have to wonder, in Python it apparently goes like this:

def consoleDlg():
    ctx =XSCRIPTCONTEXT.getComponentContext()
    smgr = ctx.getServiceManager()
    dp = smgr.createInstanceWithContext("com.sun.star.awt.DialogProvider", ctx)
    dlg = dp.createDialog( "vnd.sun.star.script:Access2Base.dlgTrace?location=application")
    dlg.execute()
    dlg.dispose()

Can those same UNO calls be duplicated in BASIC to see if things work? I’m a little out of my depth…frankly, I don’t see where to get XComponentContext from BASIC, or if a person can even “escape out that far” from BASIC.

1 Like

Will work if focus is changed:

Sub Main
  Dim oDialog
  StarDeskTop.loadComponentFromUrl ("private:factory/scalc", "_blank", 0, Array())
  wait 100
  ThisComponent.CurrentController.Frame.ContainerWindow.toFront()
  wait 100
  DialogLibraries.loadLibrary("Standard")   
  oDialog = CreateUnoDialog(DialogLibraries.Standard.Dialog1)
  oDialog.execute
End Sub