2012-05-10 5 views
7

Tôi đang cố viết một tệp Excel từ một máy chủ web ASP.NET sử dụng OpenXML. Tôi có khoảng 2100 hồ sơ và mất khoảng 20-30 giây để làm điều này. Bất kỳ cách nào tôi có thể làm cho nó nhanh hơn? Lấy 2100 hàng từ db mất một phần nhỏ của một giây. Không chắc chắn lý do tại sao thao tác chúng trong bộ nhớ sẽ mất nhiều thời gian hơn.Các vấn đề về hiệu suất OpenXML .NET

Lưu ý: ExcelWriter là lớp tùy chỉnh của chúng tôi, nhưng tất cả các phương pháp của nó là trực tiếp từ mã trong liên kết này, http://msdn.microsoft.com/en-us/library/cc861607.aspx

public static MemoryStream CreateThingReport(List<Thing> things, MemoryStream template) 
    { 
     SpreadsheetDocument spreadsheet = SpreadsheetDocument.Open(template, true); 
     WorksheetPart workSheetPart = spreadsheet.WorkbookPart.WorksheetParts.First(); 

     SharedStringTablePart sharedStringPart = spreadsheet.WorkbookPart.GetPartsOfType<SharedStringTablePart>().First(); 

     Cell cell = null; 
     int index = 0; 

     //create cell formatting for header text 
     Alignment wrappedAlignment = new Alignment { WrapText = true }; 
       uint rowOffset = 2; 

    foreach (Thing t in things) 
     { 
      //Received Date 
      cell = ExcelWriter.InsertCellIntoWorksheet("A", rowOffset, workSheetPart); 
      index = ExcelWriter.InsertSharedStringItem(t.CreateDate.ToShortDateString(), sharedStringPart); 
      cell.CellValue = new CellValue(index.ToString()); 
      cell.DataType = new DocumentFormat.OpenXml.EnumValue<CellValues>(CellValues.SharedString); 

      //Car Part Name 
      cell = ExcelWriter.InsertCellIntoWorksheet("B", rowOffset, workSheetPart); 
      index = ExcelWriter.InsertSharedStringItem(t.CarPart.Name, sharedStringPart); 
      cell.CellValue = new CellValue(index.ToString()); 
      cell.DataType = new DocumentFormat.OpenXml.EnumValue<CellValues>(CellValues.SharedString); 

    rowOffset++; 
    } 

workSheetPart.Worksheet.Save(); 

     spreadsheet.WorkbookPart.Workbook.Save(); 
     spreadsheet.Close(); 

     return template; 

Trả lời

7

Vì vậy, nó trông giống như một người nào đó trong tài liệu cộng đồng MSDN chạy vào tác động hiệu suất tương tự. Mã dưới đây rất kém hiệu quả. Có người được đề xuất sử dụng bảng băm.

Đối với giải pháp của chúng tôi, chúng tôi vừa xóa hoàn toàn chuỗi đã chia sẻ và đi từ 1:03 giây đến 0:03 giây trong thời gian tải xuống.

//Old: (1:03) 
      cell = ExcelWriter.InsertCellIntoWorksheet("A", rowOffset, workSheetPart); 
      index = ExcelWriter.InsertSharedStringItem(thing.CreateDate.ToShortDateString(), sharedStringPart); 
      cell.CellValue = new CellValue(index.ToString()); 
      cell.DataType = new DocumentFormat.OpenXml.EnumValue<CellValues>(CellValues.SharedString); 

//New: (0:03) 
      cell = ExcelWriter.InsertCellIntoWorksheet("A", rowOffset, workSheetPart); 
      cell.CellValue = new CellValue(thing.CreateDate.ToShortDateString()); 
       cell.DataType = new DocumentFormat.OpenXml.EnumValue<CellValues>(CellValues.String); 

MSDN Documents (giải pháp chậm, họ nên sử dụng một bảng Hash thay)

 private static int InsertSharedStringItem(string text, SharedStringTablePart   shareStringPart) 
    { 
// If the part does not contain a SharedStringTable, create one. 
if (shareStringPart.SharedStringTable == null) 
{ 
    shareStringPart.SharedStringTable = new SharedStringTable(); 
} 

int i = 0; 

// Iterate through all the items in the SharedStringTable. If the text already exists, return its index. 
foreach (SharedStringItem item in shareStringPart.SharedStringTable.Elements<SharedStringItem>()) 
{ 
    if (item.InnerText == text) 
    { 
     return i; 
    } 

    i++; 
} 

// The text does not exist in the part. Create the SharedStringItem and return its index. 
shareStringPart.SharedStringTable.AppendChild(new SharedStringItem(new DocumentFormat.OpenXml.Spreadsheet.Text(text))); 
shareStringPart.SharedStringTable.Save(); 

return i; 
} 
+0

Tôi đang đối mặt với cùng một vấn đề ... Tôi cần viết 1000+ hàng và trong một số trường hợp 10000+ hàng và nó đang nhận được chậm như địa ngục ... Ở đây bạn nói bạn có thể sử dụng bảng băm bạn có thể cho một ví dụ như thế nào? hoặc nếu có bất kỳ thứ gì khác bạn sử dụng để cải thiện hiệu suất ... – kunjee

+0

Tôi đang xem 500 nghìn hàng. Bạn đã thực hiện các cải tiến nào khác từ bài đăng này bạn có thể chia sẻ? Tôi đã chuyển sang phương thức SAX để giảm thiểu mức sử dụng bộ nhớ. Và tôi thấy khoảng 1000 hàng mỗi ~ 1,1 giây. Nếu bạn nhận được nhanh hơn này xin vui lòng chia sẻ. – CaptainBli

2

@kunjee

Nếu bạn muốn thực hiện tạo mọi đối tượng yêu cầu trả trước nên không được kiểm tra trên mỗi gọi phương thức này. Đây là lý do tại sao SharedStringTable được chuyển thành tham số thay vì một phần.

Từ điển dành cho tra cứu nhanh, được lập chỉ mục, có hiệu suất tốt hơn so với vòng lặp for. Có bit nhanh hơn so với hashtables vì ​​được gõ mạnh nên không cần đấm bốc. Được đánh máy mạnh mẽ là một lợi ích tuyệt vời anyway.

private static int InsertSharedStringItem(string sharedString, SharedStringTable sharedStringTable, Dictionary<string, int> sharedStrings) 
{ 
    int sharedStringIndex; 

    if (!sharedStrings.TryGetValue(sharedString, out sharedStringIndex)) 
    { 
     // The text does not exist in the part. Create the SharedStringItem now. 
     sharedStringTable.AppendChild(new SharedStringItem(new Text(sharedString))); 

     sharedStringIndex = sharedStrings.Count; 

     sharedStrings.Add(sharedString, sharedStringIndex); 
    } 

    return sharedStringIndex; 
} 
4

@The Internet

Lưu ý rằng loại Chuỗi dữ liệu thực sự cho công thức, cho văn bản nên dùng InlineString. Xem 17.18.11 ST_CellType (Type Cell):

  • inlineStr (Inline String) - tế bào có chứa một (inline) chuỗi phong phú, ví dụ: , người ta không trong bảng chuỗi chia sẻ. Nếu loại ô này được sử dụng, thì giá trị ô trong phần tử là thay vì phần tử v trong ô (phần tử c).
  • str (Chuỗi) - Ô chứa chuỗi công thức.
2

Các improment lớn là nhiều Save() chức năng ra khỏi vòng lặp

//Save data 
     shareStringPart.SharedStringTable.Save(); 
     worksheetPart.Worksheet.Save(); 

Đối với 500 hồ sơ, đối với tôi nó thay đổi từ 10 phút đến 1 phút.

+0

Đây là một phần thực sự quan trọng khi làm việc với OpenXML - vì nhiều phần phụ yêu cầu lưu, chúng ta có khuynh hướng lưu các phương thức hành động đơn lẻ hoặc vòng lặp thay vì ở phạm vi bên ngoài, nơi tiết kiệm hơn. –