我有一个Excel .xlam文件,在功能区中添加一个按钮来执行以下操作:
我以这种方式保存源文本,因为它可以受密码保护,我不需要在.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
该功能正常。我的问题是如果我想更新源文本,我现在必须在.xlam文件中手动执行此操作。我想要做的是在另一个模块中构建类似Sub ImportSource()
的东西,它将解析一些文件,以编程方式重建“源”模块,然后用我计算的源代码替换该模块。我不知道的是,是否/如何用字符串变量中的某个值替换模块的源代码。
这就像元编程在最糟糕的情况下,哲学上我反对这样做是我的核心。但实际上,我想知道是否以及如何做到这一点。
答案 0 :(得分:5)
我现在意识到,您真正想要做的是以VBA可访问的方式在文档中存储一些值,但这对电子表格的用户来说是不可读的。根据Charles Williams建议将值存储在工作表的命名区域中,并解决您不希望用户访问这些值的问题,您必须加密字符串......
this article中描述了执行此操作的“正确方法” - 但这是相当多的工作。
发现了一个更短的例程here。它只是使用简单的XOR加密和硬编码密钥 - 但它应该足以满足“大多数用途”。密钥将被“隐藏”在您的宏中,因此无法通过窥探眼睛(嗯,不容易)。
现在您可以使用此功能,让我们称之为encrypt(string)
,将您的字符串转换为电子表格中的值:
range("mySecretCell").value = encrypt("The lazy dog jumped over the fox")
当您需要使用它时,您可以使用
Public Function GetSource()
GetSource = decrypt(Range("mySecretCell").value)
End Function
如果您使用XOR
版本(第二个链接),encrypt
和decrypt
将是相同的功能......
这会更好地满足您的需求吗?
答案 1 :(得分:2)
正如@brettdj已经指出他的cpearson.com/excel/vbe.aspx 链接,您可以使用 VBA可扩展性库以编程方式更改为VBA模块的代码!要使用它,请在VBA编辑器中选择库工具 - > 参考。请注意,您还需要更改信任中心的选项,然后选择: Excel选项 - > 信任中心 - > 信任中心设置 - > 宏设置 - > 信任对VBA项目对象模型的访问
然后类似下面的代码应该做的工作:
Private mCodeMod As VBIDE.CodeModule Sub UpdateModule() Const cStrModuleName As String = "Source" Dim VBProj As VBIDE.VBProject Dim VBComp As VBIDE.VBComponent Set VBProj = Workbooks("___YourWorkbook__").VBProject 'Delete the module VBProj.VBComponents.Remove VBProj.VBComponents(cStrModuleName) 'Add module Set VBComp = VBProj.VBComponents.Add(vbext_ct_StdModule) VBComp.Name = cStrModuleName Set mCodeMod = VBComp.CodeModule 'Add procedure header and start InsertLine "Public Function GetSource() As String" InsertLine "Dim s As String", 1 InsertLine "" 'Add text InsertText ThisWorkbook.Worksheets("Sourcetext") _ .Range("___YourRange___") 'Finalize procedure InsertLine "GetSource = s", 1 InsertLine "End Function" End Sub Private Sub InsertLine(strLine As String, _ Optional IndentationLevel As Integer = 0) mCodeMod.InsertLines _ mCodeMod.CountOfLines + 1, _ Space(IndentationLevel * 4) & strLine End Sub Private Sub InsertText(rngSource As Range) Dim rng As Range Dim strCell As String, strText As String Dim i As Integer Const cLineLength = 60 For Each rng In rngSource.Cells strCell = rng.Value For i = 0 To Len(strCell) \ cLineLength strText = Mid(strCell, i * cLineLength, cLineLength) strText = Replace(strText, """", """""") InsertLine "s = s & """ & strText & """", 1 Next i Next rng End Sub
答案 2 :(得分:1)
您可以通过编程方式“导出”和“导入”.bas文件。要做你想要的,那就必须是方法。我不相信可以修改内存中的代码。见this article