加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 通过HSSF.EventUserModel使用受保护的书籍和工作表读取XLS

发布时间:2020-12-15 05:37:27 所属栏目:百科 来源:网络整理
导读:结束目标:有效地(一次性)读取一个巨大的(30,000行)受保护的工作表上的所有CellRecords. 问题: 使用HSSF.EventUserModel,如何读取具有工作簿和工作表保护的XLS文件的所有记录(包括CellRecords)? 创建输入电子表格(在Excel 2010中): 创建新的空白工作簿.
结束目标:有效地(一次性)读取一个巨大的(30,000行)受保护的工作表上的所有CellRecords.

问题:
使用HSSF.EventUserModel,如何读取具有工作簿和工作表保护的XLS文件的所有记录(包括CellRecords)?

创建输入电子表格(在Excel 2010中):

>创建新的空白工作簿.
>将A1的值设置为数字:50
>将A2的值设置为字符串:50
>将A3的值设置为公式:= 25 * 2
>评论(功能区) – >保护表 – >密码:pass1
>评论(功能区) – >保护工作簿 – >密码:pass1
>文件(功能区) – >另存为… – >保存类型:Excel 97-2003工作簿

迄今取得的进展:

>在Excel中没有密码的情况下打开XLS文件.因此,您不需要密码才能在POI中打开它.
>使用新的HSSFWorkbook(Stream fs)成功打开XLS文件.但是,我需要EventUserModel的效率用于我的实际电子表格.
>设置NPOI.HSSF.Record.Crypto.Biff8EncryptionKey.CurrentUserPassword =“pass1”;不工作.
> ProcessRecord()函数捕获一个PasswordRecord,但我找不到有关如何正确处理它的任何文档.
>也许,EncryptionInfo或Decryptor类可能有一些用处.

注意:
我正在使用NPOI.但是,我可以将任何Java示例翻译为C#.

码:
我使用以下代码捕获Record事件. My Book1-unprotected.xls(无保护)显示所有Record事件(包括单元格值). My Book1-protected.xls显示一些记录并引发异常.

我只是在调试器中查看processedEvents.

using System;
using System.Collections.Generic;
using System.IO;

using NPOI.HSSF.Record;
using NPOI.HSSF.Model;
using NPOI.HSSF.UserModel;
using NPOI.HSSF.EventUserModel;
using NPOI.POIFS;
using NPOI.POIFS.FileSystem;

namespace NPOI_small {
    class myListener : IHSSFListener {
        List<Record> processedRecords;

        private Stream fs;

        public myListener(Stream fs) {
            processedRecords = new List<Record>();
            this.fs = fs;

            HSSFEventFactory factory = new HSSFEventFactory();
            HSSFRequest request = new HSSFRequest();

            MissingRecordAwareHSSFListener mraListener;
            FormatTrackingHSSFListener fmtListener;
            EventWorkbookBuilder.SheetRecordCollectingListener recListener;
            mraListener = new MissingRecordAwareHSSFListener(this);
            fmtListener = new FormatTrackingHSSFListener(mraListener);
            recListener = new EventWorkbookBuilder.SheetRecordCollectingListener(fmtListener);
            request.AddListenerForAllRecords(recListener);

            POIFSFileSystem poifs = new POIFSFileSystem(this.fs);

            factory.ProcessWorkbookEvents(request,poifs);
        }

        public void ProcessRecord(Record record) {
            processedRecords.Add(record);
        }
    }
    class Program {
        static void Main(string[] args) {
            Stream fs = File.OpenRead(@"c:usersmedesktopxxBook1-protected.xls");

            myListener testListener = new myListener(fs); // Use EventModel 
            //HSSFWorkbook book = new HSSFWorkbook(fs); // Use UserModel

            Console.Read();
        }
    }
}

更新(胡安梅拉多):
以下是例外.我现在最好的猜测(在Victor Petrykin的回答中)是HSSFEventFactory使用RecordInputStream,它无法本机解密受保护的记录.在收到异常后,processedRecords包含22条记录,包括以下可能重要的记录:

> processedRecords [5]是一个WriteAccessRecord,带有.name的乱码(可能是加密的)值
> processedRecords [22]是一个RefreshAllRecord,是列表中的最后一个Record

例外:

NPOI.Util.RecordFormatException was unhandled
  HResult=-2146233088
  Message=Unable to construct record instance
  Source=NPOI
  StackTrace:
       at NPOI.HSSF.Record.RecordFactory.ReflectionConstructorRecordCreator.Create(RecordInputStream in1)
       at NPOI.HSSF.Record.RecordFactory.CreateSingleRecord(RecordInputStream in1)
       at NPOI.HSSF.Record.RecordFactory.CreateRecord(RecordInputStream in1)
       at NPOI.HSSF.EventUserModel.HSSFRecordStream.GetNextRecord()
       at NPOI.HSSF.EventUserModel.HSSFRecordStream.NextRecord()
       at NPOI.HSSF.EventUserModel.HSSFEventFactory.GenericProcessEvents(HSSFRequest req,RecordInputStream in1)
       at NPOI.HSSF.EventUserModel.HSSFEventFactory.ProcessEvents(HSSFRequest req,Stream in1)
       at NPOI.HSSF.EventUserModel.HSSFEventFactory.ProcessWorkbookEvents(HSSFRequest req,POIFSFileSystem fs)
       at NPOI_small.myListener..ctor(Stream fs) in c:UsersmeDocumentsVisual Studio 2012ProjectsmyTestNPOI_smallProgram.cs:line 35
       at NPOI_small.Program.Main(String[] args) in c:UsersmeDocumentsVisual Studio 2012ProjectsmyTestNPOI_smallProgram.cs:line 80
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly,String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext,ContextCallback callback,Object state,Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext,Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: NPOI.Util.RecordFormatException
       HResult=-2146233088
       Message=Expected to find a ContinueRecord in order to read remaining 137 of 144 chars
       Source=NPOI
       StackTrace:
            at NPOI.HSSF.Record.RecordInputStream.ReadStringCommon(Int32 requestedLength,Boolean pIsCompressedEncoding)
            at NPOI.HSSF.Record.RecordInputStream.ReadUnicodeLEString(Int32 requestedLength)
            at NPOI.HSSF.Record.FontRecord..ctor(RecordInputStream in1)

解决方法

我认为这是NPOI库代码中的错误.据我所知,他们使用不正确的流类型为HSSFEventFactory:它使用RecordInputStream而不是RecordFactoryInputStream与解密函数,如原始POI库或UserModel(这就是为什么HSSFWorkbook工作)

这段代码也有效,但它不是一个事件逻辑:

POIFSFileSystem poifs = new POIFSFileSystem(fs);
Entry document = poifs.Root.GetEntry("Workbook");
DocumentInputStream docStream = new DocumentInputStream((DocumentEntry)document);
//RecordFactory factory = new RecordFactory();
//List<Record> records = RecordFactory.CreateRecords(docStream);
RecordFactoryInputStream recFacStream = new RecordFactoryInputStream(docStream,true);
Record currRecord;
while ((currRecord = recFacStream.NextRecord()) != null) 
   ProcessRecord(currRecord);

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读