Создание файла Excel в ASP.NET [закрыто]
-
02-07-2019 - |
Вопрос
Я собираюсь добавить раздел в ASP.NET приложение (VB.NET codebehind), которое позволит пользователю получать данные, возвращаемые ему в виде файла Excel, который я сгенерирую на основе данных базы данных.Хотя существует несколько способов сделать это, у каждого есть свои недостатки.Как бы ты вернуть данные?Я ищу что-то максимально чистое и понятное.
Решение
CSV- файл
Плюсы:
- Простой
Минусы:
- Это может не работать в других локализациях или в других конфигурациях Excel (т. е.Разделитель списков)
- Не удается применить форматирование, формулы и т. Д
HTML
Плюсы:
- Все еще довольно просто
- Поддерживает простое форматирование и формулы
Минусы:
- Вы должны назвать файл как xls, и Excel может предупредить вас об открытии неродного файла Excel
- Один рабочий лист на рабочую книгу
OpenXML (Office 2007 .XLSX)
Плюсы:
- Собственный формат Excel
- Поддерживает все функции Excel
- Не делайте этого требовать установочная копия Excel
- Может генерировать сводные таблицы
- Может быть сгенерирован с использованием проекта с открытым исходным кодом ЭППлус
Минусы:
- Ограниченная совместимость за пределами Excel 2007 (в настоящее время это не должно быть проблемой)
- Сложно, если только вы не используете сторонний компонент
SpreadsheetML (открытый формат XML)
Плюсы:
- Простой по сравнению с собственными форматами Excel
- Поддерживает большинство функций Excel:форматирование, стили, формулы, несколько листов в рабочей книге
- Для его использования не нужно устанавливать Excel
- Никаких сторонних библиотек не требуется - просто запишите свой xml
- Документы могут быть открыты с помощью Excel XP / 2003 / 2007
Минусы:
- Отсутствие надлежащей документации
- Не поддерживается в более старых версиях Excel (до 2000 года)
- Доступен только для записи, поскольку, как только вы открываете его и вносите изменения из Excel, он преобразуется в собственный Excel.
XLS (генерируемый сторонним компонентом)
Плюсы:
- Сгенерируйте собственный файл Excel со всем форматированием, формулами и т.д.
Минусы:
- Стоит денег
- Добавление зависимостей
COM - взаимодействие
Плюсы:
- Использует собственные библиотеки Microsoft
- Поддержка чтения собственных документов
Минусы:
- Очень медленно
- Проблемы с зависимостью / сопоставлением версий
- Проблемы параллелизма / целостности данных при использовании в Интернете при чтении
- Очень медленно
- Проблемы масштабирования для использования в Интернете (в отличие от параллелизма):необходимо создать много экземпляров тяжелого приложения Excel на сервере
- Требуется Windows
- Я уже упоминал, что это медленно?
Другие советы
Вы можете вывести данные в виде ячеек html-таблицы, вставив .xls
или .xlsx
установите на нем расширение, и Excel откроет его так, как если бы это был собственный документ.Таким образом, вы даже можете выполнять некоторые ограниченные форматирования и вычисления по формулам, поэтому он намного мощнее CSV.Кроме того, вывод HTML-таблицы должен быть довольно простым для выполнения с веб-платформы, такой как ASP.Net ;)
Если вам нужно несколько листов или именованных листов в вашей книге Excel, вы можете сделать нечто подобное с помощью XML-схемы, называемой SpreadSheetML
.Это нет новый формат, поставляемый с Office 2007, но нечто совершенно иное, работающее еще в Excel 2000.Самый простой способ объяснить, как это работает, - на примере:
<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:html="http://www.w3.org/TR/REC-html40">
<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
<Author>Your_name_here</Author>
<LastAuthor>Your_name_here</LastAuthor>
<Created>20080625</Created>
<Company>ABC Inc</Company>
<Version>10.2625</Version>
</DocumentProperties>
<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
<WindowHeight>6135</WindowHeight>
<WindowWidth>8445</WindowWidth>
<WindowTopX>240</WindowTopX>
<WindowTopY>120</WindowTopY>
<ProtectStructure>False</ProtectStructure>
<ProtectWindows>False</ProtectWindows>
</ExcelWorkbook>
<Styles>
<Style ss:ID="Default" ss:Name="Normal">
<Alignment ss:Vertical="Bottom" />
<Borders />
<Font />
<Interior />
<NumberFormat />
<Protection />
</Style>
</Styles>
<Worksheet ss:Name="Sample Sheet 1">
<Table ss:ExpandedColumnCount="2" x:FullColumns="1" x:FullRows="1" ID="Table1">
<Column ss:Width="150" />
<Column ss:Width="200" />
<Row>
<Cell><Data ss:Type="Number">1</Data></Cell>
<Cell><Data ss:Type="Number">2</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="Number">3</Data></Cell>
<Cell><Data ss:Type="Number">4</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="Number">5</Data></Cell>
<Cell><Data ss:Type="Number">6</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="Number">7</Data></Cell>
<Cell><Data ss:Type="Number">8</Data></Cell>
</Row>
</Table>
</Worksheet>
<Worksheet ss:Name="Sample Sheet 2">
<Table ss:ExpandedColumnCount="2" x:FullColumns="1" x:FullRows="1" ID="Table2">
<Column ss:Width="150" />
<Column ss:Width="200" />
<Row>
<Cell><Data ss:Type="String">A</Data></Cell>
<Cell><Data ss:Type="String">B</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="String">C</Data></Cell>
<Cell><Data ss:Type="String">D</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="String">E</Data></Cell>
<Cell><Data ss:Type="String">F</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="String">G</Data></Cell>
<Cell><Data ss:Type="String">H</Data></Cell>
</Row>
</Table>
</Worksheet>
</Workbook>
Если исходящий от Поддающийся обработке данными:
public static void DataTabletoXLS(DataTable DT, string fileName)
{
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.Charset = "utf-16";
HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.GetEncoding("windows-1250");
HttpContext.Current.Response.AddHeader("content-disposition", string.Format("attachment; filename={0}.xls", fileName));
HttpContext.Current.Response.ContentType = "application/ms-excel";
string tab = "";
foreach (DataColumn dc in DT.Columns)
{
HttpContext.Current.Response.Write(tab + dc.ColumnName.Replace("\n", "").Replace("\t", ""));
tab = "\t";
}
HttpContext.Current.Response.Write("\n");
int i;
foreach (DataRow dr in DT.Rows)
{
tab = "";
for (i = 0; i < DT.Columns.Count; i++)
{
HttpContext.Current.Response.Write(tab + dr[i].ToString().Replace("\n", "").Replace("\t", ""));
tab = "\t";
}
HttpContext.Current.Response.Write("\n");
}
HttpContext.Current.Response.End();
}
Из Просмотр сетки:
public static void GridviewtoXLS(GridView gv, string fileName)
{
int DirtyBit = 0;
int PageSize = 0;
if (gv.AllowPaging == true)
{
DirtyBit = 1;
PageSize = gv.PageSize;
gv.AllowPaging = false;
gv.DataBind();
}
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.Charset = "utf-8";
HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.GetEncoding("windows-1250");
HttpContext.Current.Response.AddHeader(
"content-disposition", string.Format("attachment; filename={0}.xls", fileName));
HttpContext.Current.Response.ContentType = "application/ms-excel";
using (StringWriter sw = new StringWriter())
using (HtmlTextWriter htw = new HtmlTextWriter(sw))
{
// Create a table to contain the grid
Table table = new Table();
// include the gridline settings
table.GridLines = gv.GridLines;
// add the header row to the table
if (gv.HeaderRow != null)
{
Utilities.Export.PrepareControlForExport(gv.HeaderRow);
table.Rows.Add(gv.HeaderRow);
}
// add each of the data rows to the table
foreach (GridViewRow row in gv.Rows)
{
Utilities.Export.PrepareControlForExport(row);
table.Rows.Add(row);
}
// add the footer row to the table
if (gv.FooterRow != null)
{
Utilities.Export.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().Replace("£", ""));
HttpContext.Current.Response.End();
}
if (DirtyBit == 1)
{
gv.PageSize = PageSize;
gv.AllowPaging = true;
gv.DataBind();
}
}
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())
{
Utilities.Export.PrepareControlForExport(current);
}
}
}
Это бесплатная оболочка для SpreadML - она отлично работает.
Основываясь на полученных ответах и консультациях с коллегами, представляется, что лучшим решением является создание либо XML-файла, либо HTML-таблиц и отправка их в виде вложения.Единственное изменение, рекомендованное моими коллегами, заключается в том, что данные (т.е.HTML-таблицы) могут быть записаны непосредственно в объект Response, что устраняет необходимость в записи файла, что может быть затруднительно из-за проблем с разрешениями, конфликтов ввода-вывода и обеспечения выполнения запланированной очистки.
Вот фрагмент кода...Я еще не проверял это, и я не предоставил весь вызываемый код, но я думаю, что он хорошо отражает идею.
Dim uiTable As HtmlTable = GetUiTable(groupedSumData)
Response.Clear()
Response.ContentType = "application/vnd.ms-excel"
Response.AddHeader("Content-Disposition", String.Format("inline; filename=OSSummery{0:ddmmssf}.xls", DateTime.Now))
Dim writer As New System.IO.StringWriter()
Dim htmlWriter As New HtmlTextWriter(writer)
uiTable.RenderControl(htmlWriter)
Response.Write(writer.ToString)
Response.End()
поскольку Excel понимает HTML, вы можете просто записать данные в виде HTML-таблицы во временный файл с расширением .xls, получить FileInfo для файла и перенести его обратно, используя
Response.Clear();
Response.AddHeader("Content-Disposition", "attachment; filename=" + fi.Name);
Response.AddHeader("Content-Length", fi.Length.ToString());
Response.ContentType = "application/octet-stream";
Response.WriteFile(fi.FullName);
Response.End();
если вы хотите избежать использования временного файла, вы могли бы выполнить запись в поток в памяти и записать байты обратно вместо использования WriteFile
если заголовок content-length опущен, вы могли бы просто записать html обратно напрямую, но это может работать некорректно не всегда во всех браузерах
Лично я предпочитаю метод XML.Я верну данные из базы данных в Dataset, сохраню их в XMl, затем создам файл xslt, содержащий правило преобразования, которое отформатирует соответствующий документ, и простое преобразование XML завершит работу.Самое приятное в этом то, что вы можете форматировать ячейки, выполнять условное форматирование, настраивать верхние и нижние колонтитулы и даже устанавливать диапазоны печати.
Я делал это пару раз, и каждый раз самым простым способом было просто вернуть CSV-файл (значение, разделенное запятыми).Excel импортирует его идеально, и это относительно быстро делается.
мы постоянно экспортируем данные из datagrid в excel.Преобразуем его в HTML, а затем записываем в файл Excel
Response.ContentType = "application/vnd.ms-excel"
Response.Charset = ""
Response.AddHeader("content-disposition", "fileattachment;filename=YOURFILENAME.xls")
Me.EnableViewState = False
Dim sw As System.IO.StringWriter = New System.IO.StringWriter
Dim hw As HtmlTextWriter = New HtmlTextWriter(sw)
ClearControls(grid)
grid.RenderControl(hw)
Response.Write(sw.ToString())
Response.End()
Единственным недостатком этого метода было то, что во многих наших сетках были кнопки или ссылки, так что вам это тоже понадобится:
'needed to export grid to excel to remove link button control and represent as text
Private Sub ClearControls(ByVal control As Control)
Dim i As Integer
For i = control.Controls.Count - 1 To 0 Step -1
ClearControls(control.Controls(i))
Next i
If TypeOf control Is System.Web.UI.WebControls.Image Then
control.Parent.Controls.Remove(control)
End If
If (Not TypeOf control Is TableCell) Then
If Not (control.GetType().GetProperty("SelectedItem") Is Nothing) Then
Dim literal As New LiteralControl
control.Parent.Controls.Add(literal)
Try
literal.Text = CStr(control.GetType().GetProperty("SelectedItem").GetValue(control, Nothing))
Catch
End Try
control.Parent.Controls.Remove(control)
Else
If Not (control.GetType().GetProperty("Text") Is Nothing) Then
Dim literal As New LiteralControl
control.Parent.Controls.Add(literal)
literal.Text = CStr(control.GetType().GetProperty("Text").GetValue(control, Nothing))
control.Parent.Controls.Remove(control)
End If
End If
End If
Return
End Sub
Я где-то нашел это, это хорошо работает.
Я рекомендую бесплатная библиотека для создания Excel с открытым исходным кодом который основан на OpenXML
Это помогло мне несколько месяцев назад.
Вот отчет, который извлекается из хранимой процедуры.Результаты экспортируются в Excel.Он использует ADO вместо ADO.NET и причина, по которой эта строка
oSheet.Cells(2, 1).copyfromrecordset(rst1)
Он выполняет большую часть работы и недоступен в ado.net.
‘Calls stored proc in SQL Server 2000 and puts data in Excel and ‘formats it
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim cnn As ADODB.Connection
cnn = New ADODB.Connection
cnn.Open("Provider=SQLOLEDB;data source=xxxxxxx;" & _
"database=xxxxxxxx;Trusted_Connection=yes;")
Dim cmd As New ADODB.Command
cmd.ActiveConnection = cnn
cmd.CommandText = "[sp_TomTepley]"
cmd.CommandType = ADODB.CommandTypeEnum.adCmdStoredProc
cmd.CommandTimeout = 0
cmd.Parameters.Refresh()
Dim rst1 As ADODB.Recordset
rst1 = New ADODB.Recordset
rst1.Open(cmd)
Dim oXL As New Excel.Application
Dim oWB As Excel.Workbook
Dim oSheet As Excel.Worksheet
'oXL = CreateObject("excel.application")
oXL.Visible = True
oWB = oXL.Workbooks.Add
oSheet = oWB.ActiveSheet
Dim Column As Integer
Column = 1
Dim fld As ADODB.Field
For Each fld In rst1.Fields
oXL.Workbooks(1).Worksheets(1).Cells(1, Column).Value = fld.Name
oXL.Workbooks(1).Worksheets(1).cells(1, Column).Interior.ColorIndex = 15
Column = Column + 1
Next fld
oXL.Workbooks(1).Worksheets(1).name = "Tom Tepley Report"
oSheet.Cells(2, 1).copyfromrecordset(rst1)
oXL.Workbooks(1).Worksheets(1).Cells.EntireColumn.AutoFit()
oXL.Visible = True
oXL.UserControl = True
rst1 = Nothing
cnn.Close()
Beep()
End Sub
Если вы заполняете GridView данными, вы можете использовать эту функцию для получения данных в формате HTML, но с указанием браузера, это файл Excel.
Public Sub ExportToExcel(ByVal fileName As String, ByVal gv As GridView)
HttpContext.Current.Response.Clear()
HttpContext.Current.Response.AddHeader("content-disposition", String.Format("attachment; filename={0}", fileName))
HttpContext.Current.Response.ContentType = "application/ms-excel"
Dim sw As StringWriter = New StringWriter
Dim htw As HtmlTextWriter = New HtmlTextWriter(sw)
Dim table As Table = New Table
table.GridLines = gv.GridLines
If (Not (gv.HeaderRow) Is Nothing) Then
PrepareControlForExport(gv.HeaderRow)
table.Rows.Add(gv.HeaderRow)
End If
For Each row As GridViewRow In gv.Rows
PrepareControlForExport(row)
table.Rows.Add(row)
Next
If (Not (gv.FooterRow) Is Nothing) Then
PrepareControlForExport(gv.FooterRow)
table.Rows.Add(gv.FooterRow)
End If
table.RenderControl(htw)
HttpContext.Current.Response.Write(sw.ToString)
HttpContext.Current.Response.End()
End Sub
Private Sub PrepareControlForExport(ByVal control As Control)
Dim i As Integer = 0
Do While (i < control.Controls.Count)
Dim current As Control = control.Controls(i)
If (TypeOf current Is LinkButton) Then
control.Controls.Remove(current)
control.Controls.AddAt(i, New LiteralControl(CType(current, LinkButton).Text))
ElseIf (TypeOf current Is ImageButton) Then
control.Controls.Remove(current)
control.Controls.AddAt(i, New LiteralControl(CType(current, ImageButton).AlternateText))
ElseIf (TypeOf current Is HyperLink) Then
control.Controls.Remove(current)
control.Controls.AddAt(i, New LiteralControl(CType(current, HyperLink).Text))
ElseIf (TypeOf current Is DropDownList) Then
control.Controls.Remove(current)
control.Controls.AddAt(i, New LiteralControl(CType(current, DropDownList).SelectedItem.Text))
ElseIf (TypeOf current Is CheckBox) Then
control.Controls.Remove(current)
control.Controls.AddAt(i, New LiteralControl(CType(current, CheckBox).Checked))
End If
If current.HasControls Then
PrepareControlForExport(current)
End If
i = i + 1
Loop
End Sub
Просто избегайте COM-взаимодействия через Microsoft.Офис.Пространство имен взаимодействия.Это чертовски медленно, ненадежно и не поддается масштабированию.Не применимо к мазохистам.
Вы можете довольно легко создавать красиво отформатированные файлы Excel, используя эту библиотеку: http://officehelper.codeplex.com/documentation.
Microsoft Office не обязательно устанавливать на веб-сервер!
CSV - это самый простой способ.Большую часть времени он связан с Excel.В противном случае вам придется использовать API автоматизации или формат XML.API и XML не так уж сложны в использовании.
Я либо использую CSV-файл (как описано выше), либо, что чаще в наши дни, использую Infragistics NetAdvantage для генерации файла.(В подавляющем большинстве случаев, когда используется инфраструктура, мы просто экспортируем существующую UltraWebGrid, которая по сути является решением с одним местоположением, если не требуются дополнительные настройки форматирования.Мы могли бы также вручную сгенерировать файл Excel / BIFF, но в этом редко возникает необходимость.)
блин, в .net, я думаю, у вас мог бы быть компонент, который мог бы это делать, но в классическом asp я уже сделал это, создав html-таблицу и изменив mime-тип страницы на vnd / msexcel.Я предполагаю, что если вы используете gridview и меняете тип mime, возможно, это должно сработать, потому что gridview - это html-таблица.
Единственный пуленепробиваемый способ избежать зеленых треугольников типа "Похоже, что эти цифры хранятся в виде текста" - это использовать формат Open XML.Стоит использовать его, просто чтобы избежать неизбежных зеленых треугольников.
Лучший метод, который я видел для отчетов Excel, - это записать данные в формате XML с расширением XML и передать их клиентам с правильным типом контента.(приложение/xls)
Это работает для любого отчета, требующего базового форматирования, и позволяет сравнивать с существующими электронными таблицами с помощью инструментов сравнения текста.
Предполагая, что это для интрасети, где вы можете устанавливать разрешения и назначать IE, вы можете сгенерировать клиентскую часть рабочей книги с помощью JScript / VBScript для управления Excel.Это дает вам собственное форматирование Excel без необходимости пытаться автоматизировать Excel на сервере.
Я не уверен, что действительно рекомендовал бы этот подход, за исключением довольно узкоспециализированных сценариев, но он был довольно распространен во времена расцвета классического ASP.
Конечно, вы всегда можете использовать сторонние компоненты.Лично у меня был хороший опыт работы со Spire.XLS http://www.e-iceblue.com/xls/xlsintro.htm
Этот компонент довольно прост в использовании в вашем приложении:
Workbook workbook = new Workbook();
//Load workbook from disk.
workbook.LoadFromFile(@"Data\EditSheetSample.xls");
//Initailize worksheet
Worksheet sheet = workbook.Worksheets[0];
//Writes string
sheet.Range["B1"].Text = "Hello,World!";
//Writes number
sheet.Range["B2"].NumberValue = 1234.5678;
//Writes date
sheet.Range["B3"].DateTimeValue = System.DateTime.Now;
//Writes formula
sheet.Range["B4"].Formula = "=1111*11111";
workbook.SaveToFile("Sample.xls");
Одна из проблем, с которой я столкнулся, используя одно из предложенных выше решений, которые похожи на этот ответ заключается в том, что если вы отправляете содержимое в виде вложения (что, как я обнаружил, является самым чистым решением для браузеров, отличных от ms), затем открываете его в Excel 2000-2003, его тип - "веб-страница Excel", а не собственный документ Excel.
Затем вы должны объяснить пользователям, как использовать "Сохранить как тип" из Excel, чтобы преобразовать его в документ Excel.Это проблема, если пользователям нужно отредактировать этот документ, а затем повторно загрузить его на ваш сайт.
Моя рекомендация - использовать CSV.Это просто, и если пользователи открывают его из Excel, Excel, по крайней мере, предлагает им сохранить его в своем собственном формате.
Я бы просто создал CSV-файл на основе полученных данных, потому что я считаю его самым чистым, и Excel имеет хорошую поддержку для этого.Но если вам нужен более гибкий формат, я уверен, что есть какие-нибудь сторонние инструменты для создания реальных файлов Excel.
Вот решение, которое выводит datatable в виде CSV.Быстрый, понятный и простой, он обрабатывает запятые во входных данных.
public static void ExportToExcel(DataTable data, HttpResponse response, string fileName)
{
response.Charset = "utf-8";
response.ContentEncoding = System.Text.Encoding.GetEncoding("windows-1250");
response.Cache.SetCacheability(HttpCacheability.NoCache);
response.ContentType = "text/csv";
response.AddHeader("Content-Disposition", "attachment; filename=" + fileName);
for (int i = 0; i < data.Columns.Count; i++)
{
response.Write(data.Columns[i].ColumnName);
response.Write(i == data.Columns.Count - 1 ? "\n" : ",");
}
foreach (DataRow row in data.Rows)
{
for (int i = 0; i < data.Columns.Count; i++)
{
response.Write(String.Format("\"{0}\"", row[i].ToString()));
response.Write(i == data.Columns.Count - 1 ? "\n" : ",");
}
}
response.End();
}
только что создал функцию для экспорта из веб-формы C # в Excel, надеюсь, это поможет другим
public void ExportFileFromSPData(string filename, DataTable dt)
{
HttpResponse response = HttpContext.Current.Response;
//clean up the response.object
response.Clear();
response.Buffer = true;
response.Charset = "";
// set the response mime type for html so you can see what are you printing
//response.ContentType = "text/html";
//response.AddHeader("Content-Disposition", "attachment;filename=test.html");
// set the response mime type for excel
response.ContentType = "application/vnd.ms-excel";
response.AddHeader("Content-Disposition", "attachment;filename=\"" + filename + "\"");
response.ContentEncoding = System.Text.Encoding.UTF8;
response.BinaryWrite(System.Text.Encoding.UTF8.GetPreamble());
//style to format numbers to string
string style = @"<style> .text { mso-number-format:\@; } </style>";
response.Write(style);
// create a string writer
using (StringWriter sw = new StringWriter())
{
using (HtmlTextWriter htw = new HtmlTextWriter(sw))
{
// instantiate a datagrid
GridView dg = new GridView();
dg.DataSource = dt;
dg.DataBind();
foreach (GridViewRow datarow in dg.Rows)
{
//format specific cell to be text
//to avoid 1.232323+E29 to get 1232312312312312124124
datarow.Cells[0].Attributes.Add("class", "text");
}
dg.RenderControl(htw);
response.Write(sw.ToString());
response.End();
}
}
}
Если вам нужно использовать Excel вместо CSV-файла, вам нужно будет использовать OLE automation в экземпляре Excel на сервере.Самый простой способ сделать это - иметь файл шаблона и программно заполнить его данными.Вы сохраняете его в другой файл.
Советы:
- Не делайте этого в интерактивном режиме.Попросите пользователя запустить процесс, а затем опубликовать страницу со ссылкой на файл.Это устраняет потенциальные проблемы с производительностью при создании электронной таблицы.
- Используйте шаблон, как я описал ранее.Это облегчает его модификацию.
- Убедитесь, что в Excel отключено отображение всплывающих диалоговых окон.На веб-сервере это приведет к зависанию всего экземпляра Excel.
- Храните экземпляр Excel на отдельном сервере, предпочтительно за брандмауэром, чтобы он не представлял собой потенциальную брешь в системе безопасности.
- Следите за использованием ресурсов.Генерация spreadhseet через интерфейс OLE automation (PIA - это просто прокладки поверх этого) - довольно тяжелый процесс.Если вам нужно масштабировать это до больших объемов данных, возможно, вам придется немного поумнеть с вашей архитектурой.
Некоторые из подходов "используйте mime-типы, чтобы обманом заставить Excel открыть таблицу HTML" сработали бы, если вы не возражаете, что формат файла немного базовый.Эти подходы также перекладывают тяжелую работу процессора на плечи клиента.Если вы хотите точно контролировать формат электронной таблицы, вам, вероятно, придется использовать сам Excel для создания файла, как описано выше.