繁体   English   中英

Excel XLL 如何判断是否从公式栏中调用了 UDF?

[英]How can an Excel XLL tell if a UDF is being called from the formula bar?

我正在寻找一种方法来确定我的 XLL 中的调用是来自重新计算过程还是来自为单元格输入的新公式。 我已经看到了 XLL 可以检测是否从 Function 向导调用它的示例(通过检查 window class 等),但是如果它直接输入到单元格中呢?

在此处输入图像描述

我可以从 xlfCaller function 获取单元格的参考:

   XLOPER xlRef;
   Excel(xlfCaller, &xlRef, 0);

但这并没有让我走得太远。 我试图模仿 Excel 对 TODAY() function 的处理,如果直接在单元格中输入公式(而不是从另一个函数中粘贴或调用),它会更改单元格编号格式。

可以通过挂钩 SheetChange 事件来复制 TODAY() 行为的这一方面 - 这只会在输入公式时触发,而不是在重新计算时触发(即使使用 Ctrl-Alt-F9 也是如此)。 我不知道 TODAY() 是否使用这种方法,或者它可能使用了用户定义函数不可用的东西。 此外,复制 TODAY() 将需要解析公式并应用一些逻辑来确定它是否应用日期格式,这会有点棘手,但有一些 Excel 公式解析器在那里。

xlOil (免责声明:我写的)中,它可以实现为:

  XLO_FUNC_START(testToday())
  {
    CallerInfo caller;
    if (!caller.fullSheetName().empty()) // Check caller is worksheet
    {
      // Add a SheetChange handler
      auto handle = xloil::Event::SheetChange().bind(
        [=](const wchar_t* wsName, const Range& target)
        {
          // Need to check range here as well to avoid being triggered by another sheet change
          if (wsName == caller.sheetName())
            excelApp().Range[caller.writeAddress().c_str()]->NumberFormat = L"dd-mm-yyyy";
        }
      );
      // Wait 0.5 sec then unbind the event handler by queuing a window message with Excel
      auto milliSecsDelay = 500;
      excelPost([=]() mutable
      {
        handle.reset(); // Removes the SheetChange handler
      }, QueueType::WINDOW, 0, 0, milliSecsDelay);
    }

    // This is how to get the current date in C++
    std::tm buf; 
    auto now = std::time(0);
    localtime_s(&buf, &now);

    return returnValue(buf); // xlOil will convert the std::tm to an Excel date
  }
  XLO_FUNC_END(testToday);

这只是一个概念验证,可以进行一些整理,例如应该检查范围,如果多次调用 function,开销可能会非常大。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM