Come posso creare un file Excel (.XLS e .XLSX) in C # senza installare Microsoft Office?


1892

Come posso creare un foglio di calcolo Excel con C # senza richiedere l'installazione di Excel sul computer che esegue il codice?


Il "... senza installare Ms Office?" parte della domanda sembra molto poco professionale. È possibile generare qualsiasi tipo di file da un programma C # (con un file xlso xlsxuno di questi). Non è necessario che sul tuo computer sia presente un programma in grado di leggerlo (ad esempio binario).
Mike,

30
@Mike Il pezzo "senza installazione di Excel" non ha nulla a che fare con l'essere professionale. Si tratta di dipendenze. Il testo originale della domanda era formulato come: "Idealmente, vorrei open source, quindi non devo aggiungere dipendenze di terze parti al mio codice e vorrei evitare di usare Excel direttamente per creare il file (usando OLE Automazione.) " È un peccato che la domanda sia stata drasticamente semplificata.
Tony

5
Supponendo che stavi provando a fare qualcosa senza libreria o codice esterno, non posso parlare per il file xls, ma per i file xlsx, perché non iniziare prendendo uno esistente, rinominandolo in un file zip ed esplorando il contenuto? Un po 'di reverse engineering ti dirà un bel po'. Esistono diversi file xml e file rel nelle varie cartelle e sottocartelle. Prova a esplorarlo e vedi se è qualcosa che puoi replicare o vedi se riesci a trovare la documentazione sui vari spazi dei nomi / schemi xml.
Alexander Ryan Baggett,

@AlexanderRyanBaggett Questo è stato estremamente utile! Mi sono imbattuto in questo post mentre lavoravo alla generazione automatica di report ed esplorando documenti come un archivio zip fornisce un bel po 'di informazioni su ciò che va nella creazione di un file di documento.
SentientFlesh

Risposte:


1055

Puoi usare una libreria chiamata ExcelLibrary. È una libreria open source gratuita pubblicata su Google Code:

ExcelLibrary

Questa sembra essere una porta di ExcelWriter PHP che hai menzionato sopra. Non scriverà ancora nel nuovo formato .xlsx, ma stanno lavorando per aggiungere quella funzionalità in.

È molto semplice, piccolo e facile da usare. Inoltre ha un DataSetHelper che ti consente di utilizzare DataSet e DataTables per lavorare facilmente con i dati di Excel.

ExcelLibrary sembra funzionare ancora solo per il vecchio formato Excel (file .xls), ma potrebbe aggiungere supporto in futuro per i nuovi formati 2007/2010.

Puoi anche usare EPPlus , che funziona solo con file in formato Excel 2007/2010 (file .xlsx). C'è anche NPOI che funziona con entrambi.

Esistono alcuni bug noti in ciascuna libreria, come indicato nei commenti. Nel complesso, EPPlus sembra essere la scelta migliore col passare del tempo. Sembra essere anche attivamente aggiornato e documentato.

Inoltre, come indicato da @ АртёмЦарионов di seguito, EPPlus ha il supporto per le tabelle pivot e ExcelLibrary potrebbe avere qualche supporto ( problema della tabella pivot in ExcelLibrary )

Ecco alcuni link per una rapida
consultazione : ExcelLibrary - GNU Lesser GPL
EPPlus - GNU Lesser General Public License (LGPL)
NPOI - Licenza Apache

Ecco alcuni esempi di codice per ExcelLibrary:

Ecco un esempio prendendo i dati da un database e creando una cartella di lavoro da esso. Si noti che il codice ExcelLibrary è la riga singola in fondo:

//Create the data set and table
DataSet ds = new DataSet("New_DataSet");
DataTable dt = new DataTable("New_DataTable");

//Set the locale for each
ds.Locale = System.Threading.Thread.CurrentThread.CurrentCulture;
dt.Locale = System.Threading.Thread.CurrentThread.CurrentCulture;

//Open a DB connection (in this example with OleDB)
OleDbConnection con = new OleDbConnection(dbConnectionString);
con.Open();

//Create a query and fill the data table with the data from the DB
string sql = "SELECT Whatever FROM MyDBTable;";
OleDbCommand cmd = new OleDbCommand(sql, con);
OleDbDataAdapter adptr = new OleDbDataAdapter();

adptr.SelectCommand = cmd;
adptr.Fill(dt);
con.Close();

//Add the table to the data set
ds.Tables.Add(dt);

//Here's the easy part. Create the Excel worksheet from the data set
ExcelLibrary.DataSetHelper.CreateWorkbook("MyExcelFile.xls", ds);

Creare il file Excel è facile. Puoi anche creare manualmente file Excel, ma la funzionalità di cui sopra è ciò che mi ha davvero colpito.


247
ExcelLibrary è stato sostituito dall'eccezionale EPPlus - epplus.codeplex.com . Jan lo aggiorna regolarmente. Lo hanno usato ed è uno dei migliori progetti open source con cui abbiamo lavorato.
Segna il

3
Va notato che ExcelLibrary ha molti problemi di prestazioni quando si tratta di set di dati di grandi dimensioni (più grandi di 5000 righe con molte colonne). Attualmente sto facendo una pesante modifica della base di codice al lavoro in modo che possiamo usarla in un progetto.
Rossisdead,

EPPlus sembra molto meno difettoso di ExcelLibrary, MA è GPL e quindi solo una soluzione per progetti open source.
Seth,


6
Che dire di ClosedXML ? Potrei dimostrarti utile nei tuoi progetti.
Amadeus Sánchez,

589

Se sei soddisfatto del formato xlsx, prova il mio progetto GitHub, EPPlus . È iniziato con l'origine di ExcelPackage, ma oggi è una riscrittura totale. Supporta intervalli, stili di celle, grafici, forme, immagini, intervalli denominati, filtro automatico e molte altre cose.


77
La licenza è ora LGPL, note di rilascio qui: epplus.codeplex.com/releases/view/79802
Simon D

13
Gli esempi sono stati utili. Sono stato in grado di cambiare il mio codice dall'uso della libreria di interoperabilità Microsoft (orribilmente lenta) a questa libreria (versione 4.x) in un paio d'ore. Il mio benchmark scrive un file con due schede e circa 750.000 celle. Usando l'interoperabilità con MS ci sono voluti 13 minuti. Usando EPPlus ci sono voluti 10 secondi, una velocità di circa 80x. Molto felice!
Paul Chernoch,

3
Per chiarezza in questo thread, la LGPL consente al software di essere collegato senza che si verifichi la parte infettiva della GPL. Devi solo aprire le modifiche apportate a ClosedXml o se inserisci direttamente il codice sorgente (invece di fare riferimento agli assembly ClosedXml) all'interno della tua applicazione, devi aprire la tua applicazione.
Chris Marisic,

4
@ Paul Chernoch: popoliamo molto rapidamente fogli Excel di grandi dimensioni con interoperabilità. Il segreto è fare un aggiornamento in blocco. Creare un blocco oggetto [,], popolarlo, quindi scrivere quella matrice in Excel contemporaneamente: excelWorksheet.get_Range (range) .Value2 = block;
Marc Meketon,

2
Sembra che le licenze si stiano spostando da LGPL a Polyform Non commerciale 1.0.0
Luca

175

E che dire dell'utilizzo di Open XML SDK 2.0 per Microsoft Office?

Alcuni vantaggi:

  • Non richiede Office installato
  • Realizzato da Microsoft = buona documentazione MSDN
  • Solo una DLL .Net da utilizzare nel progetto
  • SDK viene fornito con molti strumenti come diff, validatore, ecc

link:


3
Importante notare che la DLL per questo è poco più di 5 MB e limitata ai formati di Office 2007. Ma sicuramente la soluzione più semplice e veloce che funziona per me.
Josh Brown,

18
Solo un avvertimento che v2.5 è disponibile e può essere scaricato qui .
Snuffleupagus,

10
L'SDK modella l'XML in classi, in modo che ogni tag XML sia mappato su un tag, quindi devi costruire la gerarchia di classi (ogni istanza ha una raccolta di istanze / tag figlio) correttamente. Ciò significa che devi conoscere la struttura XML di un file Excel, il che è molto complicato. È molto più facile usare un wrapper come EPPlus, menzionato sopra, che semplifica le cose.
Tsahi Asher,

2
Un ottimo esempio di Microsoft Open XML SDK - Open XML Writer è disponibile all'indirizzo polymathprogrammer.com/2012/08/06/… O vedi la soluzione Stack Overflow stackoverflow.com/questions/11370672/…
Greg

4
Ho trovato Open XML Writer di Microsoft Open XML SDK essere eccezionale. Utilizzando le soluzioni di cui sopra, (in particolare l'esempio di Vincent Tom (Poly Math)), è facile creare uno scrittore che trasmetta flussi di dati di grandi dimensioni e scriva i record in un modo simile e non troppo complesso a ciò per cui faresti CSV; ma che stai invece scrivendo xml. Open XML è la mentalità in cui Microsoft considera i suoi nuovi formati di Office. E puoi sempre rinominarli da file .xslx in .zip se hai voglia di cercare i loro contenuti XML.
Greg,


108

È possibile utilizzare OLEDB per creare e manipolare file Excel. Controlla questo: Lettura e scrittura di Excel tramite OLEDB .

Esempio tipico:

using (OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\temp\\test.xls;Extended Properties='Excel 8.0;HDR=Yes'"))
{
  conn.Open();
  OleDbCommand cmd = new OleDbCommand("CREATE TABLE [Sheet1] ([Column1] string, [Column2] string)", conn);
  cmd.ExecuteNonQuery();
}

EDIT - Alcuni altri collegamenti:


4
Qualcuno può confermare se questo funziona quando si esegue in x64? Sono abbastanza sicuro che Jet funzioni solo se la tua app è compilata o in esecuzione in modalità 32 bit.
Lamar,

2
Ho appena testato questa connessione e non è riuscito su un Windows Server 2008 R2 x64 RC, sembra che si debba installare il driver di sistema di Office 2007: Data Connectivity Components [ microsoft.com/downloads/…
Chris Richner,

25
Fai molta attenzione: è un brutto cludge (ad esempio, a volte indovina un tipo di colonna e scarta tutti i dati che non rientrano).
dbkk,

9
Bisogna stare molto attenti se si utilizza questo metodo. L'ho trovato molto traballante per i dati che non sono in un formato perfetto.
Kenny Mann,

9
Come persona che ha dovuto usare OleDb in un grande progetto, dico STARE LONTANO DA IT! A volte non è in grado di recuperare un valore di cella solo perché non è in grado di comprendere il formato. Non ha un'operazione di eliminazione. Funziona in modo totalmente diverso e imprevedibile anche con un minimo cambio di provider. Direi di provare una soluzione commerciale comprovata.
Caner Öncü,

80

La soluzione commerciale, SpreadsheetGear per .NET lo farà.

Puoi vedere esempi ASP.NET (C # e VB) live qui e scaricare una versione di valutazione qui .

Disclaimer: possiedo SpreadsheetGear LLC


10
Hai un ottimo prodotto ma penso che molte persone qui si aspettino soluzioni gratuite. Ciò potrebbe spiegare i voti negativi.
md1337,

65

Alcune opzioni che ho usato:

Se XLSX è un must: ExcelPackage è un buon inizio ma si è spento quando lo sviluppatore ha smesso di lavorarci. ExML ha raccolto da lì e ha aggiunto alcune funzionalità. ExML non è una cattiva opzione, lo sto ancora usando in un paio di siti Web di produzione.

Per tutti i miei nuovi progetti, tuttavia, sto usando NPOI , la porta .NET di Apache POI . NPOI 2.0 (Alpha) supporta anche XLSX.


Fai attenzione con ExcelPackage se devi supportare XLS. Ho avuto difficoltà con esso e alla fine sono passato a ExcelLibrary.
Jeremy,

Decisamente vero. ExcelPackage / ExML è una buona opzione solo se hai bisogno del supporto XLSX.
Nate,

5
Si noti che ExcelPackage ha un successore: EPPlus ( epplus.codeplex.com ) che supporta XLSX. La mia unica preoccupazione, rispetto ad esempio a NPOI, sono le prestazioni, ad esempio quando ci sono molte colonne.
Pragmateek,

63

Un'opzione estremamente leggera potrebbe essere l'uso di tabelle HTML. Basta creare tag head, body e table in un file e salvarlo come file con estensione .xls. Esistono attributi specifici di Microsoft che è possibile utilizzare per definire l'output, comprese le formule.

Mi rendo conto che potresti non codificarlo in un'applicazione Web, ma ecco un esempio della composizione di un file Excel tramite una tabella HTML. Questa tecnica potrebbe essere utilizzata se si stava codificando un'app console, un'app desktop o un servizio.


6
È così ad hoc ma funziona (per non parlare di Excel che emette un avviso di apertura) ed è così semplice che merita di avere un posto come soluzione. Anche se solo per dimostrare che è possibile esportare un file Excel :))
Luka Ramishvili il

3
Questa soluzione ha funzionato bene per me, nota solo che non puoi usare l'estensione .xlsx
Jill

Alcune persone della mia organizzazione non possono aprire file Excel creati in questo modo in Office 2010 e versioni successive. Non so quale sia il problema, ma ho dovuto implementare la mia implementazione OpenXML. (vedi la risposta di Sogger)
Kristen Hammack l'

49

Se stai creando file Excel 2007/2010, prova questo progetto open source: https://github.com/closedxml/closedxml

Fornisce un modo orientato agli oggetti per manipolare i file (simile a VBA) senza occuparsi delle seccature dei documenti XML. Può essere utilizzato da qualsiasi linguaggio .NET come C # e Visual Basic (VB).

ClosedXML ti consente di creare file Excel 2007/2010 senza l'applicazione Excel. L'esempio tipico è la creazione di report Excel su un server Web:

var workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add("Sample Sheet");
worksheet.Cell("A1").Value = "Hello World!";
workbook.SaveAs("HelloWorld.xlsx");

9
Ho provato a usarlo in un progetto che costruisce fogli Excel abbastanza grandi. Libreria eccellente, ma estremamente scadente nelle prestazioni. Ho appena fatto un confronto per il progetto a cui sto lavorando: ClosedXML (v 0.53.3) ha richiesto 92.489 ms mentre EPPlus (v 2.9.03, per i test - non possiamo usare perché è GPL) ha richiesto 16.500 ms.
Druido,

1
@Druid la licenza è LGPL supponendo che non modifichi il codice sorgente su ClosedXML, è libero di usare epplus.codeplex.com/license
Chris Marisic


47

In realtà potresti voler controllare le classi di interoperabilità disponibili in C # (es Microsoft.Office.Interop.Excel. Non dici OLE (cosa che non è), ma le classi di interoperabilità sono molto facili da usare. Consulta la documentazione C # qui (Interoperabilità per Excel inizia da pagina 1072 del PDF C #).

Potresti essere colpito se non li hai provati.

Si prega di essere avvisati di Microsoft posizione su questo:

Microsoft attualmente non consiglia e non supporta l'automazione delle applicazioni di Microsoft Office da qualsiasi applicazione o componente client non presidiato e non interattivo (inclusi ASP, ASP.NET, DCOM e NT Services), poiché Office può presentare comportamenti instabili e / o deadlock quando Office viene eseguito in questo ambiente.


6
Ma devi assicurarti di smaltire tutto manualmente, altrimenti
perderai

8
@Ricky B: Inoltre, nella mia esperienza con l'interoperabilità, usa Excel. Ogni volta che lo usavamo, se Excel non fosse installato sulla macchina, avremmo eccezioni COM.
MagicKat,

1
Con OLE, anche con disposizioni molto attente, alla fine perde memoria o si arresta in modo anomalo. Questo è senza dubbio OK per le applicazioni / workstation attese, ma per i server non è raccomandato (MS ha un KB che lo indica). Per il nostro server, è sufficiente riavviarlo ogni notte. Ancora una volta, funziona bene.
Jennifer Zouak,

11
@Geoffrey: ah OK, mi farai lavorare per questo :) -> support.microsoft.com/kb/257757 Microsoft attualmente non consiglia e non supporta l'automazione delle applicazioni di Microsoft Office da qualsiasi incustodito, non- applicazione client interattiva ...
Jennifer Zouak,

4
Sto venendo a questa discussione dopo aver lottato per più di una settimana sull'interoperabilità e, a meno che le tue esigenze non siano molto semplici, questo non funzionerà. Il supporto per la formattazione del foglio di calcolo è abissale, che è probabilmente la ragione per generare un file .xls e non solo un file .csv piatto. Ad esempio, hai provato a emettere più di 911 caratteri in una cella o hai provato a impostare la larghezza delle celle unite in modo coerente? Ho, e non posso dirvi quanto odio questa merda ora ... Fatevi un favore e andate con una delle biblioteche gratuite menzionate in questa discussione.
md1337,

34

Ecco un C # libreria completamente gratuito, che consente di esportare da una DataSet, DataTableo List<>in un vero e proprio file xlsx Excel 2007, utilizzando le librerie OpenXML:

http://mikesknowledgebase.com/pages/CSharp/ExportToExcel.htm

Viene fornito il codice sorgente completo - gratuitamente - insieme alle istruzioni e un'applicazione demo.

Dopo aver aggiunto questa classe alla tua applicazione, puoi esportare il tuo DataSet in Excel in una sola riga di codice:

CreateExcelFile.CreateExcelDocument(myDataSet, "C:\\Sample.xlsx");

Non è molto più semplice di così ...

E non richiede nemmeno che Excel sia presente sul tuo server.


1
Questo sembra un po 'fuorviante, poiché stai chiedendo una donazione per ottenere tutte le funzionalità.
UrbanEsc

In parte è vero: la versione completamente gratuita genererà un file .xlsx perfetto per te e verrà fornito tutto il codice sorgente. Se doni $ 10 o più a uno di quei due enti di beneficenza (di cui non ricevo assolutamente nulla), otterrai una versione "migliore" che mostra come eseguire formattazione, date, ecc. Dato il costo dei prodotti di terze parti, suppongo donare $ 10 per una buona causa invece ne vale la pena!
Mike Gledhill,


23

Potresti dare un'occhiata a GemBox.Spreadsheet .

Hanno una versione gratuita con tutte le funzionalità ma limitata a 150 righe per foglio e 5 fogli per cartella di lavoro, se ciò rientra nelle tue esigenze.

Non ho ancora avuto bisogno di usarlo da solo, ma sembra interessante.


21

Syncfusion Essential XlsIO può farlo. Non ha dipendenze da Microsoft Office e ha anche un supporto specifico per piattaforme diverse.

Esempio di codice:

//Creates a new instance for ExcelEngine.
ExcelEngine excelEngine = new ExcelEngine();
//Loads or open an existing workbook through Open method of IWorkbooks
IWorkbook workbook = excelEngine.Excel.Workbooks.Open(fileName);
//To-Do some manipulation|
//To-Do some manipulation
//Set the version of the workbook.
workbook.Version = ExcelVersion.Excel2013;
//Save the workbook in file system as xlsx format
workbook.SaveAs(outputFileName);

L'intera suite di controlli è disponibile gratuitamente attraverso il programma di licenze comunitarie se si qualificano (meno di 1 milione di dollari di entrate). Nota: lavoro per Syncfusion.


18

Bene,

puoi anche utilizzare una libreria di terze parti come Aspose .

Questa libreria ha il vantaggio che non richiede l'installazione di Excel sul tuo computer, il che sarebbe l'ideale nel tuo caso.


Per essere più precisi, è possibile utilizzare Aspose.Cells per .NET per creare file Excel (XLS, XLSX) nell'applicazione .NET.
Shahzad Latif,

9
Sì, se non ti dispiace pagare una tassa di licenza minima di $ 999. Prova la libreria MikesKnowledgeBase ... che costa $ 999 in meno rispetto a questo !!
Mike Gledhill,

17

OpenXML è anche una buona alternativa che aiuta a evitare l'installazione di MS Excel sul server. Open XML SDK 2.0 fornito da Microsoft semplifica il compito di manipolare i pacchetti Open XML e gli elementi dello schema Open XML sottostanti all'interno di un pacchetto. L'API (Application Programming Interface) Open XML incapsula molte attività comuni che gli sviluppatori eseguono su pacchetti Open XML.

Controllalo Dai OpenXML: alternativa che aiuta a evitare l'installazione di MS Excel sul server


17

Le varie librerie XML di Office 2003 disponibili funzionano abbastanza bene per file Excel di piccole dimensioni. Tuttavia, trovo che la dimensione pura di una grande cartella di lavoro salvata nel formato XML sia un problema. Ad esempio, una cartella di lavoro con cui lavoro sarebbe 40 MB nel nuovo formato XLSX (e certamente più strettamente compresso) diventa un file XML da 360 MB.

Per quanto mi ha portato la mia ricerca, ci sono due pacchetti commerciali che consentono l'output ai formati di file binari precedenti. Loro sono:

Né sono economici (500USD e 800USD rispettivamente, penso). ma entrambi funzionano indipendentemente da Excel stesso.

Ciò di cui sarei curioso è il modulo di output di Excel per artisti del calibro di OpenOffice.org. Mi chiedo se possano essere portati da Java a .Net.


Questo funziona sia su .net che su java e non è costoso. SmartXLS smartxls.com
liya,


15

Di recente ho usato FlexCel.NET e l' ho trovato un'ottima libreria! Non lo dico per troppi prodotti software. Inutile dare qui l'intera presentazione delle vendite, puoi leggere tutte le funzionalità sul loro sito web.

È un prodotto commerciale, ma ottieni la fonte completa se lo acquisti. Quindi suppongo che potresti compilarlo nel tuo assemblaggio se davvero lo volessi. Altrimenti è solo un ulteriore assemblaggio di xcopy: nessuna configurazione o installazione o qualcosa del genere.

Non penso che troverai alcun modo per farlo senza librerie di terze parti, poiché .NET Framework, ovviamente, non ha il supporto integrato e OLE Automation è solo un intero mondo di sofferenza.


15

Ho scritto un semplice codice per esportare il set di dati in Excel senza utilizzare l'oggetto Excel utilizzando System.IO.StreamWriter.

Di seguito è riportato il codice che leggerà tutte le tabelle dal set di dati e le scriverà sui fogli uno per uno. Ho preso aiuto da questo articolo .

public static void exportToExcel(DataSet source, string fileName)
{
        const string endExcelXML = "</Workbook>";
        const string startExcelXML = "<xml version>\r\n<Workbook " +
                 "xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"\r\n" +
                 " xmlns:o=\"urn:schemas-microsoft-com:office:office\"\r\n " +
                 "xmlns:x=\"urn:schemas-    microsoft-com:office:" +
                 "excel\"\r\n xmlns:ss=\"urn:schemas-microsoft-com:" +
                 "office:spreadsheet\">\r\n <Styles>\r\n " +
                 "<Style ss:ID=\"Default\" ss:Name=\"Normal\">\r\n " +
                 "<Alignment ss:Vertical=\"Bottom\"/>\r\n <Borders/>" +
                 "\r\n <Font/>\r\n <Interior/>\r\n <NumberFormat/>" +
                 "\r\n <Protection/>\r\n </Style>\r\n " +
                 "<Style ss:ID=\"BoldColumn\">\r\n <Font " +
                 "x:Family=\"Swiss\" ss:Bold=\"1\"/>\r\n </Style>\r\n " +
                 "<Style     ss:ID=\"StringLiteral\">\r\n <NumberFormat" +
                 " ss:Format=\"@\"/>\r\n </Style>\r\n <Style " +
                 "ss:ID=\"Decimal\">\r\n <NumberFormat " +
                 "ss:Format=\"0.0000\"/>\r\n </Style>\r\n " +
                 "<Style ss:ID=\"Integer\">\r\n <NumberFormat " +
                 "ss:Format=\"0\"/>\r\n </Style>\r\n <Style " +
                 "ss:ID=\"DateLiteral\">\r\n <NumberFormat " +
                 "ss:Format=\"mm/dd/yyyy;@\"/>\r\n </Style>\r\n " +
                 "</Styles>\r\n ";
        System.IO.StreamWriter excelDoc = null;
        excelDoc = new System.IO.StreamWriter(fileName);

        int sheetCount = 1;
        excelDoc.Write(startExcelXML);
        foreach (DataTable table in source.Tables)
        {
            int rowCount = 0;
            excelDoc.Write("<Worksheet ss:Name=\"" + table.TableName + "\">");
            excelDoc.Write("<Table>");
            excelDoc.Write("<Row>");
            for (int x = 0; x < table.Columns.Count; x++)
            {
                excelDoc.Write("<Cell ss:StyleID=\"BoldColumn\"><Data ss:Type=\"String\">");
                excelDoc.Write(table.Columns[x].ColumnName);
                excelDoc.Write("</Data></Cell>");
            }
            excelDoc.Write("</Row>");
            foreach (DataRow x in table.Rows)
            {
                rowCount++;
                //if the number of rows is > 64000 create a new page to continue output
                if (rowCount == 64000)
                {
                    rowCount = 0;
                    sheetCount++;
                    excelDoc.Write("</Table>");
                    excelDoc.Write(" </Worksheet>");
                    excelDoc.Write("<Worksheet ss:Name=\"" + table.TableName + "\">");
                    excelDoc.Write("<Table>");
                }
                excelDoc.Write("<Row>"); //ID=" + rowCount + "
                for (int y = 0; y < table.Columns.Count; y++)
                {
                    System.Type rowType;
                    rowType = x[y].GetType();
                    switch (rowType.ToString())
                    {
                        case "System.String":
                            string XMLstring = x[y].ToString();
                            XMLstring = XMLstring.Trim();
                            XMLstring = XMLstring.Replace("&", "&");
                            XMLstring = XMLstring.Replace(">", ">");
                            XMLstring = XMLstring.Replace("<", "<");
                            excelDoc.Write("<Cell ss:StyleID=\"StringLiteral\">" +
                                           "<Data ss:Type=\"String\">");
                            excelDoc.Write(XMLstring);
                            excelDoc.Write("</Data></Cell>");
                            break;
                        case "System.DateTime":
                            //Excel has a specific Date Format of YYYY-MM-DD followed by  
                            //the letter 'T' then hh:mm:sss.lll Example 2005-01-31T24:01:21.000
                            //The Following Code puts the date stored in XMLDate 
                            //to the format above
                            DateTime XMLDate = (DateTime)x[y];
                            string XMLDatetoString = ""; //Excel Converted Date
                            XMLDatetoString = XMLDate.Year.ToString() +
                                 "-" +
                                 (XMLDate.Month < 10 ? "0" +
                                 XMLDate.Month.ToString() : XMLDate.Month.ToString()) +
                                 "-" +
                                 (XMLDate.Day < 10 ? "0" +
                                 XMLDate.Day.ToString() : XMLDate.Day.ToString()) +
                                 "T" +
                                 (XMLDate.Hour < 10 ? "0" +
                                 XMLDate.Hour.ToString() : XMLDate.Hour.ToString()) +
                                 ":" +
                                 (XMLDate.Minute < 10 ? "0" +
                                 XMLDate.Minute.ToString() : XMLDate.Minute.ToString()) +
                                 ":" +
                                 (XMLDate.Second < 10 ? "0" +
                                 XMLDate.Second.ToString() : XMLDate.Second.ToString()) +
                                 ".000";
                            excelDoc.Write("<Cell ss:StyleID=\"DateLiteral\">" +
                                         "<Data ss:Type=\"DateTime\">");
                            excelDoc.Write(XMLDatetoString);
                            excelDoc.Write("</Data></Cell>");
                            break;
                        case "System.Boolean":
                            excelDoc.Write("<Cell ss:StyleID=\"StringLiteral\">" +
                                        "<Data ss:Type=\"String\">");
                            excelDoc.Write(x[y].ToString());
                            excelDoc.Write("</Data></Cell>");
                            break;
                        case "System.Int16":
                        case "System.Int32":
                        case "System.Int64":
                        case "System.Byte":
                            excelDoc.Write("<Cell ss:StyleID=\"Integer\">" +
                                    "<Data ss:Type=\"Number\">");
                            excelDoc.Write(x[y].ToString());
                            excelDoc.Write("</Data></Cell>");
                            break;
                        case "System.Decimal":
                        case "System.Double":
                            excelDoc.Write("<Cell ss:StyleID=\"Decimal\">" +
                                  "<Data ss:Type=\"Number\">");
                            excelDoc.Write(x[y].ToString());
                            excelDoc.Write("</Data></Cell>");
                            break;
                        case "System.DBNull":
                            excelDoc.Write("<Cell ss:StyleID=\"StringLiteral\">" +
                                  "<Data ss:Type=\"String\">");
                            excelDoc.Write("");
                            excelDoc.Write("</Data></Cell>");
                            break;
                        default:
                            throw (new Exception(rowType.ToString() + " not handled."));
                    }
                }
                excelDoc.Write("</Row>");
            }
            excelDoc.Write("</Table>");
            excelDoc.Write(" </Worksheet>");
            sheetCount++;
        }


        excelDoc.Write(endExcelXML);
        excelDoc.Close();
    }

1
Come dice l'articolo, tuttavia, è XML che Excel leggerà anziché essere effettivamente un file XLS, il che significa che potrebbe funzionare solo in Excel e non in altri programmi che leggono fogli di calcolo. Ma probabilmente è meglio che la tabella HTML equivalente risponda qui!
Rup,

Supporta xlsx ? OpenXML ?
Kiquenet,

14

Voglio solo aggiungere un altro riferimento a una soluzione di terze parti che risolva direttamente il tuo problema: http://www.officewriter.com

(Dichiarazione di non responsabilità: lavoro per SoftArtisans, la società che produce OfficeWriter)



12

Ecco un modo per farlo con LINQ to XML, completo di codice di esempio:

Importa ed esporta rapidamente i dati di Excel con LINQ in XML

È un po 'complesso, poiché devi importare spazi dei nomi e così via, ma ti consente di evitare dipendenze esterne.

(Inoltre, ovviamente, è VB .NET, non C #, ma puoi sempre isolare le cose di VB .NET nel suo progetto per usare XML Literals e fare tutto il resto in C #.)


12

Alcuni fornitori di componenti di terze parti come Infragistics o Syncfusion offrono ottime capacità di esportazione di Excel che non richiedono l'installazione di Microsoft Excel.

Poiché questi fornitori forniscono anche componenti avanzati della griglia dell'interfaccia utente, questi componenti sono particolarmente utili se si desidera che lo stile e il layout di un'esportazione excel imitino lo stato corrente di una griglia nell'interfaccia utente dell'applicazione.

Se la tua esportazione deve essere eseguita sul lato server con enfasi sui dati da esportare e senza alcun collegamento all'interfaccia utente, sceglierei una delle opzioni open source gratuite (ad esempio ExcelLibrary).

In precedenza sono stato coinvolto in progetti che hanno tentato di utilizzare l'automazione lato server nella suite di Microsoft Office. Sulla base di questa esperienza, raccomanderei fortemente questo approccio.


12
public class GridViewExportUtil
{
    public static void Export(string fileName, GridView gv)
    {
        HttpContext.Current.Response.Clear();
        HttpContext.Current.Response.AddHeader(
            "content-disposition", string.Format("attachment; filename={0}", fileName));
        HttpContext.Current.Response.ContentType = "application/ms-excel";

        using (StringWriter sw = new StringWriter())
        {
            using (HtmlTextWriter htw = new HtmlTextWriter(sw))
            {
                //  Create a form to contain the grid
                Table table = new Table();

                //  add the header row to the table
                if (gv.HeaderRow != null)
                {
                    GridViewExportUtil.PrepareControlForExport(gv.HeaderRow);
                    table.Rows.Add(gv.HeaderRow);
                }

                //  add each of the data rows to the table
                foreach (GridViewRow row in gv.Rows)
                {
                    GridViewExportUtil.PrepareControlForExport(row);
                    table.Rows.Add(row);
                }

                //  add the footer row to the table
                if (gv.FooterRow != null)
                {
                    GridViewExportUtil.PrepareControlForExport(gv.FooterRow);
                    table.Rows.Add(gv.FooterRow);
                }

                //  render the table into the htmlwriter
                table.RenderControl(htw);

                //  render the htmlwriter into the response
                HttpContext.Current.Response.Write(sw.ToString());
                HttpContext.Current.Response.End();
            }
        }
    }

    /// <summary>
    /// Replace any of the contained controls with literals
    /// </summary>
    /// <param name="control"></param>
    private static void PrepareControlForExport(Control control)
    {
        for (int i = 0; i < control.Controls.Count; i++)
        {
            Control current = control.Controls[i];
            if (current is LinkButton)
            {
                control.Controls.Remove(current);
                control.Controls.AddAt(i, new LiteralControl((current as LinkButton).Text));
            }
            else if (current is ImageButton)
            {
                control.Controls.Remove(current);
                control.Controls.AddAt(i, new LiteralControl((current as ImageButton).AlternateText));
            }
            else if (current is HyperLink)
            {
                control.Controls.Remove(current);
                control.Controls.AddAt(i, new LiteralControl((current as HyperLink).Text));
            }
            else if (current is DropDownList)
            {
                control.Controls.Remove(current);
                control.Controls.AddAt(i, new LiteralControl((current as DropDownList).SelectedItem.Text));
            }
            else if (current is CheckBox)
            {
                control.Controls.Remove(current);
                control.Controls.AddAt(i, new LiteralControl((current as CheckBox).Checked ? "True" : "False"));
            }

            if (current.HasControls())
            {
                GridViewExportUtil.PrepareControlForExport(current);
            }
        }
    }
}

Ciao, questa soluzione è esportare la visualizzazione della griglia nel file Excel che potrebbe aiutarti


7
No, questo genera HTML contrassegnato come un file Excel anziché come un vero file Excel. Sì, Excel stesso aprirà quel OK ma altri programmi che consumano fogli di calcolo - incluso il visualizzatore Excel gratuito di Microsoft, per esempio - non lo accetteranno. Faresti meglio a creare un vero file Excel usando una delle librerie qui.
Rup,

Dovresti anche usare System.Net.Mime.ContentDisposition per generare il testo dell'intestazione della disposizione del contenuto piuttosto che un'appendice di stringa, che gestirà correttamente i nomi dei file che contengono spazi ecc.
Rup,

12

Puoi creare file Excel ben formattati usando questa libreria: http://officehelper.codeplex.com/documentation
Vedi l'esempio seguente:

using (ExcelHelper helper = new ExcelHelper(TEMPLATE_FILE_NAME, GENERATED_FILE_NAME))
{
    helper.Direction = ExcelHelper.DirectionType.TOP_TO_DOWN;
    helper.CurrentSheetName = "Sheet1";
    helper.CurrentPosition = new CellRef("C3");

    //the template xlsx should contains the named range "header"; use the command "insert"/"name".
    helper.InsertRange("header");

    //the template xlsx should contains the named range "sample1";
    //inside this range you should have cells with these values:
    //<name> , <value> and <comment>, which will be replaced by the values from the getSample()
    CellRangeTemplate sample1 = helper.CreateCellRangeTemplate("sample1", new List<string> {"name", "value", "comment"}); 
    helper.InsertRange(sample1, getSample());

    //you could use here other named ranges to insert new cells and call InsertRange as many times you want, 
    //it will be copied one after another;
    //even you can change direction or the current cell/sheet before you insert

    //typically you put all your "template ranges" (the names) on the same sheet and then you just delete it
    helper.DeleteSheet("Sheet3");
}        

dove esempio assomiglia a questo:

private IEnumerable<List<object>> getSample()
{
    var random = new Random();

    for (int loop = 0; loop < 3000; loop++)
    {
        yield return new List<object> {"test", DateTime.Now.AddDays(random.NextDouble()*100 - 50), loop};
    }
}

10

Il modo più semplice e veloce per creare un file Excel da C # è utilizzare lo Strumento di produttività Open XML. Lo strumento di produttività Open XML viene fornito con l'installazione dell'SDK Open XML. Lo strumento decodifica qualsiasi file Excel in codice C #. Il codice C # può quindi essere utilizzato per rigenerare quel file.

Una panoramica del processo coinvolto è:

  1. Installa Open XML SDK con lo strumento.
  2. Crea un file Excel utilizzando l'ultimo client Excel con l'aspetto desiderato. Dillo DesiredLook.xlsx.
  3. Con lo strumento aperto DesiredLook.xlsxe fai clic sul pulsante Rifletti codice nella parte superiore. inserisci qui la descrizione dell'immagine
  4. Il codice C # per il tuo file verrà generato nel riquadro destro dello strumento. Aggiungi questo alla tua soluzione C # e genera file con l'aspetto desiderato.

Come bonus, questo metodo funziona per qualsiasi file Word e PowerPoint. Come sviluppatore C #, apporterai quindi modifiche al codice per adattarlo alle tue esigenze.

Ho sviluppato una semplice app WPF su github che verrà eseguita su Windows per questo scopo. Esiste una classe segnaposto chiamata in GeneratedClasscui è possibile incollare il codice generato. Se torni indietro di una versione del file, genererà un file Excel come questo:

inserisci qui la descrizione dell'immagine


1
Non ho ancora provato questa soluzione Open XML SDK ma Wow, lo verificherò sicuramente. Ho lavorato con strumenti come questo per molti anni e non ne ero a conoscenza. Ho pubblicato il mio semplice FOSS per convertire i file in XLSX con .NET: github.com/TonyGravagno/NebulaXConvert
TonyG,


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.