Müşterilerden gelen CSV TEXT dosyalarını (her ne kadar CSV desem de müşteriler CSV standartlarına uymuyorlar) parse edip SQL Server üzerine aktarmak istiyorum. Dosya formatları sabit olmamakla birlikte içindeki tüm alanların text olduğunu biliyorum. Kimi müşteri 8 kolonluk dosya gönderirken kimi müşteri 3 kolonluk dosya gönderebiliyor. Yani alan sayısı sabit değil. Ben SQL server üzerine aktardıktan sonra sadece kullanıcının seçtiği alanları kullanıyorum. Gerisi işe yaramıyor.
Bu işi yapmak adına FireDAC componentları arasındaki FDBatchMove'u kullandım. Tek başına çalışmayıp okunacak dosya ve yazılacak dosya componentlarını da istiyor form üzerine. Benim durumumda bunlar FDBatchMoveTextReader ve FDBatchMoveSQLWriter oldular.
FDBatchMoveTextReader özellikleri arasında "GuessFormat" diye bir prosedür var. Bu prosedür AnalyzeSample özelliğinde belirtilen satır sayısı kadar dosyayı inceliyor ve her bir alanın veri türünü, dosyada kullanılan ayırıcı karakteri (Delimiter) tahmin etmeye çalışıyor.
Benim sorunum burada başlıyor. Ben AnalyzeSample değerini 10 yaptım çünkü tüm alanlarımın string olduğunu biliyorum. Gidip tüm dosyayı inceletmenin anlamı yok. Ancak gelen veriler içinde string alan olmasına rağmen sadece rakam veriler olabiliyor. Yani GuessFormat ilk 10 satırda da sadece rakam veri gördüğü için bu alanı integer tipinde algılıyor. Bunun önüne geçmek için ise GuessFormat çalıştırıldıktan sonra tüm tanımlanmış alanların veri türünü string olarak değiştiriyorum.
Yinede aktarım sırasında ilerleyen satırlarda text değerlere rastlayınca aktarım işlemi hata veriyor (integer alana string değer olmaz anlamına gelen bir hata tabii). Yani benim alan tipi değişikliği kodum bir sebepten işe yaramıyor.
İlgili prosedür içinden örnek kod aşağıda. Yardımcı olabilecek arkadaşlara şimdiden teşekkür ederim.
Kod: Tümünü seç
d2 := now;
Memo1.Lines.Add('Kaynak dosya analiz ediliyor...');
FDBatchMoveTextReader1.FileName := Edit1.Text;
FDBatchMove1.GuessFormat([taDelimSep, taFields]);
Memo1.Lines.Add('Süre: ' + FormatDateTime('hh:mm:ss.zzz', (now-d2)));
case ComboBox1.ItemIndex of
0: FDBatchMoveTextReader1.Encoding := ecANSI;
1: FDBatchMoveTextReader1.Encoding := ecDefault;
2: FDBatchMoveTextReader1.Encoding := ecUTF16;
3: FDBatchMoveTextReader1.Encoding := ecUTF8;
end;
d2 := now;
Memo1.Lines.Add('Alan formatları tanımlanıyor...');
for i := 0 to FDBatchMoveTextReader1.DataDef.Fields.Count-1 do begin
// Tüm alanları string olarak ayarla
FDBatchMoveTextReader1.DataDef.Fields[i].DataType := atString;
end;
Memo1.Lines.Add('Süre: ' + FormatDateTime('hh:mm:ss.zzz', (now-d2)));
d1 := now;
Memo1.Lines.Add('Veri aktarımı başlıyor: ' + FormatDateTime('hh:mm:ss.zzz', d1));
// Verileri aktar
FDBatchMove1.Execute;
d2 := now;
lblSure.Caption := FormatDateTime('hh:mm:ss.zzz', d2-d1);
Memo1.Lines.Add('Saf aktarım süresi: ' + lblSure.Caption);