Excel xll 函数是否可以指示 return 值应显示为日期而不是数字?

Can an Excel xll function indicate that the return value should be displayed as a date and not a number?

Excel "dates" 是 double under the hood,XLOPER 结构似乎没有任何日期的概念,只有 xltypeNum(不像 VBA 中的 Variants)。

我有一个简单的 XLL,其函数不带参数 returns 今天的日期作为 LPXLOPER(类型“P”)。我还有其他功能,通常 return 日期但也可能 return 错误,这就是为什么我使用“P”作为 return 值而不是“B”的原因。

DLLEXPORT LPXLOPER WINAPI epToday()
{
    static XLOPER xResult;// Return value

    xResult.xltype = xltypeNum;
    xResult.val.num = ExcelDateForToday(); //A function that returns a double for today's date

    return &xResult;
}

return 值在调用电子表格中显示为数字(例如 40303)。我希望能够告诉 Excel 将我的 returned double 视为日期:与内置函数 TODAY() 的处理方式相同。有办法吗?

我看到 =TODAY() 将单元格 NumberFormat 更改为“日期”,我应该使用回调来更改调用单元格的格式吗?这似乎是 Excel 正在做的事情:例如,如果我使用 =TODAY() 函数重新计算一个单元格,它会再次将 NumberFormat 设置为 Date。

据我所知,遵循 TODAY() 通过回调设置日期格式的方法是向 Excel 表明您从 XLL 函数返回的值是一个日期。但是,它确实有一些缺点:

  1. 性能(对于大量调用,虽然我没有检查过)
  2. 如果调用者不是工作表则需要特殊处理
  3. =TODAY() - AnotherDate 做了错误的事情,但 Excel!
  4. 也是
  5. 将在每次重新计算时覆盖格式 - 如果首选其他格式,可能会惹恼用户

Excel 能够通过检测它是否作为计算周期的一部分被调用来神奇地避免 (4) - 我不知道如何在没有看到 [=31= 的情况下实现这一点] 源代码。您可以将您的函数包装在某种东西中以设置格式,这将为用户提供选择(或者撤消您的格式更改,因为回调将排在第二位),例如=SetFormat(MyToday(), "yyyy-mm-dd")

回调在 xlOil 中相当简单(免责声明:我写的):

  XLO_FUNC_START(testToday())
  {
    CallerInfo caller;
    if (!caller.fullSheetName().empty()) // Check caller is a worksheet
      excelPost([=] 
      {
        excelApp().Range[caller.writeAddress().c_str()]->NumberFormat = L"dd-mm-yyyy"; 
      });
    std::tm buf; 
    auto now = std::time(0);
    localtime_s(&buf, &now); // Slightly labourious to get current date in C++
    return returnValue(buf);
  }
  XLO_FUNC_END(testToday);