Exemplo n.º 1
0
 private void MarkAsCalculating(ExcelReference caller, AsyncCallInfo asyncCallInfo)
 {
     calculatingRefs_[caller] = asyncCallInfo;
     for (int row = caller.RowFirst; row <= caller.RowLast; row++)
     {
         for (int col = caller.ColumnFirst; col <= caller.ColumnLast; col++)
         {
             ExcelReference excelReference = new ExcelReference(row, row, col, col, caller.SheetId);
             calculatingRefs_[excelReference] = asyncCallInfo;
         }
     }
 }
Exemplo n.º 2
0
        /// <summary>
        /// Starts async UDF calculation.
        /// Returns Scheduled/Calculating or calculated value.
        /// Make sure calling UDF marked with IsMacroType=true.
        /// </summary>
        public object Calc(CallArguments args)
        {
            CheckFuncName(args);
            MarkUdfNonVolatile();
            ExcelReference caller;

            try
            {
                caller = GetCallerExcelReference();
            }
            catch (Exception e)
            {
                logService_.WriteError(
                    "Error getting reference. " +
                    FunctionLoggerHelper.LogParameters(args.FunctionName, null), e);
                // TODO Cleanup
                return("Error getting reference.");
            }

            if (IsNewEvaluationBatchStarted)
            {
                OnEvaluatingBatchStarted();
            }

            object[]      asyncKeyArgs  = GetAsyncKeyArgs(args.RawArgs, caller, batchStarted_);
            AsyncCallInfo asyncCallInfo = new AsyncCallInfo(args.FunctionName, asyncKeyArgs);

            if (!IsCalculatingTheSame(caller, asyncCallInfo) || IsScheduled(caller))
            {
                // Check simple case. Precedent is still calculating.
                Precedents precedents = caller.GetPrecedents();
                if (precedents.GetRefs().Any(IsCalculatingAny))
                {
                    SetEvalState(caller, EvalState.Scheduled, args, asyncCallInfo);
                    return(Scheduled);
                }

                if (ForcePrecedentCalculated(caller, precedents))
                {
                    SetEvalState(caller, EvalState.Scheduled, args, asyncCallInfo);
                    return(Scheduled);
                }
            }

            Validate(args);

            bool   isCalculating;
            object result = Observe(asyncKeyArgs, caller.XlfToReference(), args, out isCalculating);

            if (isCalculating)
            {
                // Async call to service scheduled.
                SetEvalState(caller, EvalState.ObservableCreated, args, asyncCallInfo);
                return(Calculating);
            }
            else
            {
                // Async call to service and result are ready.
                SetEvalState(caller, EvalState.ObservableFinished, args, asyncCallInfo);
                return(result);
            }
        }
Exemplo n.º 3
0
        private void SetEvalState(ExcelReference caller, EvalState evalState, CallArguments args, AsyncCallInfo asyncCallInfo)
        {
            evalStates_[caller] = evalState;
            switch (evalState)
            {
            case EvalState.ObservableCreated:
            case EvalState.Scheduled:
            case EvalState.ForcingFormulaUpdate:
                MarkAsCalculating(caller, asyncCallInfo);
                LogState();
                break;

            case EvalState.ObservableFinished:
                RemoveFromCalculating(caller);
                AddCalculatedFunc(caller, args);

                if (IsEvaluatingBatchSeemsToBeFinished)
                {
                    UpdateLastFinished();
                }

                LogState();
                break;
            }
        }
Exemplo n.º 4
0
        private bool IsCalculatingTheSame(ExcelReference excelReference, AsyncCallInfo asyncCallInfo)
        {
            AsyncCallInfo cached;

            return(calculatingRefs_.TryGetValue(excelReference, out cached) && cached.Equals(asyncCallInfo));
        }