2016-06-06 13 views
8

Mam aplikację mvc asp.net hostowaną na IIS. Mam formularz, z którego użytkownicy przesyłają pliki Excela zawierające 50k + wiersze. Czytałem plik excel z następującym kodem C#.Czytanie limitowanych wierszy z pliku Excela przesłanych w usługach IIS

public DataTable GetExcelDataTable(string fileName) 
    { 
     string connectionString = Path.GetExtension(fileName) == "xls" ? 
      string.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data source={0}; Extended Properties=Excel 8.0;", fileName) : 
      string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0}; Extended Properties=Excel 12.0;", fileName); 

     var conn = new OleDbConnection(connectionString); 
     using (var adapter = new OleDbDataAdapter("SELECT * FROM [Sheet1$]", conn)) 
     { 
      var ds = new DataSet(); 

      adapter.Fill(ds); 

      DataTable data = ds.Tables[0]; 

      conn.Close(); 
      conn.Dispose(); 
      adapter.Dispose(); 
      return data; 
     } 
    } 

Problem polega na tym, że odczytuje tylko do 30 tys. Wierszy, ale nigdy do całego pliku Excela.

Co ciekawe, mogę czytać (z tym samym kodem) wszystkie wiersze, jeśli uruchomię aplikację mvc z visual studio, ale znowu, nigdy z IIS (IIS jest również na mojej maszynie) hostowanej stronie.

Wszelkie pomysły, dlaczego tak się dzieje?

+1

jakiegokolwiek błędu można uzyskać po przeczytaniu 30k rekordy? –

+1

nie, nie. Nie dostaję żadnych błędów.nie ma znaczenia, czy jego iis lub iisexpress (poprzez vs) – levi

+2

Może pomóc w sprawdzeniu, jak wyglądają twoje pliki konfiguracyjne, ponieważ Twoje dane mogą przekraczać limity czytników. –

Odpowiedz

4

Czy jesteś w stanie opublikować niektóre specyfikacje swojego serwera? Czy to jest VM i chmura oparta na jakiejś szansie? W przeszłości były skuteczne przy użyciu:

  1. Koogra: https://sourceforge.net/projects/koogra/
  2. NPOI: http://npoi.codeplex.com/

    Aby odczytać pliki xls, ale jeśli można ograniczyć swoje pliki do .xlsx użyłbym ClosedXML. Przeczytałem mnóstwo dużych plików 50K + z ClosedXML na mocnej maszynie VM na Azure bez problemu. Mam wrażenie, że uderzasz w ścianę przestrzeni użytkownika na serwerze. Jeśli użytkownik trafia na taki procent, osiąga limit wykorzystania i kończy zadanie.

+1

, ale czy specyfikacja serwera ma znaczenie? ponieważ działa na VS wykonywane IISExpress na localhost, ale nie tylko na IIS (również localhost) – levi

+1

Oczywiście, IIS na Windows Server 2003+ ma zwyczaj blokować użytkowników, gdy zaczynają maksymalizować zasoby. Moja pierwsza myśl była taka, że ​​uderzyła w znak 30k i zrzuciła połączenie z powodu uderzenia w jakiś próg. Tylko przeczucie naprawdę. –

4

Ten problem można rozwiązać, odczytując dane w dwóch częściach, takich jak 25K + 25k = 50K. Wystarczy zaktualizować kwerendę wybierającą jak:

SELECT TOP 25000 * FROM [Sheet1$] 
+1

jak byś przeczytał drugą część? – levi

+1

Nie jestem pewien, ale coś w rodzaju hałaśliwego rodzaju rzeczy, które musisz użyć – Adarsh

+0

Naprawdę nie jest to zły sposób na to, można nawet rozpocząć dwa wątki jeden odczyt z góry, drugi na dole i zakończyć go znacznie szybciej. Zrobiłaby to prosta pętla for z maksymalną ilością wierszy/2. –

2

Utworzyłem małą próbkę na mojej stronie, dzięki czemu korzystanie z SELECT TOP wraz z ORDER BY następnie można uzyskać wyniki:

Sprawdź Kod:

public DataSet GetExcelDataTable(string fileName) 
    { 
     string connectionString = Path.GetExtension(fileName) == "xls" ? 
      string.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data source={0}; Extended Properties=Excel 8.0;", fileName) : 
      string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0}; Extended Properties=Excel 12.0;", fileName); 

     var conn = new OleDbConnection(connectionString); 

     DataTable data = new DataTable(); 
     DataTable data2 = new DataTable(); 
     var ds = new DataSet(); 

     using (var adapter = new OleDbDataAdapter("SELECT TOP 25000 Name, Surname FROM [Sheet1$] ORDER BY Name asc", conn)) 
     { 
      adapter.Fill(data); 
     } 

     using (var adapter = new OleDbDataAdapter("SELECT TOP 25000 Name, Surname FROM [Sheet1$] ORDER BY Name desc", conn)) 
     { 
      adapter.Fill(data2); 
     } 

     if (data.Rows.Count > 0)ds.Tables.Add(data); 
     if (data2.Rows.Count > 0) ds.Tables.Add(data2); 

     return ds; 
    } 
5

w tym podejściu nie ma potrzeby instalowania programu Excel na komputerze docelowym

NPOI.SS.UserModel.IWorkbook hssfworkbook; 

    bool InitializeWorkbook(string path) 
    { 
     try 
     { 
      if (path.ToLower().EndsWith(".xlsx")) 
      { 
       FileStream file1 = File.OpenRead(path); 
       hssfworkbook = new XSSFWorkbook(file1); 
      } 
      else 
      { 
       //read the template via FileStream, it is suggested to use FileAccess.Read to prevent file lock. 
       //book1.xls is an Excel-2007-generated file, so some new unknown BIFF records are added. 
       using (FileStream file = new FileStream(path, FileMode.Open, FileAccess.Read)) 
       { 
        hssfworkbook = new HSSFWorkbook(file); 
       } 
      } 
      return true; 
     } 
     catch 
     { 
      return false; 
     } 
    } 

w następujących przypadkach:

public DataTable GetExcelDataTable(NPOI.SS.UserModel.IWorkbook hssfworkbook, int rowCount) 
    { 
     NPOI.SS.UserModel.ISheet sheet = hssfworkbook.GetSheetAt(0); 
     System.Collections.IEnumerator rows = sheet.GetRowEnumerator(); 

     DataTable dt = new DataTable(); 

     bool skipReadingHeaderRow = rows.MoveNext(); 
     if (skipReadingHeaderRow) 
     { 
      dynamic row; 
      if (rows.Current is NPOI.HSSF.UserModel.HSSFRow) 
       row = (NPOI.HSSF.UserModel.HSSFRow)rows.Current; 
      else 
       row = (NPOI.XSSF.UserModel.XSSFRow)rows.Current; 
      for (int i = 0; i < row.LastCellNum; i++) 
      { 
       ICell cell = row.GetCell(i); 
       if (cell != null) 
       { 
        dt.Columns.Add(cell.ToString()); 
       } 
       else 
       { 
        dt.Columns.Add(string.Empty); 
       } 
      } 
     } 
     int cnt = 0; 
     while (rows.MoveNext() && cnt < rowCount) 
     { 
      cnt++; 
      dynamic row; 
      if (rows.Current is NPOI.HSSF.UserModel.HSSFRow) 
       row = (NPOI.HSSF.UserModel.HSSFRow)rows.Current; 
      else 
       row = (XSSFRow)rows.Current; 

      DataRow dr = dt.NewRow(); 

      for (int i = 0; i < row.LastCellNum; i++) 
      { 
       ICell cell = row.GetCell(i); 

       if (cell == null) 
       { 
        dr[i - 1] = null; 
       } 
       else if (i > 0) 
       { 

        dr[i - 1] = cell.ToString(); 
       } 
      } 
      dt.Rows.Add(dr); 
     } 

     return dt; 
    } 

lub:

 public DataTable GetExcelDataTable(NPOI.SS.UserModel.IWorkbook hssfworkbook, int rowCount) 
    { 

     NPOI.SS.UserModel.ISheet sheet = hssfworkbook.GetSheetAt(0); 
     System.Collections.IEnumerator rows = sheet.GetRowEnumerator(); 
     DataTable dt = new DataTable(); 
     bool skipReadingHeaderRow = rows.MoveNext(); 
     if (skipReadingHeaderRow) 
     { 
      dynamic row; 
      if (rows.Current is NPOI.HSSF.UserModel.HSSFRow) 
       row = (NPOI.HSSF.UserModel.HSSFRow)rows.Current; 
      else 
       row = (NPOI.XSSF.UserModel.XSSFRow)rows.Current; 
      for (int i = 0; i < row.LastCellNum; i++) 
      { 
       ICell cell = row.GetCell(i); 
       if (cell != null) 
       { 
        dt.Columns.Add(cell.ToString()); 
       } 
       else 
       { 
        dt.Columns.Add(string.Empty); 
       } 
      } 
     } 
     int cnt = 0; 
     while (rows.MoveNext() && cnt < rowCount) 
     { 
      cnt++; 
      dynamic row; 
      if (rows.Current is NPOI.HSSF.UserModel.HSSFRow) 
       row = (HSSFRow)rows.Current; 
      else 
       row = (XSSFRow)rows.Current; 
      DataRow dr = dt.NewRow(); 

      for (int i = 0; i < row.LastCellNum; i++) 
      { 
       ICell cell = row.GetCell(i); 

       if (cell == null && i > 0) 
       { 
        dr[i - 1] = null; 
       } 
       else if (i > 0) 
       { 
        switch (cell.CellType) 
        { 
         case CellType.Blank: 
          dr[i - 1] = "[null]"; 
          break; 
         case CellType.Boolean: 
          dr[i - 1] = cell.BooleanCellValue; 
          break; 
         case CellType.Numeric: 
          dr[i - 1] = cell.ToString(); 
          break; 
         case CellType.String: 
          dr[i - 1] = cell.StringCellValue; 
          break; 
         case CellType.Error: 
          dr[i - 1] = cell.ErrorCellValue; 
          break; 
         case CellType.Formula: 
         default: 
          dr[i - 1] = "=" + cell.CellFormula; 
          break; 
        } 

       } 
      } 
      dt.Rows.Add(dr); 
     } 

     return dt; 
    } 

czyli

public DataTable GetExcelDataTable(NPOI.SS.UserModel.IWorkbook hssfworkbook, int segment, int rowCount) 
    { 
     NPOI.SS.UserModel.ISheet sheet = hssfworkbook.GetSheetAt(0); 
     System.Collections.IEnumerator rows = sheet.GetRowEnumerator(); 

     DataTable dt = new DataTable(); 

     bool skipReadingHeaderRow = rows.MoveNext(); 
     if (skipReadingHeaderRow) 
     { 
      dynamic row; 
      if (rows.Current is NPOI.HSSF.UserModel.HSSFRow) 
       row = (NPOI.HSSF.UserModel.HSSFRow)rows.Current; 
      else 
       row = (NPOI.XSSF.UserModel.XSSFRow)rows.Current; 
      for (int i = 0; i < row.LastCellNum; i++) 
      { 
       ICell cell = row.GetCell(i); 
       if (cell != null) 
       { 
        dt.Columns.Add(cell.ToString()); 
       } 
       else 
       { 
        dt.Columns.Add(string.Empty); 
       } 
      } 
     } 
     for (int i = 0; i < (segment - 1)*rowCount; i++) 
     { 
      if (!rows.MoveNext()) break; 
     } 

     int cnt = 0; 
     while (rows.MoveNext() && cnt < rowCount) 
     { 
      cnt++; 
      dynamic row; 
      if (rows.Current is NPOI.HSSF.UserModel.HSSFRow) 
       row = (NPOI.HSSF.UserModel.HSSFRow) rows.Current; 
      else 
       row = (NPOI.XSSF.UserModel.XSSFRow) rows.Current; 

      DataRow dr = dt.NewRow(); 

      for (int i = 0; i < row.LastCellNum; i++) 
      { 
       ICell cell = row.GetCell(i); 

       if (cell == null) 
       { 
        dr[i - 1] = null; 
       } 
       else if (i > 0) 
       { 
        switch (cell.CellType) 
        { 
         case CellType.Blank: 
          dr[i - 1] = "[null]"; 
          break; 
         case CellType.Boolean: 
          dr[i - 1] = cell.BooleanCellValue; 
          break; 
         case CellType.Numeric: 
          dr[i - 1] = cell.ToString(); 
          break; 
         case CellType.String: 
          dr[i - 1] = cell.StringCellValue; 
          break; 
         case CellType.Error: 
          dr[i - 1] = cell.ErrorCellValue; 
          break; 
         case CellType.Formula: 
         default: 
          dr[i - 1] = "=" + cell.CellFormula; 
          break; 
        } 
       } 
      } 
      dt.Rows.Add(dr); 
     } 
     return dt; 
    } 
+0

Właściwie, jeśli chcesz używać OleDB do odczytu plików Excel, wystarczy zainstalować sterowniki Microsoft JET, które są bezpłatne. –

+0

@MaxLambertini Istnieje tak wiele rozwiązań dla każdego problemu, więc to zależy od nas, aby wybrać jeden w zależności od różnych okoliczności –

2

Można spróbować wypełnić DataTable czytając fragment rzędach po fragmencie zamiast robić jedną pojedynczą czytać.

Piękno tego podejścia polega na tym, że nie jesteś ograniczony do rekordu 50 000, ale dostosowuje się on do faktycznej liczności danych.

Ten kod działa na moim komputerze (Win10 x64 VS2010 Express):

public DataTable GetExcelDataTable(string fileName) 
    { 
     string connectionString = Path.GetExtension(fileName) == "xls" ? 
      string.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data source={0}; Extended Properties=Excel 8.0;", fileName) : 
      string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0}; Extended Properties=Excel 12.0;", fileName); 

     var conn = new OleDbConnection(connectionString); 
     using (var adapter = new OleDbDataAdapter("SELECT * FROM [Sheet1$]", conn)) 
     { 
      var dt = new DataTable(); 

      int recordRead = 0; 
      int recordCur = 0;  //starting point 
      int recordStep = 6789; //records to read 

      //here, we read **recordStep** records instead of reading 
      //all excel data 
      do 
      { 
       recordRead = adapter.Fill(recordCur, recordStep, dt); 
       recordCur += recordRead; //increment starting point accordingly 
      } while (recordRead > 0); 


      conn.Close(); 
      conn.Dispose(); 
      adapter.Dispose(); 
      return dt; 
     } 
    } 
Powiązane problemy