Hiding Ribbon Tab when no visible button on it - ms-access

I'm developing a multi-user application with access as a front-end, using a custom ribbon to retrieve functionalities. I'm an intermediate VBA developer, but with little experience on XML ribbons.
Well, the scenario: I have a table that relates users with forms to define permissions, when my Users Log In, I run through that table and write an array with the permissions for the current user. All my ribbon buttons have the GetVisible="GetVisibleCallback", so when the ribbon gets invalidated, the callback checks against the array to hide/unhide the buttons, with the code:
Public Sub GetVisibleCallback(control As IRibbonControl, ByRef visible As Variant)
If IsEmpty(arrayPermissoes) Then
visible = False
Else
If UBound(Filter(arrayPermissoes, control.Tag)) > -1 Then
visible = True
Else
visible = False
End If
End If
End Sub
This is working flawleslly, but the problem is: I have multiple tabs on the custom ribbon, and some users has no permission for any form on a determined tab eg.: "Register Tabs", when the Ribbon gets invalidated, the users can see the tab, but it has no Buttons in it. What I would like to achieve is: If there is no visible button on a determined tab, make it invisible too, how can I achieve this?
Sorry for the Bad English! I'm working on it!

The tab control provides the getVisible callback. So, you can check whether a user is allowed to see it or not. Also you may consider calling the Invalidate method of the IRibbonUI interface which allows to invalidate the cached values for all of the controls of the Ribbon user interface.
You can customize the Ribbon UI by using callback procedures. For each of the callbacks implemented, the responses are cached. For example, if a solution writer implements the getImage callback procedure for a button, the function is called once, the image loads, and then if the image needs to be updated, the cached image is used instead of recalling the procedure. This process remains in-place until the code signals that the cached values are invalid by using the Invalidate method, at which time, the callback procedure is again called and the return response is cached.
<customUI … OnLoad="MyAddinInitialize" …>
…
Dim MyRibbon As IRibbonUI
Sub MyAddInInitialize(Ribbon As IRibbonUI)
Set MyRibbon = Ribbon
End Sub
Sub myFunction()
MyRibbon.Invalidate() ' Invalidates the caches of all of this add-in's controls
End Sub
Read more about the Fluent UI (aka Ribbon UI) in the following series of articles:
Customizing the 2007 Office Fluent Ribbon for Developers (Part 1 of 3)
Customizing the 2007 Office Fluent Ribbon for Developers (Part 2 of 3)
Customizing the 2007 Office Fluent Ribbon for Developers (Part 3 of 3)

Related

Foundry Workshop - Prevent duplicate data entry

I am building a Workshop App which will be used for data entry by a large number of operational staff members (> 200).
I would like to implement the following set-up:
The staff will enter the data on existing Ontology Objects. To facilitate this, I embedded a Foundry Form into the Object View, and set-up a corresponding write-back data set.
The Ontology Objects in question will be displayed in an Object Table in Workshop.
The staff member will select an Object from the Object Table.
The selected Object will be opened in an Object View.
The staff member will enter data on the Object View (Foundry Form being displayed here).
I need to make sure that no concurrent data entry can/will happen. How can I achieve this?
I am thinking about removing any Object which is opened in the Object View from the Object Table, but I am not sure if this is the best solution to the problem or how to achieve the removal from the table.
I am assuming that this must be a common problem and there would be a Design Pattern/Standard Functionality to solve this.
You'll have the best behavior here if you replace your Foundry Form with Foundry Actions. These actions are defined in the Ontology Management App and provide a more robust security model for managing object edits and are more tightly integrated into the various object-layer tools in Foundry.
Then in your Object View, rather than using the Foundry Forms widget, choose to create a new "Workshop-backed" Object View tab - this option is under the dropdown next to the New Tab button - and within the Workshop module use the Inline Action Form to embed the action form that you've configured in the Ontology Management App, supplying the variable representing the current object as the default for the object parameter in the Action.
With regards to simultaneous edits, in Actions, when the form is populated (i.e. when that tab is opened), the version of the underlying object(s) are registered. When the edit request is submitted, the current version of the object is checked, and if the version is different (i.e. there have been edits applied since the form was loaded) the user will be presented with message to the effect that the object has been updated and the edits will not be applied.
This protects against the case of a user overwriting a near-simultaneous edit without reviewing the changes first and does so at the writeback layer, rather than with logic in your application front-end.
There is not currently an approach to reflect real-time user interaction between two Workshop sessions. For instance, there is no way for the session of User A to "know" that User B has opened Object X in their session and is making a change.
If you wanted to do something for a bit of convenience or display signaling, you could create a small object type related to your main object - something like "Edit Lock" that looks like:
| id | primary_object_id | user_id | timestamp | timeout
And then in your Workshop app, there's a button above the table that says "Edit Selected Object".
When you click this button, you trigger an Action to create a new "edit lock" object populated with the current user and the current timestamp and say a timeout of 15 minutes from now.
Then in the object view for the primary object in question, on the same tab where you have the edit form embedded, you can create a variable that gets the edit locks associated with that object via a search around and use a Function to create a boolean variable if there is an "active" edit lock. And use this to conditionally show a banner to the user or otherwise give them a visual indication that another user has indicated they're making changes.
This won't push to the other session, and it'd be just for display purposes, the real protection still comes from the underlying object versioning that Actions enforces, but it might be a nice user affordance to layer on top if you really expect to commonly run into this situation.

MS Teams - TaskModule close the window

I display a third party web page(client page) in the task module
using Deeplink
https://teams.microsoft.com/l/task/botid?url=https:test.com/test.html&height=450&width=510&title=Custom+Form&completionBotId=botid
new AdaptiveOpenUrlAction() { Title = "Enable MS Team access", Url = new Uri(DeeplinkHelper.DeepLink }
Here the web page is opening in Task module, I need to close this task module by clicking the button available on the web page(URL) and send the result to completionBotId.
Any sample pls that need to implement in client-side code.
There are two steps to make this work:
you need to reference the Teams Javascript SDK in your web page
When your user clicks the button, you would call microsoftTeams.tasks.submitTask in your 'click' event handler. There are a few parameter options for this method, depending on whether you want it to send anything back to your bot. To simply close the window, call microsoftTeams.tasks.submitTask(null);, or if you want to send an object back, call microsoftTeams.tasks.submitTask(whateverObjectYouWantToSendBack);

MS Access not working for multi user

I have a DB I created as a sort of real time virtual client check in log. It would be stored on an intranet network drive. In theory, a greeter can send client information back to be picked up by another worker. This is done through a series of forms, tables, and queries. When I test it myself on my own machine, opening both the greeter and reception forms I can enter information on the greeter, click the action button to send it to the table, where a timered query(held in a hidden form opened with an AutoExec macro) picks up the current record, and then displays it on the reception form. Everything works perfectly. The only problem is, when I try to test it on multiple computers, the greeter can send info back, it appears on the table, but the reception form never populates. Any ideas where the disconnect might be?
edit I have decided I want to do away with the hidden initialize form, so I've re-organized the code as follows. It still works when I do it myself on one computer, but opening the reception form on another computer it still fails to populate.
Reception 1
Private Sub Form_Timer()
If gClientID > gNextClientID Then
gblnRNC = True
Else: gblnRNC = False
End If
If gblnRNC = True And gblnRec1Free = True Then
gRec1CL = gNextClientID
MsgBox "There is a new client to be seen.", vbSystemModal, "New Client Warning"
Me.RecordSource = "RecClientIDNum"
End If
End Sub
So forgive my noob question, I sorta jumped into programming procedures without fully understanding how Access works. I declared global variables but didn't realize they were only global within the scope of the local session running on a particular machine.
Moved the variables that establish the interactions between the various forms to a table and everything works perfectly.

Sorting continuous form in Access Runtime

I have a client that doesn't actually have Access, so they use the Access Runtime 2016 to use my program. In the runtime version there is no ribbon, but mostly they manage without.
There is only one issue, there is a continuous form that the user needs to be able to sort ascending or descending. In the full version of Access, there's a convenient little button to take care of that.
I found a solution here, but it doesn't work when I try it. I'm assuming that it's because my client is using Runtime 2016. There is also a question that addresses this for Access 2003, but there's no way (as far as I know) to make buttons for Access 2007 runtime and later.
What is the recommended method to provide sorting (and filtering) for Access 2016 runtime?
Personally I never let my customers use the Access UI for sorting or anything else, I bind the double click event of the header in any sortable column to code that uses the OrderBy and OrderByOn properties of the form to set the sorting up using VBA.
Here is sample code:
Private Sub s_Description_DblClick(Cancel As Integer)
If Me.OrderBy = "Description" Then
Me.OrderBy = "Description DESC"
Else
Me.OrderBy = "Description"
End If
Me.Requery
End Sub

Windows 7 SP1 breaks access (not the ADO way)

So our corporate IT dept has determined that it is time to force SP1 on everyone's PC's.
Which means I need to get my Access 2003 ADE application working with the stupid ADO incompatibility problem.
I got the ADO portion to work by following KB2517589, but now several of my textboxes say #Name?.
These are bound to code, so, for example, the data field in the textbox is =CalcShippingAddr().
As a test, I replaced the code with the following:
Public Function CalcShippingAddr() As String
msgbox "Func Called"
CalcShippingAddr = "Test"
End Function
This works fine on my dev machine, but as soon as I make an ADE and send it to a PC without SP1, I get #Name? on the textbox. The msgbox nevers pops up.
Any ideas what might be happening?
This is a fault to do with the field calculation, I haven't seen it myself but have heard that clicking in to the relevant text box would then show the value although this is not a solution. I would always recommend using unbound forms as you can control step by step what your fields/objects are doing. As you already have a custom function to calculate the shipping address then it should be simple enough for you to add the code the the forms 'Open' or 'Load' event e.g.
Private Sub Form_Load()
textbox = CalcShippingAddr
End Sub