Alguém poderia me dizer por que o código a seguir não está funcionando. Os dados são salvos no arquivo csv, porém os dados não são separados. Tudo existe na primeira célula de cada linha.
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());
Obrigado.
c#
csv
delimited-text
Darren Young
fonte
fonte
Respostas:
A seguinte versão mais curta abre bem no Excel, talvez o seu problema seja a vírgula final
.net = 3,5
.net> = 4,0
E, como Tim apontou, se você estiver em .net> = 4, você pode torná-lo ainda mais curto:
Conforme sugerido por Christian, se você quiser lidar com caracteres especiais escapando em campos, substitua o bloco de loop por:
E a última sugestão, você pode escrever o conteúdo csv linha por linha em vez de como um documento inteiro, para evitar ter um grande documento na memória.
fonte
ItemArray
para um novoString[]
, você pode omitir.ToArray()
com o .NET 4 e usar aString.Join
sobrecarga que leva umIEnumerable<T>
(editado). 
é típica de documentos HTML / XML. Não é o código acima que o produz, a menos que a tabela contenha
explicitamenteEu envolvi isso em uma classe de extensão, que permite que você chame:
em qualquer DataTable.
fonte
Uma nova função de extensão baseada na resposta de Paul Grimshaw. Eu limpei e adicionei a capacidade de lidar com dados inesperados. (Dados vazios, citações incorporadas e vírgulas nos títulos ...)
Ele também retorna uma string que é mais flexível. Ele retorna Nulo se o objeto de tabela não contém nenhuma estrutura.
Você o chama da seguinte maneira:
fonte
Se o seu código de chamada estiver fazendo referência ao
System.Windows.Forms
assembly, você pode considerar uma abordagem radicalmente diferente. Minha estratégia é usar as funções já fornecidas pelo framework para fazer isso em poucas linhas de código e sem ter que percorrer colunas e linhas. O que o código abaixo faz é criar um programaticamenteDataGridView
em tempo real e definir oDataGridView.DataSource
como oDataTable
. Em seguida, seleciono programaticamente todas as células (incluindo o cabeçalho) naDataGridView
chamada eDataGridView.GetClipboardContent()
, colocando os resultados no WindowsClipboard
. Então, eu 'colo' o conteúdo da área de transferência em uma chamada paraFile.WriteAllText()
, certificando-me de especificar a formatação de 'colar' comoTextDataFormat.CommaSeparatedValue
.Aqui está o código:
Observe que também me certifico de preservar o conteúdo da área de transferência antes de começar e restaurá-lo assim que terminar, para que o usuário não receba um monte de lixo inesperado na próxima vez que tentar colar. As principais ressalvas a esta abordagem são 1) Sua classe deve fazer referência
System.Windows.Forms
, o que pode não ser o caso em uma camada de abstração de dados, 2) Sua montagem terá que ser direcionada para o framework .NET 4.5, já que DataGridView não existe no 4.0, e 3) O método falhará se a área de transferência estiver sendo usada por outro processo.De qualquer forma, essa abordagem pode não ser a certa para sua situação, mas é interessante mesmo assim, e pode ser outra ferramenta em sua caixa de ferramentas.
fonte
.GetClipboardContent
também lida com alguns casos extremos de valores que contêm,
."
,\t
(converte tab em espaço)Eu fiz isso recentemente, mas incluí aspas em torno dos meus valores.
Por exemplo, altere estas duas linhas:
fonte
Tente mudar
sb.Append(Environment.NewLine);
parasb.AppendLine();
.fonte
Tente colocar em
;
vez de,
Espero que ajude
fonte
Leia isso e isso ?
Uma implementação melhor seria
fonte
O erro é o separador de lista.
Em vez de escrever,
sb.Append(something... + ',')
você deve colocar algo comosb.Append(something... + System.Globalization.CultureInfo.CurrentCulture.TextInfo.ListSeparator);
Você deve colocar o caractere separador de lista configurado em seu sistema operacional (como no exemplo acima), ou o separador de lista na máquina cliente onde o arquivo será visualizado. Outra opção seria configurá-lo no app.config ou web.config como um parâmetro do seu aplicativo.
fonte
4 linhas de código:
Observe que o
ToList()
no final é importante; Preciso de algo para forçar uma avaliação de expressão. Se eu estivesse jogando golfe com código, poderia usar em seuMin()
lugar.Observe também que o resultado terá uma nova linha no final devido à última chamada para
AppendLine()
. Você pode não querer isso. Você pode simplesmente ligarTrimEnd()
para removê-lo.fonte
Aqui está um aprimoramento da postagem do vc-74 que lida com vírgulas da mesma forma que o Excel. O Excel coloca aspas em torno dos dados se os dados tiverem vírgula, mas não aspas se os dados não tiverem vírgula.
fonte
Para gravar em um arquivo, acho que o método a seguir é o mais eficiente e direto: (você pode adicionar aspas, se quiser)
fonte
Para imitar o CSV do Excel:
fonte
fonte
fonte
Possivelmente, a maneira mais fácil será usar:
https://github.com/ukushu/DataExporter
especialmente no caso de seus dados de tabela de dados contendo
/r/n
caracteres ou símbolo separador dentro de suas células de tabela de dados . Quase todas as outras respostas não funcionarão com essas células.você só precisa escrever o seguinte código:
fonte
No caso de alguém tropeçar nisso, eu estava usando File.ReadAllText para obter dados CSV e, em seguida, modifiquei e escrevi de volta com File.WriteAllText . Os \ r \ n CRLFs funcionavam bem, mas as guias \ t foram ignoradas quando o Excel o abriu. (Todas as soluções neste tópico até agora usam um delimitador de vírgula, mas isso não importa.) O bloco de notas mostrou o mesmo formato no arquivo resultante e na origem. A Diff até mostrou os arquivos como idênticos. Mas tive uma ideia quando abri o arquivo no Visual Studio com um editor binário. O arquivo de origem era Unicode, mas o destino era ASCII . Para corrigir, modifiquei ReadAllText e WriteAllText com o terceiro argumento definido como System.Text.Encoding.Unicode e, a partir daí, o Excel foi capaz de abrir o arquivo atualizado.
fonte
FYR
fonte
Aqui está minha solução, com base nas respostas anteriores de Paul Grimshaw e Anthony VO . Enviei o código em um projeto C # no Github .
Minha principal contribuição é eliminar explicitamente a criação e a manipulação de um
StringBuilder
e, em vez disso, trabalhar apenas comIEnumerable
. Isso evita a alocação de um grande buffer na memória.}
Essa abordagem combina muito bem com a conversão
IEnumerable
para DataTable, conforme solicitado aqui .fonte
Eu também precisei fazer alguma substituição de dados, por isso existem algumas instruções "if else". Eu precisava ter certeza de que se um campo estivesse vazio para inserir "N / A", ou se um campo de Data fosse formatado como "01/01/1900: 00", ele seria salvo como "01/01/1900" em vez de.
fonte
fonte
se todos os dados ainda estiverem na primeira célula, significa que o aplicativo com o qual você abriu o arquivo está esperando outro delimitador. MSExcel pode tratar a vírgula como delimitador, a menos que você especifique o contrário.
fonte