Bisakah seseorang memberi tahu saya mengapa kode berikut tidak berfungsi. Data tersebut disimpan ke dalam file csv, namun datanya tidak dipisahkan. Semuanya ada dalam sel pertama setiap baris.
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());
Terima kasih.
c#
csv
delimited-text
Darren Young
sumber
sumber
Jawaban:
Versi pendek berikut terbuka dengan baik di Excel, mungkin masalah Anda adalah tanda koma
.net = 3.5
.net> = 4.0
Dan seperti yang Tim tunjukkan, jika Anda menggunakan .net> = 4, Anda dapat membuatnya lebih pendek:
Seperti yang disarankan oleh Christian, jika Anda ingin menangani karakter khusus yang keluar dalam bidang, ganti blok loop dengan:
Dan saran terakhir, Anda bisa menulis baris demi baris konten csv daripada sebagai keseluruhan dokumen, untuk menghindari dokumen besar di memori.
sumber
ItemArray
ke yang baruString[]
, Anda dapat menghilangkan.ToArray()
dengan .NET 4 dan menggunakanString.Join
kelebihan beban yang membutuhkanIEnumerable<T>
(diedit). 
biasanya digunakan untuk dokumen HTML / XML. Bukan kode di atas yang memproduksinya kecuali tabel berisi
secara eksplisitSaya membungkus ini menjadi kelas ekstensi, yang memungkinkan Anda untuk memanggil:
di DataTable mana pun.
sumber
Fungsi ekstensi baru berdasarkan jawaban Paul Grimshaw. Saya membersihkannya dan menambahkan kemampuan untuk menangani data yang tidak terduga. (Data Kosong, Kutipan Tersemat, dan koma di judul ...)
Ini juga mengembalikan string yang lebih fleksibel. Ia mengembalikan Null jika objek tabel tidak berisi struktur apa pun.
Anda menyebutnya sebagai berikut:
sumber
Jika kode panggilan Anda merujuk ke
System.Windows.Forms
rakitan, Anda dapat mempertimbangkan pendekatan yang sangat berbeda. Strategi saya adalah menggunakan fungsi yang telah disediakan oleh kerangka kerja untuk mencapai hal ini dalam beberapa baris kode dan tanpa harus mengulang melalui kolom dan baris. Apa yang dilakukan kode di bawah ini adalah secara terprogram membuat aDataGridView
dengan cepat dan menyetelDataGridView.DataSource
keDataTable
. Selanjutnya, saya secara terprogram memilih semua sel (termasuk header) diDataGridView
dan memanggilDataGridView.GetClipboardContent()
, menempatkan hasilnya ke dalam WindowsClipboard
. Kemudian, saya 'menempelkan' konten clipboard ke dalam panggilan keFile.WriteAllText()
, memastikan untuk menentukan format 'paste' sebagaiTextDataFormat.CommaSeparatedValue
.Ini kodenya:
Perhatikan Saya juga memastikan untuk menyimpan konten clipboard sebelum saya mulai, dan memulihkannya setelah saya selesai, sehingga pengguna tidak mendapatkan banyak sampah tak terduga saat pengguna mencoba menempelkannya. Peringatan utama untuk pendekatan ini adalah 1) Kelas Anda harus referensi
System.Windows.Forms
, yang mungkin tidak terjadi pada lapisan abstraksi data, 2) Rakitan Anda harus ditargetkan untuk kerangka kerja .NET 4.5, karena DataGridView tidak ada di 4.0, dan 3) Metode ini akan gagal jika papan klip digunakan oleh proses lain.Bagaimanapun, pendekatan ini mungkin tidak tepat untuk situasi Anda, tetapi tetap menarik, dan dapat menjadi alat lain di kotak peralatan Anda.
sumber
.GetClipboardContent
juga menangani beberapa kasus tepi nilai yang berisi,
."
,\t
(ini mengubah tab menjadi spasi)Saya melakukan ini baru-baru ini tetapi menyertakan tanda kutip ganda di sekitar nilai-nilai saya.
Misalnya, ubah dua baris ini:
sumber
Coba ganti
sb.Append(Environment.NewLine);
kesb.AppendLine();
.sumber
Cobalah untuk menempatkan,
;
bukan,
Semoga membantu
sumber
Baca ini dan ini ?
Implementasi yang lebih baik adalah
sumber
Kesalahannya adalah pemisah daftar.
Alih-alih menulis,
sb.Append(something... + ',')
Anda harus meletakkan sesuatu sepertisb.Append(something... + System.Globalization.CultureInfo.CurrentCulture.TextInfo.ListSeparator);
Anda harus meletakkan karakter pemisah daftar yang dikonfigurasi di sistem operasi Anda (seperti pada contoh di atas), atau pemisah daftar di mesin klien tempat file akan ditonton. Pilihan lain adalah mengonfigurasinya di app.config atau web.config sebagai parameter aplikasi Anda.
sumber
4 baris kode:
Perhatikan bahwa
ToList()
di akhir itu penting; Saya butuh sesuatu untuk memaksa evaluasi ekspresi. Jika saya bermain golf kode, saya bisa menggunakannyaMin()
.Perhatikan juga bahwa hasilnya akan memiliki baris baru di akhir karena panggilan terakhir ke
AppendLine()
. Anda mungkin tidak menginginkan ini. Anda cukup meneleponTrimEnd()
untuk menghapusnya.sumber
Berikut adalah peningkatan pada posting vc-74 yang menangani koma dengan cara yang sama seperti Excel. Excel memberi tanda kutip di sekitar data jika data memiliki koma tetapi tidak mengutip jika data tidak memiliki koma.
sumber
Untuk menulis ke file, menurut saya metode berikut adalah yang paling efisien dan mudah: (Anda dapat menambahkan tanda kutip jika mau)
sumber
Untuk meniru CSV Excel:
sumber
sumber
sumber
Mungkin, cara paling mudah adalah menggunakan:
https://github.com/ukushu/DataExporter
terutama jika data Anda berisi
/r/n
karakter atau simbol pemisah yang berisi karakter atau simbol pemisah di dalam sel dataTable Anda. Hampir semua jawaban lain tidak akan berfungsi dengan sel seperti itu.Anda hanya perlu menulis kode berikut:
sumber
Jika ada orang lain yang tersandung dalam hal ini, saya menggunakan File.ReadAllText untuk mendapatkan data CSV dan kemudian saya memodifikasinya dan menulisnya kembali dengan File.WriteAllText . \ R \ n CRLF baik-baik saja tetapi \ t tab diabaikan saat Excel membukanya. (Semua solusi di utas ini sejauh ini menggunakan pemisah koma tetapi itu tidak masalah.) Notepad menunjukkan format yang sama di file yang dihasilkan seperti di sumbernya. A Diff bahkan menunjukkan file-file itu identik. Tapi saya mendapat petunjuk ketika saya membuka file di Visual Studio dengan editor biner. File sumbernya adalah Unicode tetapi targetnya adalah ASCII . Untuk memperbaikinya, saya memodifikasi ReadAllText dan WriteAllText dengan argumen ketiga ditetapkan sebagai System.Text.Encoding.Unicode , dan dari sana Excel dapat membuka file yang diperbarui.
sumber
FYR
sumber
Inilah solusi saya, berdasarkan jawaban sebelumnya oleh Paul Grimshaw dan Anthony VO . Saya telah mengirimkan kode dalam proyek C # di Github .
Kontribusi utama saya adalah menghilangkan secara eksplisit pembuatan dan manipulasi
StringBuilder
dan alih-alih hanya bekerja denganIEnumerable
. Ini menghindari alokasi buffer yang besar di memori.}
Pendekatan ini digabungkan dengan baik dengan mengonversi
IEnumerable
ke DataTable seperti yang ditanyakan di sini .sumber
Saya juga perlu melakukan beberapa overriding data, itulah sebabnya ada beberapa pernyataan "jika lagi". Saya perlu memastikan bahwa jika bidang kosong untuk memasukkan "T / A" sebagai gantinya, atau jika bidang Tanggal diformat sebagai "01/01/1900: 00" maka itu akan disimpan sebagai "01/01/1900" sebagai gantinya.
sumber
sumber
Jika semua data masih di sel pertama, berarti aplikasi yang Anda buka file tersebut mengharapkan pembatas lain. MSExcel dapat menangani koma sebagai pembatas kecuali Anda menentukan sebaliknya.
sumber