NPOI与OOXML Excel密码无法正常工作

时间:2012-09-25 13:27:47

标签: c# openxml npoi

尝试读取加密的2007 Excel文档时,我遇到了使用OOXML库的问题。我发送到DecryptToStream方法的密码是发回“密码无效”消息,但如果我直接进入excel,密码工作正常。以下是我正在使用的代码。

OleStorage ols = new OleStorage(d.fileLocation);
OfficeCrypto oc = new OfficeCrypto();
Stream test = oc.DecryptToStream(ols, "test123");

我也尝试使用POI Decryptor尝试读取加密的2007 excel,但我也没有运气。下面是代码。

FileStream file = new FileStream(d.fileLocation, FileMode.Open, System.IO.FileAccess.Read);
NPOI.POIFS.FileSystem.POIFSFileSystem nfs;
nfs = new NPOI.POIFS.FileSystem.POIFSFileSystem(file);
Stream excelData;
try
{
    string password = "test123";
    EncryptionInfo info = new EncryptionInfo(nfs);
    Decryptor dc = Decryptor.GetInstance(info);

    if (!dc.VerifyPassword(password))
    {
        throw new NotImplementedException();
    }

    excelData = dc.GetDataStream(nfs);

}
catch (Exception ex)
{
    excelData = (Stream)file;
}

无论我传递给它什么,VerifyPassword方法总是返回true,它仍然不会读取文档。我使用http://poi.apache.org/encryption.html作为参考创建了上述代码。

非常感谢任何帮助!

1 个答案:

答案 0 :(得分:2)

据我所知,当前的 NPOI版本1.2.5 不支持Excel2007文件。 幸运的是NPOI 2.0 alpha version 支持Excel2007文件,但不支持加密的Excel文件。

但是,有一个名为OfficeOpenXmlCrypto的项目 它支持读取加密的Excel文件。该项目基于NPOI版本1.2.1和 用于阅读Excel 2007文件的ExcelPackage项目。

您可以下载 OfficeOpenXmlCrypto 项目的来源,替换 带有新NPOI 2.0库的旧NPOI库并编译项目。

然后,您可以使用XSSFWorkbookOfficeCryptoStream类的comibnation 阅读加密的Excel文件的内容:

using (OfficeCryptoStream ocs = OfficeCryptoStream.Open("c:\\temp\\secured.xlsx", "PA$$W0rd"))
{
  NPOI.XSSF.UserModel.XSSFWorkbook w = new NPOI.XSSF.UserModel.XSSFWorkbook(ocs);

  NPOI.xssf.extractor.XSSFExcelExtractor ee = new NPOI.xssf.extractor.XSSFExcelExtractor(w);

  Console.Out.WriteLine(ee.Text);                    
}

作为替代EPPlus class library 提供了一个名为ExcelPackage的类,它提供支持 加密的Excel文档。这个类还有一些属性(Workbook) 访问Excel文档的内容。

以下是读取加密Excel文件的第一个单元格的简单示例:

using (FileStream file = new FileStream("c:\\temp\\secure.xlsx", 
       FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite))
{
  using (ExcelPackage ep = new ExcelPackage(file, "P@$$W0rd"))
  {
    Console.Out.WriteLine(ep.Workbook.Worksheets[1].Cells["A1"].Value);     
  }
} 

您还可以组合使用 OpenXml 2.0 SDK SpreadsheetDocument类 使用ExcelPackage类。

使用以下代码读取第一个单元格(加密的Excel文档)的内容:

using (FileStream file = new FileStream("c:\\temp\\secure.xlsx", 
       FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite))
{
  using (ExcelPackage ep = new ExcelPackage(file, "P@$$W0rd"))
  {     
    using (SpreadsheetDocument sd = SpreadsheetDocument.Open(ep.Package))
    {
      WorkbookPart workbookPart = sd.WorkbookPart;
      WorksheetPart worksheetPart = workbookPart.WorksheetParts.Last();
      SheetData sheetData = worksheetPart.Worksheet.Elements<SheetData>().First();

      var row = sheetData.Elements<Row>().FirstOrDefault();
      var cell = row.Elements<Cell>().FirstOrDefault();

      Console.Out.WriteLine(cell.CellValue.InnerText);
    }
  }
}

如果密码无效,ExcelPackage类的构造函数将抛出UnauthorizedAccessException