1

Konu: Yeni başlayanlar ve Foxpro 2.x'ten geçenler için VFP

Uzun zamandır yapmayı düşündüğüm birşey VFP'nin temelini gösterip yeni kullanıcıları hızla ısındıracak bir yazı serisiydi. Umarım bu yazı serisini düzemli olarak yürütüp bir yerler getirebilirim.
Şimdilik kafamdaki, hergün yeni birşeyleri bu başlık altında mesaj olarak aktarmak. Screencast,webcast işleri yapmayı da düşündüm ancak ücretsiz kayıt programları pek iyi değil (benim bulduklarım). Beğendiklerimi de en azından şimdilik alamam.
Bu ilk mesaj, önsöz niteliğinde. Bazı şeyleri baştan açıkça belirteyim, isteyen okur isteyen pas geçer:
Yazıyı yazdığım makineye göre Türkçe harfleri kullanmayabilirim (işte kullandığım makinenin tüm ayarları İngilizce-ABD). Bu makinede yazarken yazma hızım otomatikman düşüyor:(
Yazılarda bolca İngilizce terim görebilirsiniz. Bu konuda beni eleştirmeyin. Hatta bazı kod örneklerinin açıklamaları bile İngilizce olabilir (seneler içinde birikmiş test kodlarım - oturup açıklmaları değiştirmek zor).

VFP'de birşeyi yapmanın (eğer bir yolu varsa) hemen hemen her zaman en az 3 yolu vardır denir. Genelde aklımdaki en aktif yolları göstermeye çalışmakla birlikte, benim bilidiğim en iyi yol olmayabilir, bazen fazla detaya girebilirim ya da kısa kesebilirim vs. Birşeyi yapmayın, olmaz, yasak, tehlikeli dediğim zaman bir nedeni vardır. Bazen nedenini açıkça örnekle gösterebilirim, bazen de örneklemek ya çok zordur ya da ne bileyim uygun anlaşılır örneği bulmak zor, zaman alıcıdır. Bu gibi şeyler için okuyanlardan tek ricam, fazla sorgulayıcı olmayın. Şimdiden toptan cevap, "yılların birikimi". Versiyonlar arası değişiklikler nedeniyle bazen söylediğim pek geçerli de olmayacak. Ancak onun geçersiz olduğunu farkedebiliyor, ya da beni yalancı çıkarabiliyorsanız zaten bence bu yazıları da okumaya ihtiyacınız olmayacak kadar ilerlemişsiniz, ne yaptığınızı benden iyi biliyorsunuz demektir.

Tartışmalara her zaman açığım (ama teknik konuda değilse, açıkçası bana uymaz ve en kısa sürede kapatma yanlısıyım). UniversalThread.com gibi yerlerde zaten katılıyorum teknik tartışmalara ve bazen milisaniyeler düzeyindeki farklılıklar yaratacak kod örneklerine bile girdiğimiz oluyor. Bu tip tartışmalar daha çok "akademik" tartışmalar. Burada aklıma gelmişken söyleyeyim:
Daha kısa kod, daha hızlı, efektif kod olacak diye bir kanun yok.  Bazen uzun ve karmaşık görünen kod kısa versiyonlarından çok daha hızlı çalışabilir.

Bir işe başladık hadi hayırlısı.

2

Re: Yeni başlayanlar ve Foxpro 2.x'ten geçenler için VFP

başarılar dilerim
saygılarımla

3

Re: Yeni başlayanlar ve Foxpro 2.x'ten geçenler için VFP

Hocam tebriklerimi sunar , yazilarin icin simdiden kolaylıklar dilerim. Yeni başlayanından belli bir asamaya gelmis herkesin faydalanacagi cok degerli ornekler metodlar ogrenecegiz senden.
Tekrar tesekkurler,sabırsızlıkla bekliyoruz yazilari daha sonra ben onlari dokuman bolumune almak yada .chm tarzı bir dosyada toplamaya calisirim birlikte bir turkce VFP e-book yaratmis oluruz smile

Hadi hayırlısı...

4

Re: Yeni başlayanlar ve Foxpro 2.x'ten geçenler için VFP

Konuyla ilgili göndereceğin her bir mesajı heyecanla bekliyor olacağız.  Başarlar dilerim.

Ali Altun

5

Re: Yeni başlayanlar ve Foxpro 2.x'ten geçenler için VFP

Sevgili Çetin. Bu mesaja eklenecek "Ağzından salyalar akan Smiley" olsaydı hiç düşünmez eklerdim. Ama yok. Sabrına, harcadığın emeğe, gösterdiğin ilgiye teşekkürler. Bir gün bir fırıncının kızıyla evlenir ve 40 fırın ekmek yersem vfp konusunda seninle tartışmaya girerim.

6

Re: Yeni başlayanlar ve Foxpro 2.x'ten geçenler için VFP

bu bölüm benim bölümüm galiba vfp ue yeni geçmeyi düşünüyorum burasıda benim mekanım olacak galiba.
sağol hocam.
yazılarını hasretle bekliyorum

7

Re: Yeni başlayanlar ve Foxpro 2.x'ten geçenler için VFP

Giris notu:
Bazen kod orneklerinin ustune *'lar koyacagim. Bu yildizlarin sayisi cok ise, kod bir ise yaramazmis gibi gorunse de, ya da anlasilmaz, dogrudan pas gecmeyin. Bol yildizin anlami "baktiginiz sey cam gibi gorunse de elmas" demek:)
Soylediklerim genelde pratikte yapilacak seyler olacak, (resmi tanimlamalara uymak zorunda kalmadan - resmi tanimlamaya aykiri bile olabilir). Kisa olarak gectigim seyler ileride bir sekilde nasil olsa detaylanacak, orneklenecek. Her programcinin aklinda da bir an once teori yerine calisan birseyler gormek vardir, ondan girisler kisa:)

1) Database, table, view, cursor.
VFP ilk atasi foxbase'den beri 'data'ya yonelik bir dil. Bu nedenle ilk konu ilarak onu sectim. Tum detaylarina girmem imkansiz ama basitce soyle.

Table: (Tipik olarak .DBF uzantilidirlar).
Fox2x'ten gelenler icin not: Database = table ve VFP'de Database artik farkli birsey. 

Her turlu listenin diskteki sekli. Kolonlari (field) ve satirlari (record, row) var. Excel tablosu gibi. Temel fark her lolonun tutabilecegi datanin belli bir tipi var. O tipten olmayan bir veriyi o kolonda saklayamazsiniz (excelde boyle bir kisitlama yok - zaten, sakin bir zamanlar buyuk sirketlerin yaptigi gibi, Excel'i database sistemlerinin yerine koymaya kalkmayin).
Ornek:

Ad,Soyad,TelefonNo,DogumTarihi

kolonlari olsun. Ad ve Soyad tipik olarak karakter (char). TelefonNo sadece rakamlari icerse de yine karakter. Cunku telefonNo ile matematiksel islemler yapilmiyor. DogumTarihi ise tarih (date) tipinde.
Boyle bir tabloda DogumTarihi alanina daima bir tarih koymaniz ya da bos birakmaniz gerekiyor. "Ocak 1921" gibi bir not dusemezsiniz.

Ipucu: Tarih tipindeki alanlariniz "NULL" kabul etsin. Nedeni de VFP disinda hicbir database sisteminin "bos" tarih kavrami yok. Baska sistemlere aktarmaniz gerektidiginde sorun yasamazsiniz.

Cursor: Table ile ayni. Birden fazla tipi var (ileride anlatilacak). Temel olarak tek fark diske yazilmazlar (gercekte ne zaman nasil yazildiklari ayri konu - pratik olrak yazilmazlar diye bilin, farkta bir tane degil zamanla digerlerini soylecegim ama temelde boyle), memoryde tutulur ve kapandiginda gider.

View: Kullanici acisindan table/cursor gibidirler. Aslinda sadece bir dizi tanimlamayi tutarlar, kullanim sirasinda cursor olarak var olurlar.

Database: Database'ler aslinda kendileri bir tablodur. Databaselere yonelik bir dizi komut ve fonksiyon sadece bu ozel tip tablolarla calisir. Biribiriyle ilgili bir dizi table'i, view'i bu tablolar icin gerekli olan prosedurleri, eventleri, tanimlamalari  vs tutan bir "container" olarak calisirlar.


Not: Tablolar bir database'de yer almak zorunda degildir. Database'e bagli olmayan tablolara "FREE" tablolar denir. Foxpro 2.x tipi tablolarin hepsi bu gruptadir (yapilari farkli olsa da sizin icin onemi olmayabilir - foxpro2x tablolarini VFP'de kullaniyorsaniz yedekli calisin baslangicta. Herseyi yedekli calisin da bir test sirasinda birseyler ters giderse benden bilmeyin:).

Foxpro'da bircok sey aslinda tablolarda tutulmaktadir eskiden beri.
Formlar (fox2x'te screen) .scx,
Menuler .mnx
Classlar .vcx
Raporlar .frx
vs uzantili tablolarda tutulurlar. Isin guzel tarafi bu dosyalar ilgili komutlariyla dogrudan gorsel olarak dizayn ortaminda acilabildigi gibi tamamen kodlada yaratilabilen, degistirilebilen seylerdir. Database'de .dbc uzantili dosyalarda tutulur ve:

Modify Database databaseadi

komutuyla gorsel olarak dizayn edilebilir.

Bu kadar giris yeter simdilik. Tablolariniz icin bir iki kural (genelde benimsenmis olanlar + benim kisisel kurallarim):

-Mutlaka her tablonuzun bir "Primary Key" - PK fieldi olsun. Bu field kullanicilari ilgilendirmeyen ve onlarin asla gormeleri bile gerekmeyen bir fielddir. Bu alanda o tabloda yalnizca tek bir satirda bulunabilecek (unique) degerler tutulur. Amaci vatandaslik kimlik no gibi (tamam onu beceremediler ama becerdiklerini varsayin) her satirin bir kimlik degeri olmasi ve bu kimlik degeriyle bulunabilmesi (satir etiketi gibi).
Bu field'i tablonun adinin tekil sekli + ID olarak ismlendirmekte fayda var. Ornek:
Tablo: Musteriler (bir tablo bircok musteriyi tuttugu icin isimlendirme cogul)
PK field adi: MusteriID

Bu fieldin data tipi tartisma konusu. Genelde kullanilan (VFP,SQL server, Access, Oracle ...) integer (32 bit tam sayi). VFP9 (8miydi acaba)'dan beri AutoInc diye bir ozellik var. Bu ozellik istediginiz integer alanlara kurulabiliyor ve VFP tarafindan otomatik olarak arttirilan bir sayi saglaniyor (SQL server'daki IDENTITY).
Benim tavsiyem integer kullanmayin ve autoinc'i hic kullanmayin (bu arada ben kullandim ve hala kullaniyorum ama benden once kullanilmaya baslamisti ve hala soyleniyorum niye bunu kullaniyoruz diye). Bence ideal data tipi 38 uzunlugunda karakter. 38 tabii gokten zembille inen bir deger degil.
GUID - Globally Unique IDentifer. Bu bir standard. Versiyonlari gelisiyor ve sanirim su anda 4. versiyonunda. GUID degeri, dunyanin neresinde olursa olsun, bir makinenin olusturabilecegi (network'e bagli olmasa bile) ve bir baska esinin olamayacagi garanti edilen 128 bitlik bir sayi. Tarih/saat/makinenin network karti versiyona gore isin icinde olabilir ya da olmayabilir. Onlarin yanisira bir rastgele sayi ve kaynak degeri var isin icinde ve sonunda benzeri olmadigi "pratik"te kabul edilen sayilar olusuyor. Teorikte cakisma olasiligi sonlu bir deger oldugu icin var ancak "iki yildizin birbiriyle carpisma olasiligi" gibisinden olasilik olarak kabul ediliyor.
Her neyse, 128bits = 16 bytes. Bu kullanabilecegiz en kucuk uzunluk bu alan icin. Yani character 16 bir alanda tutulma imkani var (char binary). Byte degerlerini dogrudan tutarsaniz karsilasabileceginiz bazi problemler:
-Dosya bozulmaya daha acik (ozellikle tablonun ilk alani ise ve genelde PK'lar ilk alandir)
-SQL server'a cevrim. Arada kod yazmaniz gerekecek.
-Test sirasinda kullanmak isterseniz takibi zor.
gibi.

Bu 16 bytes, insanlar tarfindan rahat okunan hex formata cevrildiginde 16*2 = 32 oluyor. GUID degerlerinin standard gosterimi:

{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}

seklinde. Aradaki tireler ve {} nedeniyle toplam uzunluk 38. {}'leri atip 36'lik alanda kullanabilirsiniz (SQL server dogrudan anlar her iki formu da).

Bu arada kafasindan israrla sys(2015) gecenler unutsun:)

GUID uretmek icin basit bir kod:

Visual Fox Pro
* Dunyada bir esi benzeri olmayan degerler uretmek icin

* Not: Binlerce uretmek gerektiginde kod optimize degil
* O takdirde "Declare" satirlarini ayirip bir kez cagirin
 
Function getGUID
  Declare Integer UuidCreate In 'RPCRT4.dll' String @pguid
  Declare Integer StringFromGUID2 In 'Ole32.dll' ;
    string rguid, String @lpsz, Integer cchMax
 
  Local pGUID,rGUID
  pGUID=Replicate(Chr(0),16)
  rGUID=Replicate(Chr(0),80)
  UuidCreate(@pGUID)
  StringFromGUID2(pGUID,@rGUID,40)
  Return Strconv(Left(rGUID,76),6)
Endfunc

Yukaridaki kodu test eden kod:

Visual Fox Pro
CREATE CURSOR test (testID c(38))

LOCAL ix
FOR ix = 1 TO 10
INSERT INTO test VALUES ( getGUID() )
ENDFOR
browse

Yukaridaki fonksiyonu database'inize "stored procedure" olarak ekleyin. ID alanlarinin "default" degerine:
getGUID()
yazin. Artik o tablonuz her yeni kayitta otomatikman unique bir degeri atayacak (eger siz vermediyseniz). Kodla test etmek isterseniz:

Visual Fox Pro
CREATE CURSOR test (testID c(38) DEFAULT getGUID())

LOCAL ix
FOR ix = 1 TO 10
INSERT INTO test VALUES ( getGUID() )
ENDFOR
browse
 
Function getGUID
  Declare Integer UuidCreate In 'RPCRT4.dll' String @pguid
  Declare Integer StringFromGUID2 In 'Ole32.dll' ;
    string rguid, String @lpsz, Integer cchMax
 
  Local pGUID,rGUID
  pGUID=Replicate(Chr(0),16)
  rGUID=Replicate(Chr(0),80)
  UuidCreate(@pGUID)
  StringFromGUID2(pGUID,@rGUID,40)
  Return Strconv(Left(rGUID,76),6)
Endfunc

10 tane degerle baliyor. Ctrl+Y ile yeni kayitlar eklendikce otomatik degerleri goreceksiniz.

GUID'in dezavantaji yok mu? Tabii ki var, ancak avantajlari agir basiyor.

-Tablolarinizda aramalarin en fazla yapilacagi alanlari indexleyin, ancak isin suyunu cikarip her alani indexlemeyin. Aleyhinize calismaya baslar.

-Tablolarinizda gereginden fazla kolon yaratmayin.
-Asla "general" data tipini kullanmayin.
-Collate Turkish ile indexlemeyin.
-Alan adlarinda Turkce harfleri kullanmayin (ve diger ad vermeniz gereken yerlerde - calismaz demiyorum ama kullanmayin).

8

Re: Yeni başlayanlar ve Foxpro 2.x'ten geçenler için VFP

2) OOP, Obje, değişkenler.
OOP (Object Oriented Programming-Nesneye Yönelik Programlama) fox2x'ten geçerken en çok kafa karıştıran şey. OOP hakkında birçok harika kitap açıklamalar var. Ben kolay anlaşılması için hiç formal tanımlamalarına girmeden anlatmaya çalışayım:

Obje bir değişken. Diğer değişkenlerden farkı kendi üzerinde hem veri (property) taşıyabiliyor hem davranış kodları (metod) bulundurabiliyor hem de ortamdaki etkilere tepki (event) verebiliyor.

Class ve obje: Class objenin kağıt üstündeki planı gibi. PropertyEventMetod (PEM) classta tanımlanıp kodlanıyor. Classtan yaratılan yeni bir class ise subclass (classlar ve subclasslar dizayndaki halleri). Runtime'da class instance'lar obje adını alıyor:
TextBox bir class.
Form üzerinde subclass
Runtime'da obje (class intance, object instance, object variable)

Classlar inheritance (kalıtım), encapsulation (enkapsulasyon-kendi datasına erişimi kontrol edip saklaması), polymorphism (değişik şekiller alabilme) gibi özelliklere sahip.

Öncelikle VFP'de yeni bir class yaratamazsınız. Ancak subclass yaratırsınız (yarattıgınız her class aslında bir subclass ve var olan bir classtan yaratılmak zorunda). Örneklemek gerekirse:
C# kodu:

class test {}

class test2: test {}


C#'ta dogrudan test diye bir class yaratabiliyorsunuz. test2 ise test'den yaratılan bir subclass. VFP'de ancak ikincisi mümkün.

Visual Fox Pro
define class test

enddefine

Geçersiz.

Visual Fox Pro
define class test as [i]mevcutBirClass[/i]

enddefine

Geçerli.

Bu nedenle VFP'de genelde class/subclass aynı anlamda kullanılabiliyor. Classların yaratıldığı zaten mevcut olan classlar VFP ile birlikte install ediliyor ve bunlara "BaseClass" deniyor. Versiyon yükseldikçe göre mevcut baseClass'lar artıyor. Textbox, CheckBox, Form vs hepsi birer BaseClass.
BaseClass'ların halihazırda built-in denen PEM'leri var. Örneğin birçok classta "Click" event var. Baktığınızda kodu yok gibi ve "Default" diyor. Aslında kodları var ve onlardan form üzerindeki bir tanesine (obje hali) kilklediğinizde ne yapacağını biliyor ( text imleçi oraya konumlandırmak gibi ).

Şimdi hemen biraz fox2x ile karşılaştırıp geçişi hızlandıralım:)

v1 ve v2 gibi iki değişken düşünün.

v1 = 1 && yeni başlayanlar: = assignment, atama operatorü olarak çalışıyor burada
v2 = m.v1

v1 ve v2 şu anda 1 değerini taşıyor. Bu basit bir data tipi ve "value type" - "değer tipi"

v1 = 2

v1 değerinin değişmesi v2'yi etkilemiyor.
? m.v1, m.v2 && 2 ve 1

Objeler için bir değişken demiştik. Ancak objeler "referans" tipidir ve karmaşık data tiplerini taşıyabilirler.

o1 = createobject("line") && objeler bir classtan gelmek zorunda
o2 = m.o1

v1 ve v2'nin aksine o1 ve o2 aynı şey. İkisi de memoryde aynı karmaşık data tipinin adresine işaret ediyor.

Aynı şey olduğunu görmek için datasını değiştirelim:

Visual Fox Pro
o1 = createobject("line")

o2 = m.o1
o1.Name = "buO1"
? o1.Name, o2.Name


İpucu: Eski versiyonlarda if ( o1 = o2 )
şeklinde iki objenin aynı olup olmadığının testi yapılamıyordu.
CompObj( o1, o2 )
ile iki objenin aynı özelliklere sahip olup olmadığı kontrol ediliyordu (ancak özellikleri aynı demek o iki obje aynı şey demek değil. O zaman kullanılan yöntem yukarıdaki gibi birinin bir özelliğini (ki genelde Name) değiştirip diğerininkine bakmaktı (objeler aynı ise o da değişecek).


Visual Fox Pro
o1 = CREATEOBJECT("line")

o2 = CREATEOBJECT("line")
? COMPOBJ(o1, o2) && .T. - Tüm PEM'leri aynı şu anda
? o1 = o2 && .F.
o1.Name = "buO1"
? o1.Name, o2.Name
? COMPOBJ(o1, o2) && .F.

Fox2x'ten gelen arakadaşlar dikkat etsin, array ya da başka bir basit değişken referansla bir fonksiyona gönderilse:

dimension NewArray[5,2]
NewArray = aRefArray && aRefArray ne olursa olsun
&& sadece ilk elemanın değeri tüm NewArray elemanlarına atandı
veya:
NewVar = refVar

ile hala sadece "değer" ataması var.

Değişken tipleri:
Public,private,local

İşinizi kolaylaştırmak için hemen söyleyeyim VFPde yalnızca bir tek değişken tipi var, o da local. Bunun anlamı diğerleri dilde var ve destekleniyor ama yokmuş gibi davranın. Özel durumlarda public ve private kullaniliyor ancak ilerde yeri geldiğinde konuşuruz.
Tabii fox2x'ten ilk kez gelenler şu anda şaşırmış durumda. Private olmadan nasıl olur. Onun için hemen "scope" konusuna girelim.

Variable scope - değişkenlerin görülme alanı:
Bu konuda aslında değişiklik olmadı. Hala fox2x'teki gibi scope'lar.

Visual Fox Pro
CLEAR

ON ERROR ? LINENO(),"|",MESSAGE(1),"|",MESSAGE(),"|",PROGRAM()
v1 = 1 && 1 atandi
do prosedur1 && prosedur1 çağrıldı. Prosedur1 v1'i görüyor
? "Main",m.v1 && prosedur1 tarafından değiştirildi
? "Main",m.v2 && v2 prosedur2'de tanımlandı ve o sona erdiği an scope'ta değil. Gitti.
ON ERROR
 
procedure prosedur1
private v2 && v2'yi buradan itibaren çağrılan fonkiyon/prosedurler görüyor
v1 = 2 && v1 değiştirildi
v2 = 3
DO prosedur2
 
PROCEDURE prosedur2
? "P2",m.v1,m.v2 && scope'talar
PRIVATE v1 && yukarıdan gelen v1 saklandı (hidden) - yokmuş gibi artık
? "P2",m.v1 && hata
v1 = 4 && private,local,public olarak tanımlanmamış değişkenler
&& otomatikman private oluyor atama ile
? "P2",m.v1 && private v1

Bu yukarıdan-aşağı akan ve geri dönen "prosedural" kod.

Object metodları:
Bir objenin metodu çalışıp bittiğinde sanki objeden önceki koda geri dönmüş gibi. Orada tanımlı değişkenler artık memory'den atılıyor, ,scope'ları sona eriyor. Bir başka metodda o değişkenin değerini almaya kalkarsanız hata.

do form birForm && bir form çalıştı

Çalışan formun "init" kodunda varsayın ki:

private v1
v1 = 1
var. Do form ile ilk önce (pratik olarak-öncesinde çalışanlar önemsiz şimdi) bu kod çalıştı.

Init kodu bittiği an v1 gider. Form içinde bir buton'un click kodu:

messagebox( m.v1 )


ise o buton kilklendiğinde hata - Variable v1 not found. Çünkü v1 uçtu gitti.


Kod fox2x tarzı prosedural olarak şuna benziyor:

Visual Fox Pro
do FormInıt

do FormButtonClick
 
procedure FormInit
private v1
v1 = 1
 
Procedure FormButtonClick
messagebox( m.v1 )

Biraz farklı yazsaydık o zaman hatasız çalışırdı:

Visual Fox Pro
private v1

v1 = 1
do form birForm

v1 form öncesi tanımlandığı için artık formun içindeki buton'un "click" kodunun da görüntü alanında.

Form "do form" ile de çalışsa, oForm = createobject(...) yoluyla da çalışsa üç aşağı beş yukarı işleyiş aynı. Peki o zaman doğru yol bu mu? Hayır! Nedeni de ilk prosedural kod örneğini hatırlayın: V1 değerini prosedur1 içinde değiştirdik. Şimdi de form init kodunda ya da başka bir metod/evet kodunda değiştirebilirdik. Buton da kilklendiğinde bu yeni değiştirlmiş değeri verirdi. ANCAK başa dönerseniz objeler de bir değişken. Değişken oldukları için herhangi bir zamanda o değişkenden N tane yaratılabilir.

Visual Fox Pro
private v1

v1 = 1
do form birForm
do form birForm
do form birForm

Memory'de birbirinden bağımsız 3 değişken ve hepsi de birbirinden bağımsız V1 değerini değiştirebiliyor. En son Form 3'de değiştirip 5 yaptıysak (form1,from2 ve form3'ün) butonlarını kliklediğimizde hepsinden 5 değerini alacaktık. Oysa temelde istediğimiz her formun bu tip değişkenlerinin kendine özgü olması.

Burada devreye property'ler giriyor. Bir objenin propertyleri o objenin ve içerdikleri diğer objelerin event/metodları tarafından görülebiliyor (özellikle kısıtlanmadıysa). Kendisi gibi başlangıçta aynı olan diğer 2 form objesine bulaşmıyorlar.

Basitçe bir obje yaratıp bunu gösterelim ve bugünlük bitsin:

Visual Fox Pro
public oForm

oForm = createobject("Form") && form classindan bir değişken
oForm.Show() && formu göster

3 satırda boş bir form yaratıp gösterebiliyoruz. Fox2x'teki:
define window ...
activate window ...

gibi. Buraya kadar benzese de çok farklılar.

Visual Fox Pro
Public o1,o2,o3 && public yasak. örneklerde olmasinin nedeni kodu basit tutmak

o1 = Createobject("testform")
o2 = Createobject("testform")
o3 = Createobject("testform")
 
o2.Left = o1.Width + 10
o3.Top = o1.Height + 30
o1.Show()
o2.Show()
o3.Show()
 
Define Class testform As Form
    benimDegerim = Sys(2015)
 
    Add Object cmdGoster As CommandButton With Caption = "Degeri degistir"
 
    * Buradaki ControlSource gereksiz.
    * Sadece ne yapabileceginizi göstermek için
    Add Object txtGoster As TextBox With Top = 50,Left = 10,;
        ControlSource = "thisform.benimDegerim", ;
        width = 200
 
*!*    Initden Commenti kaldirip deneyin sonra
 
*!*        Procedure Init
*!*            This.benimDegerim = Sys(2015)
*!*        Endproc
 
    Procedure cmdGoster.Click
        Local ix
        Thisform.benimDegerim = Datetime()
        For ix = 1 To _Screen.FormCount
            _Screen.Forms[m.ix].Refresh()
        Endfor
    Endproc
 
Enddefine

9

Re: Yeni başlayanlar ve Foxpro 2.x'ten geçenler için VFP

Sağol hocam devamını bekliyorum

10

Re: Yeni başlayanlar ve Foxpro 2.x'ten geçenler için VFP

VFP adı üstünde visual, basit kodda olsa çoğu zaman işimiz formlarda geçecek. Hemen şimdi formlara girersek, görsellik sayesinde analaşılması daha da kolaylaşacak. Ancak girmeden önce ufak bir ayrıntı:

VFP'daki dizayn oratmında görsel olarak yapılan herşeyin bir de görsellik kullanmadan tamamen kodla yazılma şansı var. Boyle bir ortamda form vs'nin kendilerini göndermek ölüm, ama onların düz kod versiyonlarını göndermek mümkün. Bu nedenle birçok kod görmeye başlayacaksınız. Bu kodları doğrudan çalıştırabilirsiniz. Yeni başlayanların sorunu bu şekilde sadece kodla olan şeyleri geliştirmekte zorlanmak ve haklı olarak görsel dizayn şekillerini istemek (böylece o form üzerinde kendileri de rahatlıkla oynayabilir). Kodu ilgili görsel şekline çevirmenin birden fazla yolu var ben şimdilik basit bir tanesini anlatıyorum. Unutmadan kodlarda VFP ile birlikte gelen örnek database testdata.dbc ve onun tabloları kullanılıyor:

Visual Fox Pro
Public oForm

oForm = Createobject("ilkFormOrnegi")
oForm.Show()
 
Define Class ilkFormOrnegi As Form
  DataSession = 2
  Height = 500
  Width = 800
 
  Add Object lblCustomer As Label With ;
    left = 10, Top = 5, Width = 45, Caption = "Musteri ID"
 
  Add Object txtCustomerID As TextBox With Left = 50, Top = 5,SelectOnEntry = .T.
 
  Add Object lblCustID As Label With ;
    left = 10, Top = 35, Width = 45, Caption = "Musteri ID"
 
  Add Object lblCompany As Label With ;
    left = 50, Top = 35, AutoSize=.T., Caption = "Sirket"
 
  Add Object txtCustID As TextBox With ;
    left = 10, Top = 50, ControlSource = "Customer.Cust_id",Enabled = .F.
 
  Add Object txtCompany As TextBox With ;
    left = 50, Top = 50, ControlSource = "Customer.Company",Enabled = .F.
 
  Add Object grdOrders As Grid With ;
    Left = 10, Top = 90, Height = 400, Width = 780, ;
    RecordSource = "Orders", ;
    LinkMaster = "Customer", ;
    ChildOrder = "cust_id",;
    RelationalExpr = "cust_id"
 
  Procedure Load
    Use (_samples+"data\customer") In 0
    Use (_samples+"data\orders") In 0
 
    cursorsetprop("buffering",5,"customer")
    cursorsetprop("buffering",5,"orders")
  Endproc
 
  Procedure Init
    This.grdOrders.Columns(1).ReadOnly = .T.
    This.grdOrders.SetAll( "DynamicBackColor", ;
       "(IIF(orders.order_net > 1000, 0x4040FF, 0xFFFFFF))" )
  Endproc
 
  Procedure txtCustomerID.LostFocus
    Local lcID
    lcID = Upper(Alltrim(Thisform.txtCustomerID.Value))
    If !Seek(m.lcID, "Customer", "Cust_id")
      Messagebox("Musteri bulunamadi.")
      Nodefault
      This.SetFocus()
    Else
      Thisform.Refresh()
    Endif
  Endproc
Enddefine

Şimdi önce bu kodu çalıştırın. Çalıştırmak için VFP'nin ilginç kolaylıklarından yararlabilirsiniz.  Önce kendinize test kodlarınız için yeni bir dizin açın ve orada çalışın. Command windowda:

Visual Fox Pro
Md c:\VfpTestleri

cd c:\VFPtestleri

ve şimdi:

Modify Command [enter]

-açılan kod penceresine kodu copy/paste.
-Ctrl+A ile hepsini seçin

-Sağ klik
-Açılan menuden "Execute selection"

Bu yöntemle kod yazım sırasında bile kodunuzun istediğiniz bölümünü seçip çalıştırabiliirsiniz.

Bir form belirecek ve tabii ki ben bunalrı hep elle yaptiğim için yerlerini hesaplamak zahmet etmediğim üstüste çakışan kontroller. Yine de bazı fonksiyonları olan bir form.

Bu kod formunu saklamak isterseniz kod penceresini kapatın (veya Ctrl+W). Kapatırken saklamak isteyip istemediğinizi soracak, evet diyin ve bir isim verin (mesela ornek1.prg). Saklanmış halini de istediğiniz zaman:

do ornek1

diye çalıştırabilirsiniz. Neyse şimdi bunu görsel şekline çevirelim (.scx dosyası, Fox2x'teki gibi yalnız create/modify screen yerine create/modify form). Kodu açın (adım adım yaptığınız kısımları silerseniz takibi kolay olur - sonunda da saklamadan kapatabilirsiniz silmemek için).

İster command windowda:
create form
yazarak isterseniz menüden yeni bir form yaratın (File\New\Form - wizard seçmeyin, wizardları baştan unutsanız iyi olur).


Visual Fox Pro
Public oForm

oForm = Createobject("ilkFormOrnegi")
oForm.Show()

Kısmına ihtiyacımız yok onu geçin.

Açılan form da:

define class ...

ve en sondaki

enddefine'a karsilik. Onları da silin (define class aslında class karşılığı ama şu anda düz form -scx- yapıyoruz).

Define Class ...
altındaki 3 satır:
  DataSession = 2
  Height = 500
  Width = 800

Bunlar formun propertyleri. PEM penceresinden (sağda açık görmüyorsanız menüden "Window\Properties Window" seçin ya da toolbardaki ikonuna tıklayın). Bu propertyleri o listede bulup değerlerini karşısına yazacaksınız. PEM penceresinde bir dizi kolaylık saklı, yeri geldiğince bahsederim (ya da orada gezinirseniz, help dosyası filan, keşfedilecek çok şey var). DataSession propertysini bulmak için ya listede alfabetik olarak gidin ya da D ile başlayan ilk property için:
Ctrl+Alt+D
Sonra DataSession'u bulup değerini yazın. Orada girerken 2'nin "Private DataSession" demek olduğunu göreceksiniz.

Height ve Width'i bulup girmeye gerek yok. Mouse ile formu boyutlandırabilirsiniz.

Sonra bir dizi:

ADD OBJECT

var. Bunlar forma eklediğimiz label,textbox,grid objeleri. Bu satırlarda "as" den sonra o objenin "class"ı var.

Visual Fox Pro
Add Object lblCustomer As Label With ;

    left = 10, Top = 5, Width = 45, Caption = "Musteri ID"

Bu objeleri "form controls toolbar"dan (bir ok ikonuyla başlayıp, kitap ikonuyla devam eden araç çubuğu) seçerek forma yerleştirin. Eğer toolbar görüntülenmediyse menüden "View\form controls toolbar". Toolbarı dock edebilirsiniz (kenarlara tutup çekerek, ya da window başlığına çift tık).

Label için toolbardan "Label" (A ikonu) ikonuna kilkleyin, seçili hale gelecek, formun üstünde istediğiniz yere klikleyin. Forma bir label eklenir (Label1 hem adı hem de şu anda form saklanırsa göstereceği metin). Toolbardaki seçili ikon label'dan cursor'a (ok) dönüşür. Üstüste birkaç label ekleyecek iseniz en sağındaki kilit ikonuna tıklayın önce (ama ben galiba son 10 senedir kullanmadım onu, hiç gerekmiyor).

"Add Object"den sonraki lblCustomer onun ismi. Name propertysine onu yazın.
"With" den sonraki kısım o objenin bir dizi propertysi. Left,Top,Width için PEM sheet (Özellikler penceresi) yerine fareyle ile yerini, boyutlarını belirleyebilirsiniz. Caption propertysini girerken tırnakları yazmayın.

Bu şekilde diğer objeleri de forma yerleştirip properylerini ayarlayın.

Geriye Procedure ... endproc bloklarımız kaldı.

Procedure = Function

Event ve Metod kodları procedure. Event ile Metod'un farkı birinin çalışabilmesi için (metod) mutlaka bir yerden kod ile çağrılması gerekiyor. Event'ler ise kendilerini ilgilendiren sistem etkilerine tepkiyi otomatik olarak verir. Bizim 3 procedure de event. Form yüklenirken Load, sonra Init eventleri oluşuyor ve içlerindeki kod otomatikman çalışıyor.


Visual Fox Pro
Procedure Load

    Use (_samples+"data\customer") In 0
    Use (_samples+"data\orders") In 0
 
    cursorsetprop("buffering",5,"customer")
    cursorsetprop("buffering",5,"orders")
  Endproc

-Forma çift klikleyin.
-Açılan kod penceresinde sol üstte kodunu yazdığınız event/metodun hangi objeye ait olduğunu görüyorsunuz (object: Form1). Onun sağında ise hangi event/metodunda olduğunuz. Şu anda Load olması lazım. Değilse o combodan Load'u seçin. VFP'nin ilk olarak Load ile getirmesinin nedeni objeye göre en sık kullanılan event/metod'u ilk olarak kod penceresine getirmesi.
Şimdi ilgili kodu oraya yapıştırın. İlk ve son satırları silin. Yani Form - Load için oraya:

Visual Fox Pro
Use (_samples+"data\customer") In 0

    Use (_samples+"data\orders") In 0
 
    cursorsetprop("buffering",5,"customer")
    cursorsetprop("buffering",5,"orders")

yapıştırn.
Alt+T Y [enter]
yaparsanız sizin için düzenlenir (Format menu/Beautify - her versionda yok veya tuş serisi farklı olabilir - Türkçe windows kullananlarda Format yerine başka birşey de olabilir - biçim). Kod penceresined sağ klik menuden de seçebilirsiniz.

Sonra sağdaki combodan Init seçin ve Inıt kodu için de aynı şeyi yapın.

Geriye:

Visual Fox Pro
Procedure txtCustomerID.LostFocus

    Local lcID
    lcID = Upper(Alltrim(Thisform.txtCustomerID.Value))
    If !Seek(m.lcID, "Customer", "Cust_id")
      Messagebox("Musteri bulunamadi.")
      Nodefault
      This.SetFocus()
    Else
      Thisform.Refresh()
    Endif
  Endproc

kaldı.

Diğer ikisi
Procedure Load
Procedure Init
iken bu:
Procedure txtCustomerID.LostFocus

İlk ikisi aslında:
FormAdi.Load
FormAdi.Init

Propertyler gibi doğrudan:
define class ... as Form
ilk seviye elemanları olduklarından başlarında formAdi yoktu.

txtCustomerID.LostFocus

Formun txtCustomerID textbox objesinin LostFocus kodu demek.

Formun üstünde şu anda objeleriniz görüyorsunuz ve isimleri içinde yazıyor. txtCustomerID'ye çift klikleyerek onun kod penceresini açın. Sol yukarıda obje adını kontrol edin. Yanlış obje ise doğrusunu seçin. Sağdan da LostFocus'u bulup kodu içine yapıştırın.
(oh be - okuması zor herhalde ama inanın yazması çok daha zor)

Tabii daha önce VFP de bir işi yapmanın en az 3 yolu olduğunu söylemiştim. Bu bir yolu ve aslında zor yollarından birisi. Diğer yollar kolay ve daha kolay olsa da şimdilik sadece kafanızı daha fazla karıştırabilir.

Formu çalıştırın. Çalıştırmaya kalktığınızda önce size saklamak istiyor musunuz diye soracak evet diyip isim verin (ornek1 derseniz ornek1.scx ve ornek1.sct dosyaları oluşacak - bu formunuzun "tablo" hali. Daha sonra herhangi bir zamanda, Command windowdan çalıştırmak için "do form Ornek1").
Çalıştırmak için bir sürü yol var:
-Menüde "Form\Run Form"
-Ctrl+E
-Toolbardaki kırmızı ünlem şeklindeki ikon
-Formda (boş bir yerde) sağ klik ve Run Form

Bu formla oynayabilirsiniz. Load'daki:

Visual Fox Pro
cursorsetprop("buffering",5,"customer")

    cursorsetprop("buffering",5,"orders")

nedeniyle yaptığınız değişiklikler (datada) saklanmayacak.
Pek birşey yapan bir form değil aslında. Sadece ilk textbox'a:

anton
anatr
bonap
centc

vs gibi birşey yazarsanız oradan ayrılırken (LostFocus kodu) customer tablosunda o kodlu müşteriye gidiyor ve siparişlerini görüntülüyor (yoksa bulunamadı diye mesaj).

Kapatmadan önce Fox2x'ten gelenlere not:
Ortada "set relation" yokken ve lostfocus kodunun tüm yaptığı customer tablosunda iligili kaydı bulmak olduğu halde gridde o müşterinin siparişleri listeleniyor. Bunun nedeni relation'un kod yerine grid propertyleri ile sağlanmış olması:

LinkMaster: Customer && parent table
ChildOrder: cust_id     && child index
RelationalExpr: Cust_id  && relation

11

Re: Yeni başlayanlar ve Foxpro 2.x'ten geçenler için VFP

Kisa bir aradan sonra tekrar merhaba. Bu arada email,msn vs kaynaklardan gelen sorularla ayrica ilgilenmekten bu yaziya ayrilan zaman daraliyor:)

Devam etmeden once bazi temel ve onemli kurallari anlatayim (aklima ilk gelenler):
1) Bir degisken ya "Memory" ya da "Field" degiskenidir.
Memory degiskenlerini yazarken MUTLAKA m. on ekini kullanin. "m" memory icin ozel bir aliastir (oylesine ozel ki normal bir tabloda "m" i alias olarak kullanmaya kalkarsaniz basiniza is aldiniz demektir).

Ancak degisken atamanin solunda ise kullanmasaniz da olur.

use customer
? Company
veya:
? Customer.Company

"Company" field degiskeni.

tarih = {^2006/1/1}

"tarih" memory degiskeni.

Burada "tarih"in bir memory degiskeni oldugu kesin. Cunku VFP'de = operatoru ile sadece ve sadece memory degiskenleri ve obje propertylerine atama yapabilirsiniz.

use customer
Company = "Benim sirket"

dediginizde, Customer tablosunun Company field'ine hic dokunmamis oluyorsunuz. Dokunabilmek icin, replace, update, gather, insert vs bir komuta ihtiyaciniz var. Bu nedenle atamanin ( = operatoru) solunda oldugundan kesin olarak buradaki "company" bir memory degiskeni.

Atama islemi "assign", degeri okuma, sorgulama "access" (erisim). Assign sirasinda m. kullanmak zorunda degilsiniz ama access (erisim) sirasinda m. kullanmak zorundasiniz. Bu zorunluluk ne yazik ki VFP tarafindan uygulanan bir zorunluluk degil (arabanin onune atlamayin diye sadece dokumentasyonunda -eger bulabilirseniz o da- ogut verir ama siz atliyorsaniz tutmakla hic ugrasmaz. Daha da acisi VFP'de uzman kabul edilen bircok kisi bile bu hataya dustu hatta hala israrla dusmeye devam ediyor. Mesela benim eski kodlarimda da bu hata var, elim degdigi zaman duzeltiyorum, duzeltmediklerimin de bile bile lades oldugunun farkindayim).

use customer
Company = "Benim sirket"
? Company, Customer.Company, m.Company

"?" ile yaptigimiz islem access. ? yerine bircok komut ve fonksiyonla access yapabilirsiniz (yani o degerin okunmasi gereken her islem access). Burada artik "Company" atamanin saginda ( atamanin sagi, solundan kasit, access veya assign yapiyorsunuz - bu arada Turkceleri yerine surekli access-assign kullaniyorum cunku bir taraftan Ingilizce'si iyi olmayan arkadaslar propertylerin access-assign metodlarini gordugunde o metodlarin neyle ilgili oldugunu simdiden anlasin).
VFP yukaridaki komutta ekrana:

Alfreds Futterkiste,Alfreds Futterkiste,Benim sirket

yazar (eger customer tablosunun kayilarini degistirmediyseniz). Bu sonuctan anlayacaginiz gibi eger siz:

? Company

gibi "memory" mi yoksa "field" degiskenini mi kastettiginizi belirtmezseniz, field degiskenleri oncelikli oldugundan customer tablosundaki company fieldinin degerini istediginize karar verir.
? m.Company
ve:
? Customer.Company

ise acik secik ne istedigini belirtiyor. Peki ya sizin "Customer" diye bir objeniz ve onun "Company" diye bir propertysi varsa? O zaman:

? m.Customer.Company

(hatirlarsaniz daha once objelerin de bir degisken oldugunu soylemistim).


m. kullanmazsaniz ne olur? Programinizin tum prosedurleri, classs kodlari vs mukemmel yazilmis ve harika calisiyor olabilir. Ama programlar her zaman buyurler. Bu buyumenin icinde birgun siz soyle bir prosedur dusunun:

Procedure getMusteriBalans
lparameters musteriKodu
*...
tarih = ...
if tarih > ...
...
return ...


Burada:

if tarih > ...

satiri tehlike sinyallerinin caldigi satir. O zamana kadar mukemmel calisan bu prosedur cagrilmadan once:

use birTablo
eklediniz ve o tablonun "tarih" adinda bir fieldi varsa "if tarih > ..." satiri sanki:

if birTablo.Tarih > ...

yazilmis gibi islem gormeye baslar. Isin kotusu eger sans eseri o sirada uzerinde oldugunuz kayit o sarti "tarih" memory degiskeniyle de ayni sekilde sagliyorsa.

tarih = ... && 1 Mart 2006 oldugunu farzedin buradaki sonucun
&& tablodaki tarih ise 5 Agustos 2006 olsun

if tarih > {^2006/1/1} && her ikisi icinde dogru


kodunuzun aslinda tesadufen dogru calistigini emin olun birgun musterileriniz size bildirir (kibar olmalari icin dua edin). Cozmesi cok zordur bu tip hatalari cunku hatayi olusturmaya calisirsiniz ama koda baktikca hata yokmus gibi gelir, ancak adim adim hata ayiklamada farkedersiniz (insallah - tesadufen onlar da ayni tarih degilse).

Hemen hemen butun program dillerinin basina bu gibi dertler "Hungarian notation" denen bir isimlendirme yuzunden geldi. Hepimiz o isimlendirmenin bizi bu tip seylerden korudugunu ve m. on ekine ihtiyacimiz olmadigi yanilgisina kapildik ne yazik ki. Hala o isimlendirmeyi kullaniyoruz (istemesem de ayak uyduruyorum ben de:( ) ve herkes kurtulmaya calisiyor, darisi VFP programcilarinin basina.


Yani VFP'de memory degiskenleri icin m. on eki OPSIYONEL DEGIL, ZORUNLU. Yine de kafaniza silah dayayacak olan yok tabii.

m. onekinin kullanilmasi icin daha onemsiz bir neden performans. VFP7'den itibaren eger bir dongude degisken kullaniyorsaniz (ki %99 kullanirsiniz) ve o degiskenlerin m. on ekini yazmassaniz ciddi boyutlarda hiz farkliliklari alabilirsiniz. Ilgili koda bagli olarak m. kullanan ve kullanmayan kodlar arasindaki zaman farki milisaniyeler olabilecegi gibi dakikalar da olabilir.

2) Forumlarda sorulan sorular. Bir cevap verildiginde lutfen geriye:

"Denedim calismiyor", "Olmadi" vb gibi cok aciklayici cevaplar gondermeyin.

"Calismadi" demek ne demek? Hemen hemen her forumda cevap verenlerin en cok kizdigi sey bu:) Birsey calismadiysa:
-Hata vermistir. Hata mesaji ne? Nerede?
-Hic hata vermemistir. Beklediginiz sonucu vermemistir. O zaman ne bekliyordunuz, ne verdi?

3) Forumlarda sorularinizin yani sira gerekiyorsa data ve kod gonderin. Mesela bir SQL sorusu soracaksiniz ve isin icinde joinler filan, uzun bir SQL. Ortada deneme icin kullanilacak data yokken sorunuzu okuyanlar yine de cevap verebilmek icin belki de vakitlerini harcayip datanin bir ornegini yaratiyorlar, ya da sirf onu yaratmakla vakit kaybetmemek icin cevabi bilseler de ugrasmak istemiyorlar dogal olarak. Sonucta bazen basit olabilecek cevaplar yerine sunu dene, bunu dene vs gibi cevaplar alabilrisiniz. Oysa ellerinde datanin bir miktar ornegi olsa hemen SQL'i test edip, dogru hallerini size bildirme sanlsari var (tabii SQL'den ne beklediginizi temiz bir ornekle gosterdiyseniz).

Data gondermek icin bu programi kullanabilirsiniz:

Visual Fox Pro
*SampleData2Text.prg

Lparameters tcTableName,tnRecords
Use (m.tcTableName) In 0 Alias 'sampling'
Select 'sampling'
Local lcTemp, ix, lcData, lcRetVal
lcTemp = Sys(2015)+'.tmp'
If !Empty(m.tnRecords) And Type('m.tnRecords') = 'N'
  Copy To (m.lcTemp) Type Delimited Next m.tnRecords
Else
  Copy To (m.lcTemp) Type Delimited
Endif
lcData = Filetostr(m.lcTemp)
Erase (m.lcTemp)
 
Set Textmerge Delimiters To '%%','%%'
Set Textmerge To (m.lcTemp) Noshow
Set Textmerge On
\CreateCursor_%%m.tcTableName%%()
\
\Procedure CreateCursor_%%m.tcTableName%%
\LOCAL lcData, lcTemp
\lcTemp = SYS(2015)+'.tmp'
\TEXT TO m.lcData noshow
\%%m.lcData%%
\ENDTEXT
\
\STRTOFILE(m.lcData,m.lcTemp)
\
\create CURSOR %%m.tcTableName%% ;
\ ( ;
For ix=1 To Afields(aStruc,'sampling')
%%IIF(m.ix > 1,',','')%%
\\%%aStruc[m.ix,1]%% %%aStruc[m.ix,2]%%(%%aStruc[m.ix,3]%%,%%aStruc[m.ix,4]%%)
\\ %%IIF(aStruc[m.ix,5],'',' NOT ')%% NULL
\\ %%IIF(aStruc[m.ix,6],'NOCPTRANS','')%% ;
Endfor
)
\
\APPEND FROM (m.lcTemp) TYPE delimited
\ERASE (m.lcTemp)
\endproc
Set Textmerge To
Set Textmerge Off
Set Textmerge Delimiters
lcRetVal = Filetostr(m.lcTemp)
Erase (m.lcTemp)
Use In 'sampling'
Return m.lcRetVal

Ornegin sizin elinizde customer, employee tablolarinin olmadigini farzedin. Size onlardan hazir data gondermek istesem burada (customer'dan 2 satir, employee'den 5) :

_cliptext = SampleData2Text('customer',2) [enter]
modify command [enter]
[Ctrl+V]
[Ctrl+F2]
_cliptext = sampledata2text('employee',5)
[Ctrl+F1]
[Ctrl+Home]
[DownArrow]
[DownArrow]
[Ctrl+V]


ile asgadikai hazir kodu gonderebilirim:

Visual Fox Pro
CreateCursor_customer()

 
CreateCursor_employee()
 
Procedure CreateCursor_employee
LOCAL lcData, lcTemp
lcTemp = SYS(2015)+'.tmp'
TEXT TO m.lcData noshow
"     5","Buchanan","Steven","Sales Manager",03/04/1955,09/03/1992,"14 Garrett Hill","London","","SW1 8JR","UK","(71) 555-4848","3453","2",""
"     6","Suyama","Michael","Sales Representative",07/02/1963,09/13/1992,"Coventry House, Miner Rd.","London","","EC2 7JR","UK","(71) 555-7773","428","5",""
"     7","King","Robert","Sales Representative",05/29/1960,11/29/1992,"Edgeham Hollow, Winchester Way","London","","RG1 9SP","UK","(71) 555-5598","465","5",""
"     8","Callahan","Laura","Inside Sales Coordinator",01/09/1958,01/30/1993,"4726 - 11th Ave. N.E.","Seattle","WA","98105","USA","(206) 555-1189","2344","2",""
"    10","Hellstern","Albert","Business Manager",03/13/1960,03/01/1993,"13920 S.E. 40th Street","Bellevue","WA","98006","USA","(206) 555-4869","7559","2",""
 
ENDTEXT
 
STRTOFILE(m.lcData,m.lcTemp)
 
create CURSOR employee ;
( ;
  EMP_ID C(6,0)  NOT  NULL  ;
  ,LAST_NAME C(20,0)  NOT  NULL  ;
  ,FIRST_NAME C(10,0)  NOT  NULL  ;
  ,TITLE C(30,0)  NOT  NULL  ;
  ,BIRTH_DATE D(8,0)  NOT  NULL  ;
  ,HIRE_DATE D(8,0)  NOT  NULL  ;
  ,ADDRESS C(60,0)  NOT  NULL  ;
  ,CITY C(15,0)  NOT  NULL  ;
  ,REGION C(15,0)  NOT  NULL  ;
  ,POSTALCODE C(10,0)  NOT  NULL  ;
  ,COUNTRY C(15,0)  NOT  NULL  ;
  ,HOME_PHONE C(24,0)  NOT  NULL  ;
  ,EXTENSION C(4,0)  NOT  NULL  ;
  ,PHOTO G(4,0)  NULL  ;
  ,NOTES M(4,0)  NULL  ;
  ,REPORTS_TO C(6,0)  NOT  NULL  ;
  ,LONGFIELDNAMEHERE C(10,0)  NULL  ;
  )
 
APPEND FROM (m.lcTemp) TYPE delimited
ERASE (m.lcTemp)
endproc
Procedure CreateCursor_customer
LOCAL lcData, lcTemp
lcTemp = SYS(2015)+'.tmp'
TEXT TO m.lcData noshow
"ALFKI","Alfreds Futterkiste","CETINUPDATEDAGAIN","My sale","Obere Str. 57","Berlin","","1234567890","Germany","030-0074321","030-0076545",6300.0000,""
"ANATR","Ana Trujillo Emparedados y helados","Ana Trujillo","Myowner","Avda. de la Constitución 2222","México D.F.","","05021","Mexico","(5) 555-4729","(5) 555-3745",3500.0000,""
 
ENDTEXT
 
STRTOFILE(m.lcData,m.lcTemp)
 
create CURSOR customer ;
( ;
  CUST_ID C(6,0)  NOT  NULL  ;
  ,COMPANY C(40,0)  NOT  NULL  ;
  ,CONTACT C(30,0)  NOT  NULL  ;
  ,TITLE C(30,0)  NOT  NULL  ;
  ,ADDRESS C(60,0)  NOT  NULL  ;
  ,CITY C(15,0)  NOT  NULL  ;
  ,REGION C(15,0)  NOT  NULL  ;
  ,POSTALCODE C(10,0)  NOT  NULL  ;
  ,COUNTRY C(15,0)  NOT  NULL  ;
  ,PHONE C(24,0)  NOT  NULL  ;
  ,FAX C(24,0)  NOT  NULL  ;
  ,MAXORDAMT Y(8,4)  NOT  NULL  ;
  ,MYLONGFIELDNAME C(10,0)  NOT  NULL  ;
  )
 
APPEND FROM (m.lcTemp) TYPE delimited
ERASE (m.lcTemp)
endproc

Alan kisi bu kodu calistirarak sizin datanizin bir ornegini elde eder.

Benzer sekilde eger birseyi orneklemek icin kod yazabiliyorsaniz yazin. Bunlara 'reproduction' - yeniden olusturma kodlari deniyor. Bu tip kodlar probleminizi anlatmanin en iyi yolu. Kisiler uzun hikayeleri okumak yerine problemi gosteren kodlari dogrudan calsitirmayi seviyor acikcasi:)

Bugunu kapatmadan once ornek bir kod.

Visual Fox Pro
Public oForm

oForm = Createobject('fox2xstyle')
oForm.Show()
 
Define Class fox2xstyle As Form
  DataSession = 2
  Height = 400
  Width = 800
  Caption = 'Fox2x Style'
  orecord = .Null.
  isadding = .F.
  isediting = .F.
 
  Add Object grdcustomer As Grid With ;
    Top = 10, Left = 10, Height = 300, Width = 370,    ReadOnly = .T., RecordSource = "customer"
  Add Object txtcust_id As TextBox With ;
    Left = 462, Top = 55
  Add Object lblcust_id As Label With ;
    AutoSize = .T., Caption = "Cust_id", Left = 401, Top = 55
  Add Object txtcompany As TextBox With ;
    Left = 462, Top = 83, Width = 288
  Add Object lblcompany As Label With ;
    AutoSize = .T., Caption = "Company", Left = 401, Top = 83
  Add Object txtcontact As TextBox With ;
    Left = 462, Top = 111, Width = 219
  Add Object lblcontact As Label With ;
    AutoSize = .T., Caption = "Contact", Left = 401, Top = 111
  Add Object txttitle As TextBox With ;
    Left = 462, Top = 139, Width = 219
  Add Object lbltitle As Label With ;
    AutoSize = .T., Caption = "Title", Left = 401, Top = 139
  Add Object command1 As CommandButton With ;
    Top = 216, Left = 408, Height = 27, Width = 84, Caption = "Add"
  Add Object command2 As CommandButton With ;
    Top = 216, Left = 516, Height = 27, Width = 84, Caption = "Edit"
 
  Procedure Load
    Use customer
  Endproc
 
  Procedure Init
    With This
      Select customer
      Scatter Name This.oRecord Memo
      .txtCust_id.ControlSource = "thisform.oRecord.cust_id"
      .txtCompany.ControlSource = "thisform.oRecord.company"
      .txtContact.ControlSource = "thisform.oRecord.contact"
      .txtTitle.ControlSource   = "thisform.oRecord.title"
    ENDWITH
    this.SetAll('Enabled',.f.,'textbox')
    this.SetAll('DisabledForeColor',0,'textbox')
  Endproc
 
 
  Procedure grdcustomer.AfterRowColChange
    Lparameters nColIndex
    Scatter Name Thisform.oRecord Memo
    Thisform.Refresh()
  Endproc
 
 
  Procedure command1.Click
    If Thisform.isediting
      If Thisform.isadding
        Insert Into customer ;
          (cust_id) Values (Thisform.oRecord.cust_id)
      Endif
      Select customer
      Gather Name Thisform.oRecord Memo
      This.Caption = 'Add'
      This.Parent.Command2.Caption = 'Edit'
      Thisform.SetAll('Enabled',.F.,'textbox')
      Thisform.grdCustomer.Enabled = .T.
    Else
      Select customer
      Scatter Name Thisform.oRecord Memo Blank
      This.Caption = 'Save'
      This.Parent.Command2.Caption = 'Cancel'
      Thisform.SetAll('Enabled',.T.,'textbox')
      Thisform.grdCustomer.Enabled = .F.
    Endif
    Store !Thisform.isediting To ;
      thisform.isadding, ;
      thisform.isediting
    Thisform.Refresh()
  Endproc
 
 
  Procedure command2.Click
    If Thisform.isediting
      Select customer
      Scatter Name Thisform.oRecord Memo
      This.Caption = 'Edit'
      This.Parent.Command1.Caption = 'Add'
      Thisform.SetAll('Enabled',.F.,'textbox')
      Thisform.grdCustomer.Enabled = .T.
 
      Thisform.isadding = .F.
      Thisform.isediting = .F.
    Else
      This.Caption = 'Cancel'
      This.Parent.Command1.Caption = 'Save'
      Thisform.SetAll('Enabled',.T.,'textbox')
      Thisform.grdCustomer.Enabled = .F.
 
      Thisform.isadding = .F.
      Thisform.isediting = .T.
    Endif
    Thisform.Refresh()
  Endproc
Enddefine

Not: Bu kod kullanilmasi gereken ideal kod filan degil. Yalnizca sabirsiz arkadaslar icin hizla yazilmis ve yine de potansiyeli olan bir kod. Fox2x'ten gelen arkadaslar neden fox2xstyle adini verdigimi hemen anlayacaktir:) Yalnizca birinizin gordugu kod olarak kalmasini istemedigimden ekledim.

12

Re: Yeni başlayanlar ve Foxpro 2.x'ten geçenler için VFP

ellerine sağlık

13

Re: Yeni başlayanlar ve Foxpro 2.x'ten geçenler için VFP

Çetin hocam elinize sağlık, gerçekten aranıpta bulunamıycak bilgiler vermişsiniz. Devamını merakla bekliyorum...

Uğur
-------------------------------------------------------------------------------------------------------------
Hayat bir bisiklete binmek gibidir. Pedalı çevirmeye devam ettiğiniz sürece düşmezsiniz. Claude Peppeer
Kusuru söylenmeyen adam, ayıbını hüner sanır.  Türk Atasözü

14

Re: Yeni başlayanlar ve Foxpro 2.x'ten geçenler için VFP

Çok iyi gidiyor. Devamını bekleriz.
VFP ile ilgilenenlere gösterilebilecek Türkçe bir kaynak olması açısında da önemli.

15

Re: Yeni başlayanlar ve Foxpro 2.x'ten geçenler için VFP

Ya arkadaslar sagolun ama bir taraftan da zaman ayiramamak gibi bir derdim oluyor. Gecikmeler icin ozur dilerim simdiden.

16

Re: Yeni başlayanlar ve Foxpro 2.x'ten geçenler için VFP

Üstad, MicroSoft VFP ' den desteiğini çekti. De ... Biz hala VFP de yazıyoruz. Biraz daha VFP dersi istesek fazla mı oluruz? Yüzsüzlük mü ederiz acep ... smile

Uğur
-------------------------------------------------------------------------------------------------------------
Hayat bir bisiklete binmek gibidir. Pedalı çevirmeye devam ettiğiniz sürece düşmezsiniz. Claude Peppeer
Kusuru söylenmeyen adam, ayıbını hüner sanır.  Türk Atasözü

17

Re: Yeni başlayanlar ve Foxpro 2.x'ten geçenler için VFP

Uzunca bir aradan sonra tekrar merhaba:) Bunu bir mesaja cevap olarak yazdim. Forumdaki diger arkadaslara da faydasi dokunabilecegi icin oldugu gibi ekliyorum:



Sadece iki tabloluk bir uygulama. Birisinde kisilerin adi, soyadi gibi bilgileri tutuluyor. Digerine de bunlar sanki dukkana gelen musterlermis gibi sadece gelis tarihleri ve toplamHarcamaTutari olsun. Basit olsun diye bu kadarcik bilgi, iliskili tablo olsun diye cift tablo (muhasebede MusteriHesabi,CariHareket gibi).

Nereden baslayacagin biraz sana ve aliskanliklarina kalmis birsey, kesin kurallari yok.
-Once datayi yaratip bununla ilgili form, rapor vs yi sonradan olusuturabilirsin.
-Dogrudan form ile baslar (yani arayuzden) arayuzun ihtiyaclarina gore datani sekillendirirsin.
Tabii ideal olarak ta hepsinden once ya kagit kalemle ya da visio vb araclarla tum program akisini, formlarini filan dizayn edersin:)
Ben genelde biraz ustunde kagit kalemle dusunup, sonra bodoslama bir yerden girerim, zamanla nasil oluyorsa sekillenir:) Benim gibi yapma, ben daginik sayilirim o acidan, yillarin verdigi guvenden kaynaklaniyor herhalde bir sekilde toparlanip oluyor.

Uygulamalarin hepsinde:
1) Tum uygulamalarinda surekli kullandigin
2) O uygulamaya ozel
Form,Class ... oluyor.

Tum uygulamalarinda kullandiklarini iyi belirlemen gerekiyor. Cunku orada yapacagin her degisiklik, o andan itibaren yeniden derlenen tum uygulamalarini etkiler. Mesela kendisine iki dizinadi gonderildiginde, ilk dizinden dosyalari ikincisine kopyeleyen bir kod tum uygulamalar icin ortak bir kod. Bunun benzeri bir dizi folder/dosya islemi yapan kodlari "FileOperations" adli bir classta toplayip, onu da "ortak" bolumde saklarsan tum ygulamalarin ondan faydalanir. Uzerinde yapacagin her degisiklik, genelde yeni cikan isletim sistemleri nedeniyle guncelleme, daha hizli calisan kod, hata duzeltme vs'dir ve tum uygulamalarin yeniden derlense de iyi yonde etkilenecegi icin sorun da olmaz. Uzun lafin kisasi, jenerik olanlar orada. Bunu yapmamizin nedeni, oradaki kodlarda bir degisiklik oldugunda N tane kopyesini dusunmen, onalri bulup orada da duzeltme yapman gerekmemesi.

Tamam simdi artik ilk yapmamiz gerekeni yapalim artik:)

Explorer kullanarak yapabilirsin ancak VFP icinden daha kolay:)
-VFP'yi baslat
-Command windowda

Visual Fox Pro
MD ("c:\VFPCommon") [enter]

Modify Command ("c:\vfpCommon\CreateProjectFolders") [enter]


-Acilan kod penceresine asagidaki kodu yapistir:

Visual Fox Pro
****************************************************

* CreateProjectFolders.prg
* Proje folderlarini olusturan kod
* Parametre:
*    tcBasePath: String. Folderlarin olusturulacagi ana dizin adi.
* Remarks:
*    Gelen parametrenin string olup olmadigi, dizinin varligi
*    gibi kontroller yok.
* Kullanim ornegi:
*  do CreateProjectFolders with "c:\Yeni Dizin"
* "c:\Yeni Dizin" olmak zorunda degil.
*  Yoksa yaratiliyor. Varsa sadece alt dizinler yaratiliyor
****************************************************
LPARAMETERS tcBasePath
md (addbs(m.tcBasePath)+"BITMAPS")
md (addbs(m.tcBasePath)+"DATA")
md (addbs(m.tcBasePath)+"FORMS")
md (addbs(m.tcBasePath)+"INCLUDE")
md (addbs(m.tcBasePath)+"LIBS")
md (addbs(m.tcBasePath)+"MENUS")
md (addbs(m.tcBasePath)+"PROGS")
md (addbs(m.tcBasePath)+"REPORTS")
md (addbs(m.tcBasePath)+"TEST")


[Ctrl+W] ile kodu saklayip kapat.

-Menuden Tools\Options\File Locations'a git.
-Search path'i  bul ve "Modify". Asagidakini yapistir.
bitmaps;data;forms;include;libs;progs;reports;c:\VFPCommon\bitmaps;c:\VFPCommon\forms;c:\VFPCommon\include;c:\VFPCommon\libs;c:\VFPCommon\progs;c:\VFPCommon\reports;


-OK de, sonra Set as default secip kapat.

Birinci basamak hazirlik tamam. Projelerimiz icin iki adet ana dizinimiz olsun (explorerda filan yaratma)
1) c:\VFPProjects
Burada gercek uygulamalarimiz olacak.
2) c:\VFPTestProjects
Burada test projeleri, proje olmayan deneme kodlari vs. Bir cesit faydali 'copluk':) Herhangi bir anda silinse de fazla uzulmeyecegin yer. Ikisi bir arada olursa zamanla o kadar buyuyor ki ne nerede bulmak cok zor.
(Ileride odev olarak bu dizinlerdeki Projeleri, dosyalari, ne is yaptiklarini vs iceren bir uygulama yapabilirsin - ben hala oturup yapamadim kendim icin senden calarim:)

Simdi ilk test projemizin adinin da "VFP ogreniyorum1" oldugunu varsayalim. Su ana kadar sadece:
c:\VFPCommon dizinini yarattik ve icinde bir adet 'CreateProjectFolders' programimiz var. Explorerdan bakarsan VFP iki adet dosya yaratmis durumda (1 olabilir ayarlara gore cok onemli degil).

c:\VFPCommon\CreateProjectFolders.prg
c:\VFPCommon\CreateProjectFolders.fxp

PRG uzantili olan kaynak kod (source code) dosyasi, notepadde bile acilip duzenlenebilir. Ama ideal editor VFP'de:

modify command ("c:\VFPCommon\CreateProjectFolders") [enter]

ile gelen editor.
FXP uzantili olan ise VFP'nin derledigi ve aslinda programi calistirmak istediginde cagirdigi kod (compiled code, object code). Ona dokunma (duzenlemek icin - bakmak icin notepadde filan acarsan ya saklamadan kapat ya da kazara sakladiysan sil). Istedigin zaman silebilirsin. VFP gerekince yeniden yaratir.

Simdi ilk olarak o koda yazdigimiz alt dizinlerin olusturulmasini istiyoruz. Bunu c:\VFPCommon icin bir kere yapicaz, sonra her yeni proje icin de sadece projeye baslarken bir kere.

Command window'da:

Visual Fox Pro
do ("d:\VFPCommon\CreateProjectFolders") WITH "c:\VFPCommon" [enter]

do ("d:\VFPCommon\CreateProjectFolders") WITH "c:\VFPTestProjects\VFP ogreniyorum1" [enter]


Explorerda gidip bakarsan istedigmiz dizinler olusturuldu.
(

Ipucu:
c:\VFPTestProjects diye bir dizin yokken:

MD ("c:\VFPTestProjects\VFP ogreniyorum1\SubFolder")

komutu hata vermez ve 3 dizini de yaratir. Ilki varsa 2 ve 3'u, 2.de varsa sadece 3.yu yaratir. Ucu de varsa hata mesaji verir. Istersen kodunu saglamlastirmak icin once o dizin var mi diye bakabilir ve hata mesajini almazsin:

Visual Fox Pro
if !Directory("c:\VFPTestProjects\VFP ogreniyorum1\SubFolder")

  MD ("c:\VFPTestProjects\VFP ogreniyorum1\SubFolder")
endif


)

Bizim yaptigimiz da o koda ana dizini parametre olarak gondermek. Kod gonderdigimiz dizini (mesela "c:\VFPTestProjects\VFP ogreniyorum1") tcBasePath degiskenine aliyor.

addbs(m.tcBasePath)

Burada addbs() fonksiyonu dizinin sonunda "\" olmasini garantiliyor. Varsa dokunmuyor. Yoksa ekliyor.

addbs(m.tcBasePath)+"bitmaps"

"c:\VFPTestProjects\VFP ogreniyorum1\bitmaps"

seklini aliyor.

md (addbs(m.tcBasePath)+"BITMAPS")'de:

md ("c:\VFPTestProjects\VFP ogreniyorum1\bitmaps")

seklini aliyor.

(

Not ve biraz da pek bilinmeyenleri de icerdiginden ipucu:

VFP'de +,- gibi operatorler birden fazla gorev yuklenmis (Overloaded) operatorler.

"Merhaba" + " Fox4um" dediginde iki string birlestirilip "Merhaba Fox4um" oluyor.
"Merhaba          " + "Fox4um" dediginde "Merhaba          Fox4um" oluyor.
"Merhaba          " - "Fox4um" dediginde ise: "MerhabaFox4um          " oluyor.
- ile solundaki string'ten sonundaki bosluklar (trailing spaces) kesilip en sona konuyor.

"Cetin          "-(" " + "Basoz") dersen: "Cetin Basoz          " oluyor.

- operatorunun kullanimi stringlerde pek bilinmediginden ve aslinda SQL'lerde, View,index vs yaratmada onemi oldugundan araya ekledim:)

+,- artimetik islemlerde bilindigi gibi calisiyor.

Date ve DateTime tipleriyle calismalari farkli:
Date tipi:

Date1 - Date2: Iki tarih arasindaki fark. GUN cinsinden.
DateTime1 - DateTime2: Iki tarih ve saat arasindaki fark. SANIYE cinsinden.

Tarih + 2: Tarihe 2 GUN ekle.
TarihSaat + 2: Tarih ve saate 2 SANIYE ekle.

Tarih - 2: Tarihten 2 GUN cikar.
TarihSaat - 2: Tarih ve saatten 2 SANIYE cikar.

TarihSaat + 86400: Tarih ve saate 1 GUN ekle. (1 Gun=24saat=24*60 dk= 24*60*60 sn = 86400sn)
TarihSaat + 86400*5 +3600*2 + 60*10: Tarih ve saate 5 GUN + 2 saat + 10 dk ekle.

Bunlarin yanisira bir suru string ve date/time fonksiyonlari var. Bunlar temel dogrudan islemler.

)

(Hala sadece folder yarattik nerede ekranlar dedigini duyar gibiyim. Soz daha hizli gidicem ama cok faydali birsey daha yapalim:)

-Command window

Visual Fox Pro
create table (home()+'Projelerim') free (Caption c(50), Path c(250)) [enter]

use [enter]
 
Modi comm (home()+'Baslat') [enter]


-Asagidaki kodu yapistir, [Ctrl+W] ile sakla

Visual Fox Pro
USE HOME()+'Projelerim'

BROWSE
SET DEFAULT TO (TRIM(Projelerim.path))
_screen.Caption = TRIM(Projelerim.Caption)
USE IN 'Projelerim'


-Command window
_cliptext = home()+'Projelerim.prg'
-Tools\Options\File Locations\Startup Program. Modify.
[Ctrl+V]
OK
Set as default

-Haziriz:) VFP'yi kapat. Yeniden ac.
-Bir browse gelecek. [Ctrl+Y] ile ilk kaydi ekle.
Caption:
VFP ogreniyorum1
Path:
c:\VFPTestProjects\VFP ogreniyorum1

-Browse'i kapat (kosedeki X ile, ya da o satirin uzerinde ESC ile - once tab kayit kesinlessin, ya da [Ctrl+W] ile ki bu en kestirmesi).

Bu basit ama efektif bir baslama koduydu. VFP'nin baslik satirinda simdi 'VFP ogreniyorum1' gouyor olman lazim. Command windowda:

CD [enter]

yaparsan su anki icinde oldugun dizini yazacak.

c:\VFPTestProjects\VFP ogreniyorum1

degilse bir yanlislik yaptin. Dogru oldugunu varsayarsak. Yeni projelerinde butun yapman gereken acilista [Ctrl+Y] ile kayit ekleyip, Caption ve Path'i girmen. Boylece bir dahaki acilista yazmaktan kurtuldugun 2 satir var:) Ama inan bana o 2 satir cok bayiyor zamanla. Hem yazdigimiz o 'baslat.prg' zamanla istersen daha karmasik isleri de icerebilir ve her acilista calisan kucuk bir ortam hazirlama programi.
Kayitli projelerin icin sadece acilista ilgili satira git, esc'e bas. Birden fazla projeyle calisirken, N tane VFP acabilir, ayni sekilde ilgili satira gider ESC'e basarsan, her biri hangi proje oldugunu "baslik"ta gosterecek. Aralarinda dolasmasi kolay oluyor sonra Alt+Tab ile.

Baslamadan son aciklama. VFP'de
satir basinda * o satirin kullaniciya not (comment) oldugunu soyluyor. Oraya kendine ait notlari yaziyorsun.
Satir icinde && kullanirsan ondan sonraki hersey yine not (inline comment).
; (notali virgul - semicolon) kodun alt satirda devam ettigini belirtiyor - gorunmeyen bolume tasmasin diye.
Genelde programlar:

Visual Fox Pro
* Bu kod sunu bunu yapar

use myTable && myTable dosyasini ac
scan && tabloyu taramaya basla
  if isim = 'Ahmet' and ;
     tarih > {^2007/1/31}  && isim Ahmet ve tarih 31 Ocak 2007'den sonra ise
* Burada uyan kayit icin birsey yapilacak
  endif
endscan

gibi bunlari kullaniyor (ben o kadar detay aciklama koymam tembellikten ama yapabilrsen bastan alis:)

Komutlar tek kerelik seylerse dogrudan command windowda yazip [enter]. Aninda calisir. Hata yoksa herhangi bir mesaj alman gerekmiyor (komutuna bagli). Hata varsa hic merak etme VFP mutlaka mesaji verir:)
VFP'nin diger bir ozelligi, bir program blogunu ister command window'da, ister bir kod penceresinde olsun secip, right click, 'Execute selection' ile calistirabilmesi. Boylece kodunu daha yazarken yer yer test edebilirsin.

Modify Command [enter]

ile bir kod penceresi acarsan, buraya yazip, secip calistirmanin avantaji yavas yavas orada deneyip istersen saklamak. Command window'da yaziyorsan yeni satira gecmek icin:
[enter] yerine [Ctrl+enter] kullan. Yoksa enter'a bastigin anda o 'satir' komut calisacak. Ornek (command windowda yaziliyor):

Visual Fox Pro
for ix = 1 to 10 [Ctrl+Enter]

   ? m.ix [Ctrl+Enter]
   ? "Bu string iki satir"+; [Ctrl+enter]
      " olarak yazildi" [Ctrl+enter]
endfor [Ctrl+Enter]

-Blogu sec. Right click, Execute selection.
Ya da daha kisasi (sadece command windowda):
-Blogu sec. [Enter]

Bundan sonra yazarken ozellikle Command window demediysem bu kurallara gore ve saklayip istememene bagli olarak birini kullan. Satir sonuna [enter] yazmiyorum artik. Command windowda ise hemen calisacak (zaten bir kismi da hemen calismasini istedigimiz tek bir defa yapilacak isler). Satirlarda *, && ile ekledigim notlar aciklama icin o kismlari yazmana gerek yok keyfe keder. Bir de command window yazdiklarini sakladigindan orada dogrudan yapip sonra blogu secip istedigin bir kod penceresine kopyeleyip saklama sansin var. VFP kapatsan da o kodlari sakliyor:)

Uyari: Yapacagimiz uygulama islerin nasil yapilmasi gerektigini dogru olarak gostermiyor. Database dizayni bile kotu aslinda. Sayfalardir yazdigima bakma normalde VFP'yi acip bu uygulamayi hazirlayip exe haline getirmesi 5dk filan surer ve yeni install edilmis bir VFP9 ile yapilabilecek bir uygulama. Simdilik sadece suya ayagimizi alistiriyoruz ve kumda oynuyoruz, o gozle bak. Herseyi yaziyla gonderebilmek icinde hepsi kod olarak. Normalde gorsel ortamda cok daha basit olan seyler burada karmasik gibi. Mesela form yazilirken ADD OBJECT satirlari olacak, sonrasinda da bir suru top,left vs. Form dizayncisi ile bu is aslinda toolbardan ilgili olani sec, formda istedigin yere klikle koy seklinde.
Procedure btnEkle.Click
...
endproc

gibi bir kod gordugunde o da:
-Formda btnEkle adli butona cift klik, sol ustte 'btnEkle', sag ustte 'Click' oldugundan emin olup (degilse degistir) o ... ile belirtilen kodu oraya yaz demek. Yaz, yapistir dedigim yerlerde copy&paste yerine hakikaten yazarsan VFP'nin kod editorune alisirsin, hata yapma sansi da var. Hatalarla nasil ilgilenilecegi ise gelecekte insallah:)

(Ben bayildim hala projeye baslayamadik diye, umarim sen hala oradasindir, basliyoruz:)

1) Once datayi hazirlayalim. N tane yolu var. Ben kolayima geleni yapiyorum.

* Uygulama database'ini yarat
create database ("data\BasitData") && data alt dizinimizde BasitData.dbc database dosyasini yarat
* Tablolarin kullanacagi bir kodumuz var - once onu yarat
Modify Procedures

* Acilan kod penceresine yaz, sakla, kapat

Visual Fox Pro
Procedure GetRowKey

Local pGUID,rGUID
Declare Integer UuidCreate In 'RPCRT4.dll' String @pguid
Declare Integer StringFromGUID2 In 'Ole32.dll' ;
  string rguid, String @lpsz, Integer cchMax
 
pGUID=Replicate(Chr(0),16)
rGUID=Replicate(Chr(0),80)
 
UuidCreate(@pGUID)
StringFromGUID2(pGUID,@rGUID,40)
RETURN Strconv(Left(rGUID,76),6)
endproc

* Tablolari yarat. Iki tablo.
* 1.Tablo kisi bilgileri icin.

Visual Fox Pro
create table ("data\kisi") ;

  ( kisiID c(38) default GetRowKey(), ;
    ad c(15), ;
    soyad c(15), ;
    dogumTarihi d, ;
    telefon c(20), ;
    adres m )


* Indexler

Visual Fox Pro
index on upper(ad) tag ad

index on upper(soyad) tag soyad
* Primary key
alter table ("kisi") add primary key kisiID tag kisiID

* 2. tablo. Geldigi tarih, toplam alisveris tutari

Visual Fox Pro
create table ("data\AlisVeris") ;

  (alisverisID c(38) default GetRowKey(), ;
   kisiID c(38), ;
   tarihvesaat t, ;
   tutar y)
index on kisiID tag kisiID
* Primary key
alter table ("alisveris") add primary key alisVerisID tag alVerID
* kisiID indexi ile kisi tablosu kisiID primary key'i iliskilendir
alter table ("alisveris") ;
add foreign key tag kisiID ;
references kisi tag kisiID

-Tablolar hazir. Form yapalim. Command window
Create Form ("forms\Kisi")

-Form'da right click. Dataenvironment.
-"Kisi" tablosunu sec, Add, Close.
-Dataenvironmentta kisi tablosu secili iken, Properties penceresinde (adi PEM sheet)
Buffermodeoverride: 5
-KisiID disindaki tum fieldleri sec (click,shift+Click, ctrl+Click kullanarak)
-Secili fieldleri SAG mouse tusuyla formun uzerine surukle birak
-"Create Multiple Controls here" sec.
-Bundan sonra gorsel olarak yerlesimleri, caption propertyleriyle istedigin gibi oyna (ya da simdilik birak oldugu gibi kalsin).
-Dataenvironment'i (DE) kapat.
-Formun caption properysini: "Kisi ekleme,silme vs" yap (duzgun birsey bul iste:)
-Simdi bir dizi is yapan dugme ekleyelim (unutma ideal ile ugrasmiyoruz sadece basit calisan birsey simdilik. Olmasi gereken sekil sonra zamanla gelisir testlerden gerceklere gecerken).
-Toolbardan 4 tane buton ekliyoruz. Bu durumda toolbarda once CommandButton kontrolune klikle, sonra da en sagdaki 'Kilit' ikonuna.
-Formda oncekilerin altinda bu butonlari koyacagin yerde (formu gerekiyorsa buyut once sag-alttan cekerek) klikle (toplam 4 klik).
-Simdi toolbarda 'ok' ikonuna klikle.
-Butonlara sirayla klikleyerek 'Caption' lara sirayla:
Ekle,Sil,Sakla,Geri Al
yaz.
Name propertylerini de sirayla:
btnEkle, btnSil, btnSakla, btnGeriAl
yap.
-Toolbardan hemen CommandButton yanindaki 'Command Group'a klikle, formda onceki butonlarin altinda bir yere klikleyerek forma ekle.
-Yeni ekledigin 'Command Group'a sag klik, Builder.
-Number of buttons:4
-Altindaki gridde captionlari:
Ilk,Onceki,Sonraki,Son
Olarak yaz.
-Layout sec. Horizontal, OK.
-Name'ini de 'btnGrpNav' olarak degistir.

Isim degisiklikleri zorunlu degil ama VFP'nin verdikleriyle hayat zor.

-Simdi kodlarini yazalim.
-Once Form'un Load metodu (kisaca Form.Load)
-Form'a dblClick. Otomatikman 'Load' event kod penceresi gelmesi lazim. Sag ustten kontrol et. Degilse oradan Load sec.

Visual Fox Pro
Set Talk Off

Set Deleted On
Set Century On
Set Multilocks On
Set exclusive off


-Yaz.
-Form.Init kodu icin sag ustteki combodan 'Init' sec

Visual Fox Pro
SELECT kisi

store !EOF('kisi') to ;
this.btnSakla.Enabled, ;
this.btnGeriAl.Enabled, ;
this.btnSil.Enabled
this.btnGrpNav.SetAll('Enabled',!EOF('kisi'))


-Yaz. Kapa.
-Menuden Form\New property
Name:aktifKayit
Default/Initial value:0

[Add], [Close]

-Ekle butonuna dblklik
-Acilan kod penceresine:

Visual Fox Pro
thisform.aktifKayit = RECNO('kisi')

insert into ("kisi") (Ad,Soyad) values ("[Yeni]","[Yeni]")
store .F. to ;
this.parent.btnEkle.enabled, ;
this.parent.btnSil.enabled
store .T. to ;
this.parent.btnSakla.Enabled, ;
this.parent.btnGeriAl.Enabled
this.parent.btnGrpNav.SetAll('Enabled',.F.)
thisform.Refresh()
this.Parent.txtAd.SetFocus()


-Yaz kapa.
Diger kodlar (ayni sekilde butona dblklik ile kod penceresini ac, sag ustten gerekiyorsa ilgili kod'a git ve yaz)
*btnSakla Click

Visual Fox Pro
Tableupdate(2,.F.,'kisi')

Store !Eof('kisi') To ;
  this.Parent.btnSakla.Enabled, ;
  this.Parent.btnGeriAl.Enabled, ;
  this.Parent.btnSil.Enabled
This.Parent.btnEkle.Enabled = .T.
This.Parent.btnGrpNav.SetAll('Enabled',!Eof('kisi'))
Thisform.aktifKayit = Recno('kisi')

*btnSil Click

Visual Fox Pro
If !Eof('kisi') And ;

    MESSAGEBOX("Emin misiniz? Siliyorum ha, ona gore.",4+32+256,"Gereksiz soru",5000) = 6
  Delete In 'kisi'
  Skip In 'kisi'
  If Eof()
    Go Bottom In 'kisi'
  Endif
  Store !Eof('kisi') To ;
    this.parent.btnSil.Enabled
  this.parent.btnGrpNav.SetAll('Enabled',!EOF('kisi'))
  thisform.aktifKayit = IIF(EOF('kisi'),0,RECNO('kisi'))
  thisform.Refresh() 
Endif


* btnGeriAl Click

Visual Fox Pro
Tablerevert(.F.,'kisi')

If Thisform.aktifKayit != 0 And ;
    RECNO('kisi') != Thisform.aktifKayit
  Go Thisform.aktifKayit In 'kisi'
Endif
Store !Eof('kisi') To ;
  this.Parent.btnSakla.Enabled, ;
  this.Parent.btnGeriAl.Enabled, ;
  this.Parent.btnSil.Enabled
This.Parent.btnEkle.Enabled = .T.
This.Parent.btnGrpNav.SetAll('Enabled',!Eof('kisi'))
Thisform.Refresh()


* btnGrpNav Click

Visual Fox Pro
Select kisi

If Recno('kisi') < 0 Or At('2', Getfldstate(-1,'kisi')) > 0
  If Messagebox("Degisikligi saklayayim mi?",4+32,"Degisiklik yakalandi") = 6
    Tableupdate(2,.F.,'kisi')
  Else
    Tablerevert(.F.,'kisi')
  Endif
Endif
Do Case
  Case This.Value = 1 && ilk
    Locate
  Case This.Value = 2 && onceki
    Skip -1
    If Bof()
      Locate
    Endif
  Case This.Value = 3 && sonraki
    If !Eof()
      Skip
    Endif
    If Eof()
      Go Bottom
    Endif
  Case This.Value = 4 && son
    Go Bottom
Endcase
Thisform.aktifKayit = Iif(Eof('kisi'),0,Recno('kisi'))
Thisform.Refresh()

-Son olarak. Form'un bos bir yerine klikle (PEM sheetde formun adi gorunecek, degistirmediysen Form1 - form ikonuyla). DataSession propertysini 2 yap.

Formun calistirilmaya hazir (aslinda her hangi bir anda calistirabilirsin, nerede ne eksik ya da hatali gorup duzeltirsin). Bos bir yere sag klik ve 'Run Form'. Saklayayim mi diye sorarsa (su anda soracak cunku bir suru degisiklik oldu), Yes.
Kabaca bak. ve kapat. Dizayndaki formu da kapat.

Command Window'a gidip.
Close all
do form kisi

Istedigin gibi oyna:)

Bunca zamandir tek bir form yaptik. Onu da cok uzattik. Ustune ustluk kodlarda bir suru tekrar vs var. Ama cok fonksiyonel olmasa ve tamamiyle aslinda bitmis olmasa da calisan birsey var:)

Acikcasi yazmaktan yoruldum. Simdilik bu kadarla kesip devamina baska bir mesajda bakalim. Arada forumdaki diger arkadaslarin da yardimiyla, ne, nerede, nasil aciklamalari olur. Kod tekrarinin engellenmesi, benzeri isin tekrar tekrar baska formlarda yapilmamasi gibi seyler de daha sonra.

Yapilan formu bozmaktan vs korkma, ekle, cikar, ne oluyor bak. Tabii once calisan bir halini saklarsan iyi olur. Saklayacagin iki dosya:

c:\VFPTestProjects\VFP ogreniyorum1\Forms\kisi.scx
c:\VFPTestProjects\VFP ogreniyorum1\Forms\kisi.sct

18 Son düzenleyen, ugurlu2001 (14.01.2008 09:55:50)

Re: Yeni başlayanlar ve Foxpro 2.x'ten geçenler için VFP

Çetin Üstadım ellerinize sağlık;

Haftaya güzel bir başlangış oldu;

Addbs komutunu;
" - " Operatörünün string ifadelerinde kullanımını;
Command Window içerisinde [ Ctrl ] + [Enter ] kombinasyonunu;
Proje içerisinde çalışltığım uygulamanın Başlıkta görünmesini;
Store komutunun uygulamada kullanılmasını

Öğrenmiş ve pratikte denemiş oldum.

Aşağıdaki kod sanırım unique ID oluşturmak için ve beni aşıyor. Biraz bilgi istesek çok mu olur?


Visual Fox Pro
Procedure GetRowKey

Local pGUID,rGUID
Declare Integer UuidCreate In 'RPCRT4.dll' String @pguid
Declare Integer StringFromGUID2 In 'Ole32.dll' ;
  string rguid, String @lpsz, Integer cchMax
 
pGUID=Replicate(Chr(0),16)
rGUID=Replicate(Chr(0),80)
 
UuidCreate(@pGUID)
StringFromGUID2(pGUID,@rGUID,40)
RETURN Strconv(Left(rGUID,76),6)
endproc

Ben şu kadar satırı yazıyorken bile zorlandım. Senin gibi temposu bu kadar yoğun olan bir bilgi küpünün benim gibi arkadaşlar için sarfettiği emeğe söyliycek kelimeleri gerçekten bulamıyorum.

Sağolun Üstadım smile

Uğur
-------------------------------------------------------------------------------------------------------------
Hayat bir bisiklete binmek gibidir. Pedalı çevirmeye devam ettiğiniz sürece düşmezsiniz. Claude Peppeer
Kusuru söylenmeyen adam, ayıbını hüner sanır.  Türk Atasözü

19

Re: Yeni başlayanlar ve Foxpro 2.x'ten geçenler için VFP

valla çetin hocam  GUID olayı hakikaten mükemmel oldu.Çok işe yarayacağı kesin.Bilgileriniz için teşekkür ederiz.devamını bekleriz

En büyük sermaye nakit,nakit sermaye vakittir...

20 Son düzenleyen, cetinbasoz (14.01.2008 14:36:51)

Re: Yeni başlayanlar ve Foxpro 2.x'ten geçenler için VFP

Ugur,
Evet o kod unique ID olusturmak icin. Windows API'lerinden o isi yapmasini istiyor.

UuidCreate ve StringFromGUID2 windows API fonksiyonlari. Windows API kullanmak icin once 'declare' ile yuklenmesi gerekiyor.


Declare Integer StringFromGUID2 In 'Ole32.dll' ;
  string rguid, String @lpsz, Integer cchMax

Bunu yazarken MSDN libraryden once syntaxina ne isteyip ne dodurdugune, hangi dllde tanimlandigina filan bakiyorsun. MSDN'de orijinal syntax:

"This function converts a globally unique identifier (GUID) into a string of printable characters.

StringFromGUID2(
  REFGUID rguid,
  LPOLESTR lpsz,
  int cbMax
);
Parameters
rguid
[in] Interface identifier to be converted.
lpsz
[out] Long pointer to the resulting null-terminated string on return.
cbMax
[in] Character count of the string indicated by lpsz.
Return Values
Nonzero indicates the number of characters in the returned string, including the terminating null character. Zero indicates that the buffer is too small for returned string."

Biraz zamanla o parametre tiplerinin ne demek oldugunu filan ogreniyorsun:) "Out" olanlar icin tanimda ve gercek cagirimda 'by reference' icin @ isareti kullanip kullaniyorsun. "Out" ise once VFP'de degisken yaratilmis ilmali onun icin gerekli uzunluk ve tipte degiskeni tanimlayip kullaniyorsun.

pGUID=Replicate(Chr(0),16)
rGUID=Replicate(Chr(0),80)

Out olanlar icin yani. API kullanimi bol bol deneme daha cok yanilma vs ile zamanla ogreniliyor:)
(VFP bizzat kendisi bu APIleri degisik fonksiyonlarinda kullaniyor arka planda, kullanip isi kolaylastirdigi fonksiyonu olmadiginda boyle sen dogrudan kullaniyorsun. Ornegin sys(0), ID(), OS(), copy file ... hep winAPI cagiriyor).

O rutini SP filan olmasa da soyle bagimsiz test edebilirsin:

Visual Fox Pro
Declare Integer UuidCreate In 'RPCRT4.dll' String @pguid

Declare Integer StringFromGUID2 In 'Ole32.dll' ;
  string rguid, String @lpsz, Integer cchMax
 
Local ix
Create Cursor test1 (testID c(38))
For ix=1 To 100000
  Insert Into test1 Values ( GetRowKey() )
Endfor
 
Create Cursor test2 (testID c(38))
For ix=1 To 100000
  Insert Into test2 Values ( GetRowKey() )
Endfor
 
* Iki adet cursor ikisinde de
* 100000 kayit, hepsi GUID
* Eger bir tek deger bile tekrarlamissa
* guvenilir degil.
* Ne ayni dosya icinde tekrar olmali ne de iki
* dosyada biribirine uyan kayit
 
* Ayni dosyada kayit kontrolu
Select Distinct testID From test1 Into Cursor tekID1 nofilter
? Reccount('tekID1'), Reccount('test1') && ikisi de 100000 olmali
 
Select Distinct testID From test2 Into Cursor tekID2 nofilter
? Reccount('tekID2'), Reccount('test2') && ikisi de 100000 olmali
 
* Iki cursorda uyan kayit var mi?
Select Cnt(*) ;
  FROM test1 ;
  INNER Join test2 On test1.testID == test2.testID
* Sifir alman gerekli
 
Procedure GetRowKey
  Local pguid,rguid
 
  pguid=Replicate(Chr(0),16)
  rguid=Replicate(Chr(0),80)
 
  UuidCreate(@pguid)
  StringFromGUID2(pguid,@rguid,40)
  Return Strconv(Left(rguid,76),6)
Endproc

Not: Test kodunda 'declare' satirlari fonksiyon icinden kaldirilip kodun basinda. Kullanilacak winAPI bir kere declare edildi mi, clear DLL < DLL adi > olana kadar uygulamanin her yerinde gecerli (sanki public gibi). Declare satirlari milisaniye de olsa zaman harciyor. 100000 tane icin bu zaman toplamda cok tutar. Onun icin disari aldik. SP durumunda nasil olsa herhangi zamanda ustuste binlerce kayit insert edilmeyecegini dusundugumuzden decalre dogrudan icinde (zaten declare edilmisken bir daha cagirmann sakincasi yok). Disaridan import gibi data aliyorsak o zaman SP yerine yukaridaki gibi once declare edip, sadece kullanan fonksiyon versiyonu  kullanilabilir (bu arada makine hizli degilse, yukaridaki ornegi 100000 yerine daha dusuk bir degerle dene:)

21

Re: Yeni başlayanlar ve Foxpro 2.x'ten geçenler için VFP

Üstad çok teşekkür ediyorum. smile

Uğur
-------------------------------------------------------------------------------------------------------------
Hayat bir bisiklete binmek gibidir. Pedalı çevirmeye devam ettiğiniz sürece düşmezsiniz. Claude Peppeer
Kusuru söylenmeyen adam, ayıbını hüner sanır.  Türk Atasözü

22

Re: Yeni başlayanlar ve Foxpro 2.x'ten geçenler için VFP

Çetin hocam
Benim bir isteğim var.

SQL e yeni başlayanları için bir temel giriş alırsak çok memnun olacağım 2-3 aydır tırmalayıp duruyorum.

Bugün sırf tarih için 2 saatim gitti. datetime ı date e çevirmek için.(halen çeviremedim tabii)

Bilmediğin Neyse Yanıldığındır.

23 Son düzenleyen, cetinbasoz (17.01.2008 02:22:12)

Re: Yeni başlayanlar ve Foxpro 2.x'ten geçenler için VFP

SQL server ve VFP gercekten cok buyuk bir konu. Olayın iki boyutu var:
1) SQL server T-SQL,osql,isql,SQL-DMO,SMO ... her biri baslibasına bir konu.
2) VFP ile SQL server kullanma. Bunun da birden fazla yolu var.

2.den başlarsak, ideal yöntemin hangisi olduğunu (ki bence tek bir ideal yöntem yok, duruma göre seçmek en iyisi) bir kenara bırakıp sadece çalışan yöntemler ve birkaç ipucuna gireyim. SQL serverla sürekli çalışan arkadaşlar da eklentiler yapar, yuvarlanır gideriz:)

Önce biraz terminoloji gerekiyor.
SPT - SQL pass through. SQLConnect(),SQLStringConnect(),SQLExec() ... serisi fonksiyonlarla kullanılan erişim yöntemi. Tamamen kodla. Herhangi bir dizaynci yok. Yeni başlayanlar için zor gibi ama programcıya en fazla kontrolu verenlerden biri.
RV - Remote view. Normal database dizayncısı kullanılarak da oluşturulabilen tablolar. Oluşturduktan sonra database'deki "view"lar sanki VFPnin kendi tablolarıymış gibi kullanılıyor (hemen hemen). Yeni başlayanlar için en kolay yöntemlerden (özellikle VFP7 veya öncesi için).

SPT ve RV sadece ODBC kullanan yöntemler. ODBC sürücü olan herşeye bağlanabilir, kullanabilir (SQL server, Oracle, DB2, mySQL, ... Foxpro (VFP7 ve oncesi formatlar), excel, düz metin ...)

ADO - ActiveX serisinden. Kendisine has bir property/event/metod serisi var. OLEDB sürücüsü olan her yere (SQL server, Oracle, ... VFP, ... düz metin, XML ..., Excel, bazı OS servisleri, LDAP ve ADSI ...) bağlanabiliyor. VFP veya herhangi bir RDBMS'in dogrudan okuyamadığı field ve tablo formatlarını kullanabiliyor (örneğin NT ActiveDirectoryServislerinde kullanılan multivalue (çok değerli) alanlar, chapter adı verilen kendi içinde başa bir "tabloya" ilişki kuran alanlar vs).
Tabloları "Recordset" adında (class:ADODB.Recordset) ve obje olduğu için katmanlar arasında seyahat edebiliyor (örneğin VFP stored procedure veya olepublic class içinden yaratılan bir recordset obje olarak VBye gidebilir veya tersi). ADODB.Stream classıyla kablolarda gidebilir (nasıl soyleyecegimi bilemedim:) yani netde seyahat, dosya acıp okuma yazma vs.
ADO VFP kullanıcılarına pek yakın değil çünkü VFPciler rahatlıkla grid,textbox ... bağlanabilen, scan ... endscan, locate, replace gibi xBase komutları ve Select/Update... gibi SQL komutlarını anlayan tablo/cursorlere alışkın:) Bu kadar uzun anlatmamın nedeni bazen de VFP içinden bile çok kıymetli olması. Ömrüm yeter de ileride değinebilirsem kod örnekleriyle de gösteririm (ya da isteyen şimdiden msdn.microsoft.com/forums, foxite.com, universalthread.com ... sitelere postalanan tonlarca örneği bulup bakabilir:) Burada da örnekler var (mesela HFlexGrid örneği).

(Ufak ipucu: VFP OLEDB sürücüsü VFPOLEDB VFP9 dahil tüm VFP formatlarını tanımasının yanısıra, VFP9 data motorunu içeriyor. Hani dara düştünüz, elinizde VFP9 yok, hatta VFP bile yok, hatta yeni install edilmiş bir windows ve internet bağlantınızdan başka birşey yok, o zaman VFPOLEDB'yi MS sitesinden indirip kurmak size çok kapılar açabilir:) - basit bir örnek VFP6 içinde cast() olan, birsürü subqueryli SQLleri desteklemiyor. VFP9 destekliyor. VFP6'da yapmanın bir yolunu da bulamadıysanız ADO kullanarak VFP9'a sorun:) Ya da müşteridesiniz bir dbf içine bakacaksınız ama bakmak için o an birşey bulamadıysanız hemen notepadde VFPOLEDB kullanan bir htm yazın. Bakmanın yanısıra datayı güncellemek, eklemek, silmek de serbest. -Reklamlar-


CA - CursorAdapter. VFP8 ve 9'un yeni gözdeleri. ODBC, ADO, XML, Native (VFP'nin kendisine ait olan database/tablolar) içinden herhangi bir teknolojiyi bağlantı yöntemi olarak kullanabiliyor. CA, SPT ve RV gibi dogrudan kullanabileceginiz cursorlari yarattığı ve yalnızca ODBC kullanmadığı, bir class olup subclass yaratılabildiği, sadece bağlantı özellikleri ve birkaç propertysi değiştirilerek çok farklı datalarla çalışabildiği ve başka birtakım özellikleri nedeniyle yeni esas oğlan (ADO CA ile kullanılabildiğinden ADO programlanın gene arka planda kalması sakıncası herhalde:)

Hangisini kullanırsanız kullanın, temel iki komponent var:
1) Veri kaynağına bağlantı (Data source connection)
2) Bağlantı üzerinden DML - Data Manipulation Language ( veri işleme dili. İşlenmesi CRUD operasyonları ile - Create Retrieve Update Delete veya insert, select, update, delete ), DDL ( Data Definition Language - veri tanımlama dili. Create table, alter table, create procedure ... ) gibi bir seri farklı işlerin yapılması.

Neyse şimdi bu kısa (nasıl kısaysa) açıklamadan sonra koşmadan yürüyelim. Hep birşey vardır içimizde, "bana ufak bir başlangıç örneği versinler gerisini çözerim" diye. Bu onun gibi birşey olacak. Tabii en baştan biriki ufak ipucu da var.

SPT: Yürümeye buradan başlayın. Birçok ileri kullanıcının hala koşmak için seçtiği de SPT:) Hikaye kısmı bitti koda giriyoruz (MS SQL server kodları ancak diğer databaseler için de hemen hemen aynı):

Bağlantı:
SQLConnect() veya SQLStringConnect() ile. Kısa tutamak için SQLConnect'i boşverin.

handle = SQLStringConnect("Driver=SQL server;server=.;Trusted_connection=yes")

SQL 2005 express ve SQL 2008 CTP Express ücretsiz indirilip kullanılabilen versiyonlar olduğuna göre SQL2005 express install değerleriyle devam edelim. Ornek databaselerin kurulmadığını farzediyorum. Kendi databaseimizi yaratıp VFP den biraz datayla dolduralım. Doldururken özellikle de tarih tipiyle ilgilenelim:) Yazılan kodlar o şekliyle çalışmıyorsa bir yerde yanlışlık vardır, sorun. Her bloğu çalışacak şekilde yazıyorum (arada da hata kontrolu nasıl olacak o var).

Visual Fox Pro
handle = SQLStringConnect("Driver=SQL native client;"+;

    "server=.\SQLExpress;Trusted_connection=yes")
* kodlar
SQLDisconnect(m.handle)

Eğer çalıştıysa tebrikler SQL serverla ilk konuşma:) Sadece bağlanıp, ayrıldınız ama yolun yarısı (yalan).

SQL server'in da T-SQL dili var ve ona özgün syntax:

SQL
SELECT ad,soyad,[NOT]

-- SQL serverda iki tire ile başlayan bölümler programcıya not.
-- Garip görünse de boyle bir selectin içinde bile serbest (galiba birtek bana garip geliyor)
FROM BenimServer.[Benim Sevgili Databaseim].BenimŞema.[Müşteri Bilgileri] musteri
WHERE [NOT] LIKE '%izmir%'
AND dogumTarihi BETWEEN '19400101' AND '19501231'
 
-- SQL server tablo adları 4 parcalı.
-- tüm parcalar her zaman gerekil degil.
-- Baglantı sırasında database belirtilmiş olabilir
-- o zaman genelde sadece tabloadı gerekli
-- 4 parca sekli dosyaların tam yol adı gibi

Kodda dikkati çekenler:
1) Bazı yerlerde [] var. Bu tum alan adları, database, tablo adı ... gibi yerlerde kullanılabiyor. SQL server'a bu senin keyword'un değil benim kullandığım birşey ve içindeki boşluk dahil bir bütün anlamında. Normalde "not" bir keyword hem de işlenme önceliği yuksek olanlardan birisi. Yukarıda alan adı olarak [not] şeklinde kullanıldı (gene de kullanmayın - halletmesi her yerde basit değil).

[Müşteri Bilgileri] içinde boşluk olan tablo adı. Bunu da kullanmayın ama sonucta SQL serverda bunları nasıl kullanabiliriz derseniz boyle. []'lar diger alan adlarında filan da kullanılabilir ve hatta kullanmayı alışkanlık etmekte fayda var.

2) Satır sonlarında bizim alıştığımız ; yok. T-SQL'de yukarıdaki tek bir SQL select komutu. Bitişini SQL nasıl anlıyor? Ne bileyim çok zeki. Anlıyor işte:) Aslında kullanımı serbest olsa da arada kullanıp onu rahatlatacagınız (bazen de hakikaten gerekli bitişi o ayıramayacagı için) sembol ";" smile

SQL
SELECT * FROM customer

SELECT * FROM employee


Aşağıdaki ile aynı

SQL
SELECT * FROM customer;

SELECT * FROM employee;

3) Stringler tek tırnak içinde. VFPdeki gibi çift tırnak ya da [] kullanamazsınız. Onların anlamları farklı. Çift tırnak da [] gibi iş görüyor (set quoted... ON bağımlı).

4) SQL server tırnak içine yazılmış tarihleri anlıyor. Yukarıdaki basit bir kullanımı. Aslında her yerde her formatı olmasa da birçok değişik stringin tarih olduğunu anlıyor. Kullanımı en sağlam olan ODBC canonical format denen 'YYYYMMDD hh:mm:ss' şekli.

Yukarıda tek bir Select komutu var. VFP programlarında olduğu gibi bir sürü komut da olabilirdi. Bir sürü komut içinde de birden fazla "select" olabilirdi. Bu kodların hepsi birden çalıştırldığından SQL batch (yığın) adı veriliyor ve atomik bir ünite olarak çalışıyor. Geriye de birden fazla cursor dondurebilir.

Gene dağıttım kendimi:) Aşağıda örnek olarak database ve tablolar  yaratıp biraz veri koyalım. Yukarıdaki gibi T-SQL gecerli olduguna gore onu yazmanın en kolayı text...endtext.

SQL
lnHandle = Sqlstringconnect("Driver=SQL Native Client;"+;

  "Server=.\sqlexpress;trusted_connection=yes;")
IF m.lnHandle < 0
  Messagebox("Baglanamadik")
  RETURN
Endif
 
IF SQLExec(m.lnHandle, "CREATE DATABASE [VFP_ile_SQL]") < 0
  HataGoster(m.lnHandle)
Endif
 
SQLExec(m.lnHandle, "use [VFP_ile_SQL]")
 
TEXT TO m.lcCreateTable noshow
CREATE TABLE isim (
[isimID] uniqueidentifier ROWGUIDCOL DEFAULT newId() PRIMARY KEY,
[ad] varchar(15),
[soyad] varchar(15),
[dogumtarihi] datetime NULL,
-- hesaplanan kolon
[yas] AS datediff(year,dogumTarihi,getdate())
);
 
CREATE TABLE vizit (
  [vizitID] uniqueidentifier ROWGUIDCOL DEFAULT newId() PRIMARY KEY,
  [isimID] uniqueidentifier,
  [tarih] datetime DEFAULT getdate(),
  [notlar] varchar(MAX)
  );
 
ENDTEXT
 
IF SQLExec(m.lnHandle, m.lcCreateTable) < 0
  HataGoster(m.lnHandle)
Endif
 
TEXT TO m.lcInsertIsim noshow
  INSERT INTO isim
     (isimID, ad,soyad,dogumTarihi)
     VALUES
     (?m.isimID, ?m.ad,?m.soyad,?m.dogumTarihi)
ENDTEXT
TEXT TO m.lcInsertVizit noshow
  INSERT INTO vizit
     (isimId,tarih,notlar)
     VALUES
     (?m.isimid,?m.tarih,?m.notlar)
ENDTEXT
 
isimID = GetRowKey()
ad = "Ali"
soyad = "Veli"
dogumTarihi = Date(1940,1,15)
SQLExec(m.lnHandle, m.lcInsertIsim)
tarih = Datetime(2007,1,1,10,30)
notlar = "Uzun uzun hikaye"
SQLExec(m.lnHandle, m.lcInsertVizit)
 
isimID = GetRowKey()
ad = "Mehmet"
soyad = "Kucuk"
dogumTarihi = .NULL. && empty yok - ya NULL ya da bir date/time
SQLExec(m.lnHandle, m.lcInsertIsim)
tarih = Datetime(2007,10,1,20)
notlar = "Uzun uzun hikaye 2"
SQLExec(m.lnHandle, m.lcInsertVizit)
tarih = Datetime(2007,11,5,8,30)
notlar = "Uzun uzun hikaye 3"
SQLExec(m.lnHandle, m.lcInsertVizit)
 
SQLDisconnect(m.lnHandle)
 
Procedure HataGoster(tnHandle)
  LOCAL Array aHata[1]
  LOCAL ix,lcHata
  Aerror(aHata)
  SQLDisconnect(m.tnHandle)
 
  lcHata = ''
  FOR ix = 1 TO 7
    lcHata = m.lcHata + Transform(aHata[m.ix]) + Chr(13)
  Endfor
  Messagebox(m.lcHata)
 
  Cancel
Endproc
 
Procedure GetRowKey
  LOCAL pguid,rguid
  Declare Integer UuidCreate IN 'RPCRT4.dll' String @pguid
  Declare Integer StringFromGUID2 IN 'Ole32.dll' ;
    string rguid, String @lpsz, Integer cchMax
 
 
  pguid=Replicate(Chr(0),16)
  rguid=Replicate(Chr(0),80)
 
  UuidCreate(@pguid)
  StringFromGUID2(pguid,@rguid,40)
  RETURN Strconv(LEFT(rguid,76),6)
Endproc

Ne yaptıgımıza tekrar baglanıp bakalım:

SQL
lnHandle = Sqlstringconnect("Driver=SQL Native Client;"+;

  "Server=.\sqlexpress;trusted_connection=yes;")
 
TEXT TO m.lcQuery noshow
SELECT * FROM [VFP_ile_SQL]..isim;
SELECT *,
  CAST(notlar AS varchar(200)) AS not2
  FROM [VFP_ile_SQL]..vizit;
ENDTEXT
 
SQLExec(m.lnHandle, m.lcQuery, "SQLTablo")
SQLDisconnect(m.lnHandle)
 
SELECT SQLTablo1
INDEX ON isimID Tag isimID
 
Browse Name altGrid Nowait
 
altGrid.Top  = 400
altGrid.LEFT = 400
 
SELECT SQLTablo
SET Relation TO isimID INTO SQLTablo1
Browse

kapatmadan önce bir iki not ve ipucu:

Text ... endtext arasına yazmak guzel özellik ve aslında SQL server'in bir tek kerede işleyebileceği o tip kod (SQL batch) VFP'nin limitlerini aşacak ölçüde uzun olabilir (ama en azından benim yazmaya ömrüm yetmez eğer elle yazıyorsam).
O kodları daha onceden yazıp çalıştırarak deneyebilseniz, hatta kodunuz VFPdeki gibi renklense, hatta kolay yazım ortamı filan olsa güzel olmaz mıydı:)

Ipucu: SQL2005/2008 Management Studio (new query) SQL2000 Query Analyzer pencerelerinde kodunuzu yazabilir, tumunu ya da bloğu secip çalıştırabilirsiniz (parametreler yerine sabit koyun geçici olarak). Hatta oradaki templatelerden filan yararlanırsınız. Sonra da çalışan kodunuzu copy&paste ile getirir text...endtext arasına koyarsınız. Her zaman her kod bloğuyla olmasa da bence harika yontem.


VFPde degiskenlere koydugumuzu ? isaretleri sayesinde parametre olarak gonderiyoruz.

İpucu: C#,VB.Net express versiyonları da ücretsiz. Program yazmak için kullanmasanız bile basit bir SQL bağlantılı grid yapmaya kalkarsanız basmaklardan birinde size seçilen tablo için "Update/Insert/Delete" komutlarını uretme şansı veriyor. Bizim elle yazdıgımız zımbırtılar orada yazılıyor. Alıp biraz düzenlemeyle kullanılabilir. Galiba bunu CursorAdapter builder da yapıyordu ama builderları çok kullanmadığımdan emin değilim.


Data parametrik gittiği için SQL serverin tarih, tarihsaat vs formatlarını nasıl tanıdığı beni ilgilendirmiyor. Benim için VFPde onlar normal date, datetime tipleri. Gerekli çevirimleri VFP yapıypr SQL'e komut giderken. SQL server'da tek tırnak string ayiraci olduğundan:

Ahmet'in hikayesi

yazmak istedigimizde:

'Ahmet''in hikayesi'

yazmak gerekiyor. Parametreler kullanılınca ise VFP'de bildik yol:

Visual Fox Pro
lcMemo = "Ahmet'in hikayesi"

SQLExec(m.lnHandle, "update myTable set notlar = ?m.lcMemo where kayitID = ?m.KayıtID")

gerisini merak etme sen:) Burada sabit yazdık da bu bir:
thisform.edtMemo.Value olabilirdi.

Ustelik problemli tek karakter tek tırnak değil. Parametrik yontemle problemleri bitiyor.

Parametrik yontemin diğre bir onemi "SQL injection" adıyla meşhur tehlikeli bir SQL enjeksiyon (yankı) atağına karşı koruma sağlaması. Bazen forumlarda şöyle örnekler görebilirsiniz:

Visual Fox Pro
lcSQL = "select * from myTable where ad = "+thisform.text1.value

SQLExec(m.handle, m.lcSQL)

Parametre yerine açıkgözlük edip biraz daha hızlı çalışsın diye (nanosaniyeler) bunu yapmayın. Yaparsanız birisi size teşekkür eder ve tablolarınızı bir guzel gozden geçirir. Bunu anlatmaya gerek yok youTube'a bile düştü:

www.youtube.com/watch?v=MJNJjh4jORY

Bir sürü ornek var orada:)

Tarihler SQLde boş olamaz, null olabilir. Tarih alanlarınızı null kabul edecek şekilde yapın ve/veya eğer sağlayabiliyorsanız default değer verin.

Gelen datada VFP SQL server varchar(max) tipini anlamadığından o kolon boşmuş gibi duruyor (dertli tek datatipi de o değil). SQL'den datayı cast() kullanarak alabilirsiniz. ADO ile alınınca bu sorun yok.

24

Re: Yeni başlayanlar ve Foxpro 2.x'ten geçenler için VFP

Hocam ellerine sağlık.
Çok faydalandım.
Kendimi rektefe yapılmış gibi hissediyorum.

Bilmediğin Neyse Yanıldığındır.

25

Re: Yeni başlayanlar ve Foxpro 2.x'ten geçenler için VFP

cok faydali bilgiler vardi tesekur

(Ufak ipucu: VFP OLEDB sürücüsü VFPOLEDB VFP9 dahil tüm VFP formatlarını tanımasının yanısıra, VFP9 data motorunu içeriyor. Hani dara düştünüz, elinizde VFP9 yok, hatta VFP bile yok, hatta yeni install edilmiş bir windows ve internet bağlantınızdan başka birşey yok, o zaman VFPOLEDB'yi MS sitesinden indirip kurmak size çok kapılar açabilir:) - basit bir örnek VFP6 içinde cast() olan, birsürü subqueryli SQLleri desteklemiyor. VFP9 destekliyor. VFP6'da yapmanın bir yolunu da bulamadıysanız ADO kullanarak VFP9'a sorun:) Ya da müşteridesiniz bir dbf içine bakacaksınız ama bakmak için o an birşey bulamadıysanız hemen notepadde VFPOLEDB kullanan bir htm yazın. Bakmanın yanısıra datayı güncellemek, eklemek, silmek de serbest. -Reklamlar-


reklama bir ornek verebilirmisin ? smile