c# - Excel ExcelDNA C#/尝试复制 Bloomberg BDH() 行为(在网络请求后写入数组)

标签 c# .net excel excel-dna

我想复制 Bloomberg BDH 行为。

BDH 发出网络请求并写入数组(但不返回数组样式)。在此 Web 请求期间,该函数返回“#N/A Requesting”。 Web 请求完成后,BDH() 函数将数组结果写入工作表。

例如,在ExcelDNA中,我成功地在工作表中写入了一个线程。

如果你在 DNA 文件中使用下面的代码,结果是

=写入数组(2;2)

会是

第 1 行 > #N/A 请求数据 (0,1)

第 2 行 > (1,0) (1,1)

最后一期是将#N/A Requesting Data替换为值并复制公式。 当您取消注释//xlActiveCellType.InvokeMember("FormulaR1C1Local", 您接近结果但您没有正确的行为

文件.dna

 <DnaLibrary Language="CS" RuntimeVersion="v4.0">
<![CDATA[

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using ExcelDna.Integration;


    public static class WriteForXL
    {

        public static object[,] MakeArray(int rows, int columns)
        {
            if (rows == 0 && columns == 0)
            {
                rows = 1;
                columns = 1;
            }


            object[,] result = new string[rows, columns];
            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < columns; j++)
                {
                    result[i, j] = string.Format("({0},{1})", i, j);
                }
            }

            return result;
        }

        public static object WriteArray(int rows, int columns)
        {
            if (ExcelDnaUtil.IsInFunctionWizard())
                return "Waiting for click on wizard ok button to calculate.";

            object[,] result = MakeArray(rows, columns);

            var xlApp = ExcelDnaUtil.Application;
            Type xlAppType = xlApp.GetType();
            object caller = xlAppType.InvokeMember("ActiveCell", BindingFlags.GetProperty, null, xlApp, null);
            object formula = xlAppType.InvokeMember("FormulaR1C1Local", BindingFlags.GetProperty, null, caller, null);

            ObjectForThread q = new ObjectForThread() { xlRef = caller, value = result, FormulaR1C1Local = formula };

            Thread t = new Thread(WriteFromThread);
            t.Start(q);            

            return "#N/A Requesting Data";
        }

        private static void WriteFromThread(Object o)
        {
            ObjectForThread q = (ObjectForThread) o;

            Type xlActiveCellType = q.xlRef.GetType();

            try
            {
                for (int i = 0; i < q.value.GetLength(0); i++)
                {
                    for (int j = 0; j < q.value.GetLength(1); j++)
                    {
                        if (i == 0 && j == 0)
                            continue;

                        Object cellBelow = xlActiveCellType.InvokeMember("Offset", BindingFlags.GetProperty, null, q.xlRef, new object[] { i, j });
                        xlActiveCellType.InvokeMember("Value", BindingFlags.SetProperty, null, cellBelow, new[] { Type.Missing, q.value[i, j] });             
                    }
                }                               
            }
            catch(Exception e)
            {                
            }
            finally
            {
                //xlActiveCellType.InvokeMember("Value", BindingFlags.SetProperty, null, q.xlRef, new[] { Type.Missing, q.value[0, 0] });
                //xlActiveCellType.InvokeMember("FormulaR1C1Local", BindingFlags.SetProperty, null, q.xlRef, new [] { q.FormulaR1C1Local });               
            }
        } 

public class ObjectForThread
        {
            public object xlRef { get; set; }
            public object[,] value { get; set; }
            public object FormulaR1C1Local { get; set; }
        }

    }

    ]]>

</DnaLibrary>

@To Govert

BDH 已成为金融行业的标准。人们不知道如何操作数组(甚至是 Ctrl+Shift+Enter)。

BDH 是使彭博社如此受欢迎的功能(而不是路透社)。

但是我会考虑使用您的方法或 RTD。

感谢您在 Excel DNA 中所做的所有工作

最佳答案

我想您已经尝试过 Excel-DNA ArrayResizer示例,它小心地避免了您遇到的许多问题。我想了解您认为数组公式编写方法的缺点是什么。

现在,关于您的函数:

首先,您不能安全地将“调用者”Range COM 对象传递给另一个线程 - 而是传递一个带有地址的字符串,然后从另一个线程获取 COM 对象(使用对 worker 的 ExcelDnaUtil.Application 的调用线)。不过,大多数时候你会很幸运。 更好的方法是从工作线程让 Excel 在主线程上运行宏——通过调用 Application.Run。 Excel-DNA ArrayResizer 示例展示了如何做到这一点。

其次,您几乎肯定不需要 ActiveCell,而是 Application.Caller。 ActiveCell 可能与运行公式的单元格无关。

接下来 - 每次您再次设置公式时,Excel 都会重新计算您的函数 - 因此,当您在 finally 子句中启用公式集时,您将陷入无限循环。 您不能同时为单元格设置值和公式 - 如果单元格具有公式,则 Excel 将使用该公式计算值。如果您设置值,公式将被删除。 目前尚不清楚你想在 [0,0] 单元格中实际留下什么 - IIRC Bloomberg 修改那里的公式,使其记住写入的范围有多大。您可以尝试向您的函数添加一些参数,告诉您的函数是重新计算还是返回实际值作为其结果。

最后,您可能需要重新考虑 Bloomberg BDH 函数是否是您想要执行的操作的一个很好的示例。它打破了工作表的依赖性计算,这对性能和保持电子表格模型的一致性都有影响。

关于c# - Excel ExcelDNA C#/尝试复制 Bloomberg BDH() 行为(在网络请求后写入数组),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9668649/

相关文章:

c# - 在 C# 中使用带有类名的 “this”

c# - 为什么编译器必须知道一个 lambda 的类型?

c# - 如何在不重启 AppDomain 的情况下在运行时将模块添加到 MVC4

c# - 如何强制使用 .Include 查询 Entity Framework 6 进行外部连接

vba - 当工作表更改时,变量未存储在代码中

c# - CUDA 设备中的内存分配不是预期的

.net - IL 中的 ldsfld 和 ldstr 有什么区别?

c# - 在不阻塞主线程的情况下运行代码

json - 数组的大小 excel - json vba 解析器

vba - 两次之间的倒计时器(不是日期)