ENDE ZIEL: Effizientes (in einem Durchgang) Lesen Sie alle CellRecords
auf einem riesigen (30.000+ Reihe), geschützt Worksheet
.
lesen XLS mit geschütztem Buch und Blatt über HSSF.EventUserModel
Problem: Mit dem HSSF.EventUserModel
, wie kann ich lesen Sie alle Record
s (einschließlich CellRecords
) für eine XLS-Datei sowohl mit der Arbeitsmappe und den Schutz Arbeitsblatt?
erstellen Eingabe Tabelle (in Excel 2010):
- Erstellen Sie neue leere Arbeitsmappe.
- Sollwert von A1 bis Nummer: 50
- Set Wert von A2 auf string: fünfzig
- Set Wert von A3 Formel: = 25 * 2
- Review (Band) -> Blatt schützen -> Passwort : pass1
- Review (Band) -> Arbeitsmappe schützen -> Passwort: pass1
- Datei (Band) -> Speichern unter ... -> Speichern unter: Excel 97-2003-Arbeitsmappe
Fortschritt bisher:
new HSSFWorkbook(Stream fs)
geöffnet. Allerdings benötige ich die Effizienz von EventUserModel
für meine aktuelle Tabelle.NPOI.HSSF.Record.Crypto.Biff8EncryptionKey.CurrentUserPassword = "pass1";
hat nicht funktioniert.ProcessRecord()
Funktion fängt eine PasswordRecord
, aber ich kann keine Dokumentation finden, wie man es richtig behandelt.EncryptionInfo
oder Decryptor
von Nutzen sein.Hinweis:
Ich benutze NPOI. Ich kann jedoch jedes Java-Beispiel in C# übersetzen.
Code:
Ich verwende den folgenden Code, um Record
Ereignisse zu erfassen. My Book1-unprotected.xls
(ohne Schutz) zeigt alle Record
Ereignisse (einschließlich Zellenwerte). Mein Book1-protected.xls
zeigt einige Datensätze an und löst eine Ausnahme aus.
Ich sehe gerade processedEvents
im Debugger.
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:\users\me\desktop\xx\Book1-protected.xls");
myListener testListener = new myListener(fs); // Use EventModel
//HSSFWorkbook book = new HSSFWorkbook(fs); // Use UserModel
Console.Read();
}
}
}
UPDATE (für Juan Mellado) : Unten ist die Ausnahme. Meine beste Schätzung im Moment (in der Antwort von Victor Petrykin) ist, dass die HSSFEventFactory
RecordInputStream
verwendet, die geschützte Datensätze nicht nativ entschlüsseln kann.Auf die Ausnahme empfängt, processedRecords
22 Datensätze enthält, einschließlich der folgenden potenziell bedeutende diejenigen:
- processedRecords [5] ist ein
WriteAccessRecord
mit einem verstümmelten (wahrscheinlich verschlüsselt) Wert für.name
- processedRecords [22] ist ein
RefreshAllRecord
und in der Liste ist der letzteRecord
Ausnahme:
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:\Users\me\Documents\Visual Studio 2012\Projects\myTest\NPOI_small\Program.cs:line 35
at NPOI_small.Program.Main(String[] args) in c:\Users\me\Documents\Visual Studio 2012\Projects\myTest\NPOI_small\Program.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, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, 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)
Ich habe eine Java-gleichwertige Version Ihres Codes getestet, und es funktioniert wie erwartet. Ich meine, es ist nicht notwendig, ein Passwort zum Lesen geschützter Zellen anzugeben. Die Callback-Methode 'processRecord' empfängt alle' CellRecord'-Objekte wie 'NumberRecord' oder' FormulaRecord', sodass ich sie erkennen und auf ihre Attribute zugreifen kann (Beispiel: '((NumberRecord) record) .getValue()'). Ein 'ProtectRecord'-Objekt hat nur ein Flag-Attribut, um zu sagen, ob der aktuelle Datensatz geschützt ist. Kannst du etwas mehr darüber sagen, was "wie man damit richtig umgehen kann" bedeutet? Und natürlich die Stapelverfolgung der Ausnahme, die Sie erhalten haben. –
@JuanMellado: Siehe Hauptpostaktualisierung für Details. – Steven