Створення файлу 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 Interop

Плюси:

  • Використовується рідна бібліотека Microsoft
  • Прочитайте підтримку рідних документів

Мінуси:

  • Дуже повільно
  • Проблеми відповідності залежності / версії
  • Питання паралельності / цілісності даних для використання в Інтернеті під час читання
  • Дуже повільно
  • Проблеми з масштабуванням для веб-використання (відрізняється від одночасності): потрібно створити на сервері безліч екземплярів важкої програми Excel
  • Потрібна Windows
  • Я згадав, що це повільно?

1
Обмеження "Лише для запису", згадане для SpreadsheetML, не є повністю проблемою, оскільки ви можете зберегти файл excel як SpreadsheetML, якщо бажаєте.
Брайан

1
SpreadsheetML може вийти з ладу Excel 2003, якщо ви створюєте з ним великі файли. Не віримо: /
Брайан

2
Ви можете зберегти назад у файл SpreadsheetML просто в Office 2002 та 2003 рр. Ніякого збереження, як потрібно. SpreadsheetML не може зберігати макроси, графіки, графіку та деякі інші шанси та цілі, включаючи нові функції Office 2007 (наприклад, більше 3 умовних форматів). Оскільки XML є багатослівним, Zipping SpreadsheetML перед відправкою з сервера (використання опції SharpZipLib) чудово працює для скорочення часу завантаження - насправді слід згадати, що OpenXML зберігається у контейнері ZIP. @Brian: Я щодня використовую складні SpreadsheetML в діапазоні 50-100 МБ без проблем.
richardtallent

Якщо є можливість, вам доведеться експортувати велику кількість даних, які слід експортувати як CSV. Окрім SpreadsheetML, складніше прийняти ефективне рішення з будь-яким з інших форматів. HTML можна писати та читати ефективно, але для його корисності потрібна додаткова специфікація. І HTML, і SpreadsheetML мають інші проблеми щодо великих файлів, як Брайан згадує у своєму коментарі. Тож якщо вам просто потрібен простий експорт даних, дотримуйтесь CSV.
ЙоханнесH

2
@pomarc: Це може бути просто, але це не чисто. Користувач хоче файл Excel, і ви даєте йому HTML-файл із підробленим розширенням.
Хайнці

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"?> таким чином Windows визнає, що файл є Файл 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 вважає це рідним.
Joel Coehoorn

16

Якщо надходить із таблиці даних :

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

1
Просто код, який мені знадобився, дякую. :)
Kjensen

Скотт, що з знаком фунта ("£")? Що робити, якщо мені це потрібно? Будь-які інші персонажі, небезпечні?
Piotr Owsiak

СУЧАСНИЙ. Тільки те, що мені було потрібно.
Бред Брюс

знак £ - це насправді щось, що мені потрібно для одного з моїх клієнтів. ви можете вийняти його.
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


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 та передавайте на нього, а не безпосередньо у відповідь.
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. Я поверну дані з бази даних у наборі даних, збережу їх у XMl, тоді я створую файл xslt, що містить правило перетворення, яке буде форматувати належний документ, а просте перетворення XML закінчить завдання. Найкраще з цього питання ви можете відформатувати комірки, виконати умовне форматування, встановити заголовки та колонтитули та навіть встановити діапазони друку.


2

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


Один потенційний випуск (YMMV) з даними CSV: Microsoft Excel автоматично
обріже

2

ми експортуємо дані з сітки даних, щоб постійно перевершувати їх. Перетворення його в 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

Я виявив, що десь це добре працює.


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 Interop через простір імен Microsoft.Office.Interop. Це так чортово повільно, ненадійно і незмінно. Не застосовується для мазохістів.


1

Ви можете легко створити файли Excel, добре відформатовані за допомогою цієї бібліотеки, досить легко: http://officehelper.codeplex.com/documentation .

Microsoft Office не потрібно встановлювати на веб-сервері!


0

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

Інформація про створення XML для Excel


0

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


0

man, в .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)

Це працює для будь-якого звіту, який вимагає базового форматування, і дозволяє порівнювати з наявними електронними таблицями за допомогою інструментів порівняння тексту.


0

Якщо припустити, що це для інтрамережі, де ви можете встановлювати дозволи та мандат IE, ви можете генерувати клієнтську сторону робочої книги за допомогою програми Excel / 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

Однією з проблем, з якими я зіткнувся з використанням одного із запропонованих вище рішень, схожий на цю відповідь, є те, що якщо ви виштовхуєте вміст у вигляді вкладеного файлу (те, що я вважаю найчистішим рішенням для браузерів, що не містять повідомлення) , потім відкрийте його в 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-типи для того, щоб вивершити перехід на таблицю HTML", спрацюють, якщо ви не заперечуєте, щоб формат файлу був трохи базовим. Ці підходи також спричиняють важку роботу процесора на клієнта. Якщо ви хочете тонко контролювати формат електронної таблиці, вам, мабуть, доведеться використовувати сам Excel для створення файлу, як описано вище.


Погана ідея автоматизації з веб-сервера. Альтернативи можуть здатися хак-іш, але вони дійсно будуть працювати набагато краще.
Joel Coehoorn

Ми використовуємо OLE на стороні сервера з Excel, і це величезна біль у задній частині. Якби це не було ризиком для нашого продукту **, ми б пішли з іншим рішенням. ** Краще чорт, якого ви знаєте ...
DaveE
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.