这就是我所拥有的。有用。但是,有更简单或更好的方法吗?
一个ASPX页面,我有下载链接......
<asp:HyperLink ID="HyperLinkDownload" runat="server" NavigateUrl="~/Download.aspx">Download as CSV file</asp:HyperLink>
然后我得到了Download.aspx.vb代码......
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
答案 0 :(得分:22)
CSV格式化有一些问题。你有没有问过自己这些问题:
我在上面的代码中看到了几个问题。首先是逗号的东西......你正在删除逗号:
CsvLine.Append(Format(b.Price, "c").Replace(",", ""))
为什么呢?在CSV中,您应该围绕任何带引号的逗号:
CsvLine.Append(String.Format("\"{0:c}\"", b.Price))
(或类似的东西......我的VB不是很好)。如果你不确定是否有逗号,但在它周围加上引号。如果字符串中有引号,则需要通过加倍来转义它们。 "
变为""
。
b.Title.Replace("\"", "\"\"")
如果你愿意,可以用引号括起来。如果字符串中有换行符,则需要用引号括起字符串...是的,CSV文件中允许使用文字换行符 。对人类来说看起来很奇怪,但这一切都很好。
一个优秀的CSV编写者需要一些思考。一个好的CSV阅读器(解析器)很简单(并且没有,正则表达式不足以解析CSV ...它只会让你大约95%的方式)。
然后是Unicode ......或更普遍的I18N(国际化)问题。例如,您正在从格式化价格中删除逗号。但这是假设价格的格式符合您在美国的预期。在法国,数字格式相反(使用句号而不是逗号,反之亦然)。最重要的是,尽可能使用与文化无关的格式。
虽然此处的问题是生成 CSV,但您不可避免地需要解析CSV。在.NET中,我找到的最好的解析器(免费)是Fast CSV Reader上的CodeProject。我实际上在生产代码中使用它,它真的非常快,而且非常容易使用!
答案 1 :(得分:8)
我通过以下函数传递所有CSV数据:
Function PrepForCSV(ByVal value As String) As String
return String.Format("""{0}""", Value.Replace("""", """"""))
End Function
另外,如果你没有提供html,你可能需要一个http处理程序(.as h x文件)而不是一个完整的网页。如果你在Visual Studio中创建一个新的处理程序,你很可能只是将你现有的代码复制到main方法中,它只会起作用,你的工作会有很小的性能提升。
答案 2 :(得分:4)
您可以在查询本身中创建bookString()的等效项。这是我认为更简单的方法。
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();
}
}
答案 3 :(得分:3)
如果你想要一个冒号分隔值转换器,那么有一个名为FileHelpers的第三方开源。我不确定它是什么开源许可证,但它对我帮助很大。
答案 4 :(得分:2)
与Page类相关的开销很大。由于您只是吐出CSV文件而不需要回发,服务器控件,缓存或其余部分,因此您应该将其转换为扩展名为.ashx的处理程序。 See here
答案 5 :(得分:1)
除了西蒙所说的,你可能还想阅读CSV how-to guide,并确保你的输出不会遇到任何陷阱。
澄清西蒙所说的话:
如果你想要
,那么用引号括起来
包含双引号双引号(“”)的字段需要完全用双引号括起来。使用双引号包装所有字段应该没有任何损害,除非您特别希望解析器去掉前导和尾随空格(而不是自己修剪)。
答案 6 :(得分:1)
从DataTable构建CSV文件时,我使用以下方法。 ControllerContext只是写入文件的响应流对象。对你来说它只是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;
}
答案 7 :(得分:1)
除了在你的函数“BookString()”中看起来很好,你应该通过这样的小函数传递所有这些字符串:
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)) + ",")
该功能可以很好地格式化CSV的字符串。它用双引号替换引号,如果字符串中有引号或逗号,则在字符串周围添加引号。
请注意,它不考虑换行符,但只能安全地保证您知道没有换行符的字符串的良好CSV输出(来自简单的单行文本表单的输入等)。