Excel互操作防止显示密码对话框。

11

我正在编写一个程序,用于清理Excel文件中的空行和列。我从自己的问题“使用Interop快速删除Excel文件中的空行和列的最快方法”开始,一切都进行得很顺利。

问题在于,当工作簿受到密码保护时,我希望防止Excel显示密码对话框,而是抛出异常

输入图像描述

我正在使用以下代码使用Interop打开Excel文件:

 m_XlApp = New Excel.Application
 m_XlApp.visible = False
 m_XlApp.DisplayAlerts = False

 Dim m_xlWrkbs As Excel.Workbooks = m_XlApp.Workbooks
 Dim m_xlWrkb As Excel.Workbook
 m_xlWrkb = m_xlWrkbs.Open(strFile)

 m_xlWrkb.DoNotPromptForConvert = true          

我尝试按照一些链接的建议输入空密码。

m_xlWrkb = m_xlWrkbs.Open(strFile, Password:="")

或者使用

m_xlWrkb.Unprotect("")

但是没有运气。

有什么建议吗?


1
interop具有HasPassword属性 https://msdn.microsoft.com/zh-cn/library/microsoft.office.tools.excel.workbook.haspassword(VS.80).aspx 然后您可以自己抛出异常。 - Esselans
@Jaxedin 我同意你的观点,但在打开文件之前无法访问此属性,因此它将无法起作用。当调用workbook.open()方法时,密码对话框会显示。 - Hadi
@Jaxedin 我找到了一个解决方案,看一下吧。 - Hadi
3个回答

8
我找到了一个解决方案,但我也接受其他可行的答案。
问题:
当将空字符串作为密码传递时,Excel会将其视为无效。因此,它会要求输入密码并显示对话框。
解决方案:
解决方法是将单引号作为密码传递,Excel会将其视为空字符串。如果工作簿未受密码保护,则会打开它;否则,将抛出以下异常:
"The password you supplied is not correct. Verify that the CAPS LOCK key is off and be sure to use the correct capitalization."
代码如下:
m_xlWrkb = m_xlWrkbs.Open(strFile, Password:="'")

注意:

在微软Excel中,数值前面加上单引号代表强制文本格式。

例如:'0 会被读取为数值 0 的文本格式


4

不要在你不想提供参数的方法中使用Nothing

改为:

m_xlWrkb = m_xlWrkbs.Open(strFile, Nothing, Nothing, Nothing, "", Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing)

可以使用以下任意一种:

m_xlWrkb = m_xlWrkbs.Open(strFile, Password:="")

或者

m_xlWrkb = m_xlWrkbs.Open(strFile, , , , "", , , , , , , , , , )

或者

Dim missing As System.Reflection.Missing = System.Reflection.Missing.Value
m_xlWrkb = m_xlWrkbs.Open(strFile,missing, missing, missing, "", missing, missing, missing, missing, missing, missing, missing, missing, missing, missing)

如果工作簿受到密码保护,执行此操作将会抛出一个`COMException`异常,并显示以下信息:

"The password you supplied is not correct. Verify that the CAPS LOCK key is off and be sure to use the correct capitalization."

如果工作簿没有受到密码保护且文件可以访问,则不会抛出任何异常。
您也可以像上面展示的那样定义“missing”对象:
Dim missing As Object = Type.Missing

Type.MissingSystem.Reflection.Missing指的是同一个对象。


我尝试了你提供的内容,但它没有起作用。谢谢你的回复。 - Hadi
非常感谢您的帮助。我找到了一个解决方案,请看一下。这个问题有点棘手。 - Hadi

2

关于你的解决方案,你确定它不会与除密码以外的任何东西一起使用吗?像这样的:

Public Function wb_get_workbook(ByVal sFullName As String) As Workbook

    Dim sFile As String
    Dim wbReturn As Workbook

    sFile = Dir(sFullName)

    On Error Resume Next
        Set wbReturn = Workbooks(sFile)

        If wbReturn Is Nothing Then
            Application.AskToUpdateLinks = False
            Set wbReturn = Workbooks.Open(sFullName, , , , "ThisIsDefinitelyAPasswordThatNooneHasUsed681")
        End If
    On Error GoTo 0

    Set wb_get_workbook = wbReturn

End Function

如果受到密码保护,它也会抛出错误;如果没有受到密码保护,则不会关心您提供的密码。我正在尝试使用VBA,但在C#中,您可以使用Excel应用程序对象,所以这不应该有什么不同。


我确信这不适用于C#和VB.NET。 - Hadi
这很奇怪。你试过用TryCatch吗? - Vityata
是的,我使用了 try catch。唯一有效的方法是传递一个单引号。 - Hadi
@Yahfoufi - 谢谢,我打算今天晚些时候在C#中尝试一下,你为我节省了很多精力。但是,只要它们使用相同的Excel对象,C#不应该也是一样的吗? - Vityata
@Yahfoufi - 是的,这个问题似乎很有帮助,但是我对C#中的Excel对象的理解有所不同。 :) - Vityata
@Vityata,我删除了我的旧评论,你是对的。如果使用Workbook.Unprotect("blabla"),这将不起作用,但使用Open()方法将起作用。但是,单引号在两种方法中都适用。 - Yahfoufi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接