【问题标题】:Does Replace$() function exist in Microsoft Access?Microsoft Access 中是否存在 Replace$() 函数?
【发布时间】:2016-12-27 12:23:17
【问题描述】:

它有效,但未在此处列出:
https://msdn.microsoft.com/en-us/library/office/gg278535.aspx
... > Office 共享 > Office VBA 语言参考 > Visual Basic 概念主题
从函数返回字符串

在 VBA 编辑器中:
(视图) - 对象浏览器 - VBA - 字符串

这个功能在很多论坛都有讨论,所以人们使用它。

【问题讨论】:

  • 所以你说它有效然后问它是否存在?没有存在怎么可能工作?看来您的问题更像是“为什么没有记录在案”,然后是微软要回答的问题。但是为什么要打扰呢?这些$ 函数是过去的遗物,现在不再使用无美元函数没有任何可行的论据。
  • @trincot - 这实际上是不正确的 - $一些 返回一个强类型的 String 而不是 Variant。如果您将返回值分配给 String,则使用不带 $ 的变体会创建隐式转换。

标签: vba ms-access dollar-sign


【解决方案1】:

您的问题的答案取决于您所说的“...存在于 Access 中”的含义。如果我们在 Access 的 VBA 开发环境中打开一个即时窗口并运行

?Replace$("I like tofu!", "tofu", "bacon")

我们得到

I like bacon!

很明显,Replace$ 函数确实“存在”在 Access 本身中。但是,如果我们尝试在来自外部应用程序(例如 VBScript、.NET、...)的 Access 数据库查询中使用 Replace$,我们将得到

Undefined function 'Replace$' in expression.

更令人困惑的是,较旧的“Jet”ODBC/OLEDB 驱动程序不支持Replace 函数(没有美元符号),但较新的“ACE”ODBC/OLEDB 驱动程序支持。 (两种风格都不支持Replace$。)所以像

这样的查询
SELECT Replace([Name], 'Gordon ', 'Gord ') AS newName FROM ...

如果我们使用 ODBC 驱动程序就可以工作

Driver={Microsoft Access Driver (*.mdb, .accdb)}

但如果我们使用

Driver={Microsoft Access Driver (*.mdb)}

【讨论】:

  • 但是是什么原因,这个函数没有在文档中列出。上述驱动程序的行为不一致?
  • 如果我没记错的话,它在 Access 2002 (10) 中的 SQL 中工作,但在某些较新的 Access 运行时中不再工作。
  • @darekk - 我无法说明为什么Replace$ 没有出现在您引用的页面的列表中;这可能只是一个无意的遗漏。至于运行时行为,如果较新的 Access 运行时无法支持有效的 VBA 函数,我会感到非常惊讶。
  • 关于运行时的 SQL - 它不是 Replace$(),而是运行时 2010 中的 Len$()(但不是 Access 2002):3085 - 表达式中未定义函数 'Len$'.. 但是这样功能没有意义。 Trim$() 在 SQL 中返回了一次对象(--> Criteria Expression 中的数据类型不匹配),但我不记得具体情况,也许那是我的错误。
  • 为什么any SQL 提供程序会调用 VBA 字符串函数?我无法想象 ACE 驱动程序正在使用 vbe7.dll 来处理 SQL 函数 REPLACEJet might be a different story,但旧版本因此存在 大量 安全漏洞。 IIR,后续版本关闭了它们。
【解决方案2】:

VBA.Strings 模块中的函数在 VBA 内部处理它们的方式上是“特殊的”。对于它们中的大多数,类型库中实际上有 2 个版本 - 一个返回 String(以 $ 结尾)的版本,以及一个返回 Variant 的版本。这些在内部被声明为一对函数 - 例如,Right(来自 vbe7.dll 类型库):

[entry(618), helpcontext(0x000f6ea5)]
BSTR _stdcall _B_str_Right(
                [in] BSTR String, 
                [in] long Length);

[entry(619), helpcontext(0x000f656e)]
VARIANT _stdcall _B_var_Right(
                [in] VARIANT* String, 
                [in] long Length);

编译器显然在内部将$ 视为“类型提示”,因为(使用上面的示例)实际上没有函数@ 987654328@ 在 TypeLib 中定义。事实上,也没有声明为VBA.Strings.Right 的函数。它们存在于名为_HiddenInterface 的特殊受限界面中:

[
  odl,
  uuid(1E196B20-1F3C-1069-996B-00DD010EF676)
]
interface _HiddenInterface {
    ...
    [restricted, helpcontext(0x000f6d7c)]
    void _stdcall Right();
    ...
};

请注意,Right$ 不会出现在 _HiddenInterface 中,也不会出现任何其他字符串返回函数。 VBA 编译器使用“函数类型提示”将函数调用转发到_B_str_Right_B_var_Right

现在您可能想知道这与您的问题有什么关系。答案是Replace 实际上没有 有两种不同的内部表示。它总是返回一个字符串,在_HiddenInterface 上不存在,直接存在于VBA.Strings 模块中:

[entry(712), helpstring("Find and replace a substring within a string"), helpcontext(0x000f6522)]
BSTR _stdcall Replace(
                [in] BSTR Expression, 
                [in] BSTR Find, 
                [in] BSTR Replace, 
                [in, optional, defaultvalue(1)] long Start, 
                [in, optional, defaultvalue(-1)] long Count, 
                [in, optional, defaultvalue(0),
  custom(270D72B0-FFB8-11CF-A4BD-00A0C90F26EE, 1)

] VbCompareMethod Compare);

基本上,根本没有Replace$ 函数。 VBA 将$ 视为返回值 的类型提示(无论如何它始终是String)。就 ODBC 和 OLE 驱动程序而言,我想(TBH 我真的没有仔细研究过)它们仅限于由 TypeLib 公开的名称并且解释由 VBA 运行时转发给不同的函数。如果您在 vbe7.dll 上进行 IDispatch 查找,它们根本就不存在。

【讨论】:

  • 所以 Replace$ 被视为 Replace 的替代名称,并且在后台没有像 Replace$ 这样的功能,内部?因为 Replace$ 触发与 Replace 相同的操作?我怀疑是这样的。
  • @darekk - 差不多。 VBA 中的$ 语法实现在所有意图和目的上都是一个hack。我怀疑这是在将 VB 纳入 Office 之前的一些非常古老的兼容性要求的遗留问题。我设想它类似于 1.) 检查标识符是否具有$。 2.) 检查函数是否有 Variant 返回实现。 3.) 如果是,则重定向到相应的函数,如果不是,则调用该函数本身。
猜你喜欢
  • 2020-06-01
  • 1970-01-01
  • 2019-01-26
  • 1970-01-01
  • 1970-01-01
  • 2017-07-11
  • 2021-01-21
  • 1970-01-01
  • 2020-07-14
相关资源
最近更新 更多