- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
-编辑:在此问题的上下文中,这现在是bigger question of how to reliably move sheets about的一部分-
(注意:在准备本文和测试解决方案的过程中,我可能已经回答了我自己的问题。只是发布此文章是希望任何比我聪明的人都能提出一些建议。无论如何,我认为它仍然是将来搜索者的好资源。)
问题描述
我为其中一个拥有大量VBA的客户制作了一个Excel解决方案。因此,我自然而然地签署了VBA代码,因此我的客户没有收到宏安全性消息。但是,此解决方案要做的一件事是在同一工作簿中复制模板工作表。模板工作表位于其代号上,并且此后将通过其代码名(具有尾随序列nr。)来识别工作表的所有副本-需要对其进行标识并稍后再进行处理。
一见钟情,但是当我演示解决方案并尝试保存它时,我立即得到:
"You have modified a signed project. You do not have the correct key to sign this project. The signature will be discarded."
Worksheet.Copy
制作此工作表的副本(并修改该工作表,但此处无关紧要)。 CodeModule.CountOfLines
返回0)。或检索整个VBA代码模块的内容并对其进行哈希处理,以使终止NULL char或前导0字节计数有助于哈希处理。无论如何,这里没有运气。
Option Explicit
),并且签名仍然粘贴在救...
Option Explicit
是虚拟的,甚至VBA模块的存在都是虚拟的。当我使宏也列出所有带有代码名称的工作表时,事实证明这些“安全”工作表的代码名称为空(长度为0的字符串),实际上表明它们根本没有代码模块。
sourceSheet.Cells.Copy destSheet.Cells
就能绝对复制
,用户可以在上面扔出的所有 ...我宁愿因此继续使用内置的
Worksheet.Copy
函数来确保安全,而不必为每个函数编写大量特殊代码可能的细节。
sourceSheet.Cells.Copy destSheet.Cells
例如确实会复制工作表特定的命名范围,但显然仅在工作表本身上实际使用了它们的情况下。未引用的名称将在副本中消失!谈论我必须编写的特殊情况下的复制代码...
Worksheet.Copy
编码,记下它的名称,将其明确保存为.xlsx文件以摆脱任何VBA模块,关闭并重新打开temp工作簿以摆脱任何旧的内存碎片,再按名称找到它,然后使用
Worksheet.Move
将其返回源工作簿。
Worksheet.Copy
,然后用临时表的模板替换真实副本的VBA模块。或者只是将VBA模块作为一个整体进行核对。
shtTemplate.
而不是
ThisWorkbook.Worksheets("Template").
来访问其VBA代码名称上的模板工作表,这显然使Excel变得非常复杂,以至于无法即时切换它。到目前为止,我所有的尝试都失败了,或者使Excel崩溃了。那里没有爱:(
msoAutomationSecurityForceDisable
的Excel中的副本来再次尝试此操作,从而避免破坏正在运行的VBA主机,并且几乎每次更新后都保存并重新打开。但这无济于事,在打开已清理的工作簿时出现诸如“自动化错误-灾难性故障”之类的错误,或者极大破坏了新工作簿(为项目浏览器中的每个工作表模块使用派生名称复制了
ThisWorkbook
模块)。
Worksheet.Copy
安全复制而不会丢失签名和Worksheet.Copy
,但是通过其他方式(而不是通过其代码名)找到并识别它,并生成工作表。尽管可以使我内心的完美主义者感到畏缩,但上面有一个用户隐藏的部分,我可能会添加“这是模板/副本”状态。
最佳答案
需要付出很多,我不假装这会回答将解决您所有的问题。但是我曾经写过一个名为SoftLink的函数,该函数最多包含4个参数(i) bool(boolean) 值:CellRef(或NamedRange)(ii)字符串:范围(iii)字符串:WorksheetName(iv)字符串:WorkbookName,它将断开与任何链接的链接单元格,然后解析VBA代码中的字符串参数。
毫无疑问,这种方法会降低性能,但这是解决Link hell的一种方法。
调用公式示例
=softlink(FALSE,"Foo")
=softlink(TRUE,"C4","Sheet1","Book2")
=softlink(TRUE,"D5","Sheet2")
Option Explicit
Function SoftLink(ByVal bIsCell As Boolean, ByVal sRangeName As String, _
Optional sSheetName As String, Optional sBookName As String) As Variant
Dim vRet As Variant
If Len(sRangeName) = 0 Then vRet = "#Cannot resolve null range name!": GoTo SingleExit '* fast fail
Dim rngCaller As Excel.Range
Set rngCaller = Application.Caller
Dim wsCaller As Excel.Worksheet
Set wsCaller = rngCaller.Parent
Dim wbCaller As Excel.Workbook
Set wbCaller = wsCaller.Parent
Dim wb As Excel.Workbook
If Len(sBookName) > 0 Then
vRet = FindWorkbookWithoutOnErrorResumeNext(sBookName, wb)
If Len(vRet) > 0 Then GoTo ErrorMessageExit
Else
Set wb = wbCaller
End If
Debug.Assert Not wb Is Nothing
Dim ws As Excel.Worksheet
If Len(sSheetName) > 0 Then
vRet = FindWorksheetWithoutOnErrorResumeNext(wb, sSheetName, ws)
If Len(vRet) > 0 Then GoTo ErrorMessageExit
Else
Set ws = wsCaller
End If
Dim rng As Excel.Range
If bIsCell Then
vRet = AcquireCellRange(ws, sRangeName, rng)
If Len(vRet) > 0 Then GoTo ErrorMessageExit
Else
vRet = AcquireNamedRangeWithoutOERN(ws, sRangeName, rng)
If Len(vRet) > 0 Then GoTo ErrorMessageExit
End If
SoftLink = rng.Value2
SingleExit:
Exit Function
ErrorMessageExit:
SoftLink = vRet
GoTo SingleExit
End Function
Function AcquireCellRange(ByVal ws As Excel.Worksheet, ByVal sRangeName As String, ByRef prng As Excel.Range) As String
On Error GoTo FailedCellRef
Set prng = ws.Range(sRangeName)
SingleExit:
Exit Function
FailedCellRef:
AcquireCellRange = "#Could not resolve range name '" & sRangeName & "' on worksheet name '" & ws.Name & "' in workbook '" & ws.Parent.Name & "'!"
End Function
Function AcquireNamedRangeWithoutOERN(ByVal ws As Excel.Worksheet, ByVal sRangeName As String, ByRef prng As Excel.Range) As String
'* because I do not like OERN
Dim oNames As Excel.Names
Dim bSheetScope As Long
For bSheetScope = True To False
Set oNames = VBA.IIf(bSheetScope, ws.Names, ws.Parent.Names)
Dim namLoop As Excel.Name
For Each namLoop In oNames
If VBA.StrComp(namLoop.Name, sRangeName, vbTextCompare) = 0 Then
Set prng = ws.Range(sRangeName)
GoTo SingleExit
End If
Next
Next
ErrorMessageExit:
AcquireNamedRangeWithoutOERN = "#Could not resolve range name '" & sRangeName & "' on worksheet name '" & ws.Name & "' in workbook '" & ws.Parent.Name & "'!"
SingleExit:
Exit Function
End Function
Function FindWorksheetWithoutOnErrorResumeNext(ByVal wb As Excel.Workbook, ByVal sSheetName As String, ByRef pws As Excel.Worksheet) As String
'* because I do not like OERN
Dim wsLoop As Excel.Worksheet
For Each wsLoop In wb.Worksheets
If VBA.StrComp(wsLoop.Name, sSheetName, vbTextCompare) = 0 Then
Set pws = wsLoop
GoTo SingleExit
End If
Next wsLoop
ErrorMessageExit:
FindWorksheetWithoutOnErrorResumeNext = "#Could not resolve worksheet name '" & sSheetName & "' in workbook '" & wb.Name & "'!"
SingleExit:
Exit Function
End Function
Function FindWorkbookWithoutOnErrorResumeNext(ByVal sBookName As String, ByRef pwb As Excel.Workbook) As String
'* because I do not like OERN
Dim wbLoop As Excel.Workbook
For Each wbLoop In Application.Workbooks
If VBA.StrComp(wbLoop.Name, sBookName, vbTextCompare) = 0 Then
Set pwb = wbLoop
GoTo SingleExit
End If
Next wbLoop
ErrorMessageExit:
FindWorkbookWithoutOnErrorResumeNext = "#Could not resolve workbook name '" & sBookName & "'!"
SingleExit:
Exit Function
End Function
关于vba - 在保留数字签名的同时复印纸张,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41745559/
我正在使用 apache poi 创建一个 excel 文档。为了在工作簿中创建新工作表,我编写了下一个代码: Workbook wb = new HSSFWorkbook(); Sheet sh =
我是一名优秀的程序员,十分优秀!