Чтение файла с защитой паролем с использованием OLEDB в С#

В моем приложении С# я использую строку подключения OLEDB "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\test.xls;Extended Properties=\"Excel 8.0;HDR=NO;ReadOnly=true;IMEX=1\"" для чтения файлов Excel. Чтобы прочитать файл, защищенный паролем, я попытался добавить поле пароля в строку подключения, но не смог прочитать файл. Я хочу знать, есть ли способ прочитать защищенные паролем файлы Excel с помощью OLEDB, если я заранее знаю его пароль.

Ответ 1

Вот различные способы подключения к файлу Excel, включая OLEDB. В соответствии с этим вы не можете открыть защищенный паролем файл со стандартными методами. Вы должны использовать обходной путь.

Если книга Excel защищена пароль, вы не можете открыть его для доступа к данным, даже путем предоставления правильный пароль с вашим подключением строка. Если вы попытаетесь, вы получите следующее сообщение об ошибке: "Не удалось расшифровать файл.

Это решение, хотя и не в С#, но вы можете легко адаптировать его для своих целей.

Если вы не ЗНАТЬ пароль самостоятельно, альтернативой является перезаписать файл без пароля. Вы можете использовать этот удобный проект и добавить к нему следующую процедуру:

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);
        }

Полная информация здесь.

Ответ 2

Если вы используете запрос для чтения файла 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

Вы можете использовать поток 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();
}

Ответ 4

После того, как я исследовал снова и снова, я наконец нашел 2 вещи.
1.Using OLEDB, он не может прочитать файл excel, который защищен паролем.
2. Даже если Interop может читать файл excel независимо от того, защищен ли пароль или нет, его производительность не так хороша, как OLEDB.

Итак, я создаю ниже код, комбинируя 1. OLEDB, который имеет очень хорошую производительность и
2. Interop, который может читать все файлы excel.

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