PDA

View Full Version : مانده حساب بدهکار بستانکار در Fast Report



فرزاد دلفی باز
سه شنبه 20 شهریور 1386, 23:09 عصر
با سلام :
من مشکلی مواجه ام که طبق شکل زیر می خواهم مثلا در سطر اول 7,000,000 رو با 0 جمع کنه و در مانده همان سطر مبلغ 7,000,000 بیاید در سطر دوم باید 7,000,000 مانده سظر اول رابا 3,000,000جمع و 10,000,000 را در مانده سطر دوم بیآورد و برای آخری 10,000,000 را از 2,000,000 کم کند و نتیجه را بدهد...
آیا در فست چنین کاری شدنی است

http://img.majidonline.com/pic/116746/gardesh.jpg

با تشکر

Will_Smith
سه شنبه 20 شهریور 1386, 23:50 عصر
عزیز دل چند بار بحث شده
اطلاعات بیشتر از مواردی که بحث شده در سایت گیرت نمیاد
گشتم نبود نگرد نیست

فرزاد دلفی باز
چهارشنبه 21 شهریور 1386, 13:34 عصر
دوست عزیز میشه آدرس جایی رو که این بحث به نتیجه رسیده رو به من بدی ....


گشتم نبود نگرد نیست

با تشکر

Will_Smith
چهارشنبه 21 شهریور 1386, 14:08 عصر
http://barnamenevis.org/forum/showthread.php?t=68708&highlight=%D9%85%D8%A7%D9%86%D8%AF%D9%87
http://barnamenevis.org/forum/showthread.php?t=73811&highlight=%D9%85%D8%A7%D9%86%D8%AF%D9%87

فرزاد دلفی باز
چهارشنبه 21 شهریور 1386, 20:06 عصر
دوست عزیز من می خواهم این مشکل در fast report حل بشه که در این قسمت مطرح کردم نه در sql server (در هر صورت ممنون لطف کردی).....

فرزاد دلفی باز
پنج شنبه 22 شهریور 1386, 17:28 عصر
آقا کسی نمی تونه ما رو کمک کنه !!!!!!!!!

Mohammad_Mnt
پنج شنبه 22 شهریور 1386, 18:28 عصر
یه متغیر توی فست ریپورت درست کن و مقداری را که می خوای براش تعریف کن. بعد از یه کامپوننت Memo استفاده کن تا مقدار متغیر را نشون بدی

kamal_habibi
پنج شنبه 22 شهریور 1386, 20:03 عصر
با سلام :
من مشکلی مواجه ام که طبق شکل زیر می خواهم مثلا در سطر اول 7,000,000 رو با 0 جمع کنه و در مانده همان سطر مبلغ 7,000,000 بیاید در سطر دوم باید 7,000,000 مانده سظر اول رابا 3,000,000جمع و 10,000,000 را در مانده سطر دوم بیآورد و برای آخری 10,000,000 را از 2,000,000 کم کند و نتیجه را بدهد...
آیا در فست چنین کاری شدنی است

http://img.majidonline.com/pic/116746/gardesh.jpg

با تشکر


با سلام خدمت آقای دلفی باز این قدر سطر و ستون کردید که من درس متوجه منظور شما نشدم
فکر کنم شما میخواهید اعداد موجود در یک سطر را در Fast Report با هم جمع کنید و در آخر
مجموع ستون اول را از مجموع ستون بعدی کم کنید ؟ درسته ؟

champion
دوشنبه 02 مهر 1386, 21:29 عصر
فرزاد خان شاید ژاسخ من یک کم دیر باشه ولی خب از هیچی بهتره شما باید توی Fastrep یک متغیر تعریف کنی و توی Beforeprint باند Detail مقدار اون رو با Bed - bes جمع کنی یعنی بنویسی
My_var = My_var + (bed - bes) و بعد این متغیر رو مقدارشو مثلا توی یک ممو و یا یک متغیر دیگه که از قبل تعریف کدی و باهاش مثل فیلد رفتار شده بریزی البته یادت نره که متغیر My_Var‌ رو توی beforePrint باند Master مساوی صفر قرار بدی
اگه متوجه نشدی بگو برات کدشو بنویسم

فرزاد دلفی باز
دوشنبه 02 مهر 1386, 23:13 عصر
آقا ممنون لطف کردید..............

Amir_Safideh
سه شنبه 13 آذر 1386, 14:44 عصر
با سلام به دوستای گلم.
من امروز یه روش پیدا کردم که میشه ستون مانده حساب رو در زمان گزارشگیری ساخت یعنی نیازی نیست که فرمولی برای محاسبه فیلد مانده حساب توی کوئری نوشت یکی از محاسن این روش سرعت خوبشه اما به خاطر اینکه فکر میکنم که الان خیلی دیره برای جواب دادن و به خاطر اینکه یه کم سرم شلوغه فعلا چیزی نمیگم تا ببینم کسی از دوستان دنبال این جواب هست یا نه اگر کسی بود من مخلصش هم هستم در اسرع وقت جواب سوال رو میدم .

szabeh
پنج شنبه 15 آذر 1386, 16:40 عصر
بله بیزحمت لطف کنید.

Amir_Safideh
جمعه 16 آذر 1386, 15:55 عصر
دوست عزیز سلام
من امروز فهمیدم که این روش جدید من یه مشکلی داره الان میگم مشکل چیه . من قبلا برای محاسبه فیلد مانده حساب از روش ایجاد یک Temp Table استفاده میکردم که احتمالا میدونید چیه این روش خیلی خوب و دقیقیه ولی عیبش سرعت پائین گزارشگیری است در زمانی که حجم داده ها بالاست مثلا برای گزارش یه حساب با 2000 رکورد حدود 18 ثانیه زمان لازم داره به همین دلیل من به فکر روش دیگه ای افتادم و اون روش هم اینه :
من توی کوئری ای که نوشتم برای گزارش گیری دو فیلد بدهکار و بستانکار رو گزاشتم بعلاوه یه سری فیلدهای معمول مثل شرح و غیره ... و در قسمت Field Editor مربوط به DataSet یه Right Click - New Field و یک فیلد از نوع Calculated ساختم و اسم این فیلد رو گذاشتم Remain و بعد در قسمت Eventes در رویداد OnCalcFields مربوط به این DataSet این کد رو نوشتم :

ابتدا یک متغییر به نام Remain که مقدار مانده رکورد قبل رو نگه میداره


public
{ Public declarations }
end;
var
DM: TDM;
Remain: Real;




و سپس این کد :



procedure TDM.SPS_Bill_ReportCalcFields(DataSet: TDataSet);
begin
if DataSet.FieldByName('Bed').AsFloat > 0 then
Remain := Remain + DataSet.FieldByName('Bed').AsFloat
else
Remain := Remain - DataSet.FieldByName('Bes').AsFloat;
DataSet.FieldByName('Remain').AsFloat := Remain;
end;


و در رویداد After Close مقدار متغییر رو برابر با صفر قرار دادم تا بعد از هر بار اجرا شدن مجدد کوئری محاسبات از صفر شروع بشه


procedure TDM.SPS_Bill_ReportAfterClose(DataSet: TDataSet);
begin
Remain := 0;
end;


زمانی که کوئری اجرا میشه همه چیز درسته ولی از اونجا که رویداد OnCalcFields در Navigate کردن DataSet نیز اجرا میشه و در ضمن از اونجا که این رویداد در اصل برای انجام محاسبه بر روی رکورد جاریست به همین دلیل بعد Navigate همه چیز به هم میریزه . حالا من دارم دنبال راه حل این مشکل میگردم ..
شما هم امتحان کنید اگر راه حلی پیدا کردید من رو در جریان بزارید لطفا .

JAFO_IRAN
شنبه 17 آذر 1386, 13:27 عصر
سلام

احتمالا درست متوجه نشدم مشکل چیه و یا راه حل ساده زیر مشکلی داره که الان درست متوجه نمیشم:

اگه در هر detail band یک "جمع" داشته باشیم (با استفاده از امکانات report generator و شبیه همون جمع هایی که در انتهای گزارش میان - ولی در هر سطر) اونوقت مانده مورد نظر خود به خود حاصل میشه. اگه report generator یک کم امکان فرمول نویسی داشته باشه کافیه - مثلا در quick report میشد گفت


Sum(tr_Deb - tr_Cre)


که فیلدهای بدهکار و بستانکار با هم لحاظ شده باشند.

ارادت

Amir_Safideh
دوشنبه 19 آذر 1386, 10:30 صبح
با سلام .
مشکل در اصل اینه که چیزی که ما اینجا لازم داریم اینه که این عملیات محاسبه بشه :

(مانده در رکورد قبلی + بدهکار در رکورد جاری - بستانکار در رکورد جاری) = مانده رکورد جاری

ممنون از توجهتون .

JAFO_IRAN
دوشنبه 19 آذر 1386, 11:44 صبح
سلام و ممنون از پاسخ

1. هر زمان بحث مانده در رکورد "قبلی" مطرح است یعنی "ترتیب" گزارش دارای اهمیت است.
2. برای اینکه گزارش منطقی باشد لازم است تا "دوره" اخذ مانده تعریف شده باشد. در سیستم‌های مالی، این دوره معمولا همان سال مالی است
3. برای اینکه در دفعات مختلف اخذ گزارش پاسخ مشابهی بدست آید باید ترتیبی دهیم که محاسبه مانده ارتباطی با محدوده رکوردهایی که چاپ میشوند نداشته باشد
4. برای اینکه مانده سطر نخست گزارش دارای معنی و قابل توجیه باشد لازم است تا جمع عملیات تا پیش از آغاز محدوده اخذ گزارش نیز در گزارش منعکس شود. این جمع برای ستونهای بدهکار و بستانکار در گزارش بازنمایی خواهد شد.
5. با وجود این سطر جمع، درست مانند این خواهد بود که یک رکورد دارای هر دو مقدار بدهکار و بستانکار داشته باشیم که اختلاف آنها مانده ناشی از رکوردهای پیش از آغاز محدوده را بدست میدهد.
6. برای بدست دادن جمع عملیات پیش از آغاز محدوده مثلا میتوانیم از union استفاده کنیم.
7. در نتیجه با همان المان جمع حاوی اختلاف مبالغ بدهکار و بستانکار نتیجه دلخواه حاصل میشود:
الف - اگر گزارش از ابتدای دوره مالی اخذ شود در سطراول مانده رکورد اول و در سطر جمع مانده "ناشی از رکورد دوم" و مانده رکورد اول و به همین ترتیب تا آخر را خواهیم داشت
ب - اگر گزارش از ابتدا نباشد، مانده تا ابتدای گزارش در سطر اول بازنمایی میشود و همان المان جمع مانده مناسب را در سایر سطرها بدست خواهد داد.

8. معمولا المانهای "جمع" در سیستم های اخذ گزارش دارای یک تنظیم مهم هستند با مفهومی چون "حاصل، پس از چاپ صفر شود". لازم است تا در این کاربرد، حتما ترتیبی دهیم که حاصل مزبور صفر نشود.


ارادت

Amir_Safideh
دوشنبه 19 آذر 1386, 15:57 عصر
با سلام
دوست عزیز این با توجه به چیزی که میفرمائید این کدی که لطف کردید (منظورم این کده)


Sum(tr_Deb - tr_Cre)

کاملا درسته ولی مشکل اصلی اینه که این کد دقیقا اون چیزی رو که میخوای برنمیگردونه
به طور مثال صرف نظر از دوره مالی و صرف نظر از اینکه ما اطلاعات رو فیلتر کنیم تصور کنید که ما یه حسابی داریم که دارای صدتا رکورده . حالا ما این کدی رو که شما لطف کردید رو برای فیلد مانده حساب استفاده میکنیم و این صد رکورد رو هم بر اساس تاریخ Sort میکنیم و برای کد شما هم یه شرط قرار میدیم شبیه این کد :

ٌWhere R_Date <= @Date

حالا مشکل اینجاست که ممنکنه در یه تاریخ ما 20 رکورد داشته باشیم با این تعاریف مانده حساب ما در تمام رکوردها با تاریخ های یکسان , یکسان خواهند بود .

JAFO_IRAN
دوشنبه 19 آذر 1386, 18:11 عصر
سلام مجدد




query:
select record = cast(recnum as nvarchar(100)), debit, credit
from tbl_Src
order by record
record debit creit sum(debit - credit)
------ ----- ----- -------------------
1 10 0 10
2 0 20 -10
3 50 0 40
4 0 10 30
5 0 10 20
6 50 0 70
7 0 20 50
8 10 0 60
9 10 0 70
query:
select record = 'prev recs', debit = sum(debit), credit = sum(credit)
from tbl_Src
where recnum < 5
union
select record = cast(recnum as nvarchar(100)), debit, credit
from tbl_Src
where recnum >= 5
order by recnum
record debit creit sum(debit - credit)
------ ----- ----- -------------------
prev recs 60 30 30
5 0 10 20
6 50 0 70
7 0 20 50
8 10 0 60
9 10 0 70




مثال اول برای وقتی است که محدوده نداریم و دومی با یک محدوده و union کار کرده:

خیلی مهمه که sum رو در گزارش درست کنیم نه در query - این جوری هر رکورد مانده مستقلی خواهد داشت.
به جای recnum میشه از تاریخ هم استفاده کرد - یا ترکیب تاریخ و شماره سند...

امیدوارم کمک باشه
ارادت

Amir_Safideh
دوشنبه 19 آذر 1386, 19:22 عصر
باز هم سلام دوست گلم
ممنون از این که اینقدر وقت میزاری . مشکل اصلی من همینه که من میخوام فیلد مانده رو توی یک DBGrid نمایش بدم .. قبلا سعی کردم که موقع گزارش گیری فیلد مانده رو بااستفاده از فیلدهای Calculated بسازم ولی نشد که در بالا گفتم که مشکل چی بود و چی شد .
چیزی که من الان لازم دارم اینه که :
من یه جدولی دارم که مثل تمام جداول شبیه خودش فیلدهای بدهکار و بستانکار داره و میخوام زمان گزارش گیری فیلد مانده رو هم در کنار بدهکار و بستانکار توی یک DBGrid نمایش بده .. البته در حال حاضر من از روش ایجاد Temp table استفاده میکنم که خدمتتون عرض کردم سرعتش در هنگام گزارشگیری پائینه چون تمام اطلاعات ثبت شده قبلی رو یکبار دیگر باید ثبت کنه و فیلد مانده رو بر اساس جمع تمام بدهکاران و بستانکاران قبلی محاسبه کنه که سرعت رو پائین میاره .
------------------------------
با تشکر از شما

JAFO_IRAN
دوشنبه 19 آذر 1386, 20:43 عصر
سلام

P: خیلی عذر میخوام - اشتباه از من بود شدید (فکر کردم داستان درمورد fast report هستش). برای DBGrid اصولا روشی که من گفتم کار نمیکنه.

یک راه همون temp table هست که خودتون گفتید - اما راه دیگری که به ذهن من میرسه، استفاده از یک موجودی مثل client dataset برای بازنمایی اطلاعاته. اونجا میشه از internal calculated fields استفاده کرد و مثلا در AfterOpen یکبار مقدار فیلدها رو برای تمام سطرها تعیین کرد. میشه شبیه همون temp table، اما زمان پردازش از سرور به کلاینت منتقل میشه. در چاپ، چون همواره حالت unidirectional داریم میشد از اون روشی که من گفتم استفاده کرد ولی در نمایش در Grid باید به هر حال فیلد رو داشته باشیم... من باز هم روش فکر میکنم و اگه چیزی به نظرم اومد بهتون اطلاع میدم

ارادات

JAFO_IRAN
چهارشنبه 21 آذر 1386, 14:18 عصر
سلام

ببین این روش خیلی خوبیه

http://barnamenevis.org/forum/showthread.php?t=37909

ارادت

Amir_Safideh
چهارشنبه 21 آذر 1386, 19:43 عصر
با سلام به دوست گلم که اسمت رو هم نمیدونم
این روش رو من قبلا انجام داده بودم ولی مشکلش اینه که بر فرض اگر ما شرط را برای تابع Sum بر روی تاریخ اعمال کنیم(که دقیقا هم همین مورد لازمه)یعنی اگر بگیم که :


Select ......, (Select Sum(Field)
From table_Inner.Date <= Table_Outer.Date)
From Table Table_Outer

اونوقت این مشکل پیش میاد که این این دستور Select جمع تمام رکوردهایی رو که این شرط براونها صادق باشه رو برمیگردونه حالا بر فرض اینکه ما 10 تا ثبت با یه تاریخ مشابه داشته باشیم در اونصورت تمام ثبتها با تاریخ مشابه دارای فیلد مانده با مقدار مشابه خواهند بود در صورتی که چیزی که عملا لازمه اینه که هر رکورد مانده واقعی خودش رو داشته باشه .
به همین دلیل بود که من از Temp Table استفاده کردم و در این Temp Table داده ها رو بر اساس تاریخ Sort کردم و یک فیلد Identity یا (AutoNum ) تعریف کردم به این ترتیب تمام ثبتها بر اساس تاریخ منظم میشن و یه فیلد AutoNum از ابتدا تا پایان ثبتها شماره گذاری میشه بعد برای بدست آوردن فیلد باقیمانده این کد رو برای Sum نوشتم :



Select ......,(Select Sum(....)
From .....
Where Table_Inner.Rank(AutoNum) <= Table_Outer.Rank(AutoNum))
From Table Table_Outer



به این ترتیب در مرحله اول داده ها بر اساس تاریخ منظم میشن بعدش دیگه فیلد AutoNum مبنای شرط ما قرار میگیره نه تاریخ به این ترتیب مشکل حل میشه ولی افسوس که این روش سرعت رو پائین میاره .

ولی از هر چی بگذریم من یه تشکر حسابی به شما بدهکارم که اینقدر وقت گذاشتی واقعا ازت ممنونم . باز هم منتظر راهنمائی های شما هستم .

-----------------

JAFO_IRAN
پنج شنبه 22 آذر 1386, 11:49 صبح
سلام

اولا تشکر و این حرفها لازم نیست قربان. باعث خوشحالی است و در ضمن این داستان قدیمی خیلی وقته که ذهن من رو به خودش مشغول کرده... هم فکری میکنیم دیگه...

ببین داستان مانده به صورت تئوری یک پیش نیاز اساسی داره: فقط وقتی میشه اونرو تعریف کرد که ترتیب دقیق باشه و هیچ دو رکوردی ارزش مرتب سازی مساوی نداشته باشند. اگه اینجوری به داستان نگاه کنیم، معلوم میشه که چرا تاریخ به تنهایی مشکل رو حل نمیکنه و چرا temp table شما کار کرده (چون اون AutoNum در نقش ترتیب دقیق قرار گرفته).

تنها تفاوت در عبارت شرطی در جدول داخلیه. مستندات مالی معمولا یک سریال هم دارند که در یک تاریخ ترتیبشون رو معلوم میکنه؛ تازه در نهایت اگه واقعا ارزش ترتیبی دو رکورد یکی باشن پس برای کاربر هم فرق نمیکنه که به چه ترتیبی بازنمایی بشن و مانده شون چج.ری محاسبه بشه - در این جور موارد حتی میشه از primary key برای درست کردن ترتیب دقیق در بین رکوردهای هم ارزش استفاده کرد.

مثلا اگه fld_Date تاریخ باشد و fld_Num شماره سریال (مثلا تکراری) . fld_Key کلید اصلی باشه میشه شرط داخلی را اینجوری نوشت:



select ....,
(select Sum(...) from tbl_Src i
where (i.fld_Date < o.fld_Date) or
((i.fld_Date = o.fld_Date) and (i.fld_Num < o.fld_Num)) or
((i.fld_Date = o.fld_Date) and (i.fld_Num = o.fld_Num) and (i.fld_Key <= o.fld_Key)))
from tbl_Src o



ارادت

Amir_Safideh
پنج شنبه 22 آذر 1386, 18:13 عصر
دوست گلم دستت درد نکنه ..
این همون چیزیه که لازم داشتم چون من هم یه فیلد ID یا همون شماره سریال رو دارم و هم یه فیلد کلید با مقادیر یکتا .. با این شرطی که لطف کردی دیگه حله .
-----------
قربون شما .