Exemple #1
0
        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);
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        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);
        }
Exemple #4
0
        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());
        }