private static void ExpandSharedFormulaDependency(CalcService service, CalcGraph graph, List <CalcNode> searchingDepends, List <SharedFormulaDirtyItem> sharedDirtyItmes, CalcNode rangeIntersected, CalcLocalIdentity currentId) { CalcRangeIdentity identity = currentId as CalcRangeIdentity; CalcRangeIdentity id = rangeIntersected.Id as CalcRangeIdentity; if ((!object.ReferenceEquals(id, null) && (rangeIntersected.Dependents != null)) && ((rangeIntersected.Dependents.Count > 0) && ShouldExpand(graph, id))) { foreach (KeyValuePair <CalcNode, CalcNode> pair in rangeIntersected.Dependents) { List <CalcLocalIdentity> list; CalcRangeIdentity rangeId = pair.Key.Id as CalcRangeIdentity; if ((rangeId == null) || !graph.IsSharedFormula(rangeId)) { goto Label_019E; } if ((currentId == rangeId) || ((identity != null) && (identity.IsFullRow || identity.IsFullColumn))) { searchingDepends.Add(pair.Key); continue; } SharedFormulaDirtyItem dirtyItem = null; if (pair.Key.DirtyItem != null) { if (pair.Key.DirtyItem is SharedFormulaDirtyItem) { dirtyItem = pair.Key.DirtyItem as SharedFormulaDirtyItem; if (!dirtyItem.IsFullRangeDirty) { goto Label_0136; } } continue; } dirtyItem = new SharedFormulaDirtyItem(service, graph.Manager.Source, rangeId, graph.GetNode(rangeId)); graph.GetNode(rangeId).DirtyItem = dirtyItem; Label_0136: list = GetDepIdsInSharedFormulaRange(graph.Manager, rangeId, currentId); if ((list.Count == 1) && (list[0] == rangeId)) { dirtyItem.IsFullRangeDirty = true; searchingDepends.Add(graph.GetNode(rangeId)); } else { dirtyItem.DirtySubIds2.AddRange(list); if (dirtyItem.DirtySubIds2.Count > 0) { sharedDirtyItmes.Add(dirtyItem); } } continue; Label_019E: searchingDepends.Add(pair.Key); } } else { searchingDepends.Add(rangeIntersected); } }
private static bool ShouldExpand(CalcGraph graph, CalcRangeIdentity rangeIntersectedDepId) { if (graph.Manager.GetExpression(rangeIntersectedDepId) == null) { return(true); } CalcNode node = graph.GetNode(rangeIntersectedDepId); return(((node != null) && (node.DirtyItem is SharedFormulaDirtyItem)) && !(node.DirtyItem as SharedFormulaDirtyItem).IsFullRangeDirty); }
/// <summary> /// Normalizes the specified node to convert all external reference to internal reference. /// </summary> /// <param name="service">The service.</param> /// <param name="node">The node.</param> /// <returns> /// If <paramref name="node" /> is external identity, return a new node which identity is not external, otherwise, return <paramref name="node" />. /// </returns> internal static CalcNode Normalize(CalcService service, CalcNode node) { if (!object.ReferenceEquals(node, null) && (node.Id is CalcExternalIdentity)) { CalcExternalIdentity id = node.Id as CalcExternalIdentity; CalcGraph graph = service.GetCalculationManager(id.Source, null, true).Graph; CalcLocalIdentity identity2 = id.ConvertToLocal(); node = graph.GetNode(identity2) ?? new CalcNode(id.Source, identity2); } return(node); }
/// <summary> /// hdt 唐忠宝增加 /// </summary> /// <param name="depNode"></param> internal void CreateDirtyItem(CalcNode depNode) { if (object.ReferenceEquals(depNode.Source, this.Source)) { depNode.DirtyItem = new DirtyItem(this, depNode); } else { CalcGraph graph = this.Service.GetCalculationManager(depNode.Source, null, true).Graph; depNode.DirtyItem = new DirtyItem(graph.Manager, graph.GetNode(depNode.Id as CalcLocalIdentity)); } }
/// <summary> /// Sets the expression. /// </summary> /// <param name="id">The id.</param> /// <param name="expr">The exception.</param> /// <param name="isArrayFormula">Indicates the expression is array formula or not.</param> /// <exception cref="T:System.ArgumentNullException"><paramref name="id" /> is <see langword="null" />.</exception> public void SetExpression(CalcRangeIdentity id, CalcExpression expr, bool isArrayFormula = true) { if (object.ReferenceEquals(id, null)) { throw new ArgumentNullException("id"); } if (!isArrayFormula && !(expr is CalcSharedExpression)) { expr = new CalcSharedExpression(expr); } if ((!isArrayFormula && !id.IsFullRow) && (!id.IsFullColumn && !CalcGraph.IsLargeArray(id))) { this.ExpandSharedFormula(expr, id); } else if (this.Service.IsGraphSuspended) { this._tmpFormulas[id] = new Tuple <CalcExpression, bool>(expr, isArrayFormula); } else { this.Graph.SetNode(id, expr, this.Source.GetEvaluatorContext(id), this.Source, isArrayFormula); this._formulas[id] = expr; } }
internal void MarkAsDirty(CalcService service, bool recalculateAll = false, bool recursiveToIntersectant = true, bool recursiveToDependency = true, bool recursiveToSharedFormula = true) { if (!this.IsDirty && !this._isProcessingDirty) { int num; int num2; int num3; int num4; bool flag; this._isProcessingDirty = true; if ((this.DirtyItem == null) && !this._isTempNode) { CalcLocalIdentity objA = this.Id as CalcLocalIdentity; if (object.ReferenceEquals(objA, null)) { return; } this.DirtyItem = new DirtyItem(service, this.Source, objA, this); } CalcGraph graph = service.GetCalculationManager(this.Source, null, true).Graph; CalcReferenceHelper.Id2Range(this.Source, this.Id, out num, out num2, out num3, out num4, out flag); CalcRangeIdentity id = this.Id as CalcRangeIdentity; List <CalcNode> searchingDepends = new List <CalcNode>(); List <CalcNode> list2 = new List <CalcNode>(); if (recursiveToIntersectant && !object.ReferenceEquals(id, null)) { List <CalcNode> list3 = new List <CalcNode>(); for (int i = 0; i < num3; i++) { for (int j = 0; j < num4; j++) { CalcNode node = graph.GetNode(new CalcCellIdentity(num + i, num2 + j)); if (!object.ReferenceEquals(node, null) && node.IsDirty) { list2.Add(node); } if ((!object.ReferenceEquals(node, null) && !node._isWattingForProcess) && (!node._isProcessingDirty && !node.IsDirty)) { node._isWattingForProcess = true; list3.Add(node); } } } foreach (CalcNode node2 in list3) { node2.MarkAsDirty(service, recalculateAll, false, true, true); node2._isWattingForProcess = false; } } DirtyItem dependForehand = null; List <CalcNode> pendingDependDirtyNode = new List <CalcNode>(); if ((this.Dependents != null) && (this.Dependents.Count > 0)) { searchingDepends.AddRange(this.Dependents.Values); } List <SharedFormulaDirtyItem> sharedDirtyItmes = new List <SharedFormulaDirtyItem>(); if (flag || !recalculateAll) { foreach (CalcNode node3 in graph.GetAllDependentRangeNodes(num, num2, num3, num4)) { if ((node3 != this) && ((recalculateAll || !graph.IsSharedFormula(node3.Id as CalcRangeIdentity)) || ((node3.Dependents != null) && (node3.Dependents.Count != 0)))) { if (!recalculateAll && recursiveToDependency) { ExpandSharedFormulaDependency(service, graph, list2, sharedDirtyItmes, node3, this.Id as CalcLocalIdentity); } else if (recalculateAll) { list2.Add(node3); } } } if (recursiveToSharedFormula && this._isTempNode) { foreach (CalcNode node4 in graph.GetAllDependentSharedNodes(num, num2, num3, num4)) { list2.Add(node4); } } } if (recursiveToIntersectant) { searchingDepends.AddRange(list2); list2.Clear(); } dependForehand = SerchDependForehand(dependForehand, searchingDepends, list2, pendingDependDirtyNode, sharedDirtyItmes); if (recursiveToSharedFormula && !this._isTempNode) { if (dependForehand != null) { service.InsertToDirtyBefore(this.DirtyItem, dependForehand); } else { service.AddDirtyItem(this.DirtyItem); } } if (recursiveToDependency) { foreach (CalcNode node5 in pendingDependDirtyNode) { node5._isWattingForProcess = true; } foreach (CalcNode node6 in pendingDependDirtyNode) { node6.MarkAsDirty(service, recalculateAll, true, true, true); node6._isWattingForProcess = false; } foreach (SharedFormulaDirtyItem item2 in sharedDirtyItmes) { if (!item2.Node.IsDirty) { service.AddDirtyItem(item2); } List <CalcNode> list6 = new List <CalcNode>(); foreach (CalcLocalIdentity identity3 in item2.DirtySubIds2) { if (!item2.DirtySubIds.Contains(identity3)) { item2.DirtySubIds.Add(identity3); CalcNode item = graph.GetNode(identity3); if (item == null) { item = CreateTempNode(this.Source, identity3); } item._isWattingForProcess = true; list6.Add(item); } } foreach (CalcNode node8 in list6) { node8.MarkAsDirty(service, recalculateAll, true, true, false); node8._isWattingForProcess = false; } } } else if (recalculateAll) { foreach (CalcNode node9 in searchingDepends) { this.SetPredencyItem(service, node9); } foreach (CalcNode node10 in list2) { if (IsContains(node10.Id as CalcLocalIdentity, this.Id as CalcLocalIdentity)) { this.SetPredencyItem(service, node10); } } } this._isProcessingDirty = false; } }
/// <summary> /// hdt 唐忠宝增加 /// </summary> /// <param name="header"></param> /// <param name="tailItem"></param> private void GetAllDirtyItems(ref DirtyItem header, ref DirtyItem tailItem) { DirtyItem nextItem; DirtyItem removingItem = header; while (removingItem != null) { nextItem = removingItem.NextItem; DirtyItem previousItem = removingItem.PreviousItem; CalcNode objB = removingItem.Node; if (objB.NodeType != NodeType.None) { objB.DirtyItem.DirtyFlag = true; } else { objB.DirtyItem = null; RemoveDirtyItem(ref header, ref tailItem, removingItem); } if ((objB.Dependents == null) || (objB.Dependents.Count == 0)) { removingItem = nextItem; } else { foreach (KeyValuePair <CalcNode, CalcNode> pair in objB.Dependents) { if (((pair.Key.DirtyItem == null) && !object.ReferenceEquals(pair.Key, objB)) && ((pair.Key.Id is CalcCellIdentity) || (pair.Key.Id is CalcExternalCellIdentity))) { this.CreateDirtyItem(pair.Key); AddDirtyItem(ref header, ref tailItem, pair.Key.DirtyItem, objB); CalcLocalIdentity id = pair.Key.Id as CalcLocalIdentity; CalcGraph graph = pair.Key.DirtyItem.Manager.Graph; if (object.ReferenceEquals(id, null)) { id = (pair.Key.Id as CalcExternalIdentity).ConvertToLocal(); } foreach (CalcNode node2 in graph.Manager.EnumerateIntersectedNodesExcludeSelf(id as CalcCellIdentity)) { node2.DirtyItem = new DirtyItem(this, node2); AddDirtyItem(ref header, ref tailItem, node2.DirtyItem, pair.Key); } } } if (nextItem == null) { if ((previousItem == null) && (removingItem != header)) { removingItem = header; } else if ((previousItem != null) && (removingItem != previousItem.NextItem)) { removingItem = previousItem.NextItem; } else { removingItem = null; } continue; } removingItem = nextItem; } } for (removingItem = header; removingItem != null; removingItem = nextItem) { nextItem = removingItem.NextItem; CalcNode node = removingItem.Node; if (removingItem.Node.Dependents != null) { foreach (KeyValuePair <CalcNode, CalcNode> pair2 in removingItem.Node.Dependents) { if ((pair2.Key.DirtyItem != null) && !object.ReferenceEquals(pair2.Key, node)) { if (removingItem.DependencyCellTemp == null) { removingItem.DependencyCellTemp = new HashSet <CalcNode>(); } if (!removingItem.DependencyCellTemp.Contains(pair2.Key)) { removingItem.DependencyCellTemp.Add(pair2.Key); pair2.Key.DirtyItem.PredencyItemCount++; } } } } } }