2015-12-31 18 views
8

Esiste un modo per espandere una tabella esistente in EPPlus in C#. Il modo in cui il mio programma funziona è che creo il tavolo con solo 2 righe e continuo ad aggiungere altro. Non riesco a trovare alcun tipo di metodo di ridimensionamento in ExcelTable. C'è un metodo dedicato per questo, o devo usare una sorta di alternativa?Espandi una tabella in EPPlus C#

Modifica: Okay, ho intenzione di chiarire questo. Ho già installato EPPLus e ho creato un ExcelTable. La mia domanda è: come posso rendere un ExcelTable esistente più grande (aggiungere più righe)?

+0

EPPlus è per l'esportazione in Excel, cosa vuoi realmente? –

+0

Se sto capendo correttamente la tua domanda, la mia risposta qui sotto leggerà un file Excel in memoria e aggiungerà una riga, quindi sovrascriverà il file. –

risposta

8

Purtroppo, non esiste un metodo diretto. Non so esattamente perché, ma gli sviluppatori di EPPlus scelgono di rendere la proprietà ExcelTable.Address solo pronta. Quindi la scelta più ovvia sarebbe quella di creare una nuova tabella, copiare tutte le proprietà (supponendo che tu sappia tutte quelle necessarie) e cancellare quella vecchia. Non molto ideale dato che potresti perdere qualcosa.

Ma ne vedo altri due: il prossimo esattamente carino, ma meglio la copia/cancella. Assumere una tabella in questo modo:

enter image description here

Opzione 1 si potrebbe sborsare il codice sorgente EPPlus e rendere la proprietà aveva bisogno di lettura/scrittura. Si potrebbe fare questo nel file ExcelTable.cs modificando:

public ExcelAddressBase Address 
    { 
     get 
     { 
      return _address; 
     } 
     internal set //REMOVE internal KEYWORD 
     { 
      _address = value; 
      SetXmlNodeString("@ref",value.Address); 
      WriteAutoFilter(ShowTotal); 
     } 
    } 

togliendo la parola chiave internal. Ma ovviamente dovrai fare attenzione facendo così non rompere qualcos'altro lungo la strada. Con questo, si può fare qualcosa di simile:

var fileInfo = new FileInfo(@"c:\temp\Expand_Table.xlsx"); 

using (var pck = new ExcelPackage(fileInfo)) 
{ 
    var workbook = pck.Workbook; 
    var worksheet = workbook.Worksheets.First(); 

    //Added 11th data row assuming the table is from A1 to C11 (Header row + 10 data rows) 
    worksheet.Cells["A12"].Value = 10; 
    worksheet.Cells["B12"].Value = 100; 
    worksheet.Cells["C12"].Value = Path.GetRandomFileName(); 

    var tbl = worksheet.Tables["TestTable1"]; 
    var oldaddy = tbl.Address; 
    var newaddy = new ExcelAddressBase(oldaddy.Start.Row, oldaddy.Start.Column, oldaddy.End.Row + 1, oldaddy.End.Column); 

    tbl.Address = newaddy; 

    pck.Save(); 
} 

Opzione 2 sarebbe l'opzione più sicura ma più "sporco" utilizzando una stringa di sostituire sul XML. Non possiamo presumere che ci sia solo un riferimento all'indirizzo perché, ad esempio, il filtro automatico potrebbe essere acceso. Ecco ciò che il XML di default sarà simile a quando si crea una tabella in Excel (notare i 2 riferimenti al indirizzo):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<table xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" id="3" name="TestTable1" displayName="TestTable1" ref="A1:C11" totalsRowShown="0"> 
    <autoFilter ref="A1:C11" /> 
    <tableColumns count="3"> 
     <tableColumn id="1" name="Col1" /> 
     <tableColumn id="2" name="Col2" /> 
     <tableColumn id="3" name="Col3" /> 
    </tableColumns> 
    <tableStyleInfo name="TableStyleMedium2" showFirstColumn="0" showLastColumn="0" showRowStripes="1" showColumnStripes="0" /> 
</table> 

modo che possiamo fare una stringa sostituire in questo modo:

var fileInfo = new FileInfo(@"c:\temp\Expand_Table.xlsx"); 

using (var pck = new ExcelPackage(fileInfo)) 
{ 
    var workbook = pck.Workbook; 
    var worksheet = workbook.Worksheets.First(); 

    //Added 11th data row assuming the table is from A1 to C11 (Header row + 10 data rows) 
    worksheet.Cells["A12"].Value = 10; 
    worksheet.Cells["B12"].Value = 100; 
    worksheet.Cells["C12"].Value = Path.GetRandomFileName(); 

    var tbl = worksheet.Tables["TestTable1"]; 
    var oldaddy = tbl.Address; 
    var newaddy = new ExcelAddressBase(oldaddy.Start.Row, oldaddy.Start.Column, oldaddy.End.Row + 1, oldaddy.End.Column); 

    //Edit the raw XML by searching for all references to the old address 
    tbl.TableXml.InnerXml = tbl.TableXml.InnerXml.Replace(oldaddy.ToString(), newaddy.ToString()); 

    pck.Save(); 
} 
+0

Non penso che tutto questo sia necessario. 'Address' è di sola lettura, poiché cambia in base alla quantità di dati nel report. Se leggi il file in memoria come un 'ExcelPackage' e aggiungi dati ad esso, le informazioni di' Address' saranno modificate di conseguenza. –

+0

@dubstylee Sei riuscito a farlo con Epplus e un oggetto 'ExcelTable'? Il codice che hai postato (e aggiornato) aggiungerà un valore alla cella sotto l'ultima cella vuota nel 'Foglio di lavoro', ma NON aggiornerà il' ExcelTable'. – Ernie

+0

Non ho. Non sono sicuro di aver capito correttamente la domanda OP, ma non sembra che sia necessario usare un 'ExcelTable'. Accedo semplicemente ai dati direttamente dal 'Foglio di lavoro', che nella mia testa è logicamente uguale a un' ExcelTable' ... –

-1

Avrete bisogno di leggere il foglio di calcolo di Excel esistente in memoria, allora si sarà in grado di manipolare e salvare il file risultante:

var path = @"C:\file.xlsx"; 
var file = File.ReadAllBytes(path); 
var ms = new MemoryStream(file); 
using (var package = new ExcelPackage(ms)) 
{ 
    var ws = package.Workbook.First(); 

    // get index of last row 
    var lastRow = ws.Dimension.End.Row; 
    // add a new row at the end 
    ws.Cells(lastRow + 1, 1).Value = "new row"; 

    var bytes = package.GetAsByteArray(); 
    File.WriteAllBytes(path, bytes); 
} 
4

Questa domanda ha circa un anno di vita, ma sperando che qualcuno abbia ancora bisogno di una risposta, esiste una soluzione diretta, anche se non completa a causa di un bug in EEPlus (sto lavorando con v4.1).

ExcelWorksheet ha un metodo InsertRow(Int32, Int32, Int32). Se si inseriscono le righe in un'area che fa parte della tabella, anche la tabella viene espansa. Basta usare la proprietà Address per ottenere i limiti. Assicurati di inserire tra la prima e l'ultima riga del tavolo.

C'è un difetto che conosco relativo alla convalida della cella: anche se si utilizza il sovraccarico che può copiare lo stile da una riga esistente, la convalida non viene copiata. Ancora peggio, la convalida è rimasta dove era e non è spostata con le celle. Non ho provato, ma credo che se la validazione ha un intervallo e non una cella come target, anche questa viene espansa se si inseriscono le righe in quell'intervallo.

Questo non è di aiuto se si desidera espandere la tabella sui dati in anticipo nel foglio di lavoro, ma è comunque possibile spostare le righe. E nemmeno quando si hanno molti tavoli affiancati (che è un incubo).

+0

Grazie per la risposta. Tuttavia, se una serie di grafici fosse associata a un'intera colonna, ignorerebbe le righe inserite. Nonostante con il grafico di inserimento manuale è stato aggiornato. Forse sai un rimedio per questo caso? – Ghosthack