通过引用的部分数组

2024-04-21

我的问题很简单:是否可以像在 C++ 中那样,通过引用检索 VBA 中数组的两个部分?自从我用 C++ 编写代码以来已经有一段时间了,所以我不太记得我现在是怎么做的。如果我记得的话,也许我会举个例子。

我想做的是按单个 Double 类型属性对对象数组进行排序。我以前用C++做过,只是没有源代码了。

我怀疑是否有一个预定义的函数可以用于此目的,但如果有人知道更好的解决方案,它将受到极大的欢迎。 ;)

这基本上就是我想要的:

source array(0, 1, 2, 3, 4, 5)

split source array in two
array a(0, 1, 2)
array b(3, 4, 5)

set array a(0) = 4
array a(4, 1, 2)
array b(3, 4, 5)
source array(4, 1, 2, 3, 4, 5)

当然这只是一个抽象的描述。

如果已经有一个与此相关的问题,我很抱歉,但我还没有找到它。


Note:代码已更新,原始版本可以在修订记录 https://stackoverflow.com/posts/11713643/revisions(并不是说找到它很有用)。更新后的代码不依赖于未记录的GetMem*功能并与 Office 64 位兼容。

是的你可以。你必须构建一个安全阵列 http://msdn.microsoft.com/en-us/library/windows/desktop/ms221482(v=vs.85).aspx但是手动描述符,以便它指向原始数组数据的子集。

Module:

Option Explicit

#If VBA7 Then
  Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef source As Any, ByVal length As LongPtr)
  Private Declare PtrSafe Function SafeArrayAllocDescriptor Lib "oleaut32" (ByVal cDims As Long, ByVal ppsaOut As LongPtr) As Long
  Private Declare PtrSafe Function SafeArrayDestroyDescriptor Lib "oleaut32" (ByVal psa As LongPtr) As Long
#Else
  Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef source As Any, ByVal length As Long)
  Private Declare Function SafeArrayAllocDescriptor Lib "oleaut32" (ByVal cDims As Long, ppsaOut As Any) As Long
  Private Declare Function SafeArrayDestroyDescriptor Lib "oleaut32" (psa As Any) As Long
#End If


Private Const VT_BYREF As Long = &H4000&
Private Const S_OK As Long = &H0&


' When declared in this way, the passed array is wrapped in a Variant/ByRef. It is not copied.
' Returns **SAFEARRAY, not *SAFEARRAY
#If VBA7 Then
Private Function ppArrPtr(ByRef arr As Variant) As LongPtr
#Else
Private Function ppArrPtr(ByRef arr As Variant) As Long
#End If
  'VarType lies to you, hiding important differences. Manual VarType here.
  Dim vt As Integer
  CopyMemory ByVal VarPtr(vt), ByVal VarPtr(arr), Len(vt)

  If (vt And vbArray) <> vbArray Then
    Err.Raise 5, , "Variant must contain an array"
  End If

  'see https://msdn.microsoft.com/en-us/library/windows/desktop/ms221627%28v=vs.85%29.aspx
  If (vt And VT_BYREF) = VT_BYREF Then
    'By-ref variant array. Contains **pparray at offset 8
    CopyMemory ByVal VarPtr(ppArrPtr), ByVal VarPtr(arr) + 8, Len(ppArrPtr)  'pArrPtr = arr->pparray;
  Else
    'Non-by-ref variant array. Contains *parray at offset 8
    Err.Raise 5, , "The array must be passed by reference."
  End If
End Function

#If VBA7 Then
Public Function CreateSAFEARRAY(ByRef BlankArray As Variant, ByVal ElemSize As Long, ByVal pData As LongPtr, ParamArray Bounds()) As LongPtr
#Else
Public Function CreateSAFEARRAY(ByRef BlankArray As Variant, ByVal ElemSize As Long, ByVal pData As Long, ParamArray Bounds()) As Long
#End If

 'ParamArray Bounds describes desired array dimensions in VB style
 'bounds(0) - lower bound of first dimension
 'bounds(1) - upper bound of first dimension
 'bounds(2) - lower bound of second dimension
 'bounds(3) - upper bound of second dimension
 'etc

  If (UBound(Bounds) - LBound(Bounds) + 1) Mod 2 Then Err.Raise 5, "SafeArray", "Bounds must contain even number of entries."

#If VBA7 Then
  Dim ppBlankArr As LongPtr
#Else
  Dim ppBlankArr As Long
#End If

  ppBlankArr = ppArrPtr(BlankArray)

  If SafeArrayAllocDescriptor((UBound(Bounds) - LBound(Bounds) + 1) / 2, ByVal ppBlankArr) <> S_OK Then Err.Raise 5

  CopyMemory ByVal VarPtr(CreateSAFEARRAY), ByVal ppBlankArr, Len(CreateSAFEARRAY)  ' CreateSAFEARRAY = *ppBlankArr
  CopyMemory ByVal CreateSAFEARRAY + 4, ByVal VarPtr(ElemSize), Len(ElemSize)       ' CreateSAFEARRAY->cbElements = ElemSize
  CopyMemory ByVal CreateSAFEARRAY + 12, ByVal VarPtr(pData), Len(pData)            ' CreateSAFEARRAY->pvData = pData

  Dim i As Long

  For i = LBound(Bounds) To UBound(Bounds) - 1 Step 2
    If Bounds(i + 1) - Bounds(i) + 1 > 0 Then
      Dim dimensions_data(1 To 2) As Long
      dimensions_data(1) = Bounds(i + 1) - Bounds(i) + 1
      dimensions_data(2) = Bounds(i)

      CopyMemory ByVal CreateSAFEARRAY + 16 + (UBound(Bounds) - i - 1) * 4, ByVal VarPtr(dimensions_data(LBound(dimensions_data))), Len(dimensions_data(LBound(dimensions_data))) * 2 ' CreateSAFEARRAY->rgsabound[i] = number of elements, lower bound
    Else
      SafeArrayDestroyDescriptor ByVal CreateSAFEARRAY
      CreateSAFEARRAY = 0
      CopyMemory ByVal ppBlankArr, ByVal VarPtr(CreateSAFEARRAY), Len(ppBlankArr) ' ppBlankArr = NULL (because CreateSAFEARRAY is now 0)
      Err.Raise 5, , "Each dimension must contain at least 1 element"
    End If
  Next
End Function

Public Sub DestroySAFEARRAY(ByRef ManualArray As Variant)
#If VBA7 Then
  Dim ppManualArr As LongPtr
  Dim pManualArr As LongPtr
#Else
  Dim ppManualArr As Long
  Dim pManualArr As Long
#End If

  ppManualArr = ppArrPtr(ManualArray)
  CopyMemory ByVal VarPtr(pManualArr), ByVal ppManualArr, Len(pManualArr)  ' pManualArr = *ppManualArr

  If SafeArrayDestroyDescriptor(ByVal pManualArr) <> S_OK Then Err.Raise 5

  pManualArr = 0 ' Simply to get a LongPtr-sized zero
  CopyMemory ByVal ppManualArr, ByVal VarPtr(pManualArr), Len(ppManualArr)  'ppManualArr = NULL
End Sub

Usage:

Dim source(0 To 5) As Long
source(0) = 0: source(1) = 1: source(2) = 2: source(3) = 3: source(4) = 4: source(5) = 5

Dim a() As Long
Dim b() As Long

CreateSAFEARRAY a, 4, VarPtr(source(0)), 0, 2
CreateSAFEARRAY b, 4, VarPtr(source(3)), 0, 2

MsgBox b(0)

a(0) = 4

DestroySAFEARRAY a
DestroySAFEARRAY b

MsgBox source(0)

确保在原始数组变量被以下任一方法破坏之前手动销毁子数组Erase或超出范围。


但是,通过引用子例程传递整个数组并提供开始处理的索引号可能会更简单。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

通过引用的部分数组 的相关文章

  • 将范围内的每个值乘以常数,但跳过空白单元格

    我需要一个简单快速的解决方案 用于将范围内的所有值乘以 VBA 代码中的数值 我知道这个解决方案 将整个范围乘以值 https stackoverflow com questions 18990541 multiply entire ran
  • Python:对这个字典进行排序(字典中的字典)

    d a k 1 b whatever b k 2 b sort by k 想要在 python 中按 k 降序对这个字典进行排序 有点棘手 请帮忙 dicts 是无序的 所以没有办法直接对它们进行排序 但如果你是 愿意转换dict进入 键
  • 在 Excel 表格中选择多列的代码

    我是 Excel VBA 新手 我需要修改我的代码 以便我能够进一步进行 我想在 Excel 表格中选择多个表格列 这是我的代码 Dim ws As Worksheet Dim tbl As ListObject Set ws Sheets
  • VBA Shell 并等待退出代码

    我正在打包一个办公应用程序 VBA 它调用 C 控制台应用程序来执行应用程序 大型模拟程序 的一些繁重工作 我希望能够让 VBA 应用程序等待控制台应用程序完成并从控制台应用程序检索退出代码 我已经能够做到前者 但尚未能够从应用程序中检索退
  • C++ 返回值、引用、const 引用

    你能向我解释一下返回值 值引用和值常量引用之间的区别吗 Value Vector2D operator const Vector2D vector this gt x vector x this gt y vector y return t
  • 使用 php 在多维数组中按键排序[重复]

    这个问题在这里已经有答案了 可能的重复 在 PHP 中对多维数组进行排序 https stackoverflow com questions 2059255 sorting multidimensional array in php 如何在
  • VBA 完成 Internet 表单

    我正在寻找将 Excel 中的值放入网页的代码 Sub FillInternetForm Dim IE As Object Set IE CreateObject InternetExplorer Application IE naviga
  • 为什么我不能将一个非 const 指针传递给一个函数,该函数将以对 const 指针的引用作为其参数

    这是一个代码片段 希望能够传达我想要做的事情 void updatePointer const int i i int main int array 5 int arrayPtr array updatePointer arrayPtr r
  • 我可以获取VBA代码中的注释文本吗

    可以说我有以下内容 Public Sub Information TEST End Sub 有没有办法得到 TEST 结果 不知何故通过VBA 例如 在 PHP 中 有一个获取注释的好方法 这里有什么想法吗 编辑 应该有办法 因为像 MZ
  • VBA 中的匈牙利语好吗?

    我在 Net 中不使用匈牙利语 str int 前缀 但我仍然发现它在 VBA 中很有用 因为在 VBA 中很难看到类型 这很糟糕吗 不必要 也许我错过了一些东西 我真的很感激任何反馈 我想知道有一段时间了 谢谢大家 我想说 这种匈牙利符号
  • 在Excel中,我可以使用超链接来运行vba宏吗?

    我有一个包含多行数据的电子表格 我希望能够单击一个单元格 该单元格将使用该行中的数据运行宏 由于行数总是在变化 我认为每行的超链接可能是最好的方法 ROW MeterID Lat Long ReadX ReadY ReadZ CoeffA
  • 获取当前 VBA 函数的名称

    对于错误处理代码 我想获取发生错误的当前 VBA 函数 或子函数 的名称 有谁知道如何做到这一点 编辑 谢谢大家 我曾希望存在一个未记录的技巧来自行确定函数 但这显然不存在 我想我会保留当前的代码 Option Compare Databa
  • 在 Excel 中使用 VBA 设置图像透明度

    有没有办法使用 VBA 脚本对图像应用一些透明度 我录制了一个 宏 但似乎没有录制艺术效果 我已经找到了如何制作形状 但没有找到图像 这需要几个步骤 将自选图形 如矩形 放置在工作表上 使用以下方法将您的实际图片嵌入矩形中 ShapeRan
  • 如何按键中的值对 Redis 哈希进行排序

    Redis 有没有一种好方法来获取按值排序的哈希中的键 我查看了文档 但没有找到直接的方法 另外有人可以解释一下redis中的排序是如何实现的 以及什么吗 本文档 http redis io commands SORT using hash
  • 使用 XMLHTTP 进行抓取会在特定类名处引发错误

    我正在尝试使用此代码抓取网站以提取姓名和联系人 Sub Test Dim htmlDoc As Object Dim htmlDoc2 As Object Dim elem As Variant Dim tag As Variant Dim
  • 在 PHP 中,有人可以解释克隆与指针引用吗?

    首先 我了解编程和对象 但以下内容对我来说 PHP 没有多大意义 在 PHP 中 我们使用 运算符来检索对变量的引用 我将引用理解为用不同变量引用相同 事物 的一种方式 如果我说例如 b 1 a b a 3 echo b 将输出 3 因为对
  • 在工作表中合并行和求和值

    我有一个 Excel 工作表 其中包含以下数据 管道 来分隔列 A B C X 50 60 D E F X 40 30 A B C X 10 20 A B C Y 20 20 A B C X 20 70 D E F X 10 50 A B
  • 使用宏从 Excel 电子表格中删除任何非指定字符

    我正在尝试通过删除任何非标准字符来清理 Excel 中的 CSV 文件 我唯一关心保留的字符是 A Z 0 9 和一些标准标点符号 任何其他字符 我想删除 当它找到包含我未指定的任何字符的单元格时 我已经得到了以下宏来删除整行 但我不确定如
  • 通过引用传递时取消引用指针

    当通过引用传递给函数时取消引用指针时会发生什么 这是一个简单的例子 int returnSame int example return example int main int inum 3 int pinum inum std cout
  • 从给定的项目列表创建子列表

    我首先要说的是以下问题不是为了家庭作业目的即使因为我几个月前就完成了软件工程师的工作 无论如何 今天我正在工作 一位朋友向我询问了这个奇怪的排序问题 我有一个包含 1000 行的列表 每行代表一个数字 我想创建 10 个子列表 每个子列表都

随机推荐

  • Laravel 5 重写异常处理程序

    我想知道是否可以重写 Laravel 5 中的应用程序异常处理程序类 而不将其扩展到另一个类 也许更好的说法是我想要它 这样就不会App Exceptions Handler将在异常时调用 但是我自己的处理程序之一 提前致谢 正如 Digi
  • 在 oauth2 SignedJwtAssertionCredentials 中获得“invalid_grant”

    我正在尝试在服务器到服务器 JSON API 场景中创建 oauth2 access token 但它因 invalid grant 错误而失败 请帮助 from oauth2client client import SignedJwtAs
  • 如何检测前置摄像头放置在设备上的位置?

    有什么方法可以检测 Android 设备上前置摄像头的放置位置吗 我认为在手机上它总是在它的顶部 靠近耳机 但所有平板电脑都是不同的 我检查了华硕 Transformer 前置摄像头位于侧面 如果我以横向模式握住它 则位于顶部 但三星 Ga
  • 如何使用 EPPlus 移动工作表?

    需要什么命令EPPlus 移动工作簿中的工作表位置 我找不到任何适用于 EPPlus 互操作的移动命令 有四种移动工作表的方法 他们是 excelPackage Workbook Worksheets MoveAfter excelPack
  • 我想让图像全屏显示,直到滚动

    这是我尝试将此全屏图像应用到的页面 http www alexwiley co uk portfolio http www alexwiley co uk portfolio 我希望使图像显示 100 宽度和 100 高度 直到向下滚动 然
  • ASP.NET:Server.Execute() 中的 BOM

    我用它来写入响应流 using var writer new StringWriter context Server Execute virtualpath writer string s writer ToString Replace c
  • C++ 中的表达式必须有常量值错误[重复]

    这个问题在这里已经有答案了 可能的重复 有没有办法用非常量变量初始化数组 C https stackoverflow com questions 972705 is there a way to initialize an array wi
  • ViewPager中多个Fragment之间的通信对象

    我有 5 个片段ViewPager用于逐步用多个字段填充业务对象 在每一步中都会设置其中一些字段 我读过很多关于片段之间通信的文章 但我对其他人喜欢的方式感到不舒服 所以在考虑我应该如何在我的情况下做到这一点之后 最后我开始考虑使用所有片段
  • Jenkins中的日志解析规则

    我正在使用 Jenkins 日志解析器插件来提取并显示构建日志 规则文件看起来像 Compiler Error error i error Compiler Warning warning i warning 一切正常 但由于某些原因 在
  • 时间:2019-03-17 标签:c#makeShowItemToolTipssticky

    我有一个 ListView 其中几个项目的文本超出了列宽 ShowItemToolTips 意味着我可以将鼠标悬停在列上并查看全文 这很棒 然而 对于很长的文本 它会在有时间阅读所有内容之前消失 所以我想让它保持更长时间 或者可能直到手动关
  • 通过“递归”策略进行合并

    我知道 git merge 递归实际上发生在有超过 1 个共同祖先的情况下 并且它将创建一个虚拟提交来合并这些共同祖先 然后再继续合并最近的提交 抱歉 我不确定是否应该有一个术语这 但我一直在尝试查找有关 git merge 递归策略实际如
  • 如何从所有应用程序加载 Django 装置?

    我在 Django 应用程序中使用固定装置 但只有两个应用程序加载了固定装置 当我使用 verbosity 2 手动运行 loaddata 时 我可以看到它只在两个应用程序中查找 尽管我在内部创建了更多的固定装置目录 所有应用程序均已正确安
  • django get_or_create 返回错误:“tuple”对象没有属性

    我是 django 新手 我正在尝试使用 get or create 模型函数 但即使我的模型中有该属性 我也会收到错误 AttributeError at professor adicionar compromisso tuple obj
  • 创建自定义颜色集 TinyMCE

    我已经能够为 TinyMCE 创建自己的字体颜色选择器 但是调色板链接到原始颜色选择器 我想做的是使我的自定义颜色选择器完全独立于原始颜色选择器 这样我可以同时显示两者 这是我当前的代码 这可以工作 但是两个按钮的调色板是相同的 tinym
  • Accept_nested_attributes_for :allow_destroy, :_destroy 不起作用

    我有一个 Rails 4 1 应用程序 它使用了一些值得注意的技术 简单的形式 茧 我在销毁嵌套属性的记录时遇到问题 基于一些冗长的研究 我相信我的代码是正确的 但是我可能遗漏了一些愚蠢的东西 Model has many staff se
  • 具有固定键的字典上的多线程

    我有一本带有固定键集合的字典 是我在程序开始时创建的 后来 我有一些线程用值更新字典 一旦线程启动 就不会添加或删除任何对 每个线程都有自己的密钥 意义 只有一个线程会访问某个键 该线程可能更新值 问题是 我应该锁定字典吗 UPDATE 谢
  • jQuery 的元素或类喜欢选择器?

    无论出于何种原因 我将这些课程称为 main sub1 main sub2等等 别介意为什么我不能拥有 main sub 有没有一种方法可以用 jQuery 来获取包含属性的类 main Using class main 将选择其类名的所有
  • wso2 svn 更新 - E205011:处理一个或多个外部定义时发生故障

    我在尝试着svn update4 0 0平台分支 却屡次碰到错误 E205011 Failure occurred processing one or more externals definitions My svn info outpu
  • 将字符串作为指针或文字传递时,strcmp() 返回值不一致

    我正在玩strcmp当我注意到这一点时 这是代码 include
  • 通过引用的部分数组

    我的问题很简单 是否可以像在 C 中那样 通过引用检索 VBA 中数组的两个部分 自从我用 C 编写代码以来已经有一段时间了 所以我不太记得我现在是怎么做的 如果我记得的话 也许我会举个例子 我想做的是按单个 Double 类型属性对对象数