Excel.Application.WorksheetFunction.RTD is not recalculated when double click on the function - excel

I m writing an Excel plugin that uses a custom written RTD Server and to call ConnectData function of that RTD Server, I use Excel.Application.WorksheetFunction.RTD in VBA passing required parameters to the function.
All the functionality of RTD is working fine, but if I double-click and press enter on an RTD function in Excel (In other words, when parameters do not get changed), Excel.Application.WorksheetFunction.RTD is called but ConnectData of RTD Server does not get called.
Is there anyway of getting ConnectData called in such a situation where parameters aren t changed?
Thanks

I call Application.CalculateFull from Visual Basic. I have found that triggers the RTD function being called again. I then have a button on the spreadsheet which calls a macro that contains Application.CalculateFull. Anytime I want to restart, I press the button.

An RTD topic is created for each unique combination of topic parameters of the RTD function. When you re-enter the same function call, the RDF function is called but it does not create a new topic.
ConnectData is called only when a new topic is created.
That means if you enter the same RTD function call in multiple cells, they will all share the same RTD topic. ConnectData will only be called once.

Related

How can I replace an ActiveX ListBox by a Form Control ListBox in VBA?

I have a 'service' function that accepts from other functions requests to select an item from a list, in a List Box.
The whole process:
A caller function supplies the list of items and some parameters to the 'service' function (and wait)
The 'service' function prepares the data, and
present to the user a List Box ActiveX control in a User form, and
waits for the return, and
manipulates the result and
returns it to the caller function.
I created the function to build the Form Control on the worksheet, and the function that accept the click from the ListBox (OnAction function).
With Form Controls, I don't know how to achieve the same process. Once the OnAction function has the information, how to send it to the initial caller: the initial caller does not wait anymore.
I search for days, everywhere I could... The research is very difficult because most often than not, the discussions do not clearly specify if the subject relates to ActiveX Controls or Form Controls, even inside Microsoft documentation.
With ActiveX solution, my 'service' function was simply wait for the Userform, and then returning to the original caller.
Reason for the move: frequent crashes/freezes/out-of-memory, specially but not only in this 'service' function. After years of suffering, I migrated to Excel 64-bits. The suffering did not really stopped.
So my next step is migrate all ActiveX controls to Form Control, as much as possible.
Thank you for you help (this is my first post)
I searched for days for a generic approach to link the result to the original caller, including trying to make the 'service' function waiting.
I OnAction function was ready to communicate the result to the 'service' function, but that function was not listening anymore at that point

Excel DNA and RTD server COM visibility

In every Excel DNA RTD sample the RTD server impl. is marked as COM visible. Example: https://github.com/Excel-DNA/Samples/blob/master/RtdClocks/RtdClock-ExcelRtdServer/RtdClockServer.cs
Based on my testing when Excel DNA addin is added to Excel, the COM visibility is NOT needed.
What is the reason to make the RTD impl. COM visible?
There are two ways for the Excel-DNA based RTD server to be used from Excel:
with no registration and a wrapper UDF that internally calls XlCall.RTD(...) or,
by registering the types (with a call to ExcelDna.ComInterop.ComServer.DllRegisterServer()) and then calling the =RTD(...) function directly.
For the normal first case, you're right the ComVisible is not required for the RTD server - Excel-DNA internally does the hook-up and exposes the class without registration. For the second case, ComVisible is required (either explicitly or by having no ComVisible directive on the type or assembly - since the default for ComVisible is 'true') for the type to be registered as a COM export.
This story is complicated a bit if you try to use a wrapper function, but have a stable ProgId registered with Excel so that 'old values' can be used when a saved sheet is re-opened. In this case you need to have the COM registration and change your wrapper to call XlCall.Excel(XlCall.xlfRtd, ...).
So you're right that for most of the Excel-DNA samples it's not actually required.
It all got a bit confusing over the years...

In PyQt, I need to handle both itemClicked and itemSelectionChanged, but not both at the same time

I've created a QTreeWidget that displays data that's pulled from 3rd party API calls.
I want the data to be fresh when the user either clicks on or uses the arrow keys to navigate to any QTreeWidgetItem. This means making an API call each time the user clicks or uses an arrow key. Importantly: If the user clicks on the same item a second time, I would like the item to display fresh data (in other words, make another API call and populate with new data, aka refresh)
So far, I've tried:
connecting both itemSelectionChanged and itemClicked to the same update function. This works, but it means that for every click on a new QTreeWidgetItem, I get two calls to the update function (one from itemClicked and the other from itemSelectionChanged), and therefore two API calls that do the exact same thing. Not ideal.
Only handling itemClicked, but then using an event filter to look for Key_Up or Key_Down and then manually emitting an itemClicked. The problem with this is that the key event is handled before the selection is changed, so when using the arrow keys, I'm always getting data for the last QTreeWidgetItem selected, not the current QTreeWidgetItem.
I thought about creating a very short timer or a flag and starting/setting at the start of the update function. If the timer is running or the flag is set, don't run the function (the idea being that the first slot would run, but the second would not because the flag is set/timer is running), but that seems both sloppy and prone to race conditions.
Unfortunately, using a QTreeView with a QAbstractItemModel is not an option.
With that, is there any way to handle both a repeated click on the same item and arrow keys to select new items without double-calling the same update function?
As #ekhumoro pointed out, this can be done by handling both itemClicked and itemSelectionChanged, but introducing some logic so that both functions don't run at the same time.
When a user clicks on the widget, an itemClicked signal is fired. When the user changes selection, the itemSelectionChanged signal is fired. In my case, then, I've created two slots (functions): update (a slot for itemSelectionChanged) and updateFromClick (a slot for itemClicked). updateFromClick checks to see if the selection has changed (this means you always have to store and keep track of the current selection). If, in updateFromClick, I see that the selection has changed, then I do nothing, as update will have been called from itemSelectionChanged. If, in updateFromClick, I see that the selection has not changed, I know that itemSelectionChanged has not been fired, so I call the update function explicitly from updateFromClick.
Again, this is just a long-winded version of #ekhumoro's comment that I'm putting here so the question doesn't go unanswered.

Delphi ADO: save DBEdit changes

I opened Excel table using ADO (though it is probably the same as any other database: adoconnection, adotable, datasource) and display it in ReadOnly DBGrid.
And I have DBEdit to edit some value in currently selected row.
But how to save it? I tried adotable.Post on FormClose but it throws error that "dataset not in edit or insert mode".
Do I need to call adotable.Edit in DBEdit OnEnter and Post OnExit?
Post is automatically called when the user navigates to another record.
The only time you need to call Post is if the currently selected record has pending changes at the time you close the form.
But even then, you don't have to call Post explicitly: there's a helper function CheckBrowseMode you can use instead. If the data set is in edit mode, CheckBrowseMode checks if there are any modifications. If not, it cancels the edit, otherwise, it posts those changes. CheckBrowseMode won't raise any exception if the data set is already not in edit mode, only if the data set is closed (which shouldn't be possible in your case).

Refreshing a Lotus Notes folder

I'm working on a Lotusscript at the moment which places a menu of actions on the $Inbox (and thereby any folders derived from that design). This action menu has several items with "Hide action if formula is true" selected. The logic behind all of this works perfectly, however I now have the need to re-evaluate these formulas if the user performs certain actions within the folder (eg: if the action is hidden because a certain flag has been set, and that flag is changed I would then like to re-evaluate the formula so the action now appears). I can't seem to find any way to reload a folder or re-evaluate these formulas. Does anyone know of a way to do this?
There is a RefreshHideFormulas method for the NotesUIDocument, but not for a view. You may be able to call the ReloadWindow() method of NotesUIWorkspace, though, so that's worth a try.
As an alternative, triggering an agent that calls the #Command RefreshHideFormulas may also work for you:
Here is some code (borrowed from http://ideajam.net/ideajam/p/ij.nsf/0/3BBA7E25A972ABD88625759600445A50?OpenDocument)
1) Create an #Formula Agent called "RefreshActions", Agent List Trigger with the following code:
#SetTargetFrame("YourFrame");
#UpdateFormulaContext;
#Command([RefreshHideFormulas]);
2) In your Lotusscript, where you want to insert a "refresh frame" call, add this:
Dim agent As NotesAgent
Set agent = db.Getagent("RefreshActions")
Call agent.Run()
You can use property "Evaluate actions for every document change" found in view properties, [i] tab. Every selection (click, arrows) of document will trigger reevaluating hide whens for actions. Maybe it will work after refreshing view by some action.

Resources