protected override void DisconnectData(Topic topic) { // Retrieve the GUID from the topic's first info string - used to hook up to the Async state Guid id = _topicGuids[topic]; // ... and unsubscribe it AsyncObservableImpl.DisconnectObserver(id); _topicGuids.Remove(topic); }
protected override void DisconnectData(Topic topic) { Debug.Print("ExcelObserverRtdServer.DisconnectData: ProgId: {0}, TopicId: {1}", RegisteredProgId, topic.TopicId); // Retrieve the GUID from the topic's first info string - used to hook up to the Async state Guid id = ((ObserverRtdTopic)topic).Id; // ... and unsubscribe it AsyncObservableImpl.DisconnectObserver(id); }
protected override object ConnectData(Topic topic, IList <string> topicInfo, ref bool newValues) { Debug.Print("ExcelObserverRtdServer.ConnectData: ProgId: {0}, TopicId: {1}, TopicInfo: {2}, NewValues: {3}", RegisteredProgId, topic.TopicId, topicInfo[0], newValues); // The topic might be "completed" on a separate thread, so we need to return the initial, intended active value // Mostly this is TopicValueActive, but sometimes TopicValueActiveNA // Rather than store this for every topic, we just recalculate it here object valueActive = ValueActiveFromTopicInfo(topicInfo); if (newValues == false) { // Excel has a cached value, and we are being called from the file open refresh. // Indicating "newValues", should be safe since it is consistent with normal updates. // Result should be a Disconnect followed by a proper Connect via the wrapper. newValues = true; return(valueActive); } // Retrieve and store the GUID from the topic's first info string - used to hook up to the Async state Guid id = ((ObserverRtdTopic)topic).Id; // Create a new ExcelRtdObserver, for the Topic, which will listen to the Observable // (Internally this will also set the initial value of the Observer wrapper to #N/A) ExcelRtdObserver rtdObserver = new ExcelRtdObserver(topic); // ... and subscribe it AsyncObservableImpl.ConnectObserver(id, rtdObserver); // Now ConnectData needs to return some value, which will only be used by Excel internally (and saved in the book's RTD topic value). // Our wrapper function (ExcelAsyncUtil.Run or ExcelAsyncUtil.Observe) will return #N/A no matter what we return here. // However, it seems that Excel handles the special 'busy' error #N/A here (return ExcelErrorUtil.ToComError(ExcelError.ExcelErrorNA)) // in a special way (<tp t="e"><v>#N/A</v> in volatileDependencies.xml) - while other values seem to trigger a recalculate on file open, // when Excel attempts to restart the RTD server and fails (due to transient ProgId). // So for the ObserverRtdTopic we ensure the internal value is not an error, // (it is initialized to TopicValueActive) // which we return from here. // 2017-03-19: Except if the topic is configured as ExcelObservableOptions.NoAutoStartOnOpen, in which case we _do_ want // the internal value to be #N/A. We return whichever ective value was set in the CreateTopic according to the topic info. // 2016-11-04: We are no longer returning the current value of topic.Value here. // Since calls to UpdateValue inside the ConnectData no longer raise an // UpdateNotify automatically, we need to ensure a different value // is returned for a completed topic (so that ConnectData.returned != topic.Value) // to raise an extra UpdateNotify, for the Disconnect of the already completed topic // (I.e. if the completion happened during the ConnectData call). return(valueActive); }
protected override object ConnectData(Topic topic, IList <string> topicInfo, ref bool newValues) { // Retrieve and store the GUID from the topic's first info string - used to hook up to the Async state Guid id = new Guid(topicInfo[0]); _topicGuids[topic] = id; // Create a new ExcelRtdObserver, for the Topic, which will listen to the Observable // (Internally also set initial value - #N/A for now) ExcelRtdObserver rtdObserver = new ExcelRtdObserver(topic); // ... and subscribe it AsyncObservableImpl.ConnectObserver(id, rtdObserver); // Return something: #N/A for now. Not currently used. // TODO: Allow customize? return(ExcelErrorUtil.ToComError(ExcelError.ExcelErrorNA)); }
protected override object ConnectData(Topic topic, IList <string> topicInfo, ref bool newValues) { Debug.Print("ExcelObserverRtdServer.ConnectData: ProgId: {0}, TopicId: {1}, TopicInfo: {2}, NewValues: {3}", RegisteredProgId, topic.TopicId, topicInfo[0], newValues); if (newValues == false) { // Excel has a cached value, and we are being called from the file open refresh. // Calling UpdateNotify here seems to work (it causes the wrapper function to recalc, // which Disconnects the bad topic, and allows a fresh one to be created) // Not needed if we return a new 'fake' value, which is safe since it is consistent with normal updates. // Result should be a Disconnect followed by a proper Connect via the wrapper. // topic.UpdateNotify(); newValues = true; return(DateTime.UtcNow.ToOADate()); } // Retrieve and store the GUID from the topic's first info string - used to hook up to the Async state Guid id = ((ObserverRtdTopic)topic).Id; // Create a new ExcelRtdObserver, for the Topic, which will listen to the Observable // (Internally this will also set the initial value to #N/A) ExcelRtdObserver rtdObserver = new ExcelRtdObserver(topic); // ... and subscribe it AsyncObservableImpl.ConnectObserver(id, rtdObserver); // Now ConnectData needs to return some value, which will only be used by Excel internally (and saved in the book's RTD topic value). // Our wrapper function (ExcelAsyncUtil.Run or ExcelAsyncUtil.Observe) will return #N/A no matter what we return here. // However, it seems that Excel handles the special 'busy' error #N/A here (return ExcelErrorUtil.ToComError(ExcelError.ExcelErrorNA)) // in a special way (<tp t="e"><v>#N/A</v> in volatileDependencies.xml) - while other values seem to trigger a recalculate on file open, // when Excel attempts to restart the RTD server and fails (due to transient ProgId). // So we already return the same kind of value we'd return for updates, putting Excel into the 'value has been updated' state // even if the sheet is saved. That will trigger a proper formula recals on file open. return(DateTime.UtcNow.ToOADate()); }