簡體   English   中英

如何使用 C#/FileHelpers ExcelNPOIStorage 從 Excel 文件中提取數據

[英]How to extract data from an Excel file with C# / FileHelpers ExcelNPOIStorage

我正在嘗試使用 Filehelpers ExcelNPOIStorage 從 Excel 工作表中提取數據。 因此我創建了一個類:

public static class UalExcelReader
    {
        public static UalShipmentRecord[] ReadInput(String pathToFile)
        {
            var provider = new ExcelNPOIStorage(typeof (UalShipmentRecord))
            {
                StartRow = 2,
                StartColumn = 1,
                FileName = pathToFile
            };
            var res = (UalShipmentRecord[]) provider.ExtractRecords();
            return res;
        }
    }

當然還有模型類:

[DelimitedRecord("|")]
public class UalShipmentRecord
{
    public string contentofcol1;
    public string contentofcol2;
    ...

}

但我收到一個 IndexOutOfRangeException 調用 ExtractRecords():

System.IndexOutOfRangeException was unhandled
  HResult=-2146233080
  Message=Index was outside the bounds of the array.
  Source=FileHelpers
  StackTrace:
       at FileHelpers.RecordOperations.ValuesToRecord(Object[] values)
       at FileHelpers.DataLink.DataStorage.ValuesToRecord(Object[] values)
       at FileHelpers.ExcelNPOIStorage.ExcelNPOIStorage.ExtractRecords()
       at Test.Controller.UalExcelReader.ReadInput(String pathToFile) in c:\TEMP\test\Test\Test\Test\Controller\UalExcelReader.cs:line 17
       at Test.App.OnStartup(StartupEventArgs eventArgs) in c:\TEMP\test\Test\Test\Test\App.xaml.cs:line 23
       at System.Windows.Application.<.ctor>b__1(Object unused)
       at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
       at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
       at System.Windows.Threading.DispatcherOperation.InvokeImpl()
       at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
       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.Windows.Threading.DispatcherOperation.Invoke()
       at System.Windows.Threading.Dispatcher.ProcessQueue()
       at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
       at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
       at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
       at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
       at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
       at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
       at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
       at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
       at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
       at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
       at System.Windows.Threading.Dispatcher.Run()
       at System.Windows.Application.RunDispatcher(Object ignore)
       at System.Windows.Application.RunInternal(Window window)
       at System.Windows.Application.Run(Window window)
       at System.Windows.Application.Run()
       at Test.App.Main() in c:\TEMP\test\Test\Test\Test\obj\Debug\App.g.cs:line 0
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       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:

我是否正確使用它? 有沒有我可以看的例子?

1) 當您的 Excel 工作表中有空白單元格時,可能會發生此錯誤。 這似乎是ExcelNPOIStorage檢索給定行值的方式中的一個潛在問題。

NPOI 使用NPOI.CellWalk遍歷每一行中的單元格,這似乎跳過了空白單元格。 因此, Values數組比預期的空白單元格數量要短。

看起來需要采用不同的方法,如下所述: http : //poi.apache.org/spreadsheet/quick-guide.html#Iterator

2)當不存在時可能導致空白單元格的東西具有不正確的StartRowStartColumn值。

StartRowStartColumn的智能注釋相反,對於ExcelNPOIStorage它們是基於 0 的(而在ExcelStorage它們是基於 1)

來源: https : //github.com/MarcosMeli/FileHelpers/blob/master/FileHelpers.ExcelNPOIStorage/Test/Program.cs

鑒於我遇到的問題,我會ExcelStorage上面的評論並使用舊的ExcelStorage類,它更可靠,缺點是它依賴於 Excel Interop。

NPOI 庫中的 MissingCellPolicy 在 HSSFWorkbook 和 XSSFWorkbook 類上默認設置為 MissingCellPolicy.RETURN_NULL_AND_BLANK。

在相關工作簿實例上將值更改為 MissingCellPolicy.CREATE_NULL_AS_BLANK 可以解決該問題。

FileHelpers.ExcelNPOIStorage
ExcelNPOIStorage.cs(OpenWorkbook 方法)
修復第 101 行

  private void OpenWorkbook(string filename)
    {
        FileInfo info = new FileInfo(filename);
        if (info.Exists == false)
            throw new FileNotFoundException(string.Concat("Excel File '", filename, "' not found."), filename);

        using (FileStream file = new FileStream(filename, FileMode.Open, FileAccess.Read)) {
            var extension = Path.GetExtension(filename);
            if (extension.ToLowerInvariant() == ".xlsx" || extension.ToLowerInvariant() == ".xlsm")
            {
                mWorkbook = new XSSFWorkbook(file);
            }
            else
                mWorkbook = new HSSFWorkbook(file);
            // Next line fix
            Line 101 - mWorkbook.MissingCellPolicy = MissingCellPolicy.CREATE_NULL_AS_BLANK;
            // Previous line fix  
            if (String.IsNullOrEmpty(SheetName))
                mSheet = mWorkbook.GetSheetAt(mWorkbook.ActiveSheetIndex);  
            else {
                try {
                    mSheet = mWorkbook.GetSheet(SheetName);
                    if (mSheet == null) {
                        throw new ExcelBadUsageException(string.Concat("The sheet '",
                            SheetName,
                            "' was not found in the workbook."));
                    }

                    var sheetIndex = mWorkbook.GetSheetIndex(mSheet);
                    mWorkbook.SetActiveSheet(sheetIndex);
                }
                catch {
                    throw new ExcelBadUsageException(string.Concat("The sheet '",
                        SheetName,
                        "' was not found in the workbook."));
                }
            }
        }
    }

在 github 存儲庫上的修復程序的 URL 下方

https://github.com/MarcosMeli/FileHelpers/pull/291

我認為空單元格是一個問題。 在我的文件中,我只是在文件中圍繞數據制作了邊緣,這對我有幫助。 嘗試用鼠標標記數據並打開字段周圍的邊緣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM