Может кто-нибудь сказать мне, почему следующий код не работает. Данные сохраняются в файле csv, однако данные не разделяются. Все это существует в первой ячейке каждой строки.
StringBuilder sb = new StringBuilder();
foreach (DataColumn col in dt.Columns)
{
sb.Append(col.ColumnName + ',');
}
sb.Remove(sb.Length - 1, 1);
sb.Append(Environment.NewLine);
foreach (DataRow row in dt.Rows)
{
for (int i = 0; i < dt.Columns.Count; i++)
{
sb.Append(row[i].ToString() + ",");
}
sb.Append(Environment.NewLine);
}
File.WriteAllText("test.csv", sb.ToString());
Спасибо.
c#
csv
delimited-text
Даррен Янг
источник
источник
Ответы:
Следующая более короткая версия отлично открывается в Excel, возможно, ваша проблема заключалась в конечной запятой
.net = 3.5
.net> = 4.0
И, как заметил Тим, если вы используете .net> = 4, вы можете сделать его еще короче:
По предложению Кристиана, если вы хотите обрабатывать специальные символы, экранирующие поля, замените блок цикла на:
И последнее предложение, вы можете писать содержимое csv построчно, а не как весь документ, чтобы не хранить большой документ в памяти.
источник
ItemArray
новыйString[]
, вы можете опустить.ToArray()
с .NET 4 и использоватьString.Join
перегрузку, которая принимаетIEnumerable<T>
(отредактировано). 
типичен для документов HTML / XML. Это не приведенный выше код, который производит его, если таблица не содержит
явноЯ заключил это в класс расширения, который позволяет вам вызывать:
на любом DataTable.
источник
Новая функция расширения, основанная на ответе Пола Гримшоу. Я почистил его и добавил возможность обрабатывать неожиданные данные. (Пустые данные, встроенные цитаты и запятые в заголовках ...)
Он также возвращает более гибкую строку. Он возвращает Null, если объект таблицы не содержит никакой структуры.
Вы называете это так:
источник
Если ваш вызывающий код ссылается на
System.Windows.Forms
сборку, вы можете рассмотреть радикально другой подход. Моя стратегия состоит в том, чтобы использовать функции, уже предоставляемые фреймворком, чтобы выполнить это в очень небольшом количестве строк кода и без необходимости перебирать столбцы и строки. Приведенный ниже код создает программное обеспечениеDataGridView
на лету и устанавливаетDataGridView.DataSource
для него значениеDataTable
. Затем я программно выделяю все ячейки (включая заголовок) вDataGridView
вызове иDataGridView.GetClipboardContent()
, помещая результаты в WindowsClipboard
. Затем я «вставляю» содержимое буфера обмена в вызовFile.WriteAllText()
, не забывая указать форматирование «вставить» какTextDataFormat.CommaSeparatedValue
.Вот код:
Обратите внимание, что я также обязательно сохраню содержимое буфера обмена перед тем, как начать, и восстановлю его, как только закончу, чтобы пользователь не получил кучу неожиданного мусора в следующий раз, когда пользователь попытается вставить. Основные предостережения в отношении этого подхода: 1) ваш класс должен ссылаться
System.Windows.Forms
, что может быть не так на уровне абстракции данных, 2) ваша сборка должна быть нацелена на платформу .NET 4.5, поскольку DataGridView не существует в 4.0, и 3) метод завершится ошибкой, если буфер обмена используется другим процессом.В любом случае, этот подход может быть неправильным для вашей ситуации, но тем не менее он интересен и может стать еще одним инструментом в вашем наборе инструментов.
источник
.GetClipboardContent
также обрабатывает несколько крайних случаев значений, содержащих,
."
,\t
(конвертирует табуляцию в пробел)Я сделал это недавно, но заключил свои значения в двойные кавычки.
Например, измените эти две строки:
источник
Попробуйте сменить
sb.Append(Environment.NewLine);
наsb.AppendLine();
.источник
Попробуйте поставить
;
вместо,
Надеюсь, поможет
источник
Прочитать это и это ?
Лучшая реализация была бы
источник
Ошибка разделителя списка.
Вместо записи
sb.Append(something... + ',')
вы должны поставить что-то вродеsb.Append(something... + System.Globalization.CultureInfo.CurrentCulture.TextInfo.ListSeparator);
Вы должны поместить символ разделителя списка, настроенный в вашей операционной системе (как в приведенном выше примере), или разделитель списка на клиентском компьютере, где будет просматриваться файл. Другой вариант - настроить его в app.config или web.config как параметр вашего приложения.
источник
4 строки кода:
Обратите внимание, что
ToList()
в конце важно; Мне нужно что-то, чтобы заставить вычислить выражение. Если бы я играл в гольф код, я мог бы использоватьMin()
вместо этого.Также обратите внимание, что результат будет иметь новую строку в конце из-за последнего вызова
AppendLine()
. Вы можете этого не хотеть. Вы можете просто позвонить,TrimEnd()
чтобы удалить его.источник
Вот усовершенствование сообщения vc-74, в котором запятые обрабатываются так же, как и в Excel. Excel помещает данные в кавычки, если в них есть запятая, но не в кавычки, если в данных нет запятой.
источник
Для записи в файл я думаю, что следующий метод является наиболее эффективным и простым: (Вы можете добавить кавычки, если хотите)
источник
Чтобы имитировать Excel CSV:
источник
источник
источник
Возможно, самым простым способом будет использование:
https://github.com/ukushu/DataExporter
особенно в случае ваших данных datatable, содержащих
/r/n
символы или символ разделителя внутри ваших ячеек dataTable. Почти все остальные ответы не будут работать с такими ячейками.вам нужно только написать следующий код:
источник
На случай, если кто-то еще наткнется на это, я использовал File.ReadAllText для получения данных CSV, а затем изменил его и записал обратно с помощью File.WriteAllText . CRLF \ r \ n были в порядке, но вкладки \ t игнорировались, когда Excel открывал их. (Все решения в этом потоке пока используют разделитель запятых, но это не имеет значения.) Блокнот показал тот же формат в конечном файле, что и в исходном. Diff даже показал файлы как идентичные. Но я понял, когда открыл файл в Visual Studio с помощью двоичного редактора. Исходным файлом был Unicode, а целью - ASCII . Чтобы исправить это, я изменил ReadAllText и WriteAllText с третьим аргументом, установленным как System.Text.Encoding.Unicode , и оттуда Excel смог открыть обновленный файл.
источник
FYR
источник
Вот мое решение, основанное на предыдущих ответах по Paul Гримшоу и Энтони VO . Я отправил код в проект C # на Github .
Мой основной вклад - исключить явное создание и манипулирование a
StringBuilder
и вместо этого работать только сIEnumerable
. Это позволяет избежать выделения большого буфера в памяти.}
Этот подход прекрасно сочетается с преобразованием
IEnumerable
в DataTable, как здесь указано .источник
Мне также нужно было переопределить данные, поэтому есть несколько операторов «если еще». Мне нужно было убедиться, что если поле было пустым, чтобы ввести вместо него «N / A», или если поле Date было отформатировано как «01.01.1900: 00», оно будет сохранено как «01.01.1900» вместо.
источник
источник
если все данные по-прежнему находятся в первой ячейке, это означает, что приложение, в котором вы открыли файл, ожидает другого разделителя. MSExcel может обрабатывать запятую как разделитель, если не указано иное.
источник