在 vba 函数中绕过最大字符串大小?

Posted

技术标签:

【中文标题】在 vba 函数中绕过最大字符串大小?【英文标题】:Getting around the Max String size in a vba function? 【发布时间】:2010-03-25 15:12:18 【问题描述】:

您可以在 vba 函数中的字符串中使用的最大字符数为 255。 我正在尝试运行此功能

Var1= 1
Var2= 2
.
.
.
Var256 =256

RunMacros= "'Tims_pet_Robot """ & Var1 & """ , """ & Var2 & """ , """   ... """ & Var256 """ '"
Runat=TimeValue("15:00:00")
Application.OnTime EarliestTime:=Runat, Procedure:=RunMacros & RunMacros2 ', schedule:=True

它在某个时间运行一个过程并将一堆变量传递给它。但是字符串太长了。

更新: 遗憾的是,我确定这不是监视窗口。 此外,它并不是我正在处理的字符串的最大大小。这是最大尺寸 vba 函数中的字符串。

例如这个函数就起作用了。

Sub test()
Dim RunAt As Date
Dim RunWhat As String

RunAt = Now + 0.00001
RunWhat = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" & _
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" & _
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 'that makes 254 'a''s
Application.OnTime EarliestTime:=RunAt, Procedure:="'" & RunWhat & " 12'"

End Sub


Sub aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(m As Integer)
MsgBox ("it works!" & m)
End Sub

但是如果你把 12 改成 123 就坏了 示例

Sub test2()
Dim RunAt As Date
Dim RunWhat As String

RunAt = Now + 0.00001
RunWhat = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" & _
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" & _
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 'that makes 254 'a''s
Application.OnTime EarliestTime:=RunAt, Procedure:="'" & RunWhat & " 123'"

End Sub


Sub aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(m As Integer)
MsgBox ("it works!" & m)
End Sub

此代码不起作用,我很确定这是因为 vba 函数无法处理超过 255 个字符的字符串。 即使你在 Excel 中调用一个函数并给它一个长于 255 个字符的字符串,它也不起作用。

在单元格 A1 =vlookup("really long string", A1:Z10, 1) 中尝试,然后将非常长的字符串放在该范围内的某个位置。 vlookup 会失败(不是找不到,而是你实际上做不到)

我也知道子名称有一个最大长度,我就在它之下。对不起,它看起来很丑。

更新 2:所以我最终将变量打印到一张纸上,并让 ontime 调用的函数从纸上读取它们。 :(

【问题讨论】:

From Joel Spolsky(他领导了大部分早期的 Excel 开发):“Excel 在内部使用 Pascal 字符串,这就是为什么 Excel 中许多地方的字符串限制为 255 个字节的原因,这也是 Excel 的原因之一快得惊人。”这可能适用于您提到的 VLookup 问题,尽管正如其他人所说,VBA 没有这样的限制。 您可以使用String(number_of_repeats, char_to_repeat) 来即时创建字符串,而不是aaaaaaaaaaaaaaaaaaaaaaaaaaa... 【参考方案1】:

我可能在这里遗漏了一些东西,但是你为什么不能用所需的大小声明你的字符串呢?例如,在我的 VBA 代码中,我经常使用如下内容:

Dim AString As String * 1024

提供 1k 字符串。显然,您可以在 Excel 和可用内存等更大范围内使用您喜欢的任何声明。

在某些情况下这可能有点低效,您可能希望使用类似 Trim(AString) 的构造来消除任何多余的尾随空格。不过,它很容易超过 256 个字符。

【讨论】:

缓冲区溢出。【参考方案2】:

这样可以在消息框中显示超过 255 个字符。

Sub TestStrLength()
    Dim s As String
    Dim i As Integer

    s = ""
    For i = 1 To 500
        s = s & "1234567890"
    Next i

    MsgBox s
End Sub

消息框将字符串截断为 1023 个字符,但字符串本身可能非常大。

我还建议您使用数组,而不是使用带有数字的固定变量名称(例如Var1Var2Var3、...Var255)。这是更短的声明并且更易于使用 - 循环。

这是一个例子:

Sub StrArray()
Dim var(256) As Integer
Dim i As Integer
Dim s As String

For i = 1 To 256
    var(i) = i
Next i

s = "Tims_pet_Robot"
For i = 1 To 256
    s = s & " """ & var(i) & """"
Next i

    SecondSub (s)
End Sub

Sub SecondSub(s As String)
    MsgBox "String length = " & Len(s)
End Sub

对此进行了更新,以表明字符串可以超过 255 个字符,并以这种方式在子例程/函数中用作参数。这表明字符串长度为 1443 个字符。 VBA 中的实际限制是每个字符串 2GB。

也许您正在使用的 API 存在问题,并且对字符串有限制(例如固定长度的字符串)。问题不在于 VBA 本身。

好的,我发现问题出在 Application.OnTime 方法本身。它的行为类似于 Excel 函数,因为它们只接受长度不超过 255 个字符的字符串。 VBA 过程和函数虽然没有我所展示的这个限制。也许这个限制适用于任何内置的 Excel 对象方法。


更新: 将...longer than 256 characters... 更改为...longer than 255 characters...

【讨论】:

感谢您的回复。你是对的。 vba 中的函数可以处理高达 2 GB 的字符串!谢谢。但是当您意识到我真正的问题是 Application.OnTime 方法的行为类似于 Exel 函数时,它只能处理大小为 255 的字符串。我想我应该接受我将不得不处理这个限制?我希望有办法解决它。【参考方案3】:

你确定吗? This forum thread 建议它可能是您的监视窗口。尝试将字符串输出到 MsgBox,最多可以显示 1024 个字符:

MsgBox RunMacros

【讨论】:

255 个对象/字符是监视窗口的最大值。我过去遇到过与 Collection Object 相同的问题。 没有骰子。这不是监视窗口。错误在于 ontime 功能。见更新。感谢您的评论【参考方案4】:

这个测试表明 VBA 中的字符串至少可以有 10^8 个字符长。但是如果你把它改成 10^9 你就会失败。

Sub TestForStringLengthVBA()
    Dim text As String
    text = Space(10 ^ 8) & "Hello world"
    Debug.Print Len(text)
    text = Right(text, 5)
    Debug.Print text
End Sub

所以不要被中间窗口编辑器或 MsgBox 输出误导。

【讨论】:

我可以确认 Watches 窗口将截断显示 252 个字符的字符串变量,而使用 Immediate 窗口(使用 Debug.Print myvariable)将显示 > 252 个字符。虽然 OP 的问题可能与 Watches 窗口无关,但这种截断让我走上了一条浪费大量精力的道路(以及登陆这里!)所以我想我会插话。截断这样的 var 可能会让新手感到困惑到 VBA,它可能暗示问题出在其他地方,它确实是 Watches UI 的一个怪癖。【参考方案5】:

难道你不能让另一个 sub 充当调用者,使用模块级变量作为你想要传递的参数。比如……

Option Explicit
Public strMsg As String

Sub Scheduler()

    strMsg = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
    Application.OnTime Now + TimeValue("00:00:01"), "'Caller'"

End Sub

Sub Caller()

    Call aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa("It Works! " & strMsg)

End Sub

Sub aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(strMessage As String)

    MsgBox strMessage

End Sub

【讨论】:

【参考方案6】:

Excel 只显示 255 个字符,但实际上如果保存超过 255 个字符,要查看完整的字符串,请在即时窗口中查阅

Crl + G 并在即时窗口中输入 ?RunWhat 并按 Enter

【讨论】:

以上是关于在 vba 函数中绕过最大字符串大小?的主要内容,如果未能解决你的问题,请参考以下文章

Webshell免杀绕过waf

VBA编程中MsgBox函数怎么用

Excel vba 将数字转换成字符串的函数是哪个

VBA消息框(MsgBox)

绕过PHP代码执行中的过滤限制详解

SQL注入绕过总结