Создание файла Excel в ASP.NET [закрыто]

99

Я собираюсь добавить раздел в приложение ASP.NET (выделенный код VB.NET), который позволит пользователю получать данные, возвращаемые им в виде файла Excel, который я буду генерировать на основе данных базы данных. Хотя есть несколько способов сделать это, у каждого есть свои недостатки. Как бы вы вернули данные? Я ищу что-то максимально простое и понятное.

Дэн Коутс
источник

Ответы:

131

CSV

Плюсы:

  • просто

Минусы:

  • Он может не работать в других регионах или в других конфигурациях Excel (например, разделитель списка)
  • Не удается применить форматирование, формулы и т. Д.

HTML

Плюсы:

  • Все еще довольно просто
  • Поддерживает простое форматирование и формулы

Минусы:

  • Вы должны назвать файл как xls, и Excel может предупредить вас об открытии чужого файла Excel.
  • Один лист на книгу

OpenXML (Office 2007 .XLSX)

Плюсы:

  • Собственный формат Excel
  • Поддерживает все функции Excel
  • Не требовать установку копии Excel
  • Может создавать сводные таблицы
  • Может быть создан с использованием проекта с открытым исходным кодом EPPlus

Минусы:

  • Ограниченная совместимость за пределами Excel 2007 (в настоящее время не должно быть проблемой)
  • Сложно, если вы не используете сторонний компонент

SpreadSheetML (открытый формат XML)

Плюсы:

  • Просто по сравнению с собственными форматами Excel
  • Поддерживает большинство функций Excel: форматирование, стили, формулы, несколько листов в книге
  • Для использования Excel не нужно устанавливать
  • Никаких сторонних библиотек не требуется - просто напишите свой xml
  • Документы можно открывать в Excel XP / 2003/2007

Минусы:

  • Отсутствие хорошей документации
  • Не поддерживается в более старых версиях Excel (до 2000)
  • Только для записи: когда вы открываете его и вносите изменения из Excel, он конвертируется в собственный Excel.

XLS (создается сторонним компонентом)

Плюсы:

  • Создайте собственный файл Excel со всем форматированием, формулами и т. Д.

Минусы:

  • Стоит денег
  • Добавить зависимости

COM-взаимодействие

Плюсы:

  • Использует собственные библиотеки Microsoft
  • Прочтите поддержку для собственных документов

Минусы:

  • Очень медленно
  • Проблемы с соответствием зависимостей / версий
  • Проблемы параллелизма / целостности данных для использования в Интернете при чтении
  • Очень медленно
  • Проблемы масштабирования для использования в Интернете (в отличие от параллелизма): необходимо создать много экземпляров тяжелого приложения Excel на сервере
  • Требуется Windows
  • Я уже упоминал, что это медленно?
Эдуардо Молтени
источник
1
Ограничение «только запись», упомянутое для SpreadsheetML, не является полностью проблемой, так как вы можете сохранить файл Excel как SpreadsheetML, если хотите.
Брайан,
1
SpreadsheetML может вызвать сбой Excel 2003, если вы создадите с его помощью большие файлы. Не верь: /
Брайан,
2
Вы можете сохранить обратно в файл SpreadsheetML в Office 2002 и 2003. Сохранять как не требуется. SpreadsheetML не может хранить макросы, диаграммы, графику и некоторые другие мелочи, включая новые функции Office 2007 (например, более трех условных форматов). Поскольку XML является подробным, архивирование SpreadsheetML перед отправкой с сервера (использование SharpZipLib - вариант) отлично работает для сокращения времени загрузки - на самом деле, следует отметить, что OpenXML в любом случае хранится в ZIP-контейнере. @Brian: Я ежедневно использую сложный SpreadsheetML размером 50–100 МБ без сбоев.
richardtallent
Если есть вероятность, что вам придется экспортировать большие объемы данных, вы должны экспортировать их в формате CSV. Помимо SpreadsheetML сложнее создать эффективное решение с любым из других форматов. HTML можно эффективно писать и читать, но для того, чтобы он был полезен, с вашей стороны требуется дополнительная спецификация. Как HTML, так и SpreadsheetML имеют другие проблемы с большими файлами, о чем Брайан упоминает в своем комментарии. Так что, если вам просто нужен простой экспорт данных, используйте CSV.
JohannesH
2
@pomarc: Это может быть просто, но не чисто. Пользователь хочет файл Excel, а вы даете ему HTML-файл с поддельным расширением.
Heinzi
38

Вы можете вывести данные в виде ячеек таблицы 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> 
Джоэл Кохорн
источник
12
вы можете переименовать файл с расширением .xml и добавить следующее: <? mso-application progid = "Excel.Sheet"?> сразу после <? xml version = "1.0"?>, таким образом окна распознают, что файл является Файл Excel, получит правильный значок, откроется Excel, когда вы щелкнете по файлу, и Excel не будет жаловаться на несоответствие формата файла и содержимого. пока.
pomarc
1
@pomarc Обратной стороной этого является то, что другие программы, импортирующие файлы Excel, не распознают его. Но тогда они, вероятно, все равно не будут разбирать xml.
Joel Coehoorn
1
Я довольно успешно применил эту технику. Это была бы моя рекомендация - грязь просто и очень эффективно.
NealB
Две потенциальные проблемы (YMMV) с табличными данными HTML, замаскированными как файл XLS: (1) Microsoft Excel автоматически отсекает начальные пробелы и нули; и (2) Microsoft Excel 2010 предупреждает пользователя при открытии файла XLS, содержащего табличные данные HTML. Решение №1 кажется creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel (если ведущие пробелы / нули значительны и их необходимо сохранить).
iokevins
Просто для пояснения, хотя я упомянул таблицы HTML, основной смысл этого ответа - SpreadsheetML, который представляет собой нечто большее, чем просто табличные данные HTML. Excel считает его родным.
Джоэл Кохорн
16

Если исходить из DataTable :

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

Из Gridview :

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);
        }
    }
}
SpoiledTechie.com
источник
1
Просто код, который мне нужен, спасибо. :)
Kjensen
Скотт, что там со знаком фунта («£»)? Что делать, если мне это нужно? Есть ли другие опасные персонажи?
Петр Овсяк
ИДЕАЛЬНЫЙ. Как раз то, что мне было нужно.
Брэд Брюс,
Знак £ - это то, что мне нужно для одного из моих клиентов. вы можете вынуть это.
SpoiledTechie.com
Две потенциальные проблемы (YMMV) с табличными данными HTML, замаскированными как файл XLS: (1) Microsoft Excel автоматически отсекает начальные пробелы и нули; и (2) Microsoft Excel 2010 предупреждает пользователя при открытии файла XLS, содержащего табличные данные HTML. Решение №1 кажется creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel (если ведущие пробелы / нули значительны и их необходимо сохранить). Файлы данных CSV также страдают от №1 при открытии в Microsoft Excel.
iokevins
7

Это бесплатная оболочка для SpreadML - она ​​отлично работает.

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

рп.
источник
Я тоже этим пользовался - отлично.
Paul Suart
Эта библиотека тоже позволяет читать xls?
Alex
5

На основании полученных ответов и консультаций с коллегами выяснилось, что лучшим решением является создание либо 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()
Дэн Коутс
источник
2
Дэн, ты на правильном пути. И я определенно рекомендую SpreadsheetML вместо HTML - передышка на будущее, поскольку поддержка HTML крайне ограничена. Но с HTML, SpreadsheetML и OpenXML размеры файлов могут быть довольно большими, и сервер не будет архивировать их. OpenXML требует ZIP-контейнера с несколькими файлами внутри, а SpreadsheetML и HTML загружаются намного быстрее, если вы сначала заархивируете их и отправите zip как вложение. Используйте SharpZipLib и транслируйте его, а не напрямую в Response.
richardtallent
4

поскольку 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

если заголовок длины содержимого опущен, вы можете просто записать html обратно напрямую, но это может работать неправильно во всех браузерах.

Стивен А. Лоу
источник
2
Две потенциальные проблемы (YMMV) с табличными данными HTML, замаскированными как файл XLS: (1) Microsoft Excel автоматически отсекает начальные пробелы и нули; и (2) Microsoft Excel 2010 предупреждает пользователя при открытии файла XLS, содержащего табличные данные HTML. Решение №1 кажется creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel (если ведущие пробелы / нули значительны и их необходимо сохранить).
iokevins
3

Лично я предпочитаю метод XML. Я возвращаю данные из базы данных в Dataset, сохраняю их в XMl, затем создаю файл xslt, содержащий правило преобразования, которое отформатирует правильный документ, и простое преобразование XML завершит работу. Лучшая часть этого заключается в том, что вы можете форматировать ячейки, выполнять условное форматирование, настраивать верхние и нижние колонтитулы и даже устанавливать диапазоны печати.

Митчел Селлерс
источник
2

Я делал это пару раз, и каждый раз самым простым способом было просто вернуть файл CSV (значения, разделенные запятыми). Excel импортирует его идеально, и это относительно быстро.

Марк Аллен
источник
Одна потенциальная проблема (YMMV) с данными CSV: Microsoft Excel автоматически
обрезает
2

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

Я обнаружил, что где-то это хорошо работает.

WACM161
источник
2
Две потенциальные проблемы (YMMV) с табличными данными HTML, замаскированными как файл XLS: (1) Microsoft Excel автоматически отсекает начальные пробелы и нули; и (2) Microsoft Excel 2010 предупреждает пользователя при открытии файла XLS, содержащего табличные данные HTML. Решение №1 кажется creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel (если ведущие пробелы / нули значительны и их необходимо сохранить).
iokevins
2

Вот отчет, полученный из хранимой процедуры. Результаты экспортируются в 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
Сиддхарт Рут
источник
1

Если вы заполняете 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
Эдуардо Кампаньо
источник
Две потенциальные проблемы (YMMV) с табличными данными HTML, замаскированными как файл XLS: (1) Microsoft Excel автоматически отсекает начальные пробелы и нули; и (2) Microsoft Excel 2010 предупреждает пользователя при открытии файла XLS, содержащего табличные данные HTML. Решение №1 кажется creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel (если ведущие пробелы / нули значительны и их необходимо сохранить).
iokevins
1

Просто избегайте COM-взаимодействия через пространство имен Microsoft.Office.Interop. Он чертовски медленный, ненадежный и масштабируемый. Не применимо к мазохистам.

Андрей Рыня
источник
1

С помощью этой библиотеки вы можете довольно легко создавать красиво отформатированные файлы Excel: http://officehelper.codeplex.com/documentation .

Microsoft Office не нужно устанавливать на веб-сервере!

user698116
источник
0

CSV - самый простой способ. В большинстве случаев он связан с Excel. В противном случае вам придется использовать API автоматизации или формат XML. API и XML не так уж и сложны в использовании.

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

Кен
источник
0

Я либо использую CSV-путь (как описано выше), либо в наши дни чаще использую Infragistics NetAdvantage для создания файла. (В подавляющем большинстве случаев, когда используется Infragistics, мы просто экспортируем существующий UltraWebGrid, который, по сути, является решением с одним LOC, если не требуются дополнительные настройки форматирования. Мы также можем вручную сгенерировать файл Excel / BIFF, но в этом редко бывает необходимость.)

Джон Руди
источник
0

человек, в .net, я думаю, у вас мог бы быть компонент, который мог бы это сделать, но в классическом asp я уже сделал это, создав таблицу html и изменив mime-тип страницы на vnd / msexcel. Я предполагаю, что если вы используете gridview и измените тип mime, возможно, он должен работать, потому что gridview - это таблица html.


источник
Две потенциальные проблемы (YMMV) с табличными данными HTML, замаскированными как файл XLS: (1) Microsoft Excel автоматически отсекает начальные пробелы и нули; и (2) Microsoft Excel 2010 предупреждает пользователя при открытии файла XLS, содержащего табличные данные HTML. Решение №1 кажется creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel (если ведущие пробелы / нули значительны и их необходимо сохранить).
iokevins
0

Единственный надежный способ избежать появления зеленых треугольников «Похоже, что эти числа хранятся в виде текста» - это использовать формат Open XML. Его стоит использовать, лишь бы избежать неизбежных зеленых треугольников.

хова
источник
0

Лучший метод, который я видел для отчетов Excel, - это записывать данные в XML с расширением XML и передавать их клиентам с правильным типом содержимого. (приложение / xls)

Это работает для любого отчета, который требует базового форматирования, и позволяет сравнивать с существующими электронными таблицами с помощью инструментов сравнения текста.

Bravax
источник
0

Предполагая, что это для интрасети, где вы можете установить разрешения и поручить IE, вы можете создать клиентскую часть книги с JScript / VBScript, управляя Excel . Это дает вам собственное форматирование Excel, без хлопот по автоматизации Excel на сервере.

Я не уверен, что действительно рекомендовал бы этот подход, за исключением довольно нишевых сценариев, но он был довольно распространен в период расцвета классических ASP.

Марк Брэкетт
источник
0

Конечно, вы всегда можете использовать сторонние компоненты. Лично у меня был хороший опыт работы со 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");
Насир
источник
0

Одна из проблем, с которыми я столкнулся, используя одно из предложенных выше решений, похожих на этот ответ заключается в том, что если вы вытолкнете контент в виде вложения (что я считаю самым чистым решением для браузеров, отличных от ms) , затем откройте его в Excel 2000-2003, его тип - «Веб-страница Excel», а не собственный документ Excel.

Затем вы должны объяснить пользователям, как использовать «Сохранить как тип» в Excel, чтобы преобразовать его в документ Excel. Это неприятно, если пользователям нужно отредактировать этот документ, а затем повторно загрузить его на ваш сайт.

Я рекомендую использовать CSV. Это просто, и если пользователи открывают его из Excel, Excel, по крайней мере, предлагает им сохранить его в собственном формате.

Чад Браун-Дуин
источник
Будьте осторожны с CSV, если ваши пользователи разбросаны по всему миру. Здесь, в Германии, запятая используется в качестве десятичного разделителя, а точка с запятой используется в качестве разделителя значений. Сложно создать один файл, который можно было бы читать в разных культурах. Поэтому я бы проголосовал за один из форматов XML.
Пол
0

Я бы просто создал CSV-файл на основе данных, потому что я считаю его самым чистым, и Excel хорошо его поддерживает. Но если вам нужен более гибкий формат, я уверен, что есть некоторые сторонние инструменты для создания настоящих файлов Excel.

Алекс Форт
источник
0

Вот решение, которое передает данные в виде 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();
}
Джастин Р.
источник
-1

только что создал функцию для экспорта из веб-формы C #, чтобы преуспеть, надеюсь, что это поможет другим

    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();
            }
        }
     }
Стив Д Соуза
источник
-5

Если вам нужно использовать Excel вместо файла CSV, вам нужно будет использовать автоматизацию OLE на экземпляре Excel на сервере. Самый простой способ сделать это - создать файл шаблона и программно заполнить его данными. Вы сохраняете его в другом файле.

Подсказки:

  • Не делайте этого в интерактивном режиме. Попросите пользователя запустить процесс, а затем опубликовать страницу со ссылкой на файл. Это снижает потенциальные проблемы с производительностью во время создания электронной таблицы.
  • Используйте шаблон, как я описал ранее. Это облегчает его изменение.
  • Убедитесь, что в Excel не отображаются всплывающие диалоговые окна. На веб-сервере это повесит весь экземпляр Excel.
  • Храните экземпляр Excel на отдельном сервере, желательно за брандмауэром, чтобы он не представлял собой потенциальную дыру в безопасности.
  • Следите за использованием ресурсов. Создание таблицы с помощью интерфейса автоматизации OLE (PIA - это просто прокладки) - довольно сложный процесс. Если вам нужно масштабировать это до больших объемов данных, вам может потребоваться несколько хитрость с вашей архитектурой.

Некоторые из подходов «использовать mime-типы, чтобы обмануть excel для открытия таблицы HTML» подействовали бы, если вы не возражаете против того, чтобы формат файла был немного базовым. Эти подходы также перекладывают тяжелую работу процессора на клиента. Если вам нужен точный контроль над форматом электронной таблицы, вам, вероятно, придется использовать сам Excel для создания файла, как описано выше.

ОбеспокоенныйTunbridgeWells
источник
Плохая идея делать автоматизацию с веб-сервера. Альтернативы могут показаться хакерскими, но они действительно будут работать намного лучше.
Джоэл Кохорн,
Мы используем OLE на стороне сервера с Excel, и это огромная проблема. Если бы не риск для нашего продукта **, мы бы выбрали другое решение. ** Лучше черт тебя знает ...
Дэйв