2015-07-15 13 views
15

Sto tentando di esportare alcuni dati in un foglio Excel S1 i cui dati verrebbero visualizzati come viste imperniate nei prossimi due fogli S2 and S3. Sono in grado di creare un singolo pivot e funziona perfettamente. Ma quando creo due pivot, il conseguente file Excel viene danneggiato.ClosedXML - Creazione di più tabelle pivot

Con corrotto voglio dire,

Cliccando sì, ho questa -

Corrupt

Ecco il codice che sto usando per creare i perni -

using XL = ClosedXML.Excel; 
... 
XL.XLWorkbook wb = new XL.XLWorkbook(); 
dsData = Session["ExportData"] as DataSet; 

var sheet1 = wb.Worksheets.Add("output table"); 
sheet1.Cell(1, 1).InsertTable(dsData.Tables[0], "output table", true); 

// sheet1 is the reference sheet S1 
var dataRange = sheet1.RangeUsed(); 

// First Pivot 
XL.IXLWorksheet ptSheet1 = wb.Worksheets.Add("S2"); 

var pt1 = ptSheet1.PivotTables.AddNew("PivotTable1", ptSheet.Cell(3, 1), dataRange); 


pt1.ReportFilters.Add("CX"); 

pt1.RowLabels.Add("C1"); 
pt1.RowLabels.Add("C2"); 
pt1.RowLabels.Add("C3"); 
pt1.RowLabels.Add("C4"); 

pt1.ColumnLabels.Add("CL1"); 
pt1.ColumnLabels.Add("CL2"); 
pt1.ColumnLabels.Add("CL3"); 

pt1.Values.Add("V").SummaryFormula = XL.XLPivotSummary.Sum; 


// Second Pivot 
XL.IXLWorksheet ptSheet2 = wb.Worksheets.Add("S3"); 

var pt2 = ptSheet2.PivotTables.AddNew("PivotTable2", ptSheet1.Cell(3, 1), dataRange); 

pt2.ReportFilters.Add("QQ"); 

pt2.RowLabels.Add("C1"); 
pt2.RowLabels.Add("C2"); 

pt2.ColumnLabels.Add("CL1"); 
pt2.ColumnLabels.Add("CL2"); 
pt2.ColumnLabels.Add("CL3"); 

pt2.Values.Add("V").SummaryFormula = XL.XLPivotSummary.Sum; 

C1, C2, C3. C4 and V sono i nomi delle colonne nel mio foglio di riferimento S1.

+1

cosa intendi per rendering come corrotto? c'è qualche errore? per favore mostraci l'intero codice per esportare – jomsk1e

+0

@ jomsk1e Ho aggiornato la domanda, per favore controlla. –

+1

Sto riscontrando lo stesso identico problema. . hai mai trovato una soluzione o una soluzione? – leora

risposta

11

Il problema è causato da un bug di implementazione ClosedXML.

Può essere facilmente riprodotto utilizzando il seguente frammento di codice (una versione modificata del loro esempio Tabelle Pivot) e aprendo il file risultante in Excel:

static void CreateTestPivotTables(string filePath) 
{ 
    var wb = new XLWorkbook(); 

    var wsData = wb.Worksheets.Add("Data");    
    wsData.Cell("A1").Value = "Category"; 
    wsData.Cell("A2").Value = "A"; 
    wsData.Cell("A3").Value = "B"; 
    wsData.Cell("A4").Value = "B"; 
    wsData.Cell("B1").Value = "Number"; 
    wsData.Cell("B2").Value = 100; 
    wsData.Cell("B3").Value = 150; 
    wsData.Cell("B4").Value = 75; 
    var source = wsData.Range("A1:B4"); 

    for (int i = 1; i <= 2; i++) 
    { 
     var name = "PT" + i; 
     var wsPT = wb.Worksheets.Add(name); 
     var pt = wsPT.PivotTables.AddNew(name, wsPT.Cell("A1"), source); 
     pt.RowLabels.Add("Category"); 
     pt.Values.Add("Number") 
      .ShowAsPctFrom("Category").And("A") 
      .NumberFormat.Format = "0%"; 
    } 

    wb.SaveAs(filePath); 
} 

Il bug si trova in XLWorkbook_Save.cs-GeneratePivotTables metodo:

private static void GeneratePivotTables(WorkbookPart workbookPart, WorksheetPart worksheetPart, 
    XLWorksheet xlWorksheet, 
    SaveContext context) 
{ 
    foreach (var pt in xlWorksheet.PivotTables) 
    { 
     var ptCdp = context.RelIdGenerator.GetNext(RelType.Workbook); 

     var pivotTableCacheDefinitionPart = workbookPart.AddNewPart<PivotTableCacheDefinitionPart>(ptCdp); 
     GeneratePivotTableCacheDefinitionPartContent(pivotTableCacheDefinitionPart, pt); 

     var pivotCaches = new PivotCaches(); 
     var pivotCache = new PivotCache {CacheId = 0U, Id = ptCdp}; 

     pivotCaches.AppendChild(pivotCache); 

     workbookPart.Workbook.AppendChild(pivotCaches); 

     var pivotTablePart = 
      worksheetPart.AddNewPart<PivotTablePart>(context.RelIdGenerator.GetNext(RelType.Workbook)); 
     GeneratePivotTablePartContent(pivotTablePart, pt); 

     pivotTablePart.AddPart(pivotTableCacheDefinitionPart, context.RelIdGenerator.GetNext(RelType.Workbook)); 
    } 
} 

dalla linea workbookPart.Workbook.AppendChild(pivotCaches); che aggiunge multipla PivotCaches per workbookPart.Workbook mentre è consentito contenere 0 o 1.

Con questo detto, l'unico modo per risolvere il problema è all'interno del codice sorgente modificando il metodo di cui sopra come segue:

private static void GeneratePivotTables(WorkbookPart workbookPart, WorksheetPart worksheetPart, 
    XLWorksheet xlWorksheet, 
    SaveContext context) 
{ 
    var pivotCaches = workbookPart.Workbook.GetFirstChild<PivotCaches>(); 
    foreach (var pt in xlWorksheet.PivotTables) 
    { 
     var ptCdp = context.RelIdGenerator.GetNext(RelType.Workbook); 

     var pivotTableCacheDefinitionPart = workbookPart.AddNewPart<PivotTableCacheDefinitionPart>(ptCdp); 
     GeneratePivotTableCacheDefinitionPartContent(pivotTableCacheDefinitionPart, pt); 

     if (pivotCaches == null) 
      workbookPart.Workbook.AppendChild(pivotCaches = new PivotCaches()); 
     var pivotCache = new PivotCache { CacheId = (uint)pivotCaches.Count(), Id = ptCdp }; 
     pivotCaches.AppendChild(pivotCache); 

     var pivotTablePart = 
      worksheetPart.AddNewPart<PivotTablePart>(context.RelIdGenerator.GetNext(RelType.Workbook)); 
     GeneratePivotTablePartContent(pivotTablePart, pt); 
     pivotTablePart.PivotTableDefinition.CacheId = pivotCache.CacheId; 

     pivotTablePart.AddPart(pivotTableCacheDefinitionPart, context.RelIdGenerator.GetNext(RelType.Workbook)); 
    } 
} 

Update: La buona notizia è che il mio post ha innescato un ClosedXML source repository fix da Francois Botha (anche crediti a petelids che l'hanno portato lì), quindi puoi prendere il codice da lì fino alla prossima versione che, si spera, lo includerà.

+0

Come manutentore del pacchetto, mi piacerebbe che le persone potessero inviare patch come richieste pull. http: // GitHub.com/ClosedXML/ClosedXML –

+0

@FrancoisBotha Certo, ho appena lavorato ieri alle domande e non ho tempo per contribuire (ha alcuni requisiti aggiuntivi, credo, non è come lanciare uno snippet di codice), e poi l'utente sembra avere dei petelidi già fatto. –

+1

@IvanStoev - L'ho fatto, ma mi sono precipitato e ho fatto un po 'di hashish. Ho cancellato la mia risposta in quanto non aggiungeva alcun valore (e invece ha svalutato la tua). FrancoisBotha ha creato una patch migliore. – petelids

2

Provare questa modifica. Ho fatto una nota dove ho aggiunto una riga aggiuntiva. Inoltre, penso che il metodo AddNew() abbia avuto il riferimento errato al foglio di lavoro? Potresti aver provato ad aggiungere una tabella pivot su un'altra. Questo potrebbe essere stato il vero problema piuttosto che la linea aggiuntiva che ho aggiunto.

using XL = ClosedXML.Excel; 
... 
XL.XLWorkbook wb = new XL.XLWorkbook(); 
dsData = Session["ExportData"] as DataSet; 
var sheet1 = wb.Worksheets.Add("output table"); 
sheet1.Cell(1, 1).InsertTable(dsData.Tables[0], "output table", true); 

// sheet1 is the reference sheet S1 
var dataRange = sheet1.RangeUsed(); 
PivotCache cache = wb.PivotCaches.Add(dataRange); //---THIS LINE HAS BEEN ADDED--- 

// First Pivot 
XL.IXLWorksheet ptSheet1 = wb.Worksheets.Add("S2"); 
var pt1 = ptSheet1.PivotTables.AddNew("PivotTable1", ptSheet1.Cell(3, 1), cache); 
//Changed ptSheet.Cell... to ptSheet1.Cell... 
pt1.ReportFilters.Add("CX"); 
pt1.RowLabels.Add("C1"); 
pt1.RowLabels.Add("C2"); 
pt1.RowLabels.Add("C3"); 
pt1.RowLabels.Add("C4"); 
pt1.ColumnLabels.Add("CL1"); 
pt1.ColumnLabels.Add("CL2"); 
pt1.ColumnLabels.Add("CL3"); 
pt1.Values.Add("V").SummaryFormula = XL.XLPivotSummary.Sum; 

// Second Pivot 
XL.IXLWorksheet ptSheet2 = wb.Worksheets.Add("S3"); 
var pt2 = ptSheet2.PivotTables.AddNew("PivotTable2", ptSheet2.Cell(3, 1), cache); 
//Changed ptSheet1.Cell... to ptSheet2.Cell... 
pt2.ReportFilters.Add("QQ"); 
pt2.RowLabels.Add("C1"); 
pt2.RowLabels.Add("C2"); 
pt2.ColumnLabels.Add("CL1"); 
pt2.ColumnLabels.Add("CL2"); 
pt2.ColumnLabels.Add("CL3"); 
pt2.Values.Add("V").SummaryFormula = XL.XLPivotSummary.Sum;