找回密码
 立即注册

QQ登录

只需一步,快速开始

Richard.Ma 讲师达人认证 悬赏达人认证 SpreadJS 开发认证
超级版主   /  发表于:2021-2-25 17:02  /   查看:2686  /  回复:0
本帖最后由 Richard.Ma 于 2021-2-25 17:08 编辑

ComponentOne计算引擎“ C1CalcEngine”是一个支持解析和计算表达式/公式的.NET标准库,可用于所有ComponentOne .NET平台,并可用于促进公式计算

该库具有许多高级功能,例如对业务对象的广泛计算支持,用于分析遵循Microsoft Excel格式的文本表达式的即用型表达式分析器等。
该图显示了给FlexGrid上方添加一个类似Excel中的公式栏。

此公示栏高级功能之一是跨工作表引用。本文将逐步介绍如何在.NET WinForms应用程序中构建类似于Excel的公式栏的功能。

什么是跨工作表单元格引用?
单元格引用是一组坐标,用于指定工作表上的单元格/单元格范围位置。公式中的单元格引用用于获取和处理包含在相应单元格中的数据。使用引用的一个优点是,每次这些单元格的值更改时,公式的结果都会自动更新。
此外,在某些情况下,数据会分布在多个工作簿上。在这种情况下,单元格可以引用位于其他工作表中的单元格。这是C1CalcEngine跨工作表引用功能的有用之处。
要引用另一个工作表中的单元格,需要标识目标单元格/单元格范围,但是需要标识单元格所在的表。为此,就像Excel一样,目标工作表名称是在单元格/单元格范围引用之前定义的,用感叹号 (!)分隔。
  1. =Sum(sheet1!A1:B2) + Max(sheet2!A1:C7)
复制代码

在这个例子里,表达式使用两个sheet,“ sheet1”和“ sheet2”,并分别应用数学函数“ Sum”和“ Max”。

如何创建类似Excel的公式栏
在Excel中,公式栏是一个可视元素,允许最终用户编辑工作表单元格中包含的数据值和公式。
该图显示了MS Excel中的公式栏组件。
使用C1CalcEngine,可以在.NET应用程序中轻松添加类似于Excel的公式栏。以下为添加的步骤。

设置步骤
作为非UI组件,C1CalcEngine不提供任何可视组件以在窗体上显示。因此,为了激发WinForms应用程序中的公式栏行为并定义类似于Excel的公式,您将需要构建自己的公式栏。
要构建类似于Excel的公式栏,可以使用TextBox和Button控件显示/输入表达式,并使用C1CalcEngine解析这些表达式以进行计算。下面的步骤演示了如何从头开始在.NET WinForms应用程序中添加类似于Excel的公式栏。
我们将完整的实现分为以下几部分:
  • 设置应用
  • 向库添加引用
  • 创建数据源
  • 将C1CalcEngine绑定到数据源
  • 分配Excel样式的表达式
  • 使用C1CalcEngine计算表达式

设置应用
  • 创建一个新的Windows窗体应用程序并将其命名为_CalcEngine_CrossShee__t_。
  • 添加一个TextBox控件以显示表达式。
  • 添加一个Button控件以触发表达式的解析,并将其“ Text”属性设置为Evaluate。
  • 将标签控件添加到窗体并将其“文本”属性设置为结果。
  • 添加另一个TextBox控件以显示表达式求值结果。
  • 为了说明,将两个FlexGrid控件添加到窗体中以表示两个包含交叉引用的Excel工作表。
完成此步骤后,该表格应类似于上图。

添加引用

  • 使用NuGet软件包管理器安装C1CalcEngine NuGet软件包。
  • 切换到代码视图并添加以下名称空间:
  1. using C1.CalcEngine;
  2. using C1.CalcEngine.ExcelEngine;
  3. using C1.Win.C1FlexGrid;
复制代码


创建数据源
若要使用跨工作表引用,应将所有引用的工作表作为C1CalcEngine的数据源传递,并且列表中的每个元素都将充当C1CalcEngine的工作表。由C1CalcEngine评估的表达式使用这些工作表及其名称来实现跨工作表引用。
因此,让我们创建一个实现IDataSheet接口的自定义DataTable ,以用作FlexGrid的DataSource。这将生成绑定的FlexGrid控件,用作C1CalcEngine的数据源。
  1. //Custom DataTable implementing IDataSheet
  2. public class SheetTable : DataTable, IDataSheet
  3. {
  4.     public string Name
  5.     {
  6.         get => TableName;
  7.         set => TableName = value;
  8.     }
  9.     public object GetValue(int col, int row)
  10.     {
  11.         return Rows[row][col];
  12.     }
  13. }
复制代码

将CalcEngine绑定到数据源
使用以下代码全局定义C1CalcEngine和一个字符串变量:
  1. private C1CalcEngine _calcEngine;
  2. private const string ColumnNames = "ABCDEF";
复制代码
添加以下方法来初始化SheetTable类,以用作C1FlexGrid的DataSource:
  1. //Generate DataTable to be used as FlexGrid's DataSource
  2. public SheetTable GetDataTable(string sheetName)
  3. {
  4.     var table = new SheetTable();
  5.     table.Name = sheetName;
  6.     foreach (var col in ColumnNames)
  7.         table.Columns.Add(col.ToString(), typeof(int));
  8.     for (int i = 0; i < 80; i++)
  9.         table.Rows.Add(new object[] { i * 2, i * 3, i * 4, i * 5, i * 6, i * 7 });
  10.     return table;
  11. }
复制代码

使用上面定义的方法来生成FlexGrids的DataSource并将这些表用作C1CalcEngine的DataSource:
  1. var sheet1 = GetDataTable("Sheet1");
  2. var sheet2 = GetDataTable("Sheet2");
  3. c1FlexGrid1.DataSource = sheet1;
  4. c1FlexGrid2.DataSource = sheet2;

  5. _calcEngine.DataSource = new List<IDataSheet> { sheet1, sheet2 };
复制代码

分配表达式
要在工作表(FlexGrid)中选择更改时更新公式栏(表达式文本框),请处理FlexGrid控件的SelChange事件。如下定义事件处理程序,以根据当前选择的FlexGrid实例生成C1CalcEngine表达式。
  1. //Get grid selection and create Excel expression
  2. private void grid_SelChange(object sender, System.EventArgs e)
  3. {   
  4.     tbExpression.Text = string.Format("=Sum(sheet1!{0}) + Sum(sheet2!{1})", GetMark(c1FlexGrid1), GetMark(sheet2));
  5. }
复制代码

定义以下方法将FlexGrid选择转换为Excel表达式,以便C1CalcEngine对它进行评估:
  1. private string GetMark(C1FlexGrid grid)
  2. {
  3.     var sel = grid.Selection;
  4.     return string.Format("{0}{1}:{2}{3}", ColumnNames[sel.LeftCol - 1], sel.TopRow, ColumnNames[sel.RightCol - 1], sel.BottomRow);
  5. }
复制代码

该图显示了带有示例表达式的编辑栏。


计算结果
若要计算创建的Excel样式的表达式,请使用C1CalcEngine类的TryEvaluate方法。为此,处理按钮的Click事件,并向其中添加以下代码:
  1. //Evaluate the created Excel expression
  2. private void btnEvaluate_Click(object sender, EventArgs e)
  3. {
  4.     _calcEngine.Expression = tbExpression.Text;
  5.     if (_calcEngine.TryEvaluate(out object result))        
  6.         tbResult.Text = (result ?? "").ToString();
  7.     else        
  8.         tbResult.Text = _calcEngine.GetErrors().FirstOrDefault()?.FullMessage ?? "";
  9. }
复制代码



Demo源码项目请下载下面的附件


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

0 个回复

您需要登录后才可以回帖 登录 | 立即注册
返回顶部