This walkthrough demonstrates the implementation of cross-sheet referencing using CalcEngine in a WinForms App. Here, CalcEngine is used to parse and compute algebraic expressions, mathematical functions, and formulas using variables and across multiple spreadsheets or controls. In this walkthrough, you understand how to use a bound FlexGrid and an unbound custom FlexGrid as the datasource for CalcEngine. The former FlexGrid control has been bound to a custom DataTable which implements the IDataSheet interface. And the latter, custom FlexGrid, has been defined by implementing the IDataSheet interface.
The walkthrough generates a list of type IDataSheet. Each element in the list is an instance of either C1FlexGrid or custom C1FlexGrid. This list is used as a data source for C1CalcEngine and each element of the list acts as a sheet for C1CalcEngine. The expressions evaluated by the CalcEngine use these sheets and the sheet names to implement cross-sheet referencing.
using C1.CalcEngine;
using C1.Win.C1FlexGrid;
C# |
Copy Code
|
---|---|
//Custom FlexGrid implementing IDataSheet public class ExcelFlexGrid : C1FlexGrid, IDataSheet { public object GetValue(int col, int row) => Rows[row + 1][col + 1]; } |
Create a custom DataTable that implements the IDataSheet interface, used as the datasource for FlexGrid. This generates a bound FlexGrid control to be used as a datasource for CalcEngine.
C# |
Copy Code
|
---|---|
//Custom DataTable implementing IDataSheet public class SheetTable : DataTable, IDataSheet { public string Name { get => TableName; set => TableName = value; } public object GetValue(int col, int row) { return Rows[row][col]; } } |
C# |
Copy Code
|
---|---|
private C1CalcEngine _calcEngine; private const string Abc = "ABCDEF"; |
C# |
Copy Code
|
---|---|
//Generate DataTable to be used as FlexGrid's datasource public SheetTable GetDataTable(string sheetName) { var table = new SheetTable(); table.Name = sheetName; foreach (var c in Abc) table.Columns.Add(c.ToString(), typeof(int)); for (int i = 0; i < 80; i++) table.Rows.Add(new object[] { i * 2, i * 3, i * 4, i * 5, i * 6, i * 7 }); return table; } |
Add the following method to populate ExcelFlexGrid with unbound data.
C# |
Copy Code
|
---|---|
//Populate ExcelFlexGrid using unbound data private void LoadUnboundGrid(C1FlexGrid grid) { grid.Rows.Count = 81; grid.Cols.Count = 7; for (int i = 1; i <= Abc.Length; i++) grid.Rows[0][i] = Abc[i - 1]; for (int i = 0; i < 80; i++) for (int j = 1; j <= Abc.Length; j++) grid.Rows[i + 1][j] = i * j; } |
C# |
Copy Code
|
---|---|
//Get grid selection and create Excel expression private void grid_SelChange(object sender, System.EventArgs e) { textBox1.Text = string.Format("=Sum(sheet1!{0}) + Sum(sheet2!{1})", GetMark(c1FlexGrid1), GetMark(sheet2)); } |
C# |
Copy Code
|
---|---|
private string GetMark(C1FlexGrid grid) { var sel = grid.Selection; return string.Format("{0}{1}:{2}{3}", Abc[sel.LeftCol - 1], sel.TopRow, Abc[sel.RightCol - 1], sel.BottomRow); } |
C# |
Copy Code
|
---|---|
//Evaluate the created Excel expression private void button1_Click(object sender, EventArgs e) { _calcEngine.Expression = textBox1.Text; if (_calcEngine.TryEvaluate(out object result)) textBox2.Text = (result ?? "").ToString(); else textBox2.Text = _calcEngine.GetErrors().FirstOrDefault()?.FullMessage ?? ""; } |
using C1.CalcEngine.ExcelEngine;
C# |
Copy Code
|
---|---|
private void Form1_Load(object sender, EventArgs e) { //Initialize and populate C1FlexGrid with custom DataTable(SheetTable) var sheet1 = GetDataTable("Sheet1"); c1FlexGrid1.DataSource = sheet1; //Initialize custom FlexGrid(ExcelFlexGrid) and populate unbound data LoadUnboundGrid(sheet2); //Initialize C1CalcEngine and assign datasource _calcEngine = new C1CalcEngine(new ExcelEngine()); _calcEngine.DataSource = new List<IDataSheet> { sheet1, sheet2 }; //Perform default selection in FlexGrid/ExcelFlexGrid c1FlexGrid1.Select(1, 1, 2, 2); sheet2.Select(3, 2, 5, 3); } |