Como posso exportar um DataTablepara o Excel em C #? Estou usando o Windows Forms. O DataTableestá associado a um DataGridViewcontrole. Tenho que exportar registros DataTablepara o Excel.
A maneira mais fácil é fazer um loop foreach aninhado em itens e subitens.
Saeid Yazdani
NOTA: Se você estiver tentando passar valores de uma tabela de dados para um objeto e, em seguida, para o Excel, também deverá realizar o tratamento de erros de tipo de dados. Por exemplo, Guids eliminará sua atribuição com uma exceção HRESULT: 0x800A03EC. Uma alternativa sem testar os tipos de dados é usar "ToString ()" ao preencher seu objeto. O Excel converterá os números de volta ao formato numérico sozinho. FlashTrev abordou o problema relacionado de data / horas.
Adicionar ~ 6 MB de bibliotecas referenciadas não tornaria o aplicativo um pouco pesado?
ʞᴉɯ
4
Boa pergunta @MicheleVirgilio. Não fiz nenhum teste para quantificar um impacto. Mas pelo que vale a pena, não me incomodou em nenhum dos projetos que usei, na verdade, não posso dizer que já tenha percebido.
hmqcnoesy
Este código me retornou um excel com uma única coluna com valorClosedXML.Excel.XLWorkbook
É uma armadilha
78
Experimente um código simples para converter DataTable em arquivo excel como csv:
Que resposta excelente, cara. Não tenho espaço para dar mais de um voto favorável à sua resposta, caso contrário, poderia ter dado até mais de 100 votos positivos.
Ashok kumar
2
@Cuong Le - Se a célula tiver duas vírgulas, será um problema em "string.Join (", ")"
suneel ranga
@Cuong Le onde será a "excel.csv"localização?
Jogi
2
@suneelranga - Se uma célula (ou seja, na linha.ItemArray) contém uma ,(vírgula), pelo padrão CSV, essa célula deve ser circundada por aspas ","e, em seguida, aparecer no arquivo como de costume. Portanto, sim - isso causará um problema porque este código não detecta ,e aplica aspas.
Tom Leys
1
@ Si8 uma vez salvo, você pode fazer um Process.Start (Your File) e ele irá abri-lo para eles. Isso é o mais perto que você pode chegar, eu acredito.
TimmRH 01 de
40
Uma opção elegante é escrever um método de extensão (veja abaixo) para a classe DataTable da estrutura .net.
Este método de extensão pode ser chamado da seguinte maneira:
using System;
using System.Collections.Generic;
using System.Linq;
using Excel=Microsoft.Office.Interop.Excel;
using System.Data;
using System.Data.OleDb;DataTable dt;// fill table data in dt here ...// export DataTable to excel// save excel file without ever making it visible if filepath is given// don't save excel file, just make it visible if no filepath is given
dt.ExportToExcel(ExcelFilePath);
Método de extensão para a classe DataTable:
publicstaticclassMy_DataTable_Extensions{// Export DataTable into an excel file with field names in the header line// - Save excel file without ever making it visible if filepath is given// - Don't save excel file, just make it visible if no filepath is givenpublicstaticvoidExportToExcel(thisDataTable tbl,string excelFilePath =null){try{if(tbl ==null|| tbl.Columns.Count==0)thrownewException("ExportToExcel: Null or empty input table!\n");// load excel, and create a new workbookvar excelApp =newExcel.Application();
excelApp.Workbooks.Add();// single worksheetExcel._Worksheet workSheet = excelApp.ActiveSheet;// column headingsfor(var i =0; i < tbl.Columns.Count; i++){
workSheet.Cells[1, i +1]= tbl.Columns[i].ColumnName;}// rowsfor(var i =0; i < tbl.Rows.Count; i++){// to do: format datetime values before printingfor(var j =0; j < tbl.Columns.Count; j++){
workSheet.Cells[i +2, j +1]= tbl.Rows[i][j];}}// check file pathif(!string.IsNullOrEmpty(excelFilePath)){try{
workSheet.SaveAs(excelFilePath);
excelApp.Quit();MessageBox.Show("Excel file saved!");}catch(Exception ex){thrownewException("ExportToExcel: Excel file could not be saved! Check filepath.\n"+ ex.Message);}}else{// no file path is given
excelApp.Visible=true;}}catch(Exception ex){thrownewException("ExportToExcel: \n"+ ex.Message);}}}
@ alex.pulver também não funciona quando tento usá-lo em um servidor. Bom ponto para mencionar.
Si8
Isso vai funcionar, mas é lento. É melhor copiar para a área de transferência e colar no Excel. Se você trabalhar em mais de 1000 registros, isso demorará um pouco.
Alex M
25
Solução baseada no artigo tuncalik (obrigado pela ideia), mas no caso de mesas grandes está funcionando muito mais rápido (e é um pouco menos claro).
publicstaticclassMy_DataTable_Extensions{/// <summary>/// Export DataTable to Excel file/// </summary>/// <param name="DataTable">Source DataTable</param>/// <param name="ExcelFilePath">Path to result file name</param>publicstaticvoidExportToExcel(thisSystem.Data.DataTableDataTable,stringExcelFilePath=null){try{intColumnsCount;if(DataTable==null||(ColumnsCount=DataTable.Columns.Count)==0)thrownewException("ExportToExcel: Null or empty input table!\n");// load excel, and create a new workbookMicrosoft.Office.Interop.Excel.ApplicationExcel=newMicrosoft.Office.Interop.Excel.Application();Excel.Workbooks.Add();// single worksheetMicrosoft.Office.Interop.Excel._WorksheetWorksheet=Excel.ActiveSheet;object[]Header=newobject[ColumnsCount];// column headings for(int i =0; i <ColumnsCount; i++)Header[i]=DataTable.Columns[i].ColumnName;Microsoft.Office.Interop.Excel.RangeHeaderRange=Worksheet.get_Range((Microsoft.Office.Interop.Excel.Range)(Worksheet.Cells[1,1]),(Microsoft.Office.Interop.Excel.Range)(Worksheet.Cells[1,ColumnsCount]));HeaderRange.Value=Header;HeaderRange.Interior.Color=System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.LightGray);HeaderRange.Font.Bold=true;// DataCellsintRowsCount=DataTable.Rows.Count;object[,]Cells=newobject[RowsCount,ColumnsCount];for(int j =0; j <RowsCount; j++)for(int i =0; i <ColumnsCount; i++)Cells[j, i]=DataTable.Rows[j][i];Worksheet.get_Range((Microsoft.Office.Interop.Excel.Range)(Worksheet.Cells[2,1]),(Microsoft.Office.Interop.Excel.Range)(Worksheet.Cells[RowsCount+1,ColumnsCount])).Value=Cells;// check fielpathif(ExcelFilePath!=null&&ExcelFilePath!=""){try{Worksheet.SaveAs(ExcelFilePath);Excel.Quit();System.Windows.MessageBox.Show("Excel file saved!");}catch(Exception ex){thrownewException("ExportToExcel: Excel file could not be saved! Check filepath.\n"+ ex.Message);}}else// no filepath is given{Excel.Visible=true;}}catch(Exception ex){thrownewException("ExportToExcel: \n"+ ex.Message);}}}
A resposta de tuncalik demorou quase um minuto para mim, este é a 1 segundo se demorar ... Na verdade, fiquei assustado.
Wilsu
2
Esta é a amostra mais rápida que experimentei, ótimo trabalho. Tive que usar Marshal para liberar o arquivo depois. Excel.Quit(); Marshal.FinalReleaseComObject(Worksheet); Marshal.FinalReleaseComObject(HeaderRange); Marshal.FinalReleaseComObject(Excel);
Dave Kelly
É necessário que o Office seja instalado?
Parshuram Kalvikatte
Funciona perfeitamente de outra forma, mas minha cor de fundo do cabeçalho de fundo é definida como Preto sempre ao usar esta solução no aplicativo de console. Qual seria a razão??
Zaveed Abbasi
15
Tente esta função passar a tabela de dados e o caminho do arquivo para onde você deseja exportar
publicvoidCreateCSVFile(refDataTable dt,string strFilePath){try{// Create the CSV file to which grid data will be exported.StreamWriter sw =newStreamWriter(strFilePath,false);// First we will write the headers.//DataTable dt = m_dsProducts.Tables[0];int iColCount = dt.Columns.Count;for(int i =0; i < iColCount; i++){
sw.Write(dt.Columns[i]);if(i < iColCount -1){
sw.Write(",");}}
sw.Write(sw.NewLine);// Now write all the rows.foreach(DataRow dr in dt.Rows){for(int i =0; i < iColCount; i++){if(!Convert.IsDBNull(dr[i])){
sw.Write(dr[i].ToString());}if(i < iColCount -1){
sw.Write(",");}}
sw.Write(sw.NewLine);}
sw.Close();}catch(Exception ex){throw ex;}}
Observe que isso não usará realmente as células da tabela no documento do Excel; em vez disso, tudo para cada linha será impresso na primeira célula de cada linha.
Banshee
@Banshee Não, o Excel entende totalmente os arquivos CSV.
NickG
Também não funciona com o meu excel. Os dados de cada linha estão na primeira célula.
Mitulát báti
5
A melhor e mais fácil maneira
privatevoid exportToExcel(DataTable dt){/*Set up work book, work sheets, and excel application*/Microsoft.Office.Interop.Excel.Application oexcel =newMicrosoft.Office.Interop.Excel.Application();try{string path =AppDomain.CurrentDomain.BaseDirectory;object misValue =System.Reflection.Missing.Value;Microsoft.Office.Interop.Excel.Workbook obook = oexcel.Workbooks.Add(misValue);Microsoft.Office.Interop.Excel.Worksheet osheet =newMicrosoft.Office.Interop.Excel.Worksheet();// obook.Worksheets.Add(misValue);
osheet =(Microsoft.Office.Interop.Excel.Worksheet)obook.Sheets["Sheet1"];int colIndex =0;int rowIndex =1;foreach(DataColumn dc in dt.Columns){
colIndex++;
osheet.Cells[1, colIndex]= dc.ColumnName;}foreach(DataRow dr in dt.Rows){
rowIndex++;
colIndex =0;foreach(DataColumn dc in dt.Columns){
colIndex++;
osheet.Cells[rowIndex, colIndex]= dr[dc.ColumnName];}}
osheet.Columns.AutoFit();string filepath ="C:\\Temp\\Book1";//Release and terminate excel
obook.SaveAs(filepath);
obook.Close();
oexcel.Quit();
releaseObject(osheet);
releaseObject(obook);
releaseObject(oexcel);
GC.Collect();}catch(Exception ex){
oexcel.Quit();
log.AddToErrorLog(ex,this.Name);}}
(por favor, esteja aqui) se houver mais de um arquivo excel aberto, esta função de liberação destrói todos eles ou apenas aquele passado como parâmetro?
Elliott Addi
1
Excel Interop:
Este método evita que as datas sejam invertidas de dd-mm-aaaa para mm-dd-aaaa
publicboolDataTableToExcelFile(DataTable dt,string targetFile){constbool dontSave =false;bool success =true;//Exit if there is no rows to exportif(dt.Rows.Count==0)returnfalse;object misValue =System.Reflection.Missing.Value;List<int> dateColIndex =newList<int>();Excel.Application excelApp =newExcel.Application();Excel.Workbook excelWorkBook = excelApp.Workbooks.Add(misValue);Excel.Worksheet excelWorkSheet = excelWorkBook.Sheets("sheet1");//Iterate through the DataTable and populate the Excel work sheettry{for(int i =-1; i <= dt.Rows.Count-1; i++){for(int j =0; j <= dt.Columns.Count-1; j++){if(i <0){//Take special care with Date columnsif(dt.Columns(j).DataTypeistypeof(DateTime)){
excelWorkSheet.Cells(1, j +1).EntireColumn.NumberFormat="d-MMM-yyyy;@";
dateColIndex.Add(j);}//else if ... Feel free to add more Formatselse{//Otherwise Format the column as text
excelWorkSheet.Cells(1, j +1).EntireColumn.NumberFormat="@";}
excelWorkSheet.Cells(1, j +1)= dt.Columns(j).Caption;}elseif(dateColIndex.IndexOf(j)>-1){
excelWorkSheet.Cells(i +2, j +1)=Convert.ToDateTime(dt.Rows(i).ItemArray(j)).ToString("d-MMM-yyyy");}else{
excelWorkSheet.Cells(i +2, j +1)= dt.Rows(i).ItemArray(j).ToString();}}}//Add Autofilters to the Excel work sheet
excelWorkSheet.Cells.AutoFilter(1,Type.Missing,Excel.XlAutoFilterOperator.xlAnd,Type.Missing,true);//Autofit columns for neatness
excelWorkSheet.Columns.AutoFit();if(File.Exists(exportFile))File.Delete(exportFile);
excelWorkSheet.SaveAs(exportFile);}catch{
success =false;}finally{//Do this irrespective of whether there was an exception or not.
excelWorkBook.Close(dontSave);
excelApp.Quit();
releaseObject(excelWorkSheet);
releaseObject(excelWorkBook);
releaseObject(excelApp);}return success;}
Se você não se preocupa com a inversão das datas, use o link consulte que mostra como preencher todas as células na planilha do Excel em uma linha de código:
Basta fazer uso da Biblioteca CloseMXL.Excel . É fácil e muito rápido também.
Classe
privateDataTable getAllList(){string constr =ConfigurationManager.ConnectionStrings["RConnection"].ConnectionString;
using (SqlConnection con =newSqlConnection(constr)){
using (SqlCommand cmd =newSqlCommand("SELECT EmpId, gender, EmpName, pOnHold FROM Employee WHERE EmpId= '"+AnyVariable+"' ORDER BY EmpName")){
using (SqlDataAdapter da =newSqlDataAdapter()){DataTable dt =newDataTable();
cmd.CommandType=CommandType.Text;
cmd.Connection= con;
da.SelectCommand= cmd;
da.Fill(dt);
dt.Columns[0].ColumnName="Employee Id";
dt.Columns[1].ColumnName="Gender";
dt.Columns[2].ColumnName="Employee Name";
dt.Columns[3].ColumnName="On Hold";return dt;}}}}
Em seguida, outro método que obtém o conjunto de dados
publicDataSet getDataSetExportToExcel(){DataSet ds =newDataSet();DataTable dtEmp =newDataTable("CLOT List");
dtEmp = getAllList();
ds.Tables.Add(dtEmp);
ds.Tables[0].TableName="Employee";//If you which to use Mutliple Tabsreturn ds;}
Agora você botão Click Event
protectedvoid btn_Export_Click(object sender,EventArgs e){DataSet ds = getDataSetExportToExcel();
using (XLWorkbook wb =newXLWorkbook()){
wb.Worksheets.Add(ds);
wb.Style.Alignment.Horizontal=XLAlignmentHorizontalValues.Center;
wb.Style.Font.Bold=true;Response.Clear();Response.Buffer=true;Response.Charset="";Response.ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";Response.AddHeader("content-disposition","attachment;filename=EmployeeonHoldList.xlsx");
using (MemoryStreamMyMemoryStream=newMemoryStream()){
wb.SaveAs(MyMemoryStream);MyMemoryStream.WriteTo(Response.OutputStream);Response.Flush();Response.End();}}}
Você pode usar minha biblioteca SwiftExcel . É especialmente bom quando o desempenho e o baixo uso de memória ocorrem, pois grava dados diretamente no arquivo:
using (var ew =newExcelWriter("C:\\temp\\test.xlsx")){for(var row =1; row <=100; row++){for(var col =1; col <=10; col++){
ew.Write($"row:{row}-col:{col}", col, row);}}}
Eu queria adicionar esta resposta porque gastei muito tempo procurando um método rápido e confiável para fazer isso e nenhum exemplo completo do uso de OpenXMLWriter para essa finalidade existia em qualquer lugar que eu pudesse encontrar.
Em primeiro lugar, COM / Interop (que muitas das outras respostas usam) é adequado para esse propósito, mas sofre de algumas sensibilidades. Eu o uso há décadas e ele é praticamente estável, mas ao implementar um front-end de data warehouse para centenas de usuários, descobri que ele estava sujeito a muitos problemas, dependendo da máquina e do que o usuário fazia, então mudei para OpenXML. OpenXML DOM é bastante bom para esse propósito, mas é mais lento do que usar OpenXMLWriter. Quando você entra em grandes conjuntos de dados (100K +) com muitas colunas, o DOM é muito mais lento do que o OpenXMLWriter, então eu uso o último. O método abaixo grava mais de 420 mil linhas com mais de 30 campos em menos de 30 segundos.
Espero que os comentários sejam suficientes para orientar qualquer pessoa sobre o que está fazendo. Ele é simplificado, pois grava todos os valores no arquivo como strings, mas você pode implementar a lógica para gravar vários tipos de dados (e usar vários formatos de células) com base no conteúdo dos seus dados. Você também pode adaptar isso para uso em um DataGridView (em vez de um DataTable) alterando apenas algumas coisas (ou seja, os loops através de colunas / linhas).
É necessária uma referência a DocumentFormat.OpenXML (d / l com OpenXML SDK) e WindowsBase.
ImportsDocumentFormat.OpenXmlImportsDocumentFormat.OpenXml.SpreadsheetImportsDocumentFormat.OpenXml.PackagingPublicSubExportToExcelXML(ByRef dt AsDataTable, filename AsString)Dim wbp AsWorkbookPart, wsp AsWorksheetPart'IfthisDataTable has more rows in it than can fit inExcel,throw an exception
If dt.Rows.Count>1048575ThenThrowNewException("The DataTable is too large to export to Excel.")'Delete any previous file of the same name that may exist.File.Delete(filename)'Create an OpenXMLSpreadsheetDocument...Using xls =SpreadsheetDocument.Create(filename,SpreadsheetDocumentType.Workbook)'Add a WorkbookPart to the SpreadsheetDoc, then add a WorksheetPart to the WorkbookPart.
wbp = xls.AddWorkbookPart()
wsp = wbp.AddNewPart(OfWorksheetPart)'Now we need to add the "StyleSheet" to the WorkbookPart(that we just added above).This will allow us to apply formatting to our Cells.'Add the WbStylesPart and the StyleSheet.Dim stp AsWorkbookStylesPart= wbp.AddNewPart(OfWorkbookStylesPart)Dim ss AsNewStylesheet'Create the only two Fonts we're going to use (Regular and Bold).Dim fBold AsNewFont
fBold.Append(NewBold)Dim fnts AsNewFonts
fnts.Append(NewFont)'This creates the default (unmodified, regular) Font. It's added first, so its index is0.
fnts.Append(fBold)'This creates the Bold font. It's added second, so its index is1.'Create the default Fill/Border settings (these have to be here, even though I don't set any custom fills/borders).Dim flls AsNewFillsDim brdrs AsNewBorders
flls.Append(NewFill)
brdrs.Append(NewBorder)'Now I have to add formats (NumberFormat and CellFormat).First, you create a NumberFormat.Thisis basically the pattern of
' the format (i.e."@"forText).For now, I only need a Text format, but I can add more patterns if needed.' I give the format an ID of 164, since 163iswhere the built-inExcel formats end.Dim nbrfmts AsNewNumberingFormats
nbrfmts.Append(NewNumberingFormatWith{.NumberFormatId=164,.FormatCode="@"})'Create the first two CellFormats:Default, which will have an index of 0 and "Header"(Bold/Centered) with an index of 1.Dim cellfmts AsNewCellFormats()
cellfmts.Append(NewCellFormat()With{.FontId=0,.NumberFormatId=164,.FillId=0,.BorderId=0})
cellfmts.Append(NewCellFormat()With{.FontId=1,.NumberFormatId=164,.Alignment=NewAlignment()With{.WrapText=True,.Horizontal=HorizontalAlignmentValues.Center}})'Add all of the Fonts/Fills/Borders/etc to the StyleSheet and add it all to the WorkbookStylesPart.
ss.Append(fnts)
ss.Append(flls)
ss.Append(brdrs)
ss.Append(cellfmts)
ss.NumberingFormats= nbrfmts
stp.Stylesheet= ss
stp.Stylesheet.Save()'Now create an OpenXMLWriter using the WorksheetPart to write the cells to the worksheet.Using oxw AsOpenXmlWriter=OpenXmlWriter.Create(wsp)'Write the start element for the Worksheet and the Columns...
oxw.WriteStartElement(NewWorksheet)
oxw.WriteStartElement(NewColumns())'Now I'm going to loop through the columns in the DataTable...For c AsInteger=0To dt.Columns.Count-1'Now we'll get the width for the column.Todothis, we loop through all of the rows and measure the width of the text
' using the defaultExcelFont(currently Font:CalibriSize:11) and return the largest width (in pixels) to use below.' Why not do this loop below (when I loop through the rows to write the Cells)? Because you can't.You have to
' write the Column XML first before writing the SheetData/Row/Cell XML (I confirmed this by trying it), so there's
' no way (that I'm aware of) to avoid looping through all of the rows twice if you want to AutoFit.'Setup vars we'll use for getting the column widths (below).Dim g =System.Drawing.Graphics.FromHwnd(IntPtr.Zero)Dim fnt =NewSystem.Drawing.Font("Calibri",11)Dim wid AsDouble=0'Get the width of the header (because if this is wider than the widest value, we'll use the header text's width).' I found that adding 2 pixels to the width was necessary to get the column as wide asExcel would make it.Dim tmp AsDouble= g.MeasureString(dt.Columns(c).ColumnName,NewSystem.Drawing.Font(fnt,System.Drawing.FontStyle.Bold)).Width+2'Loop through the rows in the dt and get the width of the value in that row/col. If it's wider than the widest
' width we've encountered thus far, use the new wider width as our basis.ForEach row AsDataRowIn dt.RowsIf tmp > wid Then wid = tmp
tmp = g.MeasureString(row(c).ToString, fnt).WidthNext'Set the column attributes and write it to the file. The Width is set using a formula that converts from pixels to Excel's column width values.Dim oxa AsNewList(OfOpenXmlAttribute)From{NewOpenXmlAttribute("min",Nothing, c +1),NewOpenXmlAttribute("max",Nothing, c +1),NewOpenXmlAttribute("width",Nothing,System.Math.Round((wid -12+5)/7D+1,2))}
oxw.WriteStartElement(NewColumn(), oxa)
oxw.WriteEndElement()Next'CLoseout the Columns collection.
oxw.WriteEndElement()'Write the start element for the SheetData...
oxw.WriteStartElement(NewSheetData)'Write the start element for the Header row.
oxw.WriteStartElement(NewRow)'Loop through the Columnsin the dt.ForEach col AsDataColumnIn dt.Columns'Write a cell for this column's Header.AllHeader cells are written with a DataType of String("str").' I ALSO apply the "Header"CellFormat(StyleIndex1) to all of the HeaderCells.This makes them Bold and Centered.WriteCell(oxw, col.ColumnName,"str",1)Next'Closeout the Header row.
oxw.WriteEndElement()'Loop through all of the rows in the dt...ForEach row AsDataRowIn dt.Rows'Write a StartElementforthis row...
oxw.WriteStartElement(NewRow)'Loop through all of the columns in the dt...For c AsInteger=0To dt.Columns.Count-1'Write a valueinthis row/column to the Excel file. I use the datatype of "String" and the defaultCellFormat/StyleIndex.WriteCell(oxw, row(c).ToString,"str",0)Next'Closeoutthis row.
oxw.WriteEndElement()Next'Closeout the Worksheet and SheetData elements...
oxw.WriteEndElement()
oxw.WriteEndElement()EndUsing'Now we're going to create an OpenXMLWriter using the WorkbookPart(that we created above)...Using oxw AsOpenXmlWriter=OpenXmlWriter.Create(wbp)'Add starting elements for the Workbook and Sheets collection.
oxw.WriteStartElement(NewWorkbook())
oxw.WriteStartElement(NewSheets())'Add the Sheet(name the Sheet after the file name minus the extension).
oxw.WriteElement(NewSheet()With{.Name=Path.GetFileNameWithoutExtension(filename),.SheetId=1,.Id= xls.WorkbookPart.GetIdOfPart(wsp)})'WriteEnd elements for the Workbook/Sheets
oxw.WriteEndElement()
oxw.WriteEndElement()EndUsingEndUsingEndSub'ThisSubis used to write a value to a Cell using OpenXMLWriter.PrivateSubWriteCell(ByRef oxw AsOpenXmlWriter,valueAsString, datatype AsString, style AsUInt32Value)Dim oxa AsNewList(OfOpenXmlAttribute)From{NewOpenXmlAttribute("t",Nothing, datatype),NewOpenXmlAttribute("s",Nothing, style)}
oxw.WriteStartElement(NewCell(), oxa)Ifvalue<>NothingThen oxw.WriteElement(NewCellValue(value))
oxw.WriteEndElement()EndSub
Muito obrigado por dedicar tempo a esta resposta. Tenho um cliente que tem uma solução funcionando no Excel Interop, mas está reclamando da lentidão. Eu vi algumas outras respostas a perguntas que me orientaram em direção ao OpenXML, mas estou feliz por ter um atalho para começar.
Brandon Barkley
1
Sem problemas. Ainda uso COM, mas apenas em ambientes sobre os quais tenho total controle. Tenho usado essa abordagem OpenXML em um aplicativo com algumas centenas de usuários por alguns meses e não tive nenhum problema em comparação com erros semanais com COM. Também pesquisei soluções de terceiros, como as mencionadas aqui, mas prefiro escrever eu mesmo para torná-las o mais eficiente possível.
WATYF
0
Em relação à resposta do tuncalik , que é ótima, especialmente se você quiser brincar um pouco com o código :) mas estou colocando minhas datas no Excel no formato americano, ou seja, 2 de março de 2014 no Reino Unido é 03/02/2014, mas nos EUA é 02/03/2014 com o primeiro mês, depois o dia da semana. Eu preciso ter no formato do Reino Unido, alguma idéia, por favor?
Eu verifiquei que ele está armazenado no formato do Reino Unido em minha DataTable e também que meu Excel está definido como Reino Unido, mas por alguma razão, quando ele cria o documento do Excel, ele pensa que é dos EUA (isso porque a Microsoft é uma empresa dos EUA :)
Vou tentar fazer experiências com códigos de cultura, mas não tenho certeza de onde colocá-los ainda. Tentei, mas não surtiu efeito.
ps
Eu tive que mudar uma linha para fazê-lo funcionar, adicionando um 'elenco' como abaixo
// single worksheetExcel._Worksheet workSheet =(Excel._Worksheet)excelApp.ActiveSheet;
Atualização: eu consegui a formatação das datas no Reino Unido ao converter para o formato LongDateTime, mas é apenas uma solução alternativa.
Tópico antigo - mas pensei em colocar meu código aqui. Eu escrevi uma pequena função para escrever uma tabela de dados em uma nova planilha do Excel em um caminho especificado (local). Além disso, você precisará adicionar uma referência à biblioteca do microsoft excel 14.0.
Eu usei isso para extrapolar como escrever uma tabela de dados
* observe que, nas declarações catch, tenho uma referência de classe estática de manipulador de erros (você pode ignorá-los)
using excel =Microsoft.Office.Interop.Excel;
using System.IO;
using System.Data;
using System.Runtime.InteropServices;//class and namespace wrapper is not shown in this example privatevoidWriteToExcel(System.Data.DataTable dt,string location){//instantiate excel objects (application, workbook, worksheets)
excel.ApplicationXlObj=new excel.Application();XlObj.Visible=false;
excel._WorkbookWbObj=(excel.Workbook)(XlObj.Workbooks.Add(""));
excel._WorksheetWsObj=(excel.Worksheet)WbObj.ActiveSheet;//run through datatable and assign cells to values of datatabletry{int row =1;int col =1;foreach(DataColumn column in dt.Columns){//adding columnsWsObj.Cells[row, col]= column.ColumnName;
col++;}//reset column and row variables
col =1;
row++;for(int i =0; i < dt.Rows.Count; i++){//adding dataforeach(var cell in dt.Rows[i].ItemArray){WsObj.Cells[row, col]= cell;
col++;}
col =1;
row++;}WbObj.SaveAs(location);}catch(COMException x){ErrorHandler.Handle(x);}catch(Exception ex){ErrorHandler.Handle(ex);}finally{WbObj.Close();}}
Isso funciona bem, no entanto, você nunca mata seus processos do Excel depois, então sugiro adicionar isso, substituindo sua SaveAslinha como está incluída aqui: 'XlObj.DisplayAlerts = false; WbObj.SaveAs (local); WbObj.Close (); XlObj.Quit (); Marshal.ReleaseComObject (WsObj); Marshal.ReleaseComObject (WbObj); Marshal.ReleaseComObject (XlObj); ' Para usar o Marshal.ReleaseComObjectmétodo, adicione o using System.Runtime.InteropServicesassembly ao seu projeto.
GrammatonCleric
0
Uma maneira de fazer isso também seria com o ACE OLEDB Provider (consulte também strings de conexão para Excel ). Claro, você precisa ter o provedor instalado e registrado. Você deve tê-lo, se tiver o Excel instalado, mas isso é algo que deve ser considerado ao implantar o aplicativo.
Este é o exemplo de como chamar o método auxiliar de ExportHelper:ExportHelper.CreateXlsFromDataTable(myDataTable, @"C:\tmp\export.xls");
O auxiliar para exportar para arquivo Excel usando ACE OLEDB:
publicclassExportHelper{privateconststringExcelOleDbConnectionStringTemplate="Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 8.0;HDR=YES\";";/// <summary>/// Creates the Excel file from items in DataTable and writes them to specified output file./// </summary>publicstaticvoidCreateXlsFromDataTable(DataTable dataTable,string fullFilePath){string createTableWithHeaderScript =GenerateCreateTableCommand(dataTable);
using (var conn =newOleDbConnection(String.Format(ExcelOleDbConnectionStringTemplate, fullFilePath))){if(conn.State!=ConnectionState.Open){
conn.Open();}OleDbCommand cmd =newOleDbCommand(createTableWithHeaderScript, conn);
cmd.ExecuteNonQuery();foreach(DataRow dataExportRow in dataTable.Rows){AddNewRow(conn, dataExportRow);}}}privatestaticvoidAddNewRow(OleDbConnection conn,DataRow dataRow){string insertCmd =GenerateInsertRowCommand(dataRow);
using (OleDbCommand cmd =newOleDbCommand(insertCmd, conn)){AddParametersWithValue(cmd, dataRow);
cmd.ExecuteNonQuery();}}/// <summary>/// Generates the insert row command./// </summary>privatestaticstringGenerateInsertRowCommand(DataRow dataRow){var stringBuilder =newStringBuilder();var columns = dataRow.Table.Columns.Cast<DataColumn>().ToList();var columnNamesCommaSeparated =string.Join(",", columns.Select(x => x.Caption));var questionmarkCommaSeparated =string.Join(",", columns.Select(x =>"?"));
stringBuilder.AppendFormat("INSERT INTO [{0}] (", dataRow.Table.TableName);
stringBuilder.Append(columnNamesCommaSeparated);
stringBuilder.Append(") VALUES(");
stringBuilder.Append(questionmarkCommaSeparated);
stringBuilder.Append(")");return stringBuilder.ToString();}/// <summary>/// Adds the parameters with value./// </summary>privatestaticvoidAddParametersWithValue(OleDbCommand cmd,DataRow dataRow){var paramNumber =1;for(int i =0; i <= dataRow.Table.Columns.Count-1; i++){if(!ReferenceEquals(dataRow.Table.Columns[i].DataType,typeof(int))&&!ReferenceEquals(dataRow.Table.Columns[i].DataType,typeof(decimal))){
cmd.Parameters.AddWithValue("@p"+ paramNumber, dataRow[i].ToString().Replace("'","''"));}else{objectvalue=GetParameterValue(dataRow[i]);OleDbParameter parameter = cmd.Parameters.AddWithValue("@p"+ paramNumber,value);if(valueisdecimal){
parameter.OleDbType=OleDbType.Currency;}}
paramNumber = paramNumber +1;}}/// <summary>/// Gets the formatted value for the OleDbParameter./// </summary>privatestaticobjectGetParameterValue(objectvalue){if(valueisstring){returnvalue.ToString().Replace("'","''");}returnvalue;}privatestaticstringGenerateCreateTableCommand(DataTable tableDefination){StringBuilder stringBuilder =newStringBuilder();bool firstcol =true;
stringBuilder.AppendFormat("CREATE TABLE [{0}] (", tableDefination.TableName);foreach(DataColumn tableColumn in tableDefination.Columns){if(!firstcol){
stringBuilder.Append(", ");}
firstcol =false;string columnDataType ="CHAR(255)";switch(tableColumn.DataType.Name){case"String":
columnDataType ="CHAR(255)";break;case"Int32":
columnDataType ="INTEGER";break;case"Decimal":// Use currency instead of decimal because of bug described at // http://social.msdn.microsoft.com/Forums/vstudio/en-US/5d6248a5-ef00-4f46-be9d-853207656bcc/localization-trouble-with-oledbparameter-and-decimal?forum=csharpgeneral
columnDataType ="CURRENCY";break;}
stringBuilder.AppendFormat("{0} {1}", tableColumn.ColumnName, columnDataType);}
stringBuilder.Append(")");return stringBuilder.ToString();}}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using excel =Microsoft.Office.Interop.Excel;
using EL =ExcelLibrary.SpreadSheet;
using System.Drawing;
using System.Collections;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace _basic
{publicclassExcelProcesser{publicvoidWriteToExcel(System.Data.DataTable dt){
excel.ApplicationXlObj=new excel.Application();XlObj.Visible=false;
excel._WorkbookWbObj=(excel.Workbook)(XlObj.Workbooks.Add(""));
excel._WorksheetWsObj=(excel.Worksheet)WbObj.ActiveSheet;object misValue =System.Reflection.Missing.Value;try{int row =1;int col =1;foreach(DataColumn column in dt.Columns){//adding columnsWsObj.Cells[row, col]= column.ColumnName;
col++;}//reset column and row variables
col =1;
row++;for(int i =0; i < dt.Rows.Count; i++){//adding dataforeach(var cell in dt.Rows[i].ItemArray){WsObj.Cells[row, col]= cell;
col++;}
col =1;
row++;}WbObj.SaveAs(fileFullName, excel.XlFileFormat.xlWorkbookNormal, misValue, misValue, misValue, misValue, excel.XlSaveAsAccessMode.xlExclusive, misValue, misValue, misValue, misValue, misValue);}catch(Exception ex){MessageBox.Show(ex.Message);}finally{WbObj.Close(true, misValue, misValue);}}}
Esta solução é basicamente enviar List<Object>dados para o Excel, ele usa DataTable para fazer isso, eu implementei um método de extensão, então basicamente há duas coisas necessárias. 1. Um método de extensão.
publicstaticclassReportHelper{publicstaticstringToExcel<T>(thisIList<T> data){PropertyDescriptorCollection properties =TypeDescriptor.GetProperties(typeof(T));DataTable table =newDataTable();foreach(PropertyDescriptor prop in properties){//table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);if(prop.Attributes[typeof(FGMS.Entity.Extensions.ReportHeaderAttribute)]!=null){
table.Columns.Add(GetColumnHeader(prop),Nullable.GetUnderlyingType(prop.PropertyType)?? prop.PropertyType);}}//So it seems like when there is only one row of data the headers do not appear//so adding a dummy blank row which fixed the issues//Add a blank Row - Issue # 1471DataRow blankRow = table.NewRow();
table.Rows.Add(blankRow);foreach(T item in data){DataRow row = table.NewRow();foreach(PropertyDescriptor prop in properties)//row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;if(prop.Attributes[typeof(FGMS.Entity.Extensions.ReportHeaderAttribute)]!=null){
row[GetColumnHeader(prop)]= prop.GetValue(item)??DBNull.Value;}
table.Rows.Add(row);}
table.TableName="Results";var filePath =System.IO.Path.GetTempPath()+"\\"+System.Guid.NewGuid().ToString()+".xls";
table.WriteXml(filePath);return filePath;}privatestaticstringGetColumnHeader(PropertyDescriptor prop){return((FGMS.Entity.Extensions.ReportHeaderAttribute)(prop.Attributes[typeof(FGMS.Entity.Extensions.ReportHeaderAttribute)])).ReportHeaderText;}}
Decore suas classes DTO com o atributo [ReportHeaderAttribute("Column Name")]
Tudo o que precisa ser uma coluna no Excel tem que ser decorado com [ReportHeaderAttribute("Column Name")]
Então simplesmente
Var userList =Service.GetUsers()//Returns List of UserDTO;var excelFilePath = userList.ToExcel();HttpResponseMessage result =newHttpResponseMessage(HttpStatusCode.OK);var stream =newFileStream(excelFilePath,FileMode.Open);
result.Content=newStreamContent(stream);
result.Content.Headers.ContentType=newMediaTypeHeaderValue("application/vnd.ms-excel");
result.Content.Headers.ContentDisposition=newContentDispositionHeaderValue("attachment"){FileName="UserList.xls"};return result;
e se o op não quiser criar DTOs para todas as tabelas em que ele vai rodar? Como, por exemplo, foreach de minhas 1 mil mesas faça isso. Adicionar o atributo de cabeçalho de relatório não é rápido - muita codificação lá e isso antes mesmo de trabalhar no trabalho real. Sem criticar sua solução - apenas apontando que o princípio da preguiça não é utilizado aqui, pois esta solução adiciona a etapa de criar dto's e depois compilar. Devo dizer - gostei que você usou os genéricos.
Ken
0
Para exportar dados para o Excel, você pode usar a biblioteca ClosedXML.Report ( https://github.com/ClosedXML/ClosedXML.Report ). Acredite em mim, esta é uma biblioteca maravilhosa e fácil de usar. A biblioteca não precisa do Excel Interop. ClosedXML.Report gera um arquivo Excel baseado em um modelo que você pode criar no Excel usando qualquer formatação. Por exemplo:
var template =newXLTemplate(@".\Templates\report.xlsx");
using (var db =newDbDemos()){var cust = db.customers.LoadWith(c => c.Orders).First();
template.AddVariable(cust);
template.Generate();}
template.SaveAs(outputFile);
Private tmr AsSystem.Windows.Forms.TimerPrivateSubTestExcel()HandlesButton1.Click'// Initial data: SQL Server table with 6 columns and 293000 rows.'// Data table holding all dataDim dt AsNewDataTable("F161")'// Create connectionDim conn AsNewSqlConnection("Server=MYSERVER;Database=Test;Trusted_Connection=Yes;")Dim fAdapter AsNewSqlDataAdapterWith{.SelectCommand=NewSqlCommand($"SELECT * FROM dbo.MyTable", conn)}'// Fill DataTable
fAdapter.Fill(dt)'// Create Excel applicationDim xlApp AsNewExcel.ApplicationWith{.Visible=True}'// Temporarily disable screen updating
xlApp.ScreenUpdating=False'// Create brand new workbookDim xlBook AsExcel.Workbook= xlApp.Workbooks.Add()Dim xlSheet AsExcel.Worksheet=DirectCast(xlBook.Sheets(1),Excel.Worksheet)'// Get number of rowsDim rows_count = dt.Rows.Count'// Get number of columnsDim cols_count = dt.Columns.Count'// Here 's the core idea: after receiving data
'// you need to create an array and transfer it to sheet.'// Why array?'// Because it's the fastest way to transfer data to Excel's sheet.'// So, we have two tasks:'// 1) Create array'// 2) Transfer array to sheet'// ========================================================='// TASK 1: Create array'// ========================================================='// In order to create array, we need to know that'// Excel's Rangeobject expects 2-D array whose lower bounds
'// of both dimensions start from 1.'// This means you can't use C# array.'// You need to manually create such array.'// Since we already calculated number of rows and columns,'// we can use these numbers in creating array.Dim arr =Array.CreateInstance(GetType(Object),{rows_count, cols_count},{1,1})'// Fill arrayFor r =0To rows_count -1For c =0To cols_count -1
arr(r +1, c +1)= dt.Rows(r)(c)NextNext'// ========================================================='// TASK 2: Transfer array to sheet'// ========================================================='// Now we need to transfer array to sheet.'// So, how transfer array to sheet fast?'// '// THE FASTEST WAY TO TRANSFER DATA TO SHEET IS TO ASSIGN ARRAY TO RANGE.'// We could, of course, hard-code values, but Resize property'// makes this work a breeze:
xlSheet.Range("A1").Resize.Resize(rows_count, cols_count).Value= arr
'// If we decide to dump data by iterating over array,'// it will take LOTS of time.'// For r = 1 To rows_count'// For c = 1 To cols_count'// xlSheet.Cells(r, c) = arr(r, c)'// Next'// Next'// Here are time results:'// 1) Assigning array to Range: 3 seconds'// 2) Iterating over array: 45 minutes'// Turn updating on
xlApp.ScreenUpdating=True
xlApp =Nothing
xlBook =Nothing
xlSheet =Nothing'// Here we have another problem:'// creating array took lots of memory (about 150 MB).'// Using 'GC.Collect()', by unknown reason, doesn't help here.'// However, if you run GC.Collect() AFTER this procedure is finished'// (say, by pressing another button and calling another procedure),'// then the memory is cleaned up.'// I was wondering how to avoid creating some extra button to just release memory,'// so I came up with the idea to use timer to call GC.'// After 2 seconds GC collects all generations.'// Do not forget to dispose timer since we need it only once.
tmr =NewTimer()AddHandler tmr.Tick,Sub()
GC.Collect()
GC.WaitForPendingFinalizers()
GC.WaitForFullGCComplete()
tmr.Dispose()EndSub
tmr.Interval=TimeSpan.FromSeconds(2).TotalMilliseconds()
tmr.Start()EndSub
publicclassTestObject{publicintCol1{get;set;}publicintCol2{get;set;}publicstringCol3{get;set;}publicDateTimeCol4{get;set;}}[TestMethod]publicvoidLoadFromCollection_MemberList_Test(){///programming/32587834/epplus-loadfromcollection-text-converted-to-number/32590626#32590626varTestObjectList=newList<TestObject>();for(var i =0; i <10; i++)TestObjectList.Add(newTestObject{Col1= i,Col2= i*10,Col3=(i*10)+"E4"});//Create a test filevar fi =newFileInfo(@"c:\temp\LoadFromCollection_MemberList_Test.xlsx");if(fi.Exists)
fi.Delete();
using (var pck =newExcelPackage(fi)){//Do NOT include Col1var mi =typeof(TestObject).GetProperties().Where(pi => pi.Name!="Col1").Select(pi =>(MemberInfo)pi).ToArray();var worksheet = pck.Workbook.Worksheets.Add("Sheet1");
worksheet.Cells.LoadFromCollection(TestObjectList,true,TableStyles.Dark1,BindingFlags.Public|BindingFlags.Instance, mi);
pck.Save();}}
Respostas:
Eu recomendaria ClosedXML -
Você pode transformar um DataTable em uma planilha do Excel com algum código muito legível:
O desenvolvedor é responsivo e útil. O projeto é desenvolvido ativamente e a documentação é excelente.
fonte
ClosedXML.Excel.XLWorkbook
Experimente um código simples para converter DataTable em arquivo excel como csv:
Isso gravará um novo arquivo
excel.csv
no diretório de trabalho atual, que geralmente é onde o .exe está ou de onde você o inicia.fonte
"excel.csv"
localização?,
(vírgula), pelo padrão CSV, essa célula deve ser circundada por aspas","
e, em seguida, aparecer no arquivo como de costume. Portanto, sim - isso causará um problema porque este código não detecta,
e aplica aspas.Uma opção elegante é escrever um método de extensão (veja abaixo) para a classe DataTable da estrutura .net.
Este método de extensão pode ser chamado da seguinte maneira:
Método de extensão para a classe DataTable:
fonte
ExcelFilePath != null && ExcelFilePath != ""
poderia ser!String.IsNullOrEmpty(ExcelFilePath)
Solução baseada no artigo tuncalik (obrigado pela ideia), mas no caso de mesas grandes está funcionando muito mais rápido (e é um pouco menos claro).
fonte
Excel.Quit(); Marshal.FinalReleaseComObject(Worksheet); Marshal.FinalReleaseComObject(HeaderRange); Marshal.FinalReleaseComObject(Excel);
Tente esta função passar a tabela de dados e o caminho do arquivo para onde você deseja exportar
fonte
A melhor e mais fácil maneira
fonte
private void releaseObject(object o) { try { while (System.Runtime.InteropServices.Marshal.ReleaseComObject(o) > 0) { } } catch { } finally { o = null; } }
Excel Interop:
Excel Interop - Eficiência e desempenho
CSV:
fonte
Classe
Em seguida, outro método que obtém o conjunto de dados
Agora você botão Click Event
fonte
Você pode usar minha biblioteca SwiftExcel . É especialmente bom quando o desempenho e o baixo uso de memória ocorrem, pois grava dados diretamente no arquivo:
Comando Nuget para instalar:
fonte
Eu queria adicionar esta resposta porque gastei muito tempo procurando um método rápido e confiável para fazer isso e nenhum exemplo completo do uso de OpenXMLWriter para essa finalidade existia em qualquer lugar que eu pudesse encontrar.
Em primeiro lugar, COM / Interop (que muitas das outras respostas usam) é adequado para esse propósito, mas sofre de algumas sensibilidades. Eu o uso há décadas e ele é praticamente estável, mas ao implementar um front-end de data warehouse para centenas de usuários, descobri que ele estava sujeito a muitos problemas, dependendo da máquina e do que o usuário fazia, então mudei para OpenXML. OpenXML DOM é bastante bom para esse propósito, mas é mais lento do que usar OpenXMLWriter. Quando você entra em grandes conjuntos de dados (100K +) com muitas colunas, o DOM é muito mais lento do que o OpenXMLWriter, então eu uso o último. O método abaixo grava mais de 420 mil linhas com mais de 30 campos em menos de 30 segundos.
Espero que os comentários sejam suficientes para orientar qualquer pessoa sobre o que está fazendo. Ele é simplificado, pois grava todos os valores no arquivo como strings, mas você pode implementar a lógica para gravar vários tipos de dados (e usar vários formatos de células) com base no conteúdo dos seus dados. Você também pode adaptar isso para uso em um DataGridView (em vez de um DataTable) alterando apenas algumas coisas (ou seja, os loops através de colunas / linhas).
É necessária uma referência a DocumentFormat.OpenXML (d / l com OpenXML SDK) e WindowsBase.
fonte
Em relação à resposta do tuncalik , que é ótima, especialmente se você quiser brincar um pouco com o código :) mas estou colocando minhas datas no Excel no formato americano, ou seja, 2 de março de 2014 no Reino Unido é 03/02/2014, mas nos EUA é 02/03/2014 com o primeiro mês, depois o dia da semana. Eu preciso ter no formato do Reino Unido, alguma idéia, por favor?
Eu verifiquei que ele está armazenado no formato do Reino Unido em minha DataTable e também que meu Excel está definido como Reino Unido, mas por alguma razão, quando ele cria o documento do Excel, ele pensa que é dos EUA (isso porque a Microsoft é uma empresa dos EUA :)
Vou tentar fazer experiências com códigos de cultura, mas não tenho certeza de onde colocá-los ainda. Tentei, mas não surtiu efeito.
ps
Eu tive que mudar uma linha para fazê-lo funcionar, adicionando um 'elenco' como abaixo
Atualização: eu consegui a formatação das datas no Reino Unido ao converter para o formato LongDateTime, mas é apenas uma solução alternativa.
Felicidades.
fonte
Você pode usar o EasyXLS, que é uma biblioteca para exportar arquivos do Excel.
Verifique este código:
Veja também este exemplo sobre como exportar tabela de dados para o Excel em C # .
fonte
Tópico antigo - mas pensei em colocar meu código aqui. Eu escrevi uma pequena função para escrever uma tabela de dados em uma nova planilha do Excel em um caminho especificado (local). Além disso, você precisará adicionar uma referência à biblioteca do microsoft excel 14.0.
Eu puxei deste tópico sobre como escrever qualquer coisa para o Excel - como escrever alguns dados para o arquivo do Excel (.xlsx)
Eu usei isso para extrapolar como escrever uma tabela de dados
* observe que, nas declarações catch, tenho uma referência de classe estática de manipulador de erros (você pode ignorá-los)
fonte
SaveAs
linha como está incluída aqui: 'XlObj.DisplayAlerts = false; WbObj.SaveAs (local); WbObj.Close (); XlObj.Quit (); Marshal.ReleaseComObject (WsObj); Marshal.ReleaseComObject (WbObj); Marshal.ReleaseComObject (XlObj); ' Para usar oMarshal.ReleaseComObject
método, adicione ousing System.Runtime.InteropServices
assembly ao seu projeto.Uma maneira de fazer isso também seria com o ACE OLEDB Provider (consulte também strings de conexão para Excel ). Claro, você precisa ter o provedor instalado e registrado. Você deve tê-lo, se tiver o Excel instalado, mas isso é algo que deve ser considerado ao implantar o aplicativo.
Este é o exemplo de como chamar o método auxiliar de
ExportHelper
:ExportHelper.CreateXlsFromDataTable(myDataTable, @"C:\tmp\export.xls");
O auxiliar para exportar para arquivo Excel usando ACE OLEDB:
fonte
use a seguinte classe
}
fonte
Tudo o que precisa ser uma coluna no Excel tem que ser decorado com
[ReportHeaderAttribute("Column Name")]
Então simplesmente
fonte
Para exportar dados para o Excel, você pode usar a biblioteca ClosedXML.Report ( https://github.com/ClosedXML/ClosedXML.Report ). Acredite em mim, esta é uma biblioteca maravilhosa e fácil de usar. A biblioteca não precisa do Excel Interop. ClosedXML.Report gera um arquivo Excel baseado em um modelo que você pode criar no Excel usando qualquer formatação. Por exemplo:
fonte
fonte
Código de amostra puramente (no caso de ajudar alguém com algumas ideias), com base em resposta de Tomasz Wiśniewski aqui: https://stackoverflow.com/a/21079709/2717521
MainWindow ExportButton:
Classe ExportToExcel:
fonte
Com o pacote EPPlus NuGet, é muito fácil .
Observe que
Col1
NÃO está na saída:fonte