Хорошо, я хочу создать файл .csv в C #. Я осматривался и заметил, что многие люди используют system.IO.memorystream и system.io.streamwriter.
Проблема в следующем: у меня есть веб-приложение. Я хочу дать пользователю возможность экспортировать в Excel. Проблема в том, что Excel не может быть установлен на сервере (не спрашивайте). Я хочу быть в состоянии написать экспорт листа .csv для отчета. Теперь заголовки отчетов и данные будут отличаться для всех отчетов (циклический переход решит эту проблему). У кого-нибудь есть пример или лучшие ресурсы для меня?
Я обычно использую этот подход. Хотя, наверное, не самый эффективный.
/// <summary>
/// Generates the contents of the log file.
/// </summary>
/// <returns>The contents of the log file.</returns>
internal string GenerateLogFile()
{
StringBuilder csvExport = new StringBuilder();
csvExport.AppendLine(Resources.CSVHeader);
foreach (DataRow row in this.logEntries.Rows)
{
csvExport.AppendLine(
string.Format(
"\"{0}\",\"{1}\",\"{2}\",\"{3}\",\"{4}\",\"{5}\",\"{6}\",\"{7}\",\"{8}\", \"{9}\"",
row[ColumnNames.LogTime], row[ColumnNames.Field1], row[ColumnNames.Field2], row[ColumnNames.Field3], row[ColumnNames.Field4], row[ColumnNames.Field5], row[ColumnNames.Field6], row[ColumnNames.Field7], row[ColumnNames.Field8], row[ColumnNames.Field9]));
}
return csvExport.ToString();
}
/// <summary>
/// Adds the CSV file to the response.
/// </summary>
/// <param name="csvExportContents">The contents of the CSV file.</param>
internal void DisplayLogFile(string csvExportContents)
{
byte[] data = new ASCIIEncoding().GetBytes(csvExportContents);
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ContentType = "APPLICATION/OCTET-STREAM";
HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment; filename=Export.csv");
HttpContext.Current.Response.OutputStream.Write(data, 0, data.Length);
HttpContext.Current.Response.End();
}
Excel требуется, только если вы используете Office Interop. Используя StringWriter, вы просто собираетесь создать файл и добавить некоторую ответную информацию. Excel требуется только при открытии файла.
private void WriteItem<T>(StreamWriter sr, T item)
{
string itemString = item.ToString();
if(itemString.IndexOfAny(new char[] { '"', ',', '\n', '\r' }) != -1)//skip test and always escape for different speed/filesize optimisation
{
sr.Write('"');
sr.Write(itemString.Replace("\"", "\"\""));
sr.Write('"');
}
else
sr.Write(itemString);
}
private void WriteLine<T>(StreamWriter sr, IEnumerable<T> line)
{
bool first = true;
foreach(T item in line)
{
if(!first)
sr.Write(',');
first = false;
WriteItem(sr, item);
}
}
private void WriteCSV<T>(StreamWriter sr, IEnumerable<IEnumerable<T>> allLines)
{
bool first = true;
foreach(IEnumerable<T> line in allLines)
{
if(!first)
sr.Write('\n');
first = false;
WriteLine(sr, line);
}
}
private void WriteCSV<T>(HttpResponse response, IEnumerable<IEnumerable<T>> allLines)
{
response.ContentType = "text/csv";
WriteCSV(response.Output, allLines);
}
Также может быть полезно отправить заголовок Content-Disposition с рекомендованным именем файла.
Редактировать: В последнее время, когда нужно размещать действие между элементами в перечислении (например, запятая и новая строка выше), я предпочел оставить логическое значение, которое постоянно проверяется, я обрабатываю перечислитель напрямую , а затем обработайте первый элемент отдельно от остальных. Я начал делать это как микрооптимальную опцию для повышения эффективности, но вырос, чтобы найти лучшее выражение пути кода, который отличается для первого элемента. Таким образом, я бы теперь написал выше как:
private void WriteLine<T>(StreamWriter sr, IEnumerable<T> line)
{
using(var en = line.GetEnumerator())
if(en.MoveNext())
{
WriteItem(sr, en.Current);
while(en.MoveNext())
{
sr.Write(',');
WriteItem(sr, en.Current);
}
}
private void WriteCSV<T>(StreamWriter sr, IEnumerable<IEnumerable<T>> allLines)
{
using(var en = allLines.GetEnumerator())
if(en.MoveNext())
{
WriteLine(sr, en.Current);
while(en.MoveNext())
{
sr.Write('\n');
WriteLine(sr, en.Current);
}
}
}
Если вы не против использования сторонней библиотеки и для вашего проекта подойдет лицензия LGPL , то FileHelpers - отличный инструмент для этого.
Вы должны иметь возможность использовать примеры с использованием System.IO.MemoryStream
и System.IO.StreamWriter
нормально.
Вместо того, чтобы записывать MemoryStream в файл, вы должны вернуть его как ResponseStream в ASP.NET (убедитесь, что вы установили соответствующие значения заголовка, чтобы браузер знал, что он загружает файл).
В создании файла CSV нет никакого волшебства. Единственная проблема с файлами CSV заключается в том, что на самом деле нет стандарта, и большинство импортеров просто реализуют одно конкретное поведение для процесса импорта. Если вам повезет, вы получите то, о чем сможете относительно хорошо угадывать.
Создание файла CSV - это просто вопрос печати строк. Что касается фактических деталей, ознакомьтесь с:
http://en.wikipedia.org/wiki/Comma-separated_values
При этом, если вы хотите экспортировать в Excel, вы можете использовать Microsoft OOXML SDK:
http://msdn.microsoft.com/en-us/library/bb448854.aspx
OOXML SDK - это библиотека C #, которую можно использовать для создания файлов Excel на сервере. Блог Брайана Джонса - отличный ресурс о том, как использовать эту библиотеку: