Back to Devexpress

ICustomCalculationService.OnBeginCellCalculation(CellCalculationArgs) Method

officefileapi-devexpress-dot-xtraspreadsheet-dot-services-dot-icustomcalculationservice-dot-onbegincellcalculation-x28-devexpress-dot-spreadsheet-dot-formulas-dot-cellcalculationargs-x29.md

latest12.5 KB
Original Source

ICustomCalculationService.OnBeginCellCalculation(CellCalculationArgs) Method

Called when the calculation is started for a particular cell.

Namespace : DevExpress.XtraSpreadsheet.Services

Assembly : DevExpress.Spreadsheet.v25.2.Core.dll

NuGet Package : DevExpress.Spreadsheet.Core

Declaration

csharp
void OnBeginCellCalculation(
    CellCalculationArgs args
)
vb
Sub OnBeginCellCalculation(
    args As CellCalculationArgs
)

Parameters

NameTypeDescription
argsCellCalculationArgs

A instance which allows you to identify a cell and obtain its value before calculation.

|

Remarks

If circular references are found, the OnBeginCellCalculation method for the cell with circular reference is called two times. Subsequently, the ICustomCalculationService.OnBeginCircularReferencesCalculation method is called, and the ICustomCalculationService.OnEndCircularReferencesCalculation is called if the ICustomCalculationService.OnBeginCircularReferencesCalculation method did not return false. In this situation, the ICustomCalculationService.OnEndCellCalculation method is not called at all.

Example

This example illustrates the use of the service which implements the ICustomCalculationService interface and allows to manage the process of worksheet calculations.

The application creates log entries when worksheet calculation starts and finishes, when cell calculation begins and ends, when a cell with the circular reference starts and finishes its calculation.

csharp
using DevExpress.Spreadsheet;
using DevExpress.Spreadsheet.Formulas;
using DevExpress.XtraTreeList.Nodes;
using System;
using System.Collections.Generic;
    public class TestCustomCalculationService : DevExpress.XtraSpreadsheet.Services.ICustomCalculationService {
        private DevExpress.XtraTreeList.TreeList loggingControl;
        private TreeListNode rootListNode = null;
        public HashSet<CellKey> CircularReferencedCells = new HashSet<CellKey>();

        public TestCustomCalculationService(object controlForLogging)
        {
            loggingControl = controlForLogging as DevExpress.XtraTreeList.TreeList;
        }

        public bool OnBeginCalculation() {
            // Set the root node for displaying info on the current calculation.
            rootListNode = loggingControl.AppendNode(new object[] {String.Format("Calculation starts at {0}", DateTime.Now)}, null);
            // To highlight cells with circular references, this example uses a hash set of such cells. 
            // Clear it when a new calculation starts.
            CircularReferencedCells.Clear();
            // True to perform a calculation. Return False to cancel it.
            return true;
        }
        public void OnBeginCellCalculation(CellCalculationArgs args) {
            // Add a record about the cell being calculated.
            CreateLogEntry("Cell calculation begins", new string[] {String.Format("CellKey: ({0})", args.CellKey)} );
        }
        public bool OnBeginCircularReferencesCalculation() {
            // Indicate that a circular reference calculation starts. 
            // If the SpreadsheetControl.Document.DocumentSettings.Calculation.Iterative property is false (default),
            // this method is not called.
            // If a circular reference calculation starts, the OnBeginCellCalculation method is called again.
            CreateLogEntry("Circular Reference calculation begins", new string[] {});
            // True to perform a calculation. Return False to cancel it.
            return true;
        }
        public void OnEndCalculation() {
            // Add a record that the calculation has finished.
            CreateLogEntry(String.Format("Calculation finishes at {0}", DateTime.Now), new string[] {});
            rootListNode = null;
        }
        public void OnEndCellCalculation(CellKey cellKey, CellValue startValue, CellValue endValue) {
            // Display cell information, a cell value before calculation and the calculated cell value.
            string info = String.Format("CellKey: ({0}) Before: {1}, After: {2}", cellKey, startValue, endValue);
            CreateLogEntry("Cell calculation ends", new string[] {info} );
        }
        public void OnEndCircularReferencesCalculation(IList<CellKey> cellKeys) {
            // Store cell keys of cells with circular references for further use.
            CircularReferencedCells = new HashSet<DevExpress.Spreadsheet.CellKey>(cellKeys); 
            string[] sKeys = new string[cellKeys.Count];
            int i = 0;
            foreach (CellKey key in cellKeys) {
                sKeys[i] = key.ToString();
                i++;
            } 
            // Display the information on cells with circular references.
            CreateLogEntry("Circular Reference calculation ends", sKeys);
        }
        public bool ShouldMarkupCalculateAlwaysCells() {
            // Mark as needing calculation the "calculate always" cells, 
            // such as cells containing volatile function or referencing another "calculate always" cell.
            return true;
        }

        private void CreateLogEntry(string actionName, string[] info)
        {
            TreeListNode firstLevelNode = loggingControl.AppendNode(new object[] { actionName }, rootListNode);
            if (info.Length != 0)
            {
                for (int i = 0; i < info.Length; i++)
                {
                    TreeListNode secondLevelNode = loggingControl.AppendNode(new object[] { info[i] }, firstLevelNode);
                }
            }
            firstLevelNode.ExpandAll();
            loggingControl.MakeNodeVisible(firstLevelNode);
        }
    }
vb
Imports DevExpress.Spreadsheet
Imports DevExpress.Spreadsheet.Formulas
Imports DevExpress.XtraTreeList.Nodes
Imports System
Imports System.Collections.Generic
    Public Class TestCustomCalculationService
        Implements DevExpress.XtraSpreadsheet.Services.ICustomCalculationService

        Private loggingControl As DevExpress.XtraTreeList.TreeList
        Private rootListNode As TreeListNode = Nothing
        Public CircularReferencedCells As New HashSet(Of CellKey)()

        Public Sub New(ByVal controlForLogging As Object)
            loggingControl = TryCast(controlForLogging, DevExpress.XtraTreeList.TreeList)
        End Sub

        Public Function OnBeginCalculation() As Boolean Implements DevExpress.XtraSpreadsheet.Services.ICustomCalculationService.OnBeginCalculation
            ' Set the root node for displaying info on the current calculation.
            Dim rootNode As TreeListNode = Nothing
            rootListNode = loggingControl.AppendNode(New Object() {String.Format("Calculation starts at {0}", Date.Now)}, rootNode)
            ' To highlight cells with circular references, this example uses a hash set of such cells. 
            ' Clear it when a new calculation starts.
            CircularReferencedCells.Clear()
            ' True to perform a calculation. Return False to cancel it.
            Return True
        End Function
        Public Sub OnBeginCellCalculation(ByVal args As CellCalculationArgs) Implements DevExpress.XtraSpreadsheet.Services.ICustomCalculationService.OnBeginCellCalculation
            ' Add a record about the cell being calculated.
            CreateLogEntry("Cell calculation begins", New String() {String.Format("CellKey: ({0})", args.CellKey)})
        End Sub
        Public Function OnBeginCircularReferencesCalculation() As Boolean Implements DevExpress.XtraSpreadsheet.Services.ICustomCalculationService.OnBeginCircularReferencesCalculation
            ' Indicate that a circular reference calculation starts. 
            ' If the SpreadsheetControl.Document.DocumentSettings.Calculation.Iterative property is false (default),
            ' this method is not called.
            ' If a circular reference calculation starts, the OnBeginCellCalculation method is called again.
            CreateLogEntry("Circular Reference calculation begins", New String() {})
            ' True to perform a calculation. Return False to cancel it.
            Return True
        End Function
        Public Sub OnEndCalculation() Implements DevExpress.XtraSpreadsheet.Services.ICustomCalculationService.OnEndCalculation
            ' Add a record that the calculation has finished.
            CreateLogEntry(String.Format("Calculation finishes at {0}", Date.Now), New String() {})
            rootListNode = Nothing
        End Sub
        Public Sub OnEndCellCalculation(ByVal cellKey As CellKey, ByVal startValue As CellValue, ByVal endValue As CellValue) Implements DevExpress.XtraSpreadsheet.Services.ICustomCalculationService.OnEndCellCalculation
            ' Display cell information, a cell value before calculation and the calculated cell value.
            Dim info As String = String.Format("CellKey: ({0}) Before: {1}, After: {2}", cellKey, startValue, endValue)
            CreateLogEntry("Cell calculation ends", New String() {info})
        End Sub
        Public Sub OnEndCircularReferencesCalculation(ByVal cellKeys As IList(Of CellKey)) Implements DevExpress.XtraSpreadsheet.Services.ICustomCalculationService.OnEndCircularReferencesCalculation
            ' Store cell keys of cells with circular references for further use.
            CircularReferencedCells = New HashSet(Of DevExpress.Spreadsheet.CellKey)(cellKeys)
            Dim sKeys(cellKeys.Count - 1) As String
            Dim i As Integer = 0
            For Each key As CellKey In cellKeys
                sKeys(i) = key.ToString()
                i += 1
            Next key
            ' Display the information on cells with circular references.
            CreateLogEntry("Circular Reference calculation ends", sKeys)
        End Sub
        Public Function ShouldMarkupCalculateAlwaysCells() As Boolean Implements DevExpress.XtraSpreadsheet.Services.ICustomCalculationService.ShouldMarkupCalculateAlwaysCells
            ' Mark as needing calculation the "calculate always" cells, 
            ' such as cells containing volatile function or referencing another "calculate always" cell.
            Return True
        End Function

        Private Sub CreateLogEntry(ByVal actionName As String, ByVal info() As String)
            Dim firstLevelNode As TreeListNode = loggingControl.AppendNode(New Object() { actionName }, rootListNode)
            If info.Length <> 0 Then
                For i As Integer = 0 To info.Length - 1
                    Dim secondLevelNode As TreeListNode = loggingControl.AppendNode(New Object() { info(i) }, firstLevelNode)
                Next i
            End If
            firstLevelNode.ExpandAll()
            loggingControl.MakeNodeVisible(firstLevelNode)
        End Sub
    End Class

See Also

Calculation Process

ICustomCalculationService Interface

ICustomCalculationService Members

DevExpress.XtraSpreadsheet.Services Namespace