在 excel 用户定义函数中使用工作表

gid*_*eon 5 excel vba excel-2003 user-defined-functions

我正在尝试编写的 VBA 相当简单,但我从未编写过 VBA 并且来自 Visual Studio 和 C# 世界,这真的是地狱!!

所以我真的很感激这里的任何帮助/指示/提示

替代文字

所以我有两个重要的表。范围表每个日期有 2 个值。它需要一个结果,Calc 表需要两个值,然后给我一个结果。

我想将每个日期的 Current 和 OneYear 值放入 Calc 表中,并将结果放入结果列中。

所以我尝试定义一个 UDF,但后来我了解到我无法修改 UDF 中的工作表内容。

我尝试录制一个宏,然后希望从那里开始,但我得到了这样的东西:

Range("A2").Select
Sheets("24Feb05-24FEB10").Select
Range("K9").Select
ActiveCell.FormulaR1C1 = "=Calc!R[-8]C[-10]"
Range("K9").Select
Run Code Online (Sandbox Code Playgroud)

我假设 R1C1 是行和列,但为什么它说 -8 和 -10!??

有人可以让我朝着正确的方向前进吗?

注意:大约有 2000 多个日期。

希望我的问题很清楚!


更新 我会澄清一些更多的事情:

大大简化了 Calc 表,实际上,它需要 5 个值(有列到 SixYears)然后该表调用了大约 4 个其他表,并进行了一些技术专家编写的财务计算。

我试图让财务人员用代数向我表达他在做什么,所以我可以编写一个 C# 函数。

我也试着写一个UDF,但就像我说的,它需要投入的价值和得到的结果,这意味着UDF将修改表

Function Func1(txt As Variant) As String
//Returns the nth element from a delimited text string
    Dim txt As String
    txt = text
   Sheet4.Cells(1, 1) = txt
   Func1 = Sheet4.Cells(2, 1)//get the result value'
End Function
Run Code Online (Sandbox Code Playgroud)

基本上,我在学习/理解 VBA 语法和 API 时头疼。

我正在寻找一个小例子,说明我如何将值从一张纸转换到另一张纸,然后取回其他一些值?也许在一个循环中!?

jto*_*lle 4

您可能使事情变得比您需要的更加复杂。作为一名程序员,我相信您会意识到,在学习新系统时,花一点时间借助 Google、“傻瓜”书籍等是值得的。Excel 强调一种与 C# 等截然不同的编程风格。

因此,这里有一些选项,从最简单、最符合 Excel 习惯的开始:

1)在结果列中使用公式。如果您想要进行的计算足够简单,那么这就是正确的选择。举一个简单的例子,假设您的计算只是将两个数字相加。你会把公式

=B2+C2
Run Code Online (Sandbox Code Playgroud)

到单元格 E2 中,然后将其向下拖动到 E 列。Excel 会知道要做什么并为 E3=B3+C3 等制作论坛。

仅使用公式您就可以做很多事情。Excel 具有许多内置的工作表函数,您可以在网络和书店中找到大量材料。

2)用VBA编写UDF并从结果列中调用它。UDF 是一种不会修改工作表中其他任何内容的函数。它只是根据输入参数计算结果。当公式中的某些操作过于复杂而无法执行时,或者想要在多个位置使用公式时,您需要编写 UDF。(请注意,将论坛拖过某个范围是 Excel 惯用的做法,出于 DRY 目的,也算作“一个位置”)。

因此,要编写 UDF(让我们使用加法示例,但您会编写更复杂的逻辑),您需要将这样的函数放入 VBA 代码模块中:

Public Function myUDF(current, oneYear)
    myUDF = current + oneYear
End Function
Run Code Online (Sandbox Code Playgroud)

然后你把公式

=myUDF(B2, C2)
Run Code Online (Sandbox Code Playgroud)

到单元格 E2 并将其向下拖动到 E 列。

请注意,在本例中我忽略了诸如错误处理之类的内容。这就是公式比 UDF 更“Excel”的原因之一。现在您必须开始编写与 Excel 的声明式函数风格不同的代码,这是一种不同的思维模型。

编辑:2.5)使用 Excel 数据表- 我很尴尬,我之前忘记了这一点,但是如果您恰好有一个或两个单元格是您的独立参数,并且恰好有一个单元格是您的结果,那么 Excel 有一个内置的 -您可以使用“假设”分析工具。“数据表”这个名字令人遗憾,因为这两个词的含义都太重了,但这就是它的名字。您告诉 Excel 您的输入和输出是什么,它就会执行您想要的操作。看:

http://office.microsoft.com/en-us/excel-help/calculate-multiple-results-by-using-a-data-table-HP010072656.aspx

这是该链接的小介绍:

数据表是一系列单元格,显示如何更改公式中的一个或两个变量(公式:单元格中的一系列值、单元格引用、名称、函数或运算符,它们一起生成新值。公式始终以带有等号 (=).) 将影响这些公式的结果。数据表提供了在一次操作中计算多个结果的快捷方式,以及在工作表上查看和比较所有不同变体的结果的方法。

3)编写一个使用计算表的宏,就像使用函数一样。如果该工作表上的逻辑非常复杂,并且转换为 VBA 太困难,因为它一直在变化,或者因为它是由不了解 VBA 且不熟悉的 Excel 用户开发的,那么您可能会这样做使用命令式编程。我不会提供代码,但伪代码可能如下所示:

Public Sub doCalc()
    'for each cell in the result column
        'copy the corresponding current and oneYear cells to the calc sheet
        'Excel will recalc the calc sheet
        'copy the result cell on the calc sheet back to the Range sheet in the right place
    'end
End Sub
Run Code Online (Sandbox Code Playgroud)

现在,这与“Excel 方式”相去甚远,因为您必须自己设置数据,然后运行宏。如果您返回并更改某些“输入”,则需要重新运行宏。(使用工作表事件,这可以在某种程度上自动化。)

很多刚接触 Excel 的程序员都会直接跳到这一步,将 Excel 降级为一个巨大的网格控件,而忽略了它存在的首要原因 - 自动重新计算。

编辑以回应有问题的其他信息:

好的,看起来情况 (3) 是合适的,因为您有一个复杂的工作表,不容易手动转换为 VBA 或 C# 代码。下面是一些(过度简化、硬编码、缺少 EH 等)代码,可让您更多地了解如何在 VBA 中执行此操作:

首先,有一个 VBA 宏,它假装它是一个 UDF。请注意,它是一个 Sub,而不是函数,并且您不能从公式中调用它。您可以调用子例程来响应用户执行的操作,例如选择菜单选项或按下命令按钮:

Public Sub fakeFunct(input1, input2, outputRng As Range)
    CalcSheet.[b1] = input1
    CalcSheet.[b2] = input2

    'Excel recalcs what's in cell B3 if you have it set to automatic recalcualation

    outputRng = CalcSheet.[b3]
End Sub
Run Code Online (Sandbox Code Playgroud)

在此示例中,“CalcSheet”是工作表模块的“代号”。(有关此内容的更多信息,请参阅 Chip Pearson 的优秀网站:http://www.cpearson.com/excel/codemods.htm

实际上,您可以从循环“输入”的另一个宏中调用上面的宏:

Public Sub loopFakeFunct()
    Dim i As Long
    For i = 2 To 2000
        Call fakeFunct(RangeSheet.Cells(i, 2), RangeSheet.Cells(i, 3), RangeSheet.Cells(i, 5))
    Next i
End Sub
Run Code Online (Sandbox Code Playgroud)

这是您为响应用户操作或从 Worksheet_Change 事件等而调用的内容。它会很慢且笨重,并且我将保留很多实用的 VBA 内容,但它应该足以让您入门。(我使用“RangeSheet”而不是“Range”作为工作表代码名称,以避免与 Range 类和 Excel 定义的 Application.Range 方法发生冲突。)

4)使用一些第三方工具将您的工作表转换为 UDF,然后您可以按照 (2) 中的方式调用该 UDF。有一些商业工具可以获取您的工作表,让您指定哪些单元格是输入和输出,然后生成 C++ 代码或任何可以编译到 XLL 插件中的代码。

5)等待微软这样做:

http://research.microsoft.com/en-us/um/people/simonpj/papers/excel/excel.htm

6)使用解析器一

http://www.resolversystems.com/products/resolver-one/

它有一个功能,允许您将整个工作簿用作另一个工作簿中的函数,或者我认为是任何 Python 代码中的函数。