Jak utworzyć plik Excel (.XLS i .XLSX) w C # bez instalowania pakietu Microsoft Office?


1889

Jak mogę utworzyć arkusz kalkulacyjny Excel z C # bez konieczności instalowania programu Excel na komputerze, na którym działa kod?


„... bez instalacji Ms Office?” część pytania brzmi bardzo nieprofesjonalnie. Możesz wygenerować dowolny typ pliku z programu C # (z jednym xlslub xlsxjednym z nich jest plik). Nie jest wymagane, aby na twoim komputerze był program, który może go odczytać (powiedzmy, binarny).
Mike

30
@ Mike Fragment „bez konieczności instalowania programu Excel” nie ma nic wspólnego z byciem profesjonalistą. Chodzi o zależności. Oryginalny tekst pytania brzmiał następująco: „Idealnie chciałbym mieć open source, więc nie muszę dodawać żadnych zależności stron trzecich do mojego kodu i chciałbym unikać używania Excela bezpośrednio do tworzenia pliku (używając OLE Automatyzacja.) „ To niefortunne, że pytanie zostało drastycznie uproszczone.
Tony

5
Zakładając, że próbujesz zrobić coś bez biblioteki lub kodu zewnętrznego, nie mogę mówić o pliku xls, ale w przypadku plików xlsx, dlaczego nie zacząć od zapisania istniejącego pliku, zmiany jego nazwy na plik zip i zbadanie zawartości? Trochę inżynierii odwrotnej powie ci sporo. Istnieje kilka różnych plików XML i plików rel w różnych folderach i podfolderach. Spróbuj to zbadać i sprawdź, czy jest to coś, co można replikować, lub sprawdź, czy możesz znaleźć dokumentację dotyczącą różnych przestrzeni nazw / schematów xml.
Alexander Ryan Baggett

@AlexanderRyanBaggett To było bardzo pomocne! Natknąłem się na ten post podczas pracy nad automatycznym generowaniem raportów i eksplorowaniem dokumentów, ponieważ archiwum zip zapewnia całkiem sporo wglądu w proces tworzenia pliku dokumentu.
SentientFlesh

Odpowiedzi:


1054

Możesz użyć biblioteki o nazwie ExcelLibrary. Jest to darmowa biblioteka open source opublikowana w Google Code:

ExcelLibrary

Wygląda to na port programu Excel ExcelWriter, o którym wspomniałeś powyżej. Nie napisze jeszcze w nowym formacie .xlsx, ale pracują nad dodaniem tej funkcji.

Jest bardzo prosty, mały i łatwy w użyciu. Ponadto ma DataSetHelper, który pozwala używać DataSets i DataTables do łatwej pracy z danymi Excel.

Wydaje się, że ExcelLibrary nadal działa tylko dla starszego formatu Excela (pliki .xls), ale może dodawać obsługę w przyszłości dla nowszych formatów 2007/2010.

Możesz także użyć EPPlus , który działa tylko dla plików w formacie Excel 2007/2010 (pliki .xlsx). Istnieje również NPOI, które działa z oboma.

Istnieje kilka znanych błędów w każdej bibliotece, jak zauważono w komentarzach. Podsumowując, EPPlus wydaje się najlepszym wyborem w miarę upływu czasu. Wydaje się, że jest również aktywniej aktualizowany i dokumentowany.

Ponadto, jak zauważa @ АртёмЦарионов poniżej, EPPlus obsługuje tabele przestawne, a ExcelLibrary może mieć pewne wsparcie ( problem z tabelą przestawną w ExcelLibrary )

Oto kilka linków do szybkiego odniesienia:
ExcelLibrary - GNU Lesser GPL
EPPlus - GNU Lesser General Public License (LGPL)
NPOI - Licencja Apache

Oto przykładowy kod dla ExcelLibrary:

Oto przykład pobierania danych z bazy danych i tworzenia z niej skoroszytu. Zauważ, że kod ExcelLibrary to pojedynczy wiersz na dole:

//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);

Utworzenie pliku Excel jest tak proste. Możesz także ręcznie tworzyć pliki Excela, ale powyższa funkcjonalność naprawdę zrobiła na mnie wrażenie.


247
ExcelLibrary została zastąpiona przez wyjątkowy program EPPlus - epplus.codeplex.com . Jan aktualizuje go regularnie. Korzystałem z niego i jest to jeden z najlepszych projektów open source, z którymi współpracowaliśmy.
Mark A

3
Należy zauważyć, że ExcelLibrary ma wiele problemów z wydajnością w przypadku dużych zestawów danych (większych niż 5000 wierszy z dużą ilością kolumn). Obecnie przeprowadzamy ciężką modyfikację bazy kodu w pracy, abyśmy mogli go użyć w projekcie.
rossisdead

EPPlus wydaje się znacznie mniej wadliwy niż ExcelLibrary, ALE jest to GPL, a zatem tylko rozwiązanie dla projektów open source.
Seth


6
Co z ClosedXML ? Mogę okazać się przydatny w twoich projektach.
Amadeus Sánchez

589

Jeśli jesteś zadowolony z formatu xlsx, wypróbuj mój projekt GitHub, EPPlus . Zaczęło się od źródła z ExcelPackage, ale dziś jest to całkowite przepisanie. Obsługuje zakresy, stylizację komórek, wykresy, kształty, zdjęcia, nazwane zakresy, AutoFilter i wiele innych rzeczy.


77
Licencja jest teraz LGPL, informacje o wydaniu tutaj: epplus.codeplex.com/releases/view/79802
Simon D

13
Przykłady były pomocne. Udało mi się zmienić kod z używania biblioteki Microsoft Interop (strasznie wolno) na tę bibliotekę (wersja 4.x) w ciągu kilku godzin. Mój test porównawczy zapisuje plik z dwiema zakładkami i około 750 000 komórek. Za pomocą MS interop zajęło 13 minut. Korzystanie z EPPlus zajęło 10 sekund, około 80-krotnie przyspieszenie. Bardzo szczęśliwy!
Paul Chernoch

3
Dla przejrzystości tego wątku, LGPL pozwala na połączenie oprogramowania bez występowania zakaźnej części GPL. Wystarczy otworzyć zmiany w kodzie źródłowym, które wprowadzasz w ClosedXml, lub jeśli bezpośrednio umieścisz kod źródłowy (w przeciwieństwie do odwoływania się do zestawów ClosedXml) w aplikacji, wówczas musisz otworzyć aplikację.
Chris Marisic,

4
@Paul Chernoch: Bardzo szybko zapełniamy duże arkusze Excel interopem. Sekret polega na przeprowadzeniu zbiorczej aktualizacji. Utwórz blok obiektu [,], wypełnij go, a następnie zapisz tę macierz do Excela jednocześnie: excelWorksheet.get_Range (zakres) .Value2 = blok;
Marc Meketon

2
Wygląda na to, że licencja przechodzi z LGPL na licencję Polyform Noncommercial 1.0.0
Luke

175

A co z użyciem Open XML SDK 2.0 dla Microsoft Office?

Kilka korzyści:

  • Nie wymaga zainstalowanego pakietu Office
  • Wykonane przez Microsoft = przyzwoita dokumentacja MSDN
  • Tylko jeden dll .Net do użycia w projekcie
  • SDK zawiera wiele narzędzi, takich jak diff, walidator itp

Spinki do mankietów:


3
Ważne jest, aby pamiętać, że biblioteka DLL tego pliku ma nieco ponad 5 MB i jest ograniczona do formatów pakietu Office 2007. Ale z pewnością najłatwiejsze i najszybsze rozwiązanie, które działa dla mnie.
Josh Brown

18
Tylko jedna wiadomość, że wersja 2.5 jest już dostępna i można ją pobrać tutaj .
Snuffleupagus

10
Zestaw SDK modeluje XML na klasy, dzięki czemu każdy znacznik XML jest mapowany na znacznik, a następnie trzeba poprawnie zbudować hierarchię klas (każda instancja ma kolekcję instancji / znaczników potomnych). Oznacza to, że musisz znać strukturę XML pliku Excel, co jest bardzo skomplikowane. O wiele łatwiej jest użyć wspomnianego powyżej opakowania takiego jak EPPlus, co upraszcza rzeczy.
Tsahi Asher,

2
Świetny przykład Microsoft Open XML SDK - Open XML Writer można znaleźć na stronie polymathprogrammer.com/2012/08/06/... Lub zobacz Rozwiązanie przepełnienia stosu stackoverflow.com/questions/11370672/...
Greg

4
Uważam, że Open XML Writer Microsoft Open XML SDK jest świetny. Korzystając z powyższych rozwiązań (zwłaszcza próbka Vincenta Toma (Poly Math)), łatwo jest zbudować program piszący, który przesyła strumieniowo duże zestawy danych i zapisuje rekordy w sposób podobny i niezbyt skomplikowany w stosunku do tego, co zrobiłbyś dla CSV; ale zamiast tego piszesz xml. Open XML to sposób myślenia, w którym Microsoft uważa, że ​​to nowe formaty pakietu Office. Zawsze możesz zmienić ich nazwy z .xslx na pliki .zip, jeśli masz ochotę pogrzebać w ich zawartości XML.
Greg


108

Możesz użyć OLEDB do tworzenia i manipulowania plikami Excel. Sprawdź to: czytanie i pisanie programu Excel za pomocą OLEDB .

Typowy przykład:

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();
}

EDYCJA - Kilka dodatkowych linków:


4
Czy ktoś może potwierdzić, czy to działa, gdy działa w środowisku x64? Jestem prawie pewien, że Jet działa tylko wtedy, gdy twoja aplikacja jest skompilowana lub działa w trybie 32-bitowym.
Lamar,

2
Właśnie przetestowałem to połączenie i nie powiodło się na Windows Server 2008 R2 x64 RC, wygląda na to, że trzeba zainstalować sterownik pakietu Office 2007 System: Data Connectivity Components [ microsoft.com/downloads/…
Chris Richner

25
Bądź z tym bardzo ostrożny - to duża brzydka gratka (na przykład czasami odgaduje typ kolumny i odrzuca wszystkie dane, które nie pasują).
dbkk

9
Używając tej metody należy być bardzo ostrożnym. Uważam, że jest bardzo niestabilna w przypadku danych, które nie są w idealnym formacie.
Kenny Mann,

9
Jako osoba, która musiała korzystać z OleDb w dużym projekcie, mówię, że trzymaj się z dala od IT! Czasami nie jest w stanie pobrać wartości komórki tylko dlatego, że nie mógł zrozumieć formatu. Nie ma operacji usuwania. Działa zupełnie inaczej i jest nieprzewidywalny, nawet przy najmniejszej zmianie dostawcy. Powiedziałbym, że idź po sprawdzone rozwiązanie komercyjne.
Caner Öncü

80

Rozwiązanie komercyjne, SpreadsheetGear dla platformy .NET zrobi .

Można zobaczyć na żywo ASP.NET (C # i VB) próbek tutaj i pobrać wersję próbną tutaj .

Oświadczenie: Jestem właścicielem SpreadsheetGear LLC


10
Masz świetny produkt, ale myślę, że wiele osób oczekuje tutaj darmowych rozwiązań. To może tłumaczyć negatywne głosy.
md1337

65

Kilka opcji, z których skorzystałem:

Jeśli XLSX jest koniecznością: pakiet Excel jest dobrym początkiem, ale zmarł, gdy programista przestał nad nim pracować. ExML podniósł się stamtąd i dodał kilka funkcji. ExML nie jest złą opcją, wciąż używam go na kilku stronach produkcyjnych.

Jednak do wszystkich moich nowych projektów korzystam z NPOI , portu .NET dla Apache POI . NPOI 2.0 (Alpha) obsługuje również XLSX.


Zachowaj ostrożność przy korzystaniu z ExcelPackage, jeśli potrzebujesz obsługi XLS. Miałem z tym trudności i ostatecznie przerzuciłem się na ExcelLibrary.
Jeremy

Zdecydowanie prawda. ExcelPackage / ExML to dobra opcja, jeśli potrzebujesz obsługi XLSX.
Nate

5
Zauważ, że ExcelPackage ma następcę: EPPlus ( epplus.codeplex.com ), który obsługuje XLSX. Moją jedyną troską, na przykład w porównaniu do NPOI, jest wydajność, np. Gdy jest dużo kolumn.
Pragmateek

63

Niezwykle lekką opcją może być użycie tabel HTML. Po prostu utwórz znaczniki head, body i table w pliku i zapisz je jako plik z rozszerzeniem .xls. Istnieją specyficzne dla Microsoft atrybuty, których można użyć do stylizowania wyników, w tym formuły.

Zdaję sobie sprawę, że możesz nie kodować tego w aplikacji internetowej, ale oto przykład kompozycji pliku Excel za pomocą tabeli HTML. Tej techniki można użyć, jeśli kodujesz aplikację konsolową, aplikację komputerową lub usługę.


6
Jest tak ad hoc, ale działa (nie wspominając o wydaniu ostrzeżenia o otwarciu programu Excel) i jest tak prosty, że zasługuje na miejsce jako rozwiązanie. Chociaż tylko za pokazanie, że możesz wyeksportować plik Excela :))
Luka Ramishvili

3
To rozwiązanie działało dla mnie dobrze, pamiętaj, że nie możesz używać rozszerzenia .xlsx
Jill

Niektóre osoby w mojej organizacji nie mogą otwierać plików Excel utworzonych w ten sposób w pakiecie Office 2010 i nowszych wersjach. Nie wiem na czym polega problem, ale musiałem wdrożyć własną implementację OpenXML. (patrz odpowiedź Soggera)
Kristen Hammack,

49

Jeśli tworzysz pliki programu Excel 2007/2010, wypróbuj ten projekt open source: https://github.com/closedxml/closedxml

Zapewnia obiektowy sposób manipulowania plikami (podobny do VBA) bez radzenia sobie z kłopotami związanymi z dokumentami XML. Może być używany w dowolnym języku .NET, takim jak C # i Visual Basic (VB).

ClosedXML pozwala tworzyć pliki Excel 2007/2010 bez aplikacji Excel. Typowym przykładem jest tworzenie raportów Excel na serwerze WWW:

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

9
Próbowałem użyć tego w projekcie, który buduje dość duże arkusze Excela. Doskonała biblioteka, ale wyjątkowo słaba wydajność. Właśnie zrobiłem porównanie dla projektu, nad którym pracuję: ClosedXML (wersja 0.53.3) zajął 92 489 ms, podczas gdy EPPlus (wersja 2.9.03, do testowania - nie możemy używać, ponieważ jest to GPL) zajął 16 500 ms.
Druid

1
@Druid licencja jest LGPL przy założeniu, że nie modyfikujesz kodu źródłowego do ClosedXML, korzystanie z witryny
Chris


47

W rzeczywistości możesz chcieć sprawdzić klasy interop dostępne w C # (np Microsoft.Office.Interop.Excel. Mówisz, że nie ma OLE (co nie jest), ale klasy interop są bardzo łatwe w użyciu. Sprawdź dokumentację C # tutaj (Interop dla programu Excel zaczyna się od strona 1072 C # PDF).

Możesz być pod wrażeniem, jeśli ich nie wypróbowałeś.

Ostrzegamy przed stanowiskiem Microsoftu w tej sprawie:

Firma Microsoft obecnie nie zaleca i nie obsługuje automatyzacji aplikacji pakietu Microsoft Office z dowolnej nienadzorowanej, nieinteraktywnej aplikacji lub komponentu klienta (w tym usług ASP, ASP.NET, DCOM i NT), ponieważ pakiet Office może wykazywać niestabilne zachowanie i / lub zakleszczenie, gdy pakiet Office jest uruchomiony w tym środowisku.


6
Ale musisz upewnić się, że
pozbywasz się

8
@ Ricky B: Z mojego doświadczenia z interopem wynika również, że korzysta z programu Excel. Za każdym razem, gdy go używaliśmy, jeśli Excel nie był zainstalowany na komputerze, otrzymywaliśmy wyjątki COM.
MagicKat,

1
Dzięki OLE, nawet przy bardzo ostrożnym usuwaniu, ostatecznie wycieka pamięć lub ulega awarii. Jest to prawdopodobnie poprawne w przypadku obsługiwanych aplikacji / stacji roboczych, ale w przypadku serwerów nie jest zalecane (MS ma takie stwierdzenie KB). W przypadku naszego serwera po prostu restartujemy go co noc. Znowu to działa OK.
Jennifer Zouak,

11
@Geoffrey: ah OK, zamierzasz zmusić mnie do pracy :) -> support.microsoft.com/kb/257757 Microsoft obecnie nie zaleca i nie obsługuje automatyzacji aplikacji Microsoft Office z jakichkolwiek nienadzorowanych, innych niż interaktywna aplikacja kliencka ...
Jennifer Zouak,

4
Przychodzę do tej dyskusji po ponad tygodniu zmagania się z interopem i jeśli twoje potrzeby nie są bardzo proste, to nie zadziała. Obsługa formatowania arkusza kalkulacyjnego jest fatalna, co jest prawdopodobnie powodem generowania pliku .xls, a nie tylko płaskiego pliku .csv. Na przykład, czy próbowałeś wypisać więcej niż 911 znaków w komórce, czy próbowałeś ustawić szerokość scalonych komórek w spójny sposób? Mam i nie mogę Wam powiedzieć, jak bardzo nienawidzę tego badziewia ... Zrób sobie przysługę i skorzystaj z jednej z bezpłatnych bibliotek wymienionych w tej dyskusji.
md1337

34

Oto całkowicie darmowa biblioteka C #, która pozwala eksportować z DataSet, DataTablelubList<> do prawdziwego Excel 2007 .xlsx, przy użyciu biblioteki OpenXML:

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

Pełny kod źródłowy jest dostarczany - bezpłatnie - wraz z instrukcjami i aplikacją demonstracyjną.

Po dodaniu tej klasy do aplikacji możesz wyeksportować swój DataSet do Excela w jednym wierszu kodu:

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

Nie ma nic prostszego ...

I nawet nie wymaga obecności Excela na twoim serwerze.


1
To wydaje się nieco mylące, ponieważ prosisz o darowiznę, aby uzyskać wszystkie funkcje.
UrbanEsc

To częściowo prawda: całkowicie darmowa wersja wygeneruje dla Ciebie idealny plik .xlsx i podasz cały kod źródłowy. Jeśli przekażesz 10 USD lub więcej na rzecz jednej z tych dwóch organizacji charytatywnych (z których absolutnie nic nie otrzymuję), otrzymasz „lepszą” wersję pokazującą sposób formatowania, daty itp. Biorąc pod uwagę koszt produktów innych firm, uważam zamiast tego warto przekazać 10 $ na dobrą sprawę!
Mike Gledhill


23

Możesz rzucić okiem na GemBox.Spreadsheet .

Mają darmową wersję ze wszystkimi funkcjami, ale ograniczoną do 150 wierszy na arkusz i 5 arkuszy na skoroszyt, jeśli to odpowiada Twoim potrzebom.

Nie musiałem go jeszcze używać, ale wygląda interesująco.


21

Syncfusion Essential XlsIO może to zrobić. Nie ma zależności od pakietu Microsoft Office, a także obsługuje określone platformy.

Przykładowy kod:

//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);

Cały pakiet kontroli jest dostępny bezpłatnie w ramach programu licencji społecznościowej , jeśli się kwalifikujesz (dochód poniżej 1 miliona USD). Uwaga: Pracuję dla Syncfusion.


18

Dobrze,

możesz także użyć biblioteki innej firmy, takiej jak Aspose .

Ta biblioteka ma tę zaletę, że nie wymaga instalacji programu Excel na komputerze, co byłoby idealne w twoim przypadku.


Mówiąc ściślej, możesz użyć Aspose.Cells dla platformy .NET, aby utworzyć pliki Excel (XLS, XLSX) w aplikacji .NET.
Shahzad Latif,

9
Tak, możesz, jeśli nie masz nic przeciwko płaceniu minimalnej opłaty licencyjnej wynoszącej 999 USD. Wypróbuj bibliotekę MikesKnowledgeBase ... która jest tańsza o 999 USD!
Mike Gledhill


17

Różne biblioteki XML pakietu Office 2003 działają całkiem dobrze w przypadku mniejszych plików programu Excel. Jednak uważam, że sama wielkość dużego skoroszytu zapisanego w formacie XML jest problemem. Na przykład skoroszyt, z którym pracuję, miałby 40 MB w nowym (i, co prawda bardziej ciasno spakowanym) formacie XLSX, staje się plikiem XML 360 MB.

O ile moje badania mnie zaprowadziły, istnieją dwa komercyjne pakiety, które umożliwiają wyjście do starszych formatów plików binarnych. Oni są:

Żadne z nich nie jest tanie (myślę, że odpowiednio 500 USD i 800 USD). ale oba działają niezależnie od samego Excela.

Byłbym ciekawy modułu wyjściowego Excela, takiego jak OpenOffice.org. Zastanawiam się, czy można je przenieść z Javy do .Net.


Ten działa zarówno na .net i java i nie jest drogi. SmartXLS smartxls.com
liya


15

Niedawno korzystałem z FlexCel.NET i okazało się, że jest to doskonała biblioteka! Nie mówię tego o zbyt wielu produktach. Nie ma sensu podawać tutaj całej oferty sprzedaży, możesz przeczytać wszystkie funkcje na ich stronie internetowej.

Jest to produkt komercyjny, ale jeśli kupisz, otrzymasz pełne źródło. Więc przypuszczam, że mógłbyś go skompilować w swoim zespole, gdybyś naprawdę chciał. W przeciwnym razie jest to tylko jeden dodatkowy zestaw do xcopy - bez konfiguracji lub instalacji lub coś podobnego.

Nie sądzę, że znajdziesz sposób, aby to zrobić bez bibliotek stron trzecich, ponieważ .NET Framework, oczywiście, nie ma wbudowanej obsługi tego, a OLE Automation to po prostu cały świat bólu.


15

Napisałem prosty kod do eksportowania zestawu danych do programu Excel bez użycia obiektu programu Excel przy użyciu System.IO.StreamWriter.

Poniżej znajduje się kod, który odczyta wszystkie tabele z zestawu danych i zapisze je kolejno w arkuszach. Wziąłem pomoc z tego artykułu .

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
Tak jak mówi ten artykuł, jest to XML, który Excel będzie czytał, a nie plik XLS, co oznacza, że ​​może działać tylko w Excelu, a nie w innych programach, które czytają arkusze kalkulacyjne. Ale prawdopodobnie jest to lepsze niż równoważne odpowiedzi w tabeli HTML tutaj!
Rup,

Obsługuje xlsx ? OpenXML ?
Kiquenet



12

Oto sposób, aby to zrobić za pomocą LINQ to XML, wraz z przykładowym kodem:

Szybko importuj i eksportuj dane Excel za pomocą LINQ do XML

Jest to trochę skomplikowane, ponieważ musisz zaimportować przestrzenie nazw i tak dalej, ale pozwala uniknąć zewnętrznych zależności.

(Oczywiście jest to również VB .NET, nie C #, ale zawsze możesz wyizolować VB .NET w swoim własnym projekcie, aby używać literałów XML i robić wszystko inne w C #.)


12

Niektórzy zewnętrzni dostawcy komponentów, tacy jak Infragistics lub Syncfusion, zapewniają bardzo dobre możliwości eksportu do Excela, które nie wymagają instalacji Microsoft Excel.

Ponieważ ci dostawcy zapewniają również zaawansowane komponenty interfejsu użytkownika, komponenty te są szczególnie przydatne, jeśli chcesz, aby styl i układ eksportu programu Excel naśladował bieżący stan siatki w interfejsie użytkownika aplikacji.

Jeśli twój eksport ma być wykonywany po stronie serwera z naciskiem na dane, które mają być eksportowane i bez łącza do interfejsu użytkownika, wybrałbym jedną z bezpłatnych opcji open source (np. ExcelLibrary).

Wcześniej byłem zaangażowany w projekty, które próbowały wykorzystać automatyzację po stronie serwera w pakiecie Microsoft Office. Na podstawie tego doświadczenia zdecydowanie odradzam takie podejście.


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);
            }
        }
    }
}

Cześć, tym rozwiązaniem jest wyeksportowanie widoku siatki do pliku programu Excel, który może ci pomóc


7
Nie, generuje HTML oznaczony jako plik Excela, a nie prawdziwy plik Excela. Tak, sam program Excel otworzy to OK, ale inne programy korzystające z arkuszy kalkulacyjnych - w tym na przykład bezpłatna przeglądarka Excel Microsoft - na przykład - nie zaakceptują tego. Lepiej byłoby utworzyć prawdziwy plik Excel za pomocą jednej z bibliotek tutaj.
Rup

Powinieneś także użyć System.Net.Mime.ContentDisposition, aby wygenerować tekst nagłówka rozmieszczenia treści, a nie ciąg znaków dołączający - to odpowiednio poradzi sobie z nazwami plików, które zawierają spacje itp.
Rup

12

Korzystając z tej biblioteki, możesz tworzyć ładnie sformatowane pliki Excela: http://officehelper.codeplex.com/documentation
Zobacz poniższy przykład:

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");
}        

gdzie próbka wygląda następująco:

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

Najprostszym i najszybszym sposobem utworzenia pliku Excel z C # jest użycie narzędzia Open XML Productivity Tool. Narzędzie Open XML Productivity Tool jest dostarczane z instalacją Open XML SDK. Narzędzie to przekształca dowolny plik Excela w kod C #. Kod C # można następnie wykorzystać do ponownego wygenerowania tego pliku.

Przegląd tego procesu jest następujący:

  1. Zainstaluj Open XML SDK za pomocą narzędzia.
  2. Utwórz plik Excel za pomocą najnowszego klienta Excel o pożądanym wyglądzie. Nazwij to DesiredLook.xlsx.
  3. Przy otwartym narzędziu DesiredLook.xlsxkliknij przycisk Odbij kod u góry. wprowadź opis zdjęcia tutaj
  4. Kod C # dla twojego pliku zostanie wygenerowany w prawym panelu narzędzia. Dodaj to do swojego rozwiązania C # i wygeneruj pliki o pożądanym wyglądzie.

Jako bonus, ta metoda działa dla wszystkich plików Word i PowerPoint. Jako programista C # wprowadzisz zmiany w kodzie, aby dostosować je do swoich potrzeb.

Opracowałem prostą aplikację WPF na github, która w tym celu będzie działać w systemie Windows. Istnieje klasa zastępcza o nazwie, w GeneratedClassktórej można wkleić wygenerowany kod. Jeśli cofniesz jedną wersję pliku, wygeneruje on plik Excel taki jak ten:

wprowadź opis zdjęcia tutaj


1
Nie próbowałem jeszcze tego rozwiązania Open XML SDK, ale Wow, na pewno to sprawdzę. Pracowałem z takimi narzędziami od wielu lat i nie wiedziałem o tym. Opublikowałem własny prosty FOSS do konwersji plików do XLSX za pomocą .NET: github.com/TonyGravagno/NebulaXConvert
TonyG


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.