是否可以在Excel VBA中更改另一个模块中的Module的源代码

nee*_*lsg 4 excel vba excel-vba

我有一个Excel .xlam文件,在功能区中添加一个按钮来执行以下操作:

  1. 扫描ActiveSheet以获取一些预设参数
  2. 获取我的源文本(字符串值,直接在VBA模块中硬编码),并使用从步骤1中检索的参数替换指定区域
  3. 生成包含计算文本的文件

我以这种方式保存源文本,因为它可以受密码保护,我不需要在.xlam文件所在的任何地方拖动另一个文件.源文本保存在一个名为"Source"的单独模块中,看起来像这样(感谢VBA没有Heredocs):

'Source Module
Public Function GetSource() As String
    Dim s As String
    s = ""

    s = s & "This is the first line of my source text" & vbCrLf
    s = s & "This is a parameter {par1}" & vbCrLf
    s = s & "This is another line" & vbCrLf

    GetSource = s
End Function
Run Code Online (Sandbox Code Playgroud)

功能正常.我的问题是如果我想更新源文本,我现在必须在.xlam文件中手动执行此操作.我想做的是构建类似于Sub ImportSource()另一个模块的东西,它将解析一些文件,以编程方式重建"源"模块,然后用我计算的源代码替换该模块.我不知道的是,是否/如何用字符串变量中的某个值替换模块的源代码.

这就像元编程在最糟糕的情况下,哲学上我反对这样做是我的核心.但实际上,我想知道是否以及如何做到这一点.

Flo*_*ris 5

我现在意识到你真正想要做的是以一种VBA可访问的方式在文档中存储一些值,但这对电子表格的用户来说是不可读的.根据Charles Williams建议将值存储在工作表的命名区域中,并解决您不希望用户访问这些值的问题,您必须加密字符串......

本文描述了执行此操作的"正确方法" - 但这是相当多的工作.

一个更短的程序找到这里.它只是使用简单的XOR加密和硬编码密钥 - 但它应该足以满足"大多数用途".密钥将被"隐藏"在您的宏中,因此无法窥探(很好,不容易).

现在您可以使用此函数,让我们调用它encrypt(string),将您的字符串转换为电子表格中的值:

range("mySecretCell").value = encrypt("The lazy dog jumped over the fox")
Run Code Online (Sandbox Code Playgroud)

当你需要使用它时,你使用

Public Function GetSource()
    GetSource = decrypt(Range("mySecretCell").value)
End Function
Run Code Online (Sandbox Code Playgroud)

如果你使用XOR版本(第二个链接),encrypt并且decrypt将是相同的功能...

这更符合您的需求吗?


Pet*_*ert 5

正如@brettdj 已经通过他指向cpearson.com/excel/vbe.aspx 的链接指出的那样,您可以使用VBA 扩展库以编程方式更改为 VBA 模块的代码!要使用它,请在 VBA 编辑器Tools -> References 中选择库。请注意,您还需要更改信任中心中的选项并选择:Excel 选项->信任中心->信任中心设置->宏设置->信任访问 VBA 项目对象模型

然后像下面的代码应该完成这项工作:

私有 mCodeMod 作为 VBIDE.CodeModule

子更新模块()
    Const cStrModuleName As String = "Source"

    将 VBProj 调暗为 VBIDE.VBProject
    将 VBComp 调暗为 VBIDE.VBComponent

    设置 VBProj = Workbooks("___YourWorkbook__").VBProject

    '删除模块
    VBProj.VBComponents.Remove VBProj.VBComponents(cStrModuleName)

    '添加模块
    设置 VBComp = VBProj.VBComponents.Add(vbext_ct_StdModule)
    VBComp.Name = cStrModuleName
    设置 mCodeMod = VBComp.CodeModule

    '添加程序头并启动
    InsertLine "公共函数 GetSource() As String"
    InsertLine "Dim s As String", 1
    插入行“”

    '添加文字
    InsertText ThisWorkbook.Worksheets("Sourcetext") _
        .Range("___你的范围___")

    '完成程序
    InsertLine "GetSource = s", 1
    插入行“结束函数”

结束子

Private Sub InsertLine(strLine As String, _
    可选的 IndentationLevel 作为整数 = 0)
    mCodeMod.InsertLines _
        mCodeMod.CountOfLines + 1, _
        Space(IndentationLevel * 4) & strLine
结束子

私有子插入文本(rngSource As Range)
    调光范围
    Dim strCell As String, strText As String
    Dim i 作为整数

    常量 cLineLength = 60
    对于 rngSource.Cells 中的每个 rng
        strCell = rng.Value
        对于 i = 0 到 Len(strCell) \ cLineLength
            strText = Mid(strCell, i * cLineLength, cLineLength)
            strText = Replace(strText, """", """""")
            InsertLine "s = s & """ & strText & """", 1
        接下来我
    下一个
结束子