Konuyu Oyla:
  • Derecelendirme: 0/5 - 0 oy
  • 1
  • 2
  • 3
  • 4
  • 5
Dataset to CSV Export
#1
Zaman zaman, çoğumuz veri tabanındaki bir tablodan bazen Excel, bazen de diğer veritabanlarına veri aktarmak zorunda kalabiliyoruz. Genelde kullanıcılar da bu tarz bir istekle bize gelebiliyor. Çoğunlukla kullanıcıların ihtiyacı, verileri Excel gibi programlara aktarıp üzerinde çalışma yapmak oluyor. Kullanıcıların bu tarz isteklerini karşılayacak bir çalışmayı paylaşmak istedim.

Aşağıda kodlarını verdiğim çalışma, bir TDataSet nesnesinden türetilmiş olan tüm DataSet mirasçısı nesnelerde rahatlıkla kullanılabilir. TUNIQuery, TUNITable, TADODataSet, TFDQuery, TCustomSQLDataSet, TSQLQuery, TVirtualTable, TVirtualQuery, TVirtualDataSet, TdxMemData, TCustomClientDataSet, TClientDataSet, TInternalSQLDataSet, TSimpleDataSet ve unuttuğum diğerleri bunlara örnek verilebilir.

Tabi bunu sağlamak için (alışkanlık oldu artık) Class Helper tekniğini kullandım, dolayısıyla (XE2 ve öncesi idi "sanırım") eski Delphi sürümlerinde (en azından bu haliyle) çalışmayabilir. Şayet öyleyse ExportToCSV prosedürünü açığa alıp , prosedür içindeki Self ifadelerini de ("aDataSet: TDataSet" gibi) bir parametreye bağlayabilirsiniz...

CSV Formatına gelecek olursak, "Comma Separated Values" kelimelerinin baş harfleri kullanılarak isimlendirilmiştir. Bu dosyalar, virgülle ayrılmış değerler içeren bir dosyadır. En üst satırında başlıklar, devamında ise metin ve sayılar içeren tablo şeklinde dökme bir veri listesi yer alır. Hücre ve satır mantığına uygundur. Hücreler virgül, noktalı virgül veya tab karakteriyle, satırlar ise #13#10 karakterleriyle birbirinden ayrılabilir. Bu dosyalar daha çok elektronik tablo verilerini bir programdan diğerine kolayca aktarmak için kullanılır. CSV dosyaları, Excel ile veya lotus 123 gibi diğer elektronik tablo programlarıyla da kullanılabilir. CSV dosyaları sadece ham veri içerdiği, hücreler arasında bir bağ kurulmadığı, grafiksel ve binary öğeleri barındırmayan bir yapısı olması nedeniyle JSON, BSON, XML gibi diğer veri aktarım türlerinden bu anlamda ayrışır.

// =============================================               
// Author: Uğur PARLAYAN
// Create Date: 2015-04-15-1530
// Description : Genel Helper Classların toplandığı birimdir...
// =============================================               


unit Helpers_Data;

interface

uses
   Data.DB                         //  TBookmarks, TDataSet
 , System.SysUtils                 //  TFileName, Format, FormatDateTime, QuotedString
 ;

type
 TStringArray = array of string;
 TStringArrayHelper = record helper for TStringArray
   public
     function Ayracli(aAyrac: String): String;
     //...
 end;
 { DATABASE }
 TDataSetHelper = class helper for TDataSet
   public
    procedure ExportToCSV(aFileName: TFileName; const aEncoding: TEncoding; aAyrac: String = ';');
    //...
 end;

implementation

uses
   System.Variants //  NULL fonksiyonu...
 , System.Classes  //  TStreamWriter
 ;

{ TStringArrayHelper }

function TStringArrayHelper.Ayracli(aAyrac: String): String;
var
 I: Integer;
begin
 for I := Low(Self) to High(Self)
  do if  (I < High(Self) )
     then Result := Result + Self[I] + aAyrac
     else Result := Result + Self[I];
end;

{ TDataSetHelper }


procedure TDataSetHelper.ExportToCSV(aFileName: TFileName; const aEncoding: TEncoding; aAyrac: String = ';');
var
 I       : Integer;         // Klasik genel sayaç değişkenimiz...
 Dosya   : TStreamWriter;   // UTF8 şeklinde BOMLU olarak kodlanacak olan dosyayı temsil eder...
 Imlec   : TBookmark;       // Kullanıcı, Datasetin hangi satırında bilgisini tutar...
 Hucre   : TStringArray;    // Sütunları, Fieldleri temsil eder...
 function TQ(aString: String): String;
 begin
   Result := format('"%s"', [aString.Trim]);
 end;
begin
 if (Self.Active = FALSE)
 or (Self.IsEmpty = TRUE) then Exit;
 Imlec := Self.Bookmark;                                         // Datasetin mevcut konumunu imleç değişkenine alıyoruz.
 Self.DisableControls;                                           // görsel senkronizasyonu devre dışı bırakıyoruz, böylece işlemler daha hızlı ilerliyor...
 Self.First;                                                     // En baştaki kayda geçiyoruz.
 try
   Dosya := TStreamWriter.Create(aFileName, False, aEncoding);   // Parametreyi "TEncoding.UTF8" olarak verirseniz dosya UTF8 şeklinde kodlanacak ve "BOMLU" olarak oluşturulacaktır...
   try
     SetLength(Hucre, Self.Fields.Count);                        // dinamik bir dizi olduğu için bellekte alan tahsisi yapıyoruz...
     for I := 0 to Self.Fields.Count - 1
     do  Hucre[I] := TQ(Self.Fields[I].FieldName);               // alan başlıklarını en tepeye çekiyoruz.
     Dosya.WriteLine( Hucre.Ayracli( aAyrac ) );                 // Alanlar dizisinin her bir hücrenin "ARASINA" noktalı virgül basıyor ve dosyamıza tek satır halinde "SÜTUN BAŞLIKLARINI" yazıyoruz...
     while not Self.Eof do begin                                 // Tüm Dataseti baştan sona tarayacağız...
           for I := 0 to Self.Fields.Count - 1 do begin          // Tüm sütunları/Alanları tek tek elden geçireceğiz...
               if (Self.Fields[I].DataType
                   in [ ftByte                                   // 8 bit tamsayı
                      , ftShortint                               // 8 bit tamsayı
                      , ftSmallint                               // 16 bit tamsayı
                      , ftWord                                   // 16 bir işaretsiz tamsayı
                      , ftInteger                                // 32 bit tamsayı
                      , ftFloat                                  // 32 bit Floating-point sayısalı
                      , ftAutoInc                                // 32 bit tamsayı
                      , ftSingle                                 // 32 bit işaretsiz tamsayı
                      , ftLongWord                               // 32 bit işaretsiz tamsayı
                      , ftCurrency                               // 80 bit Floating-point sayısalı
                      , ftBCD                                    // 80 bit // BCD = Binary Coded Decimal
                      , ftLargeint                               // 64 bit işaretsiz tamsayı
                      , ftExtended                               // 80 bit
                    //, ftFMTBcd                                 // String gibi işlenir...
                      ])
               then Dosya.Write( Self.Fields[I].AsString )       // Sayısal verileri tırnak içine almadan yazıyoruz
               else begin
                    if (Self.Fields[I].IsBlob = TRUE)
                    then Dosya.Write( TQ('') )                       // CSV formatı blob / binary dataları desteklemez...
                    else Dosya.Write( TQ(Self.Fields[I].AsString) );  // Metinsel ifadeler ve formatlı veriler tırnak içine alınmak zorunda (CSV formatı gereği...)
               end;

               if  (I < Self.FieldCount - 1)
               then Dosya.Write( aAyrac )                        // Hücrelerin arasını açıyoruz
               else Dosya.WriteLine;                             // Yeni bir satıra geçiyoruz...
           end;
           Self.Next;                                            // Sonraki recorda geçiyoruz
     end;
   finally
     FreeAndNil(Dosya);                                          // Nihayetinde Çöpümüzü temizledik...
   end;
 finally
   if (Self.BookmarkValid(Imlec) = TRUE) then Self.GotoBookmark(Imlec); // Nihayetinde Datasetteki satır pozisyonumuzu ilk bulduğumuz yere geri çektik...
   Self.EnableControls;                                         // Nihayetinde Görsel Senkronizasyonu yeniden açtık
 end;
end;

end.

Kullanımı da şu şekildedir;

uses Helpers_Data;

//...

DataSet.ExportToCSV ( 'C:\EXPORTS\TEST.CSV', TEncoding.UTF8, ';' );

UTF8 kodlamasını kullanarak arap, kiril, japon alfabesi gibi farklı karakter kodlarına sahip veri tipleri de düzgün aktarılmış olacaktır.
YouTube Delphi Tips
"Yaşlanarak değil, yaşayarak tecrübe kazanılır. Zaman insanları değil, armutları olgunlaştırır" Peyami Safa
WWW
Cevapla
#2
Paylaşım için teşekkürler. Emeğinize sağlık.
There's no place like 127.0.0.1
WWW
Cevapla
#3
(29-08-2017, Saat: 14:09)uparlayan Adlı Kullanıcıdan Alıntı: Zaman zaman, çoğumuz veri tabanındaki bir tablodan bazen Excel, bazen de diğer veritabanlarına veri aktarmak zorunda kalabiliyoruz. Genelde kullanıcılar da bu tarz bir istekle bize gelebiliyor. Çoğunlukla kullanıcıların ihtiyacı, verileri Excel gibi programlara aktarıp üzerinde çalışma yapmak oluyor. Kullanıcıların bu tarz isteklerini karşılayacak bir çalışmayı paylaşmak istedim.

Aşağıda kodlarını verdiğim çalışma, bir TDataSet nesnesinden türetilmiş olan tüm DataSet mirasçısı nesnelerde rahatlıkla kullanılabilir. TUNIQuery, TUNITable, TADODataSet, TFDQuery, TCustomSQLDataSet, TSQLQuery, TVirtualTable, TVirtualQuery, TVirtualDataSet, TdxMemData, TCustomClientDataSet, TClientDataSet, TInternalSQLDataSet, TSimpleDataSet ve unuttuğum diğerleri bunlara örnek verilebilir.

Tabi bunu sağlamak için (alışkanlık oldu artık) Class Helper tekniğini kullandım, dolayısıyla (XE2 ve öncesi idi "sanırım") eski Delphi sürümlerinde (en azından bu haliyle) çalışmayabilir. Şayet öyleyse ExportToCSV prosedürünü açığa alıp , prosedür içindeki Self ifadelerini de ("aDataSet: TDataSet" gibi) bir parametreye bağlayabilirsiniz...

CSV Formatına gelecek olursak, "Comma Separated Values" kelimelerinin baş harfleri kullanılarak isimlendirilmiştir. Bu dosyalar, virgülle ayrılmış değerler içeren bir dosyadır. En üst satırında başlıklar, devamında ise metin ve sayılar içeren tablo şeklinde dökme bir veri listesi yer alır. Hücre ve satır mantığına uygundur. Hücreler virgül, noktalı virgül veya tab karakteriyle, satırlar ise #13#10 karakterleriyle birbirinden ayrılabilir. Bu dosyalar daha çok elektronik tablo verilerini bir programdan diğerine kolayca aktarmak için kullanılır. CSV dosyaları, Excel ile veya lotus 123 gibi diğer elektronik tablo programlarıyla da kullanılabilir. CSV dosyaları sadece ham veri içerdiği, hücreler arasında bir bağ kurulmadığı, grafiksel ve binary öğeleri barındırmayan bir yapısı olması nedeniyle JSON, BSON, XML gibi diğer veri aktarım türlerinden bu anlamda ayrışır.

// =============================================               
// Author: Uğur PARLAYAN
// Create Date: 2015-04-15-1530
// Description : Genel Helper Classların toplandığı birimdir...
// =============================================               


unit Helpers_Data;

interface

uses
   Data.DB                         //  TBookmarks, TDataSet
 , System.SysUtils                 //  TFileName, Format, FormatDateTime, QuotedString
 ;

type
 TStringArray = array of string;
 TStringArrayHelper = record helper for TStringArray
   public
     function Ayracli(aAyrac: String): String;
     //...
 end;
 { DATABASE }
 TDataSetHelper = class helper for TDataSet
   public
    procedure ExportToCSV(aFileName: TFileName; const aEncoding: TEncoding; aAyrac: String = ';');
    //...
 end;

implementation

uses
   System.Variants //  NULL fonksiyonu...
 , System.Classes  //  TStreamWriter
 ;

{ TStringArrayHelper }

function TStringArrayHelper.Ayracli(aAyrac: String): String;
var
 I: Integer;
begin
 for I := Low(Self) to High(Self)
  do if  (I < High(Self) )
     then Result := Result + Self[I] + aAyrac
     else Result := Result + Self[I];
end;

{ TDataSetHelper }


procedure TDataSetHelper.ExportToCSV(aFileName: TFileName; const aEncoding: TEncoding; aAyrac: String = ';');
var
 I       : Integer;         // Klasik genel sayaç değişkenimiz...
 Dosya   : TStreamWriter;   // UTF8 şeklinde BOMLU olarak kodlanacak olan dosyayı temsil eder...
 Imlec   : TBookmark;       // Kullanıcı, Datasetin hangi satırında bilgisini tutar...
 Hucre   : TStringArray;    // Sütunları, Fieldleri temsil eder...
 function TQ(aString: String): String;
 begin
   Result := format('"%s"', [aString.Trim]);
 end;
begin
 if (Self.Active = FALSE)
 or (Self.IsEmpty = TRUE) then Exit;
 Imlec := Self.Bookmark;                                         // Datasetin mevcut konumunu imleç değişkenine alıyoruz.
 Self.DisableControls;                                           // görsel senkronizasyonu devre dışı bırakıyoruz, böylece işlemler daha hızlı ilerliyor...
 Self.First;                                                     // En baştaki kayda geçiyoruz.
 try
   Dosya := TStreamWriter.Create(aFileName, False, aEncoding);   // Parametreyi "TEncoding.UTF8" olarak verirseniz dosya UTF8 şeklinde kodlanacak ve "BOMLU" olarak oluşturulacaktır...
   try
     SetLength(Hucre, Self.Fields.Count);                        // dinamik bir dizi olduğu için bellekte alan tahsisi yapıyoruz...
     for I := 0 to Self.Fields.Count - 1
     do  Hucre[I] := TQ(Self.Fields[I].FieldName);               // alan başlıklarını en tepeye çekiyoruz.
     Dosya.WriteLine( Hucre.Ayracli( aAyrac ) );                 // Alanlar dizisinin her bir hücrenin "ARASINA" noktalı virgül basıyor ve dosyamıza tek satır halinde "SÜTUN BAŞLIKLARINI" yazıyoruz...
     while not Self.Eof do begin                                 // Tüm Dataseti baştan sona tarayacağız...
           for I := 0 to Self.Fields.Count - 1 do begin          // Tüm sütunları/Alanları tek tek elden geçireceğiz...
               if (Self.Fields[I].DataType
                   in [ ftByte                                   // 8 bit tamsayı
                      , ftShortint                               // 8 bit tamsayı
                      , ftSmallint                               // 16 bit tamsayı
                      , ftWord                                   // 16 bir işaretsiz tamsayı
                      , ftInteger                                // 32 bit tamsayı
                      , ftFloat                                  // 32 bit Floating-point sayısalı
                      , ftAutoInc                                // 32 bit tamsayı
                      , ftSingle                                 // 32 bit işaretsiz tamsayı
                      , ftLongWord                               // 32 bit işaretsiz tamsayı
                      , ftCurrency                               // 80 bit Floating-point sayısalı
                      , ftBCD                                    // 80 bit // BCD = Binary Coded Decimal
                      , ftLargeint                               // 64 bit işaretsiz tamsayı
                      , ftExtended                               // 80 bit
                    //, ftFMTBcd                                 // String gibi işlenir...
                      ])
               then Dosya.Write( Self.Fields[I].AsString )       // Sayısal verileri tırnak içine almadan yazıyoruz
               else begin
                    if (Self.Fields[I].IsBlob = TRUE)
                    then Dosya.Write( TQ('') )                       // CSV formatı blob / binary dataları desteklemez...
                    else Dosya.Write( TQ(Self.Fields[I].AsString) );  // Metinsel ifadeler ve formatlı veriler tırnak içine alınmak zorunda (CSV formatı gereği...)
               end;

               if  (I < Self.FieldCount - 1)
               then Dosya.Write( aAyrac )                        // Hücrelerin arasını açıyoruz
               else Dosya.WriteLine;                             // Yeni bir satıra geçiyoruz...
           end;
           Self.Next;                                            // Sonraki recorda geçiyoruz
     end;
   finally
     FreeAndNil(Dosya);                                          // Nihayetinde Çöpümüzü temizledik...
   end;
 finally
   if (Self.BookmarkValid(Imlec) = TRUE) then Self.GotoBookmark(Imlec); // Nihayetinde Datasetteki satır pozisyonumuzu ilk bulduğumuz yere geri çektik...
   Self.EnableControls;                                         // Nihayetinde Görsel Senkronizasyonu yeniden açtık
 end;
end;

end.

Kullanımı da şu şekildedir;

uses Helpers_Data;

//...

DataSet.ExportToCSV ( 'C:\EXPORTS\TEST.CSV', TEncoding.UTF8, ';' );

UTF8 kodlamasını kullanarak arap, kiril, japon alfabesi gibi farklı karakter kodlarına sahip veri tipleri de düzgün aktarılmış olacaktır.

 Paylaşım için teşekkürler!
kisisel_logo_dark.png
WWW
Cevapla
#4
Rica ederim, teşekkürler Arkadaşlar,

Makale ile ilişkisi olduğu için Embarcadero / Community'de yayınlanan şu linki de paylaşmakta fayda görüyorum. Konu CSV dosyasının bir TFDMemTable nesnesine uyumlu JSON dosyasına nasıl dönüştürüleceğine dair kodlar içeriyor.

https://community.embarcadero.com/blogs/...um=twitter

Bu linkteki C++ Kodlarında CSV dosyasının TFDMemTable biçimindeki JSON dosyasına nasıl dönüştürüleceğine dair bir kod paylaşılmış. Farklı uygulamalardan üretilmiş olan CSV dosyalarının bir dataset yapısında nasıl import edilebileceği ile ilgili bir fikir verebilir düşüncesindeyim...

Konu ile ilgili kaynak kodlara da aşağıdaki linkten ulaşılabilir;

https://github.com/mojeld/csvfstream_to_TFDMemTable
YouTube Delphi Tips
"Yaşlanarak değil, yaşayarak tecrübe kazanılır. Zaman insanları değil, armutları olgunlaştırır" Peyami Safa
WWW
Cevapla
#5
Merhaba,
Makalenizi tamamlar nitelikte bir paylaşımım olmuştu. Excel Belgesini FireDAC ile JSON Formatına Dönüştürme
Cevapla
#6
(05-09-2017, Saat: 11:24)Fesih ARSLAN Adlı Kullanıcıdan Alıntı: Merhaba,
Makalenizi tamamlar nitelikte bir paylaşımım olmuştu. Excel Belgesini FireDAC ile JSON Formatına Dönüştürme

Çok güzel bir paylaşım. Teşekkürler.
YouTube Delphi Tips
"Yaşlanarak değil, yaşayarak tecrübe kazanılır. Zaman insanları değil, armutları olgunlaştırır" Peyami Safa
WWW
Cevapla
#7
(05-09-2017, Saat: 10:24)uparlayan Adlı Kullanıcıdan Alıntı: Rica ederim, teşekkürler Arkadaşlar,

Makale ile ilişkisi olduğu için Embarcadero / Community'de yayınlanan şu linki de paylaşmakta fayda görüyorum. Konu CSV dosyasının bir TFDMemTable nesnesine uyumlu JSON dosyasına nasıl dönüştürüleceğine dair kodlar içeriyor.

https://community.embarcadero.com/blogs/...um=twitter

Bu linkteki C++ Kodlarında CSV dosyasının TFDMemTable biçimindeki JSON dosyasına nasıl dönüştürüleceğine dair bir kod paylaşılmış. Farklı uygulamalardan üretilmiş olan CSV dosyalarının bir dataset yapısında nasıl import edilebileceği ile ilgili bir fikir verebilir düşüncesindeyim...

Konu ile ilgili kaynak kodlara da aşağıdaki linkten ulaşılabilir;

https://github.com/mojeld/csvfstream_to_TFDMemTable
Konuyla doğrudan ilgisi yok fakat emb sitesinde ki cpp kodunda gördüğüm kadarıyla tokyo'da Cpp11 standardı desteği gelmiş.
WWW
Cevapla




Konuyu Okuyanlar: 1 Ziyaretçi