public object GetValue() { if (_currentObserver == null || !IsCompleted()) { // NOTE: At this point the SynchronizationManager must be registered! if (!SynchronizationManager.IsInstalled) { Debug.Print("SynchronizationManager not registered!"); throw new InvalidOperationException("SynchronizationManager must be registered for async and observable support. Call ExcelAsyncUtil.Initialize() in an IExcelAddIn.AutoOpen() handler."); } // Ensure that Excel-DNA knows about the RTD Server, since it would not have been registered when loading ExcelObserverRtdServer.EnsureRtdServerRegistered(); // Refresh RTD call // NOTE: First time this will result in a call to ConnectData, which will call Subscribe and set the _currentObserver object unused = XlCall.RTD("ExcelDna.Integration.Rtd.ExcelObserverRtdServer", null, _id.ToString()); } // No assumptions about previous state here - could have re-entered this class // We use #N/A as the 'busy' indicator, as RTD does normally. // Add-in creator can remap the 'busy' result in the UDF or another wrapper. if (_currentObserver == null) { return(ExcelError.ExcelErrorNA); } // Subsequent calls get value from Observer return(_currentObserver.Value); }
public object GetValue() { if (_currentObserver == null || !_currentObserver.IsCompleted) { // NOTE: At this post the SynchronizationManager must be registered! if (!SynchronizationManager.IsInstalled) { Debug.Print("SynchronizationManager not registered!"); throw new InvalidOperationException("SynchronizationManager must be registered for async and observable support"); } // Ensure that Excel-DNA knows about the RTD Server, since it would not have been registered when loading ExcelObserverRtdServer.EnsureRtdServerRegistered(); // Refresh RTD call // NOTE: First time this will result in a call to ConnectData, which will call Subscribe and set the _currentObserver object unused = XlCall.RTD("ExcelDna.Integration.Rtd.ExcelObserverRtdServer", null, _id.ToString()); } // No assumptions about previous state here - could have re-entered this class. // TODO: Allow customize this value? // Not too serious since the user can remap in the UDF. if (_currentObserver == null) { return(ExcelError.ExcelErrorNA); } // Subsequent calls get value from Observer return(_currentObserver.Value); }
public bool TryGetValue(out object value) { // We need to be careful when this is called from an array formula. // In the 'completed' case we actually still have to call xlfRtd, then only skip if for the next (single-cell calller) call. // That gives us a proper Disconnect... ExcelReference caller = XlCall.Excel(XlCall.xlfCaller) as ExcelReference; bool isCallerArray = caller != null && (caller.RowFirst != caller.RowLast || caller.ColumnFirst != caller.ColumnLast); if (_currentObserver == null || isCallerArray || !IsCompleted()) { // NOTE: At this point the SynchronizationManager must be registered! if (!SynchronizationManager.IsInstalled) { Debug.Print("SynchronizationManager not registered!"); throw new InvalidOperationException("SynchronizationManager must be registered for async and observable support. Call ExcelAsyncUtil.Initialize() in an IExcelAddIn.AutoOpen() handler."); } // Ensure that Excel-DNA knows about the RTD Server, since it would not have been registered when loading ExcelObserverRtdServer.EnsureRtdServerRegistered(); // Refresh RTD call // NOTE: First time this will result in a call to ConnectData, which will call Subscribe and set the _currentObserver // For the first array-group call, this returns null (due to xlUncalced error), // but Excel will call us again... (I hope). if (!RtdRegistration.TryRTD(out value, _observerRtdServerProgId, null, _id)) { // This is the special case... // We return false - to the state creation function that indicates the state should not be saved. value = ExcelError.ExcelErrorNA; return(false); } } else if (_currentObserver != null && IsCompleted()) { // Special call for the Excel 2010 bug helper to indicate we are not refreshing (due to completion) if (ExcelRtd2010BugHelper.ExcelVersionHasRtdBug) { ExcelRtd2010BugHelper.RecordRtdComplete(_observerRtdServerProgId, _id); } } // No assumptions about previous state here - could have re-entered this class // We use #N/A as the 'busy' indicator, as RTD does normally. // Add-in creator can remap the 'busy' result in the UDF or another wrapper. if (_currentObserver == null) { value = ExcelError.ExcelErrorNA; return(true); } // Subsequent calls get value from Observer value = _currentObserver.Value; return(true); }
// NOTE: That the topic is initialized with the value TopicValueActive is // important to the ConnectData implementation below // - there is some interaction between topic values and the return value from ConnectData. public ObserverRtdTopic(ExcelObserverRtdServer server, int topicId, Guid id) : base(server, topicId, TopicValueActive) { Id = id; }
public ObserverRtdTopic(ExcelObserverRtdServer server, int topicId, Guid id) : base(server, topicId) { Id = id; }
// NOTE: That the topic is initialized with the value TopicValueActive is // important to the ConnectData implementation below // - there is some interaction between topic values and the return value from ConnectData. public ObserverRtdTopic(ExcelObserverRtdServer server, int topicId, Guid id, object valueActive) : base(server, topicId, valueActive) { Id = id; }