Вопрос

Я собираюсь добавить раздел в 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 - она отлично работает.

http://www.carlosag.net/Tools/ExcelXmlWriter/

Основываясь на полученных ответах и консультациях с коллегами, представляется, что лучшим решением является создание либо 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 не так уж сложны в использовании.

Информация о создании XML для Excel

Я либо использую 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 для создания файла, как описано выше.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top