在C#中使用OLEDB读取受密码保护的Excel文件

11
在我的C#应用程序中,我使用OLEDB连接字符串"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\test.xls;Extended Properties=\"Excel 8.0;HDR=NO;ReadOnly=true;IMEX=1\""来读取Excel文件。 为了读取密码保护的文件,我尝试在连接字符串中添加密码字段,但无法读取文件。 我想知道是否有办法在事先已知文件密码的情况下,使用OLEDB读取密码保护的Excel文件。
4个回答

5
以下是与Excel文件连接的不同方法,包括OLEDB。根据此文,您无法使用标准方法打开受密码保护的文件。您需要使用解决方法。

如果Excel工作簿受密码保护,则无法通过提供正确的密码与连接字符串打开它以进行数据访问。如果尝试,则会收到以下错误消息:“无法解密文件。”

这是解决方案,虽然不是用C#编写的,但您可以轻松地将其适应于您的目的。

如果您自己不知道密码,另一种选择是重新编写没有密码的文件。您可以使用这个方便的项目并添加以下例程:

public void SaveFile()

        {
            this.excelWorkbook.SaveAs(
                this.excelWorkbook.FullName,
                vk_format,
                "",
                vk_write_res_password,
                vk_read_only,
                null,
                Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange,
                null,
                vk_add_to_mru,
                null,null,vk_local);
        }

点击此处查看完整细节


5

如果您使用查询来读取Excel文件,那么一些工作表受到保护并不会影响其正常工作:无论如何都可以正常运行。

    private string ExcelConnection(string fileName)
    {
        return
            @"Provider=Microsoft.Jet.OLEDB.4.0;" +
            @"Data Source=" + fileName + ";" +
            @"Extended Properties=" + Convert.ToChar(34).ToString() +
            @"Excel 8.0" + Convert.ToChar(34).ToString() + ";";
    }

    private DataTable readExcel(string fileName, string sql)
    {
        OleDbConnection conn = new OleDbConnection(ExcelConnection(fileName));
        OleDbCommand cmd = new OleDbCommand(sql, conn);
        OleDbDataAdapter adp = new OleDbDataAdapter();
        adp.SelectCommand = cmd;
        DataTable dt = new DataTable();

        try
        {
            adp.FillSchema(dt, SchemaType.Source);
            adp.Fill(dt);
        }
        catch
        { 

        }
        return dt;
    }

3

经过反复研究,我最终发现两件事情。
1. 使用OLEDB,它无法读取受密码保护的Excel文件。
2. 即使Interop可以读取Excel文件,无论是否受到密码保护,其性能也不如OLEDB好。

因此,我通过组合以下代码来创建:
1.具有非常好性能的OLEDB和
2.可以读取任何Excel文件的Interop。

public DataTable ReadPasswordProtectedExcel(string ExcelFilePath, string Password)
{
    String TempExcelFilePath = string.Empty;            
    DataTable _DataTable = new DataTable();

    #region Get ExcelFile and Remove Password
    {
        String TempExcelFileName = string.Empty;
        String DirectoryPath = string.Empty;
        Microsoft.Office.Interop.Excel.Application excelapp = new Microsoft.Office.Interop.Excel.Application();
        excelapp.Visible = false;

        Microsoft.Office.Interop.Excel.Workbook newWorkbook = excelapp.Workbooks.Open(ExcelFilePath, 0,
                                            true, 5, Password, "", false, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "", true,
                                            false, 0, true, false, false);

        TempExcelFileName = string.Format("{0}_{1}", "__", Path.GetFileName(ExcelFilePath)); // __xxx.xlsx
        TempExcelFilePath = String.Format("{0}/{1}", Path.GetDirectoryName(ExcelFilePath), TempExcelFileName);

        /// Create new excel file and remove password.
        newWorkbook.SaveAs(TempExcelFilePath, Microsoft.Office.Interop.Excel.XlFileFormat.xlWorkbookDefault, "", "",
        false, false, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange,
        Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);

        newWorkbook.Close(true, "", false);

        excelapp.Quit();
        Marshal.ReleaseComObject(excelapp);
    }
    #endregion

    #region Get data from excel file by using OLEDB
    {
        _DataTable = ReadExcelFileInOLEDB(TempExcelFilePath);
        ///Delete excel file
        File.Delete(TempExcelFilePath);
    }
    #endregion

    return _DataTable;
}

public DataTable ReadExcelFileInOLEDB(string _ExcelFilePath)
{
    string ConnectionString = string.Empty;
    string SheetName = string.Empty;           
    DataTable _DataTable = null;
    DataSet _DataSet = null;

    try
    {
        ConnectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties='Excel 12.0;HDR=YES;IMEX=0;'", _ExcelFilePath);
        using (OleDbConnection _OleDbConnection = new OleDbConnection(ConnectionString))
        {
            _OleDbConnection.Open();
            _DataTable = _OleDbConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);

            if (_DataTable == null)
                return null;

            SheetName = _DataTable.Rows[0]["TABLE_NAME"].ToString();
            ConnectionString = string.Format("SELECT * FROM [{0}]", SheetName);

            using (OleDbCommand _OleDbCommand = new OleDbCommand(ConnectionString, _OleDbConnection))
            {
                using (OleDbDataAdapter _OleDbDataAdapter = new OleDbDataAdapter())
                {
                    _OleDbDataAdapter.SelectCommand = _OleDbCommand;

                    _DataSet = new DataSet();
                    _OleDbDataAdapter.Fill(_DataSet, "PrintInfo");
                    return _DataSet.Tables["PrintInfo"];
                }
            }
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

最后,如果您想在从Excel检索数据时删除空行,请查看此链接和下面的代码。

SELECT * FROM NAMED_RANGE WHERE [YourColumnTitle] IS NOT NULL 

2
您可以使用 OoXmlCrypto流 访问 Office 2007 加密文件。此为开源项目,包括修改过的 ExcelPackage。

示例代码:

using (OfficeCryptoStream stream = OfficeCryptoStream.Open("a.xlsx", "password"))
{
    // Do stuff (e.g. create System.IO.Packaging.Package or 
    // ExcelPackage from the stream, make changes and save)

    // Change the password (optional)
    stream.Password = "newPassword";

    // Encrypt and save the file
    stream.Save();
}

如果文件被加密了,那么它适用吗? - gumuruh

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