c# - 在 C# 中计算值的数组(从 Excel 转换公式)

标签 c# excel multidimensional-array lazy-evaluation calculated-columns

我目前正在构建一个半复杂的计算器,它基本上是从我提供的 Excel 电子表格转换而来的。

我已经解决了大部分问题,但在 Excel 电子表格中有一部分在 6 行和 7 列之间进行了多次计算,但问题是这些计算无论如何都没有特定的顺序发生。

例如,Row0[Column1] 是使用 (Row2[Column4] * Row2[Column5])Row1[Column4] 计算的> 是使用 (Row4[Column2]/Row5[Column1]) 等计算的。您明白了。

我考虑过使用二维数组,但担心这些值将按特定顺序计算,因此在达到它们时没有任何值(value)。据我所知,将首先计算 Row1,然后是 Row2Row3

那么,如果不为我的 Excel 电子表格中的每个单元格创建一个变量(并对其进行适当排序),有没有一种方法可以使用 C# 进行计算?

我非常感谢任何帮助、建议、指点,无论您认为可能是什么 - 我很想听听!

编辑 在实现了 @dtb 提供的 Lazy 类之后,我得到了以下代码。它是我所提供的 Excel 电子表格中内容的直接副本,包括指针和计算。

var sr = new Lazy<decimal>[6, 6];
sr[0, 0] = new Lazy<decimal>(() => sr[1, 0].Value - eNumber);
sr[0, 3] = new Lazy<decimal>(() => sr[0, 4].Value - sr[1, 0].Value - sr[1, 4].Value);
sr[0, 4] = new Lazy<decimal>(() => sr[0, 0].Value * edD);
sr[0, 5] = new Lazy<decimal>(() => sr[0, 0].Value);

sr[1, 0] = new Lazy<decimal>(() => sr[1, 5].Value);
sr[1, 4] = new Lazy<decimal>(() => sr[1, 0].Value * edD);
sr[1, 5] = new Lazy<decimal>(() => sr[2, 0].Value + sr[2, 5].Value);

sr[2, 0] = new Lazy<decimal>(() => eNumber * rRate);
sr[2, 4] = new Lazy<decimal>(() => sr[2, 0].Value * hdD);
sr[2, 5] = new Lazy<decimal>(() => sr[1, 5].Value);

sr[3, 1] = new Lazy<decimal>(() => sr[2, 5].Value);

sr[4, 2] = new Lazy<decimal>(() => eNumber * (ePc / 100) + sr[2, 0].Value * (hlPc / 100) - sr[3, 1].Value);

sr[5, 0] = new Lazy<decimal>(() => (sr[0, 0].Value + sr[1, 0].Value + sr[2, 0].Value) / ePerR);
sr[5, 2] = new Lazy<decimal>(() => sr[5, 0].Value / rLifecycle);
sr[5, 4] = new Lazy<decimal>(() => sr[5, 2].Value);
sr[5, 5] = new Lazy<decimal>(() => sr[5, 0].Value + sr[5, 2].Value - sr[5, 4].Value);

但是我得到以下错误
ValueFactory 试图访问此实例的 Value 属性。

谷歌搜索错误返回了一堆垃圾搜索类型的网站。

马可

最佳答案

看看惰性求值:

var table = new Lazy<int>[2, 2];

table[0, 0] = new Lazy<int>(() => table[1, 1].Value * 2);
table[0, 1] = new Lazy<int>(() => 42);
table[1, 0] = new Lazy<int>(() => 100);
table[1, 1] = new Lazy<int>(() => table[0, 1].Value + table[1, 0].Value);

for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
{
    Console.WriteLine("Row = {0}  Column = {1}  Value = {2}",
                             i,            j,           table[i, j].Value);
}

注意表格单元格的内容是如何以任意顺序定义的。只要单元格之间没有循环依赖关系,它就会自行计算顺序。

输出:

Row = 0  Column = 0  Value = 284
Row = 0  Column = 1  Value = 42
Row = 1  Column = 0  Value = 100
Row = 1  Column = 1  Value = 142

It becomes slightly more readable with LINQ-to-Lazy:

var table = new Lazy<int>[2, 2];

table[0, 0] = from t in table.AsLazy()
              from x in t[1, 1]
              select 2 * x;
table[0, 1] = 42.AsLazy();
table[1, 0] = 100.AsLazy();
table[1, 1] = from t in table.AsLazy()
              from a in t[0, 1]
              from b in t[1, 0]
              select a + b;

使用

static class LazyExtensions
{
    public static Lazy<TResult> SelectMany<TSource, TCollection, TResult>(this Lazy<TSource> source, Func<TSource, Lazy<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
    {
        return new Lazy<TResult>(() => resultSelector(source.Value, collectionSelector(source.Value).Value));
    }

    public static Lazy<TSource> AsLazy<TSource>(this TSource value)
    {
        return new Lazy<TSource>(() => value);
    }
}

.NET 4.0 的自定义替换 Lazy<T> Class :

sealed class MyLazy<T>
{
    private readonly Func<T> valueFactory;
    private T value;
    private bool valueCreated;

    public MyLazy(Func<T> valueFactory)
    {
        if (valueFactory == null)
        {
            throw new ArgumentNullException("valueFactory");
        }
        this.valueFactory = valueFactory;
    }

    public bool IsValueCreated
    {
        get { return this.valueCreated; }
    }

    public T Value
    {
        get
        {
            if (!this.valueCreated)
            {
                this.value = this.valueFactory();
                this.valueCreated = true;
            }
            return this.value;
        }
    }
}

关于c# - 在 C# 中计算值的数组(从 Excel 转换公式),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3712954/

相关文章:

c# - 手动添加参数?

将普通旧 CLR 对象序列化为 JSON 的 C# 代码

c# - 属性/方法内联和对反射的影响

c# - Entity Framework 6 - 多个 DefaultConnectionFactory?

excel - 计算单元格中的特定字符数 - Excel

mysql - 使用 "MySQL for Excel plugin"从 Excel 导出到 MySQL 非常慢

excel - 是否可以根据在 Excel 中过滤源表中的行来过滤数据透视表使用的数据?

c - 如何创建可变大小的数组,将可变二维数组传递给函数并返回另一个二维数组?

javascript - 如何在电子表格的 Google Apps 脚本中使用数组作为自定义函数的参数

javascript - 如何在二维数组中找到字符串?