ASP.NET'te bir Excel dosyası oluşturma [kapalı]


99

Bir ASP.NET uygulamasına (VB.NET codebehind), bir kullanıcının veritabanı verilerine dayanarak oluşturacağım bir Excel dosyası olarak kendisine döndürülen verileri almasına izin verecek bir bölüm eklemek üzereyim. Bunu yapmanın birkaç yolu olsa da, her birinin kendi dezavantajları vardır. Verileri nasıl iade edersiniz ? Mümkün olduğunca temiz ve anlaşılır bir şey arıyorum.


Yanıtlar:


131

CSV

Artıları:

  • Basit

Eksileri:

  • Diğer yerel ayarlarda veya farklı Excel yapılandırmalarında çalışmayabilir (yani Liste ayırıcı)
  • Biçimlendirme, formül vb. Uygulanamaz

HTML

Artıları:

  • Hala oldukça basit
  • Basit biçimlendirmeyi ve formülleri destekler

Eksileri:

  • Dosyayı xls olarak adlandırmanız gerekir ve Excel, yerel olmayan bir Excel dosyasını açma konusunda sizi uyarabilir
  • Çalışma kitabı başına bir çalışma sayfası

OpenXML (Office 2007 .XLSX)

Artıları:

  • Yerel Excel biçimi
  • Tüm Excel özelliklerini destekler
  • Excel'in kurulum kopyasına gerek yok
  • Pivot tablolar oluşturabilir
  • Açık kaynak projesi EPPlus kullanılarak oluşturulabilir

Eksileri:

  • Excel 2007 dışında sınırlı uyumluluk (günümüzde sorun olmamalı)
  • Üçüncü taraf bir bileşen kullanmadığınız sürece karmaşıktır

SpreadSheetML (açık biçim XML)

Artıları:

  • Yerel Excel formatlarına kıyasla basit
  • Çoğu Excel özelliğini destekler: biçimlendirme, stiller, formüller, çalışma kitabı başına birden çok sayfa
  • Kullanmak için Excel'in yüklenmesi gerekmez
  • Üçüncü taraf kitaplık gerekmez - sadece xml'nizi yazın
  • Belgeler Excel XP / 2003/2007 ile açılabilir

Eksileri:

  • İyi dokümantasyon eksikliği
  • Excel'in eski sürümlerinde desteklenmez (2000 öncesi)
  • Salt yazılır, bunda bir kez açıp Excel'den değişiklik yaptığınızda yerel Excel'e dönüştürülür.

XLS (üçüncü taraf bileşeni tarafından oluşturulmuştur)

Artıları:

  • Tüm biçimlendirme, formül vb. İle yerel Excel dosyası oluşturun.

Eksileri:

  • Maliyet parası
  • Bağımlılık ekleyin

COM Birlikte Çalışma

Artıları:

  • Yerel Microsoft kitaplıklarını kullanır
  • Yerel belgeler için desteği okuyun

Eksileri:

  • Çok yavaş
  • Bağımlılık / sürüm eşleştirme sorunları
  • Okurken web kullanımı için eşzamanlılık / veri bütünlüğü sorunları
  • Çok yavaş
  • Web kullanımı için ölçekleme sorunları (eşzamanlılıktan farklı): sunucuda çok sayıda yoğun Excel uygulaması örneği oluşturma ihtiyacı
  • Windows gerektirir
  • Yavaş olduğundan bahsetmiş miydim?

1
SpreadsheetML için bahsedilen "Salt yazma" kısıtlaması tam olarak bir sorun değildir, çünkü isterseniz bir excel dosyasını SpreadsheetML olarak kaydedebilirsiniz.
Brian

1
SpreadsheetML, onunla büyük dosyalar oluşturursanız Excel 2003'ün çökmesine neden olabilir. Güvenme: /
Brian

2
Office 2002 ve 2003'te bir SpreadsheetML dosyasına sorunsuz bir şekilde geri kaydedebilirsiniz. Farklı Kaydetme gerekmez. SpreadsheetML makroları, çizelgeleri, grafikleri ve Office 2007'nin yeni özellikleri (ör. 3'ten fazla koşullu biçim) dahil olmak üzere diğer birkaç olasılık ve sonu depolayamaz. XML ayrıntılı olduğundan, sunucudan göndermeden önce SpreadsheetML'i sıkıştırmak (SharpZipLib'i kullanmak bir seçenektir) indirme sürelerini azaltmak için harika çalışıyor - aslında OpenXML'in yine de bir ZIP konteynerinde saklandığından bahsetmek gerekir. @Brian: 50-100MB aralığında karmaşık SpreadsheetML'i günlük olarak çökme sorunları olmadan kullanıyorum.
richardtallent

Büyük miktarda veriyi dışa aktarmanızın gerekmesi ihtimali varsa, CSV olarak dışa aktarmalısınız. SpreadsheetML dışında, diğer biçimlerden herhangi biriyle yüksek performanslı bir çözüm yapmak daha zordur. HTML verimli bir şekilde yazılabilir ve okunabilir, ancak yararlı olması için sizin açınızdan daha fazla spesifikasyona ihtiyaç duyar. Brian'ın yorumunda bahsettiği gibi, hem HTML hem de SpreadsheetML'in büyük dosyalarla ilgili başka sorunları var. Yani, CSV ile basit bir veri dışa aktarma çubuğuna ihtiyacınız varsa.
JohannesH

2
@pomarc: Basit olabilir ama temiz değil. Kullanıcı bir Excel dosyası istiyor ve siz ona sahte uzantıya sahip bir HTML dosyası veriyorsunuz.
Heinzi

38

Verileri html tablo hücreleri olarak çıkarabilir, üzerine bir .xlsveya .xlsxuzantı yapıştırabilirsiniz ve Excel bunu yerel bir belgeymiş gibi açar. Bu şekilde bazı sınırlı biçimlendirme ve formül hesaplamaları bile yapabilirsiniz, bu nedenle CSV'den çok daha güçlüdür. Ayrıca, ASP.Net gibi bir web platformundan bir html tablosunun çıktısını almak oldukça kolay olmalıdır;)

Excel Çalışma Kitabınızda birden çok çalışma sayfasına veya adlandırılmış çalışma sayfasına ihtiyacınız varsa, adı verilen bir XML şeması aracılığıyla benzer bir şey yapabilirsiniz SpreadSheetML. Bu, Office 2007 ile birlikte gelen yeni biçim değil , Excel 2000 kadar eskiye dayanan tamamen farklı bir biçimdir. Nasıl çalıştığını açıklamanın en kolay yolu bir örnek vermektir:

<?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
Dosyayı bir .xml uzantısıyla yeniden adlandırabilir ve şunu ekleyebilirsiniz: <? mso-application progid = "Excel.Sheet"?> <? xml version = "1.0"?> hemen sonrasına bu şekilde pencereler dosyanın bir Excel dosyası, ona doğru ikonu verecek, dosyayı tıkladığınızda excel'i açacak ve Excel dosya formatının ve içeriğinin eşleşmediğinden şikayet etmeyecektir. Hoşçakal.
pomarc

1
@pomarc Bunun dezavantajı, excel dosyalarını içe aktaran diğer programların onu tanımamasıdır. Ama sonra, muhtemelen xml'yi ayrıştırmazlar.
Joel Coehoorn

1
Bu tekniği oldukça başarılı bir şekilde kullandım. Bu benim tavsiyem olacaktır - çok basit ve çok etkili.
NealB

XLS dosyası olarak maskelenen HTML tablo verileriyle ilgili iki olası sorun (YMMV): (1) Microsoft Excel baştaki boşlukları ve sıfırları otomatik olarak kırpacaktır; ve (2) Microsoft Excel 2010, HTML tablo verileri içeren bir XLS dosyasını açarken kullanıcıyı uyarır. Birinci çözüm, creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel gibi görünüyor (baştaki boşluklar / sıfırlar önemliyse ve tutulması gerekiyorsa).
iokevins

Sadece açıklama için, HTML tablolarından söz ederken, bu cevabın ana noktası, HTML tablo verilerinden daha fazlası olan SpreadsheetML'dir. Excel bunu yerel olarak görüyor.
Joel Coehoorn

16

Bir DataTable'dan geliyorsa :

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

Bir Gönderen 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
Sadece ihtiyacım olan kod, teşekkürler. :)
Kjensen

Scott, pound ("£") işaretinde ne var? Ya ihtiyacım olursa? Tehlikeli olan başka karakterler var mı?
Piotr Owsiak

MÜKEMMEL. Tam ihtiyacım olan şey.
Brad Bruce

£ işareti aslında müşterilerimden biri için ihtiyacım olan bir şey. çıkarabilirsin.
SpoiledTechie.com

XLS dosyası olarak maskelenen HTML tablo verileriyle ilgili iki olası sorun (YMMV): (1) Microsoft Excel baştaki boşlukları ve sıfırları otomatik olarak kırpacaktır; ve (2) Microsoft Excel 2010, HTML tablo verileri içeren bir XLS dosyasını açarken kullanıcıyı uyarır. Birinci çözüm, creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel gibi görünüyor (baştaki boşluklar / sıfırlar önemliyse ve tutulması gerekiyorsa). CSV veri dosyaları da Microsoft Excel'de açıldığında 1 numaradan zarar görür.
iokevins


5

Verilen cevaplara ve iş arkadaşlarıyla yapılan görüşmelere dayanarak, en iyi çözümün bir XML dosyası veya HTML tabloları oluşturup bir ek olarak aşağı itmek olduğu görülmektedir. İş arkadaşlarımın önerdiği bir değişiklik, verilerin (yani HTML tablolarının) doğrudan Yanıt nesnesine yazılabilmesidir, böylece izin sorunları, G / Ç nedeniyle sorun yaratabilecek bir dosya yazma ihtiyacını ortadan kaldırır. çekişme ve planlı tasfiyenin gerçekleşmesini sağlama.

İşte kodun bir parçası ... Bunu henüz kontrol etmedim ve aranan kodun tamamını sağlamadım, ancak fikri iyi temsil ettiğini düşünüyorum.

    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
Dan, doğru yoldasın. Ve HTML üzerinden SpreadsheetML'i kesinlikle öneririm - HTML desteği sinir bozucu bir şekilde sınırlı olduğu için gelecek için nefes alma alanı. Ancak HTML, SpreadsheetML ve OpenXML ile dosya boyutları oldukça büyük olabilir ve sunucu tarafından gzip ile sıkıştırılmayacaktır. OpenXML , içinde birden çok dosya bulunan bir ZIP kapsayıcısı gerektirir ve SpreadsheetML ve HTML'yi, önce sıkıştırıp ek olarak gönderirseniz indirilmesi çok daha hızlıdır. SharpZipLib'i kullanın ve doğrudan Yanıt yerine ona akış yapın.
richardtallent

4

Excel HTML'yi anladığından, verileri bir HTML tablosu olarak .xls uzantılı bir geçici dosyaya yazabilir, dosya için FileInfo'yu alabilir ve kullanarak geri alabilirsiniz.

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

geçici dosyadan kaçınmak istiyorsanız, WriteFile kullanmak yerine bellek içi akışa yazabilir ve baytları geri yazabilirsiniz.

içerik uzunluğu başlığı atlanırsa, html'yi doğrudan geri yazabilirsiniz, ancak bu, tüm tarayıcılarda her zaman doğru çalışmayabilir


2
XLS dosyası olarak maskelenen HTML tablo verileriyle ilgili iki olası sorun (YMMV): (1) Microsoft Excel baştaki boşlukları ve sıfırları otomatik olarak kırpacaktır; ve (2) Microsoft Excel 2010, HTML tablo verileri içeren bir XLS dosyasını açarken kullanıcıyı uyarır. Birinci çözüm, creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel gibi görünüyor (baştaki boşluklar / sıfırlar önemliyse ve tutulması gerekiyorsa).
iokevins

3

Ben şahsen XML yöntemini tercih ediyorum. Veritabanındaki verileri bir Veri Kümesinde geri getireceğim, XMl'e kaydedeceğim, ardından uygun bir belgeyi biçimlendirecek bir dönüştürme kuralı içeren bir xslt dosyası oluşturacağım ve basit bir XML dönüşümü işi bitirecek. Bunun en iyi yanı, hücreleri biçimlendirebilir, koşullu biçimlendirme yapabilir, üstbilgileri ve altbilgileri ayarlayabilir ve hatta yazdırma aralıklarını ayarlayabilirsiniz.


2

Bunu birkaç kez yaptım ve her seferinde en kolay yol basitçe bir CSV (Virgülle Ayrılmış Değer) dosyası döndürmekti. Excel bunu mükemmel bir şekilde içe aktarır ve nispeten hızlıdır.


CSV verileriyle ilgili bir olası sorun (YMMV): Microsoft Excel
baştaki

2

Her zaman mükemmel olmak için verileri bir veri sayfasından dışa aktarırız. HTML'ye dönüştürdükten sonra bir excel dosyasına yazarak

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

Bu yöntemle elde edilen tek şey, ızgaralarımızın çoğunda düğmeler veya bağlantılar olmasıydı, bu yüzden buna da ihtiyacınız var:

'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

İyi çalıştığını bir yerde buldum.


2
XLS dosyası olarak maskelenen HTML tablo verileriyle ilgili iki olası sorun (YMMV): (1) Microsoft Excel baştaki boşlukları ve sıfırları otomatik olarak kırpacaktır; ve (2) Microsoft Excel 2010, HTML tablo verileri içeren bir XLS dosyasını açarken kullanıcıyı uyarır. Birinci çözüm, creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel gibi görünüyor (baştaki boşluklar / sıfırlar önemliyse ve tutulması gerekiyorsa).
iokevins


2

İşte saklı yordamdan alınan bir rapor. Sonuçlar Excel'e aktarılır. ADO.NET yerine ADO kullanıyor ve bu satırın nedeni

oSheet.Cells(2, 1).copyfromrecordset(rst1)

İşin çoğunu yapar ve ado.net'te mevcut değildir.

‘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

Bir GridView'ü verilerle doldurursanız, bu işlevi HTML formatlı verileri almak için kullanabilirsiniz, ancak tarayıcıya bunun bir excel dosyası olduğunu belirtebilirsiniz.

 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

XLS dosyası olarak maskelenen HTML tablo verileriyle ilgili iki olası sorun (YMMV): (1) Microsoft Excel baştaki boşlukları ve sıfırları otomatik olarak kırpacaktır; ve (2) Microsoft Excel 2010, HTML tablo verileri içeren bir XLS dosyasını açarken kullanıcıyı uyarır. Birinci çözüm, creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel gibi görünüyor (baştaki boşluklar / sıfırlar önemliyse ve tutulması gerekiyorsa).
iokevins

1

Microsoft.Office.Interop ad alanı aracılığıyla COM Interop'tan kaçının. Çok yavaş, güvenilmez ve ölçeklenemez. Mazoşistler için geçerli değildir.




0

Ya CSV yoluna gidiyorum (yukarıda açıklandığı gibi) ya da bu günlerde daha sık olarak dosyayı oluşturmak için Infragistics NetAdvantage kullanıyorum. (Infragistics'in işin içinde olduğu zamanların büyük çoğunluğunda, sadece ekstra biçimlendirme ince ayarlarına ihtiyaç duyulmadıkça esasen tek LOC çözümü olan mevcut bir UltraWebGrid'i dışa aktarıyoruz. Bir Excel / BIFF dosyasını manuel olarak da oluşturabiliriz, ancak nadiren ihtiyaç duyulur.)


0

adam, .net içinde sanırım bunu yapabilecek bir bileşene sahip olabilirsiniz, ancak klasik asp'de bunu bir html tablosu oluşturup sayfanın mime ucunu vnd / msexcel olarak değiştirdim zaten yaptım. Bir gridview kullanırsanız ve mime tipini değiştirirseniz belki işe yarayacaktır, çünkü gridview bir html tablosudur.


XLS dosyası olarak maskelenen HTML tablo verileriyle ilgili iki olası sorun (YMMV): (1) Microsoft Excel baştaki boşlukları ve sıfırları otomatik olarak kırpacaktır; ve (2) Microsoft Excel 2010, HTML tablo verileri içeren bir XLS dosyasını açarken kullanıcıyı uyarır. Birinci çözüm, creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel gibi görünüyor (baştaki boşluklar / sıfırlar önemliyse ve tutulması gerekiyorsa).
iokevins

0

"Bu numaralar metin olarak saklanıyor gibi görünüyor" yeşil üçgenlerden kaçınmanın tek kurşun geçirmez yolu, Açık XML biçimini kullanmaktır. Kaçınılmaz yeşil üçgenlerden kaçınmak için kullanmaya değer.


0

Excel raporları için gördüğüm en iyi yöntem, verileri XML uzantısıyla XML olarak yazmak ve doğru içerik türüne sahip istemcilere yayınlamaktır. (uygulama / xls)

Bu, temel biçimlendirme gerektiren tüm raporlarda işe yarar ve metin karşılaştırma araçlarını kullanarak mevcut elektronik tablolarla karşılaştırma yapmanıza olanak tanır.


0

Bunun izinleri ayarlayabileceğiniz ve IE'yi zorunlu kılabileceğiniz bir intranet için olduğunu varsayarsak, çalışma kitabı istemci tarafını Excel'i çalıştıran JScript / VBScript ile oluşturabilirsiniz . Bu, sunucuda Excel'i otomatikleştirmeye çalışmak zorunda kalmadan yerel Excel biçimlendirmesini sağlar.

Oldukça niş senaryolar dışında bu yaklaşımı artık gerçekten tavsiye edeceğime emin değilim, ancak klasik ASP'nin en parlak dönemlerinde oldukça yaygındı.


0

Elbette her zaman üçüncü taraf bileşenlere gidebilirsiniz. Kişisel olarak, Spire.XLS ile iyi bir deneyim yaşadım http://www.e-iceblue.com/xls/xlsintro.htm

Bileşenin uygulamanızda kullanımı oldukça kolaydır:

        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

Bu cevaba benzeyen yukarıda önerilen çözümlerden birini kullanarak karşılaştığım sorunlardan biri , içeriği bir ek olarak dışarı atarsanız (ms olmayan tarayıcılar için en temiz çözüm bulduğum şey) ardından Excel 2000-2003'te açın, türü "Excel Web Sayfası" dır ve yerel bir Excel belgesi değildir.

Daha sonra, Excel belgesini bir Excel belgesine dönüştürmek için Excel içinden "Kayıt türü" nün nasıl kullanılacağını kullanıcılara açıklamanız gerekir. Kullanıcıların bu belgeyi düzenlemesi ve ardından sitenize yeniden yüklemesi gerekiyorsa bu bir acıdır.

Benim tavsiyem CSV kullanmaktır. Çok basittir ve kullanıcılar bunu Excel'in içinden açarsa, Excel en azından kendi yerel biçiminde kaydetmelerini ister.


Kullanıcılarınız dünyanın dört bir yanına dağılmış durumdaysa CSV konusunda dikkatli olmanız gerekir. Burada Almanya'da ondalık ayırıcı olarak virgül kullanılır ve bu nedenle değer ayırıcı olarak noktalı virgül kullanılır. Tüm farklı kültürlerde okunabilen tek bir dosya oluşturmayı zorlaştırır. Bu nedenle benim oyum XML formatlarından biri olacaktır.
paul

0

Verilere dayalı olarak bir CSV dosyası oluştururdum, çünkü bunu en temiz olarak görüyorum ve Excel bunun için iyi bir desteğe sahip. Ancak daha esnek bir biçime ihtiyacınız varsa, eminim gerçek excel dosyaları oluşturmak için bazı 3. taraf araçlar vardır.


0

Verileri CSV olarak dışarı aktaran bir çözüm burada. Hızlı, temiz ve kolaydır ve girişte virgülle işlem yapar.

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

başkalarına yardımcı olacağını ummak için bir web formundan C # dışa aktarmak için bir işlev oluşturdu

    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

CSV dosyası yerine Excel kullanmanız gerekiyorsa, sunucudaki bir Excel örneğinde OLE otomasyonunu kullanmanız gerekecektir. Bunu yapmanın en kolay yolu, bir şablon dosyasına sahip olmak ve bunu programatik olarak verilerle doldurmaktır. Onu başka bir dosyaya kaydedersiniz.

İpuçları:

  • Etkileşimli olarak yapmayın. Kullanıcıdan işlemi başlatmasını ve ardından dosyanın bağlantısını içeren bir sayfa yayınlamasını isteyin. Bu, elektronik tablo oluşturulurken olası performans sorunlarını azaltır.
  • Şablonu daha önce anlattığım gibi kullanın. Değiştirmeyi kolaylaştırır.
  • Excel'in iletişim kutuları açmayacak şekilde ayarlandığından emin olun. Bir web sunucusunda bu, tüm excel örneğini asacaktır.
  • Excel örneğini ayrı bir sunucuda, tercihen bir güvenlik duvarının arkasında tutun, böylece olası bir güvenlik açığı olarak ortaya çıkmaz.
  • Kaynak kullanımına bir göz atın. OLE otomasyon arayüzü üzerinden bir spreadhseet oluşturmak (PIA'lar bunun üzerine bir şimdir) oldukça ağır bir süreçtir. Bunu yüksek veri hacimlerine ölçeklendirmeniz gerekiyorsa, mimariniz konusunda biraz akıllı olmanız gerekebilir.

Dosyanın biçiminin biraz basit olmasına aldırmazsanız, 'HTML tablosunu açmak için Excel'i kandırmak için mime türlerini kullanın' yaklaşımlarından bazıları işe yarayacaktır. Bu yaklaşımlar ayrıca CPU'nun ağır işini istemciye aktarır. Elektronik tablonun biçimi üzerinde ayrıntılı kontrol istiyorsanız, dosyayı yukarıda açıklandığı gibi oluşturmak için muhtemelen Excel'in kendisini kullanmanız gerekecektir.


Bir web sunucusundan otomasyon yapmak kötü bir fikir. Alternatifler hack-ish görünebilir, ancak gerçekten çok daha iyi çalışacaklar.
Joel Coehoorn

Excel ile sunucu tarafı OLE kullanıyoruz ve bu arka tarafta çok büyük bir sorun. Ürünümüz için risk olmasaydı **, başka bir çözüm seçerdik. ** Bildiğiniz şeytan daha iyi ...
DaveE
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.