通过引用的部分数组

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(使用前将#替换为@)

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

  • Linux下对多个文件进行排序

    我有多个 很多 文件 每个都非常大 file0 txt file1 txt file2 txt 我不想将它们合并到一个文件中 因为生成的文件将超过 10 场演出 每个文件中的每一行都包含一个 40 字节的字符串 现在字符串的排序相当好 大约
  • 如何从 php 中的值数组中对特定字符串进行排序?

    array array 2011 September 38 2011 June 4 2010 November 9 2011 November 29 2010 December 19 我想按如下方式对这个数组字符串进行排序 它应该首先对年份
  • 使用 For Next 循环转换超过 500 行的日期格式

    我需要将 C 列中的日期 直到最后一行 从现有格式 24 01 2016 转换为 24 01 2016 结果必须采用日期格式 我当前的代码是 LastRow9 ws5 Cells Rows Count C End xlUp Row For
  • 调整 MailItem 中粘贴的 JPEG 的大小

    我正在尝试从 Excel 工作表发送图片 但尺寸非常小 我怎样才能获得合适的尺寸 基本上是整个屏幕 这是代码 Sub send as a pic Copy range of interest Dim r As Range Set r Ran
  • VBA Excel 提示用户选择默认文件夹中的文件

    我想提示用户在默认文件夹中打开 Excel 文件 我不知道如何打开默认文件夹 Sub Program1 DefaultFolder C user dump FName Application GetOpenFilename If FName
  • 查找使用连接的位置 Excel VBA

    我有大量需要优化的 Excel 2013 工作簿 每个工作簿都有多个工作表和多个数据连接 我正在寻找一种快速列出的方法 连接名称 连接字符串 使用连接的位置 工作表名称或范围很有用 我可以在连接对话框中看到所有这些信息 但无法以编程方式跟踪
  • 从数据集中提取唯一的产品 ID 和相应的其他列值到新工作表

    我有一个宏 可以从 A 列 中提取唯一数据 但我也希望从 A 列中的这些唯一值的其他列中获取相应的值 并且我希望它们位于不同的电子表格中 我尝试在代码中使用 Worksheet Vlookup 函数 但对于超过 70 000 行和 42 列
  • Excel 2007 Visual Basic 编辑器:占用空格,四处移动光标

    我无法解决这个问题 我发现了类似的问题here https stackoverflow com questions 1164138 vba editor auto deletes spaces at the ends of lines bu
  • JavaScript 排序列表

    Javascript 或 jQuery 中有排序列表吗 我有一个巨大的列表 随着时间的推移 插入操作很少 每次添加单个项目时 我无法为整个列表调用 object sort 我需要插入 o log n 不 没有 你拥有的只是Array sor
  • 如何在 excel 2007 vba 中以编程方式对一组形状进行分组?

    我正在迭代电气表表上的数据并在形状表上创建形状 创建形状后 我想以编程方式对它们进行分组 但是我无法找出正确的语法 形状就在那里 被选中 如果我单击分组按钮 它们就会完美分组 但是通过下面的代码我得到 运行时错误 438 对象不支持此方法或
  • 如何在vba中向形状添加点或节点?

    I am trying to add points or nodes to a shape so instead of having 4 points I can have more 这是我添加形状的代码 Set shap2 w Shape
  • 为什么链接生命周期仅与可变引用相关?

    前几天 有一个问题 https stackoverflow com questions 32089410 lifetimes and references to objects containing references有人对包含借用数据本
  • 关于合并排序代码中的组合步骤的困惑

    我有一个关于数组上的合并排序如何工作的问题 我理解 划分 步骤 它将输入数组划分为 1 长度的元素 然而 当谈到 合并 部分 组合步骤 时 我感到困惑 例如 给定输入 3 5 1 8 2 除法过程将产生 5 个元素 3 5 1 8 2 我只
  • Java 按日期作为字符串对列表 进行排序

    我有一个类型列表 我想按日期元素对该列表进行排序 我用谷歌搜索 看到了一些具有可比性的解决方案 但是是否有可能在不实现类中接口的情况下做到这一点 我的列表如下所示 列表 id 33 文本 test1 日期 06 02 15 id 81 文本
  • VBA COM 库中的这些 _B_var_Xxxxx 和 _B_str_Xxxxx 成员到底是什么?

    想象一下以下函数调用 foo UCase bar 我正在解析这段代码 并确定UCase是一个函数调用 现在我想将该函数调用解析为定义它的 COM 库中函数的声明 这个想法是实现一个代码检查来确定何时Variant当使用内置函数时String
  • 如何使用 VBA 将符号/图标格式化为单元格而不使用条件格式

    我使用 VBA 代码放置条件格式以覆盖大型表格中的值 每个单元格使用 2 个公式来确定使用 3 个符号中的哪一个 我需要根据列使用不同的单元格检查每个单元格的值 因此据我了解 我必须将条件格式规则单独放置在每个单元格上 以确保每个单元格中的
  • Excel VBA application.visible 立即设置回 True

    我已经设置了一个新的 空的 无模式的用户表单 用最少的代码来解决我的问题 当工作簿打开时 执行以下代码来隐藏 Excel 并显示用户窗体 这是工作簿的唯一代码 Private Sub Workbook Open UserForm1 Show
  • JS 按特定排序顺序排序

    我需要按特定顺序对数据进行排序 如下所示 const sortBy b a c e d const data a d e 我知道如何按升序 降序排序 console log data sort a b gt a gt b a d e con
  • 无法在函数内将数据写入 Excel 2007/2010 中的 VBA 单元格

    我想通过 VBA 设置单元格的值 我用谷歌搜索了一下 看到了一些解决方案 Sheets SheetName Range A1 value someValue Sheets SheetName Cells 1 1 value someValu
  • 从html中获取属性字符串值

    我正在构建一个宏来使用从网站提取数据vba questions tagged vba 目前 我可以使用元素语法轻松地从表内容中获取值 例如obj getElementsByTagName td innerText 但是 当某些单元格中有一些

随机推荐

  • 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 类型属性对对象数