2016-05-30 19 views
0

データベーステーブルからたくさんのデータをexcel(xls/xlsx)ファイルにエクスポートする必要があります。 簡単に10万行以上になる可能性があります。大量のデータを書き出してCをエクセルする#

私はOfficeをインストールする必要のないオープンソースのソリューションが必要です(SpreadsheetGearとinteropソリューションは私のためには機能しません)。

OpenXML SDKとEPPlusの2つのライブラリを確認しています。 OpenXMLのSDKについては

私はこの方法が見つかりました:

private static void Write(string fileName, int numRows, int numCols) 
     { 
      using (var spreadsheetDocument = SpreadsheetDocument.Open(fileName, true)) 
      { 
       WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart; 
       WorksheetPart worksheetPart = workbookPart.WorksheetParts.First(); 

       string origninalSheetId = workbookPart.GetIdOfPart(worksheetPart); 

       WorksheetPart replacementPart = workbookPart.AddNewPart<WorksheetPart>(); 
       string replacementPartId = workbookPart.GetIdOfPart(replacementPart); 

       using (OpenXmlReader reader = OpenXmlReader.Create(worksheetPart)) 
       { 
        using (OpenXmlWriter writer = OpenXmlWriter.Create(replacementPart)) 
        { 
         Row row = new Row(); 
         Cell cell = new Cell(); 
         //CellFormula cellFormula = new CellFormula(); 
         //cellFormula.CalculateCell = true; 
         //cellFormula.Text = "RAND()"; 
         //cell.Append(cellFormula); 
         CellValue cellValue = new CellValue("val val"); 
         cell.Append(cellValue); 

         while (reader.Read()) 
         { 
          if (reader.ElementType == typeof(SheetData)) 
          { 
           if (reader.IsEndElement) 
            continue; 
           writer.WriteStartElement(new SheetData()); 

           for (int rowNumber = 0; rowNumber < numRows; rowNumber++) 
           { 
            writer.WriteStartElement(row); 
            for (int col = 0; col < numCols; col++) 
            { 
             writer.WriteElement(cell); 
            } 
            writer.WriteEndElement(); 
           } 

           writer.WriteEndElement(); 
          } 
          else 
          { 
           if (reader.IsStartElement) 
           { 
            writer.WriteStartElement(reader); 
           } 
           else if (reader.IsEndElement) 
           { 
            writer.WriteEndElement(); 
           } 
          } 
         } 
        } 
       } 

       Sheet sheet = workbookPart.Workbook.Descendants<Sheet>().First(s => s.Id.Value.Equals(origninalSheetId)); 
       sheet.Id.Value = replacementPartId; 
       workbookPart.DeletePart(worksheetPart); 
      } 
     } 

をしかし、それはOut of memory例外がスローされます。 私はbatch orientedアプローチが必要であり、Excel文書の最後にappendデータを入力できるようにする必要があります。 残念ながら、OpenXML SDKで行を追加する方法が見つかりませんでした。

また、EPPlus soluionLoadFromCollectionの方法でチェックしました。 とIDataReaderをサポートしていますが、コードのその時点でdatareaderがありません。

質問:ライターのような既存のシートxls/xlsxファイルにデータを追加する方法はありますか? OpenXMLWrite rのようにOpenXML SDKにあります。

UPD。 Excelは明らかに1000万行をサポートしていません。メモリ不足の例外を除いて、1mの行と列を失いたくない。

UPD。 EPPlusサンプルが追加されました。 200k行は6分でエクスポートされ、最大1GBのRAMが必要です。

private const string TempFile = @"C:\Users\vnechyp\Desktop\temp.xlsx"; 

private static void EPPlusExport() 
{ 
    var random = new Random(); 

    var dt = new System.Data.DataTable(); 
    for (int i = 0; i < 15; i++) 
    { 
     dt.Columns.Add($"column_{i}"); 
    } 

    var values = Enumerable.Range(0, 15).Select(val => random.Next().ToString()).ToArray(); 

    for (int i = 0; i < 10000; i++) 
    { 
     dt.Rows.Add(values); 
    } 

    using (ExcelPackage excelPackage = new ExcelPackage()) 
    { 
     var workSheet = excelPackage.Workbook.Worksheets.Add("sheet"); 
     workSheet.Cells[1, 1].LoadFromDataTable(dt, true); 
     excelPackage.SaveAs(new FileInfo(TempFile)); 
    } 


    for (int i = 1; i < 50; i++) 
    { 
     Console.WriteLine($"Iteration: {i}"); 

     var updateRow = i*10000; 
     Console.WriteLine($"Rows: {updateRow}"); 

     FileInfo existingFile = new FileInfo(TempFile); 
     using (ExcelPackage excelPackage = new ExcelPackage(existingFile)) 
     { 
      // get the first worksheet in the workbook 
      ExcelWorksheet worksheet = excelPackage.Workbook.Worksheets[1]; 
      worksheet.Cells[updateRow, 1].LoadFromDataTable(dt, true); 
      excelPackage.SaveAs(new FileInfo(TempFile)); 
     } 
    } 
} 
+0

私はこれを「チュートリアルを探しています」と票決しました。私はEPPlusをこのタイプの操作に数回使用しました。彼らのウェブサイトには、既存のワークシートへの書き込みを続ける例がたくさんあります。あなたの問題は、あまりにも多くのデータをメモリに保存して一度にダンプするということです。ドキュメントを見続けるだけです。 – krillgar

+0

Excelは、そのサイズのデータ​​セットに適したコンテナではありません。 –

+0

@krillgarドキュメントを確認していただきありがとうございます。最後に私は何も見つけませんでした – makambi

答えて

2
+-----------------+-----------+--------------+---------------------+ 
|     | Max. Rows | Max. Columns | Max. Cols by letter | 
+-----------------+-----------+--------------+---------------------+ 
| Excel 365*  | 1,048,576 | 16,384  | XFD     | 
| Excel 2013  | 1,048,576 | 16,384  | XFD     | 
| Excel 2010  | 1,048,576 | 16,384  | XFD     | 
| Excel 2007  | 1,048,576 | 16,384  | XFD     | 
| Excel 2003  | 65,536 | 256   | IV     | 
| Excel 2002 (XP) | 65,536 | 256   | IV     | 
| Excel 2000  | 65,536 | 256   | IV     | 
| Excel 97  | 65,536 | 256   | IV     | 
| Excel 95  | 16,384 | 256   | IV     | 
| Excel 5   | 16,384 | 256   | IV     | 
+-----------------+-----------+--------------+---------------------+ 

あなたは1000万行のCSVファイルを使用することができますExcelにエクスポートする

+0

ご連絡ありがとうございます。それは私が知っておくべきことです。 残念ながら、csvはオプションではありません。 – makambi

0

私の新しいお気に入りの方法は、CSVが十分でないと仮定すると、オープンXML SDKを使用することです。以下のソリューションは、大規模なデータのエクスポートを実装する方法についてVincent Tom氏が執筆した素晴らしい記事にリンクしています。新しいユーザー向けにサンプルをわずかに整理しました。私はこれを自分で行うと

Export a large data query (60k+ rows) to Excel

は、私は基本的にのIQueryableの各ループのためのオープンXMLライターを使用し、そして。 ToList()を呼び出さないでください。そうしないと、メモリ内のすべてのデータを含むリストが生成され、ポイント全体が破棄されます。

たとえば、このテクニックを使用して190,000+レコードと87+の列を使用してExcelファイルをエクスポートしました。ここで試した他のExcelライブラリはすべて失敗しました。

関連する問題