Pack / UnPack Metodu

İçinde diaolg bulunan bir Clases değişik kullanıcılar tarafından farklı zamanlarda çalıştırıldığında, data ve değişken karışıklıklarını önlemek amacıyla classes dioloğundan girilmiş olan değişkenleri ve yapılmış olan ayıklama işlemlerini kullanıcı bazında tutmak isteyebiliriz. Axaptada bu isteğimize çözüm olarak Pack ve UnPack metodlarını kullanabiliriz.

Bir Classes'ın çalışmasını izlemeye aldığımızda göreceğimiz gibi Classes 'da gerekli değişkenleri girip OK/TAMAM tuşuna bastığımızda pack metodu da tetiklenmiş olur. Bu şu anlamada gelir, bizim dialog üzerinden girdiğimiz değişkenler Axapta tarafından saklanacaktır. Bu Classes'ı tekrardan çalıştırdığızda ise bu Classes daha önce çalıştırıldığı için UnPack metodu tetiklenmiş olur ve dialog'a bir önce girdiğimiz değişkenler görüntülenir. Peki bu işlemleri Axapta nasıl yapıyor. Pack ve UnPack metodlarını tanımaya çalışalım.

Pack metodunun son derece bazit bir içeriği vardır. Bu metod dialog'a girdiğimiz değerleri Axapta tarafından saklanmasını sağlar. Yalnız girilen değişkinlerden hangisinin saklanacağına ise Classes Declaration 'un da yerel olarak tanımladığımız macro ile belirleriz. Bu macronun oluşturulmuş olması gereklidir.

Pack metodu Container tipinde değişken döndürür ve dönen Container'ın elemanları bizim oluşturduğumuz macro elemanlarıdır.

Basit bir şekilde Pack metodu ;

public container pack()
{
return [#CurrentVersion,#CurrentList];
}

UnPack metodu ise Pack metodunun kardeşidir. UnPack metodu ise bu Classes daha önce çalıştırılmış mı çalıştırıldıysa hangi değerle çalıştırıldı onun bilgisini getir. Aslında birisi değerleri yazarken dieri değerleri okur.

UnPack metodu Container tipinde değişken alır ve boolean tipinde değişen döndürür. Eğer geri yüklenecek değer sistemde mevcutsa Unpack metodu bize true döndürecektir.

Basit bir şekilde Unpack metodu;

public boolean unpack(container packedClass)
{
Version version = runbase::getVersion(packedClass);
;
switch (version)
{
case #CurrentVersion:
[version,#CurrentList] = packedClass;
break;
default:
return false;
}
return true;
}

Classes'da lookup İşlemi

Bildiğiniz gibi Dynamics Ax'da kodlarımızı X++ dilinde yazmaktayız. X++ dilinin içeriği ve biçimi C#, Visual .Net ve java dillerine benzemekte. X++ dili bu dillerin referanslarına ve benzer içeriklerine sahiptir. Tabi Java biçimine daha çok benzediğini söylemeliyiz. X++ dilini daha iyi anlayabilmemiz ve farklılıkları daha iyi tespit edebilmemiz için object oriented programlama yöntemlerini iyi anlamamız gerekecektir.

Axapta içersinde object oriented programlama'ya ait en güçlü örnekleri Classes'larda görmekteyiz. Axapta 'da Classes yazmak ve yönetmek son derece kolaydır. Biz Classes'ları birçok uygulamamızda veya yaptığımız geliştirmelerde kullanmaktayız. Axapta'da Classes'ları bu kadar çok kullanmamızı sağlayan en güçlü özelliklerinden biri Dialog metodudur. Bu metod ile değişkenlerimizi ( parametre, girdi) tanımlamamızı sağlar.

Bu makalede de Classes'larda kullandığımız Dialog metodunda StringEdit tipinde bir değişkende(alanda) Lookup metodunu nasıl oluşturacağımızı bir örnekle anlamaya çalışacağız.

Örneğimizde Fiş Numarası ve Fiş tarihi bilgilerini alan, bu parametrelerle de muhasebe günlüğü işlemlerini bir StringEdit alanında görüntüleyeceğiz.

Bu örnek için LedgerJournalTrans tablosunu kullanacağız. Tabi olaya dialog metodumuzu yazarak başlayacağız yalnız Classes'la ilgili diğer metodların ve gerekli değişkenlerin tanımlandığını var saymaktayım.

Object dialog(DialogRunbase _dialog, boolean _forceOnClient )
{
DialogGroup dimensionGroup;
Dialog dialog = super(_dialog, _forceOnClient);
;

dialogVoucher = dialog.addFieldValue(typeid(voucher),voucher,"Fiş Numarası");
dialogTransDate = dialog.addFieldValue(typeid(TransDate),transDate,"İşlem Tarihi");
dialogJournalRecId = dialog.addFieldValue(typeid(RecId),journalRecId,"Fiş Satırı");
dialogJournalRecId.lookupButton(FormLookupButton::Always);


return dialog;
}

Classes'ımızı dialog'unda görüntülenmek üzere 3 adet dialog alanı oluşturuyoruz. Yukarıda belirtiğim gibi bu alanlardan dialogVoucher ve dialogTransDate alanları görüntüleyeceğimiz fiş ve fişin tarihi. Günlük işlemlerini ise dialogJournalRecId alanında lookup olarak görüntüleyeceğiz. Burada dikkat etmemiz geren nokta bu alanın LookUpButton özelliğini "herzaman" olarak atamak olmalıdır. Bu özellik bize StringEdit alanı için lookup işlemini açacaktır. Şimdi lookup metodumuzu yazalım.

Classes'ların dialog'larına alan eklediğimizde bunlar birer object olduğu için, Axapta bunlara birer isim atayacaktır. "Fld_1_1" gibi. Bizim eklediğimiz alanın ismini ise (info(dialogJournalRecId .name)) ile alabiliriz.

Aslında şimdi yapacağımız işlem .Net den alışık olduğumuz bir object'in metodunu OverWrite (Üzerine Yazmak) etmeden farklı değildir. Bizde Axapta tarafından ismi verilmiş olan dialogJournalRecId isimli alanımızın Lookup metodunu OverWrite edeceğiz.

Şimdi Axapta dialogJournalRecId alanına Fld3_1 ismini verecektir. Classes'ımızın içine aşağadaki metod'u yazarak işlemimizi tamamlayalım.

void Fld3_1_lookup()
{
FormRun fr=this.dialogModify().parmDialog().formRun();
object control = fr.controlCallingMethod();

SysTableLookupsysTableLookup=SysTableLookup::newParameters(tableNum(LedgerJournalTrans), control);
Query query = new Query();
QueryBuildDataSource qbds;
;

sysTableLookup.addLookupfield(fieldNum(LedgerJournalTrans, RecId));
sysTableLookup.addLookupfield(fieldNum(LedgerJournalTrans, JournalNum));
sysTableLookup.addLookupfield(fieldNum(LedgerJournalTrans, AccountType));
sysTableLookup.addLookupfield(fieldNum(LedgerJournalTrans, AccountNum));
sysTableLookup.addLookupfield(fieldNum(LedgerJournalTrans, txt));
sysTableLookup.addLookupfield(fieldNum(LedgerJournalTrans, AmountCurDebit));
sysTableLookup.addLookupfield(fieldNum(LedgerJournalTrans, AmountCurCredit));

qbds = query.addDataSource(tableNum(LedgerJournalTrans));
qbds.addRange(fieldNum(LedgerJournalTrans,Voucher)).value(queryValue(dialogVoucher.value()));
qbds.addRange(fieldNum(LedgerJournalTrans,TransDate)).value(queryValue(dialogTransDate.value()));
sysTableLookup.parmQuery(query);
sysTableLookup.performFormLookup();
}

Classes'ı çalıştırdığımıda fiş ve fiş tarihi girdiğimizde dialogJournalRecId alanında yukarıda belirttiğimiz alanları gösteren bir lookup açılacaktır. Benzer yöntemlerle lookup haricindeki diğer özellikleri de kullanabilirsiniz.

Yukarıda yazılan metodların içeriklerine ve detaylarına girmedim. Bunlarla ilgili açıklamaları birçok yerde bulabilirsiniz.

Volkan Acar

volkan.vacar@gmail.com

Kod içinden rapor dosyası oluşturma

Axapta içinden kod ile bir raporu (PDF formatında) nasıl oluşturacağımızı görelim.
Örnek olarakta bir satış şiparişine ait faturayı PDF formatında kaydedelim.
Arzu ederseniz raporu HTML formatına dönüştürüp e-mail olarakta gönderebiliriz.

CustInvoiceJour custInvoice;
SalesId salesId;
ReportRun report;
RecordSortedList List = new RecordSortedList(62);

SalesId='00001';

Select custInvoice Index hint SalesIdx Where custInvoice.SalesId == salesId;

List.ins(custInvoice);
report = new ReportRun(new Args(ReportStr(SalesInvoice)));
report.args().caller(null);
report.args().parmEnum(1);
report.args().parmEnumType(920);
report.args().object(List);
report.args().name("KeepSettings");
report.printJobSettings().setTarget(PrintMedium::File);
report.printJobSettings().format(PrintFormat::PDF);
report.printJobSettings().fileName("C:\\Invoice.pdf");
report.prompt();
report.run();

C# kullanarak Axapta işlemleri

VB.net kullanarak Axapta'ya nasıl bağlanacağımızı (Login) olacağımızı ve Axapta Class'larını nasıl kullanacağımızı bir önceki makelemizde görmüştük.

Şimdi ise VB.net ile yazdığımız kodların C# şeklide yazılmış şekillerini görelim.

private object Logon2(string defaultLogon, string configuration, string company, string Password)
{
const object FUNCTION_NAME = "GetNotificationHeader";
try {
axapta = new AxaptaCOMConnector.Axapta2();
axapta.Logon2(defaultLogon, Password, company, "", "", "", configuration, "false", "", "");
}
catch (Exception ex) {
string strErrorMessage;
strErrorMessage = " ERROR IN " + MODULE_NAME + "." + FUNCTION_NAME + " ERRSOURCE: " + Err.Source + " ERRCODE: " + Err.Number + " ERRDESC: " + Err.Description + " ERRLINE: " + Erl();
InformationManager.HandleError(MODULE_NAME, FUNCTION_NAME, strErrorMessage, InformationManager.LOG_TYPE_ERROR);
Err.Clear();
}
finally {
}

Axapta'ya bağlandıktan sonra aynı Axapta nesnesini kullanarak Axapta içinde bulunan Global Class ına ait operatingSystem metod'unu çağırmaya çalışalım.

private string getOSName()
{
object result;
try {
result = axapta.CallStaticClassMethod("Global", "operatingSystem", null, null, null, null, null, null);
if ((!(result == null))) {
return result.ToString();
} else {
return null;
}
}
catch (Exception ex) {
}
finally {
if (!(axapta == null)) {
try {
axapta.Logoff();
}
catch (Exception ex) {
}
}
}
}

Axapta Class'ını nasıl çağıracağımıza bakalım. Yukarıda yazdığımız fonksiyonu da kullanalım. Yazacağımız örnekte bir recordSet'i göndermeye çalışacağız.

private object CallAxaptaClassMethod(ADODB.Recordset axRecorset, string strAxMethodName)
{
const object FUNCTION_NAME = "CallAxaptaClassMethod";
string osName;
object returnd;
string ssss;
try {
osName = getOSName();
if (!(osName == null)) {
axapta.TTSBegin();
returnd = axapta.CallStaticClassMethod("dataInAxapta", strAxMethodName, axRecorset, null, null, null, null, null);
axapta.TTSCommit();
} else {
throw new Exception("Axapta Connection Not Setvvvv");
}
}
catch (Exception ex) {
string strErrorMessage;
axapta.TTSAbort();
if (!(axapta == null)) {
axapta.Logoff();
}
strErrorMessage = " ERROR IN " + MODULE_NAME + "." + FUNCTION_NAME + " ERRSOURCE: " + Err.Source + " ERRCODE: " + Err.Number + " ERRDESC: " + Err.Description + " ERRLINE: " + Erl();
InformationManager.HandleError(MODULE_NAME, FUNCTION_NAME, strErrorMessage, InformationManager.LOG_TYPE_ERROR);
Err.Clear();
}
finally {
}
}