DISABILITARE ADBLOCK

ADBlock sta bloccando alcuni contenuti del sito

ADBlock errore
risultati trovati: 

DOMANDA

Questo è quello che ho. Funziona. Ma esiste un modo più semplice o migliore?

Una pagina ASPX, ho il link per il download ...

<asp:HyperLink ID="HyperLinkDownload" runat="server" NavigateUrl="~/Download.aspx">Download as CSV file</asp:HyperLink>

E poi ho il codice Download.aspx.vb dietro ...

Public Partial Class Download
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        'set header
        Response.Clear()
        Response.ContentType = "text/csv"
        Dim FileName As String = "books.csv"
        Response.AppendHeader("Content-Disposition", "attachment;filename=" + FileName)

        'generate file content
        Dim db As New bookDevelopmentDataContext
        Dim Allbooks = From b In db.books _
                       Order By b.Added _
                       Select b
        Dim CsvFile As New StringBuilder
        CsvFile.AppendLine(CsvHeader())
        For Each b As Book In Allbooks
            CsvFile.AppendLine(bookString(b))
        Next

        'write the file
        Response.Write(CsvFile.ToString)
        Response.End()
    End Sub

    Function CsvHeader() As String
        Dim CsvLine As New StringBuilder
        CsvLine.Append("Published,")
        CsvLine.Append("Title,")
        CsvLine.Append("Author,")
        CsvLine.Append("Price")
        Return CsvLine.ToString
    End Function

    Function bookString(ByVal b As Book) As String
        Dim CsvLine As New StringBuilder
        CsvLine.Append(b.Published.ToShortDateString + ",")
        CsvLine.Append(b.Title.Replace(",", "") + ",")
        CsvLine.Append(b.Author.Replace(",", "") + ",")
        CsvLine.Append(Format(b.Price, "c").Replace(",", ""))
        Return CsvLine.ToString
    End Function

End Class

SOLUZIONE

La formattazione CSV ha alcuni gotchas. Ti sei posto queste domande:

  • Qualcuno dei miei dati ha delle virgole incorporate?
  • Qualcuno dei miei dati ha virgolette doppie incorporate?
  • Qualcuno dei miei dati ha nuove righe?
  • Devo supportare le stringhe Unicode?

Vedo diversi problemi nel codice sopra. La cosa virgola prima di tutto ... stai rimuovendo le virgole:

CsvLine.Append(Format(b.Price, "c").Replace(",", ""))

Perché? In CSV, dovresti circondare tutto ciò che ha virgole tra virgolette:

CsvLine.Append(String.Format("\"{0:c}\"", b.Price))

(o qualcosa del genere ... il mio VB non è molto buono). Se non sei sicuro se ci sono virgole, ma inserisci delle virgolette. Se ci sono virgolette nella stringa, devi evitarle raddoppiandole. " diventa " " .

b.Title.Replace("\"", "\"\"")

Quindi racchiudilo tra virgolette, se lo desideri. Se ci sono newline nella tua stringa, devi racchiudere la stringa tra virgolette ... sì, le newline letterali sono consentite nei file CSV. Sembra strano agli umani, ma va tutto bene.

Un buon scrittore CSV richiede qualche riflessione. Un buon lettore CSV (parser) è semplicemente difficile (e no, regex non è abbastanza buono per analizzare CSV ... ti porterà solo circa il 95% del percorso).

E poi ci sono problemi Unicode ... o più in generale I18N (internazionalizzazione). Ad esempio, stai rimuovendo le virgole da un prezzo formattato. Ma questo presuppone che il prezzo sia formattato come previsto negli Stati Uniti. In Francia, la formattazione dei numeri è invertita (punti utilizzati al posto delle virgole e viceversa ). In conclusione, usa la formattazione indipendente dalla cultura, ove possibile.

Mentre il problema qui è generazione CSV, inevitabilmente dovrai analizzare CSV. In .NET, il miglior parser che ho trovato (gratuitamente) è Fast CSV Reader su CodeProject . L'ho effettivamente utilizzato nel codice di produzione ed è davvero molto veloce e molto facile da usare!

Se ti va lasciaci una tua opinione

L'articolo ti è stato utile ed è tradotto correttamente?

ALTRI SUGGERIMENTI

Trasmetto tutti i miei dati CSV attraverso una funzione come questa:

Function PrepForCSV(ByVal value As String) As String
    return String.Format("""{0}""", Value.Replace("""", """"""))
End Function

Inoltre, se non stai offrendo html probabilmente vuoi un gestore http (.as h x file) piuttosto che una pagina web completa. Se crei un nuovo gestore in Visual Studio, è probabile che potresti semplicemente copiare il codice esistente nel metodo principale e funzionerà, con un piccolo aumento delle prestazioni per i tuoi sforzi.

È possibile creare l'equivalente di bookString () nella query stessa. Ecco quello che penso sarebbe un modo più semplice.

protected void Page_Load(object sender, EventArgs e)
{
    using (var db = new bookDevelopmentDataContext())
    {
        string fileName = "book.csv";
        var q = from b in db.books
                select string.Format("{0:d},\"{1}\",\"{2}\",{3:F2}", b.Published, b.Title.Replace("\"", "\"\""), b.Author.Replace("\"", "\"\""), t.price);

        string outstring = string.Join(",", q.ToArray());

        Response.Clear();
        Response.ClearHeaders();
        Response.ContentType = "text/csv";
        Response.AppendHeader("Content-Disposition", string.Format("attachment;filename={0}", fileName));
        Response.Write("Published,Title,Author,Price," + outstring);
        Response.End();
    }
}

Se desideri un convertitore di valori delimitato da due punti, esiste un open source di terze parti chiamato FileHelpers . Non sono sicuro di quale licenza open source sia soggetta, ma mi ha aiutato molto.

C'è molto overhead associato alla classe Page. Dato che stai semplicemente sputando un file CSV e non hai bisogno di postback, controlli del server, cache o il resto di esso, dovresti trasformarlo in un gestore con un'estensione .ashx. Vedi qui .

Oltre a ciò che ha detto Simon, potresti voler leggere il CSV come -per guidare e assicurarti che il tuo output non attraversi nessuno dei gotcha.

Per chiarire qualcosa che Simon ha detto:

  

Quindi racchiudilo tra virgolette se vuoi

I campi che contengono virgolette doppie raddoppiate (" ") dovranno essere completamente racchiuse tra virgolette doppie. Non dovrebbe esserci alcun danno nel racchiudere tutti i campi con virgolette doppie, a meno che non si desideri specificamente che il parser elimini gli spazi bianchi iniziali e finali (invece di tagliarli da soli).

Uso il seguente metodo per creare un file CSV da una DataTable. ControllerContext è solo l'oggetto flusso di risposta in cui viene scritto il file. Per te sarà solo l'oggetto Response.

public override void ExecuteResult(ControllerContext context)
        {
            StringBuilder csv = new StringBuilder(10 * Table.Rows.Count * Table.Columns.Count);

            for (int c = 0; c < Table.Columns.Count; c++)
            {
                if (c > 0)
                    csv.Append(",");
                DataColumn dc = Table.Columns[c];
                string columnTitleCleaned = CleanCSVString(dc.ColumnName);
                csv.Append(columnTitleCleaned);
            }
            csv.Append(Environment.NewLine);
            foreach (DataRow dr in Table.Rows)
            {
                StringBuilder csvRow = new StringBuilder();
                for(int c = 0; c < Table.Columns.Count; c++)
                {
                    if(c != 0)
                        csvRow.Append(",");

                    object columnValue = dr[c];
                    if (columnValue == null)
                        csvRow.Append("");
                    else
                    {
                        string columnStringValue = columnValue.ToString();


                        string cleanedColumnValue = CleanCSVString(columnStringValue);

                        if (columnValue.GetType() == typeof(string) && !columnStringValue.Contains(","))
                        {
                            cleanedColumnValue = "=" + cleanedColumnValue; // Prevents a number stored in a string from being shown as 8888E+24 in Excel. Example use is the AccountNum field in CI that looks like a number but is really a string.
                        }
                        csvRow.Append(cleanedColumnValue);
                    }
                }
                csv.AppendLine(csvRow.ToString());
            }

            HttpResponseBase response = context.HttpContext.Response;
            response.ContentType = "text/csv";
            response.AppendHeader("Content-Disposition", "attachment;filename=" + this.FileName);
            response.Write(csv.ToString());
        }

        protected string CleanCSVString(string input)
        {
            string output = "\"" + input.Replace("\"", "\"\"").Replace("\r\n", " ").Replace("\r", " ").Replace("\n", "") + "\"";
            return output;
        }

Aspetto per lo più buono tranne nella tua funzione "BookString ()" dovresti passare tutte quelle stringhe attraverso una piccola funzione come questa prima:

Private Function formatForCSV(stringToProcess As String) As String
    If stringToProcess.Contains("""") Or stringToProcess.Contains(",") Then
        stringToProcess = String.Format("""{0}""", stringToProcess.Replace("""", """"""))
    End If
    Return stringToProcess
End Function

'So, lines like this:
CsvLine.Append(b.Title.Replace(",", "") + ",")
'would be lines like this instead:
CsvLine.Append(formatForCSV(b.Title)) + ",")

La funzione formatterà bene le tue stringhe per CSV. Sostituisce le virgolette con doppie virgolette e aggiunge le virgolette attorno alla stringa se nella stringa sono presenti virgole o virgole.

Nota che non tiene conto delle nuove righe, ma può garantire in modo sicuro un buon output CSV solo per quelle stringhe che sai sono prive di nuove righe (input da semplici moduli di testo a una riga, ecc.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow