2012-07-10 16 views
6

'a taşıyın Bir Excel elektronik tablosunu HTML'ye dönüştürmek için Epplus kullanıyorum. Şimdiye kadar çok, çok iyi gidiyor, tek bir şey hariç ... birleştirilmiş hücreler yayıyor. Mantığı doğru göremiyorum. Topluluğun bununla nasıl başa çıkacağını görmek için dışarı atabileceğimi düşündüm. İşte benim kodum şu ana kadar.Epplus Excel dönüşümde birleştirilmiş hücreleri HTML

public String ParseExcelStamps(String FileName) 
{ 
    FileInfo theFile = new FileInfo(FileName); 
    String html = ""; 
    using (ExcelPackage xlPackage = new ExcelPackage(theFile)) 
    { 
     var workbook = xlPackage.Workbook; 
     if (workbook != null) 
     { 
      for (int j = 1; j <= workbook.Worksheets.Count; j++) 
      { 
       Tab tab = new Tab(); 
       html+= "<table style='border-collapse: collapse;font-family:arial;'><tbody>"; 
       var worksheet = workbook.Worksheets[j]; 
       tab.Title = worksheet.Name; 
       if (worksheet.Dimension == null) { continue; } 
       int rowCount = 0; 
       int maxColumnNumber = worksheet.Dimension.End.Column; 
       var convertedRecords = new List<List<string>>(worksheet.Dimension.End.Row); 
       var excelRows = worksheet.Cells.GroupBy(c => c.Start.Row).ToList(); 
       excelRows.ForEach(r => 
       { 
        rowCount++; 
        html += String.Format("<tr>"); 
        var currentRecord = new List<string>(maxColumnNumber); 
        var cells = r.OrderBy(cell => cell.Start.Column).ToList(); 
        Double rowHeight = worksheet.Row(rowCount).Height; 
        for (int i = 1; i <= maxColumnNumber; i++) 
        { 
         var currentCell = cells.Where(c => c.Start.Column == i).FirstOrDefault(); 

         //look aheads for colspan and rowspan 
         ExcelRangeBase previousCellAbove = null; 
         ExcelRangeBase previousCell = null; 
         ExcelRangeBase nextCell = null; 
         ExcelRangeBase nextCellBelow = null; 
         try { previousCellAbove = worksheet.Cells[rowCount-1, i]; }catch (Exception) { } 
         try { previousCell = worksheet.Cells[rowCount, (i - 1)]; }catch (Exception) { } 
         try { nextCell = worksheet.Cells[rowCount, (i + 1)]; }catch (Exception) { } 
         try { nextCellBelow = worksheet.Cells[rowCount+1, i]; }catch (Exception) { } 

         if ((previousCell != null) && (previousCell.Merge) && (currentCell != null) && (currentCell.Merge)){continue;} 
         if ((previousCellAbove != null) && (previousCellAbove.Merge) && (currentCell != null)) {continue; } 

         if (currentCell == null) 
         { 
          html += String.Format("<td>{0}</td>", String.Empty); 
         } 
         else 
         { 
          int colSpan = 1; 
          int rowSpan = 1; 
          if ((nextCell != null) && (nextCell.Merge) && (currentCell.Merge)) { 
           colSpan = 2; 
           // Console.WriteLine(String.Format("{0} - {1}", currentCell.Address, nextCell.Address)); 
          } 

          if ((nextCellBelow != null) && (nextCellBelow.Merge) && (currentCell.Merge)) { 
           Console.WriteLine(String.Format("{0} - {1}", currentCell.Address, nextCellBelow.Address)); 
          } 

          html += String.Format("<td colspan={0} rowspan={1}>{2}</td>", colSpan, rowSpan, currentCell.Value); 
         } 
        } 
        html += String.Format("</tr>"); 
       }); 
       html += "</tbody></table>"; 
      }//worksheet loop 
     } 
    } 
    return html; 
} 
+0

ben isteyeceğini ilk soru bu Hücreleri çözmek için çalışma sayfasını düzenlemek mümkündür olup olmadığıdır. Denemeye değer? –

+0

Kaynağı düzenlemek zorunda kalmadan bunu gerçekten çözmek istiyorum, ayrıca kaynak belgelerin kontrolünde değilim. – BigBadOwl

+0

Buradaki hile, Epplus'un cell.merge öğesinin yalnızca bir Boole döndürdüğüdür. Birleştirilmiş olup olmadığını görmek için bir hücreyi işaretlediğinizde, önce, sonra, altında veya üzerinde hücreyle birleştirilip birleştirilmediğini söyleyemezsiniz ve bu nedenle bir colspan veya rowspan olup olmadığını belirleyemezsiniz. – BigBadOwl

cevap

13

Bu, tam olarak neye ihtiyacınız olduğunu söyleyebildiğim kadarıyla. Eksik olan şey, çalışma sayfasındaki tüm birleştirilmiş hücreleri listeleyen çalışma sayfasındaki MergedCells özelliğiydi.

Kodum satır boşluklarını, sütun aralıklarını ve her ikisini aynı anda işler. Hem satır, hem de sütun ve satır/sütun kapsayan bir elektronik tablo ile bazı testler yaptım. Her durumda mükemmel çalıştılar.

Kod

int colSpan = 1; 
int rowSpan = 1; 

//check if this is the start of a merged cell 
ExcelAddress cellAddress = new ExcelAddress(currentCell.Address); 

var mCellsResult = (from c in worksheet.MergedCells 
       let addr = new ExcelAddress(c) 
        where cellAddress.Start.Row >= addr.Start.Row && 
        cellAddress.End.Row <= addr.End.Row && 
        cellAddress.Start.Column >= addr.Start.Column && 
        cellAddress.End.Column <= addr.End.Column 
       select addr); 

if (mCellsResult.Count() >0) 
{ 
    var mCells = mCellsResult.First(); 

    //if the cell and the merged cell do not share a common start address then skip this cell as it's already been covered by a previous item 
    if (mCells.Start.Address != cellAddress.Start.Address) 
     continue; 

    if(mCells.Start.Column != mCells.End.Column) { 
     colSpan += mCells.End.Column - mCells.Start.Column; 
    } 

    if (mCells.Start.Row != mCells.End.Row) 
    { 
     rowSpan += mCells.End.Row - mCells.Start.Row; 
    } 
} 

//load up data 
html += String.Format("<td colspan={0} rowspan={1}>{2}</td>", colSpan, rowSpan, currentCell.Value); 
+0

Bu harika, çekicilik gibi çalışıyor. Son olarak bir Excel belgesini HTML olarak gösterebilmek çok güzel. Kodun tamamını yakında GitHub'a koyacağım ve bağlantıyı buraya göndereceğim. Teşekkürler Peter, çözümün 50 puan ve üstü. – BigBadOwl

+1

currentCell.Value öğenizin çevresine bir HtmlEncode yerleştirdiğinizden emin olun. Bir < or > işareti olduğu için, oluşturma işleminde bazı sorunlara neden olabileceğinden eminim. – Peter

+2

+1, küçük bir gelişme: her zaman 'Enumerable.Count()' yerine 'Enumerable.Any()' kullanın. Birincisi, herhangi bir elementin var olup olmadığını kontrol eder, ikincisi tüm elemanları tekrarlar. Daha iyi: 'if (mCellsResult.Any())' –