1 ضمیمه
فیلد محاسباتی در After Update
با سلام
بعد از وارد کردن تاریخ قرارداد (t8)، تاریخ انقضای 6 ماهه، با کد زیر در فیلدش (m6) دیده میشه:
Private Sub t8_AfterUpdate()
m6 = DateAdd("m", 6, t8)
End Sub
نیاز دارم مهلت باقیمانده در فیلد مربوطه (mohlatm6) محاسبه و دیده بشه. (چون اول، تاریخ انقضا (m6) باید محاسبه بشه، کد زیر در خاصیت After Update فیلد قرارداد (t8)، جواب نمیده)
mohlatm6 = TotalDiff (txtToday, m6)
نقل قول: فیلد محاسباتی در After Update
سلام و روز خوش
1- مطمئن نیستم منظور شما رو درست گرفته باشم،
ولی همین باید درست باشه:
Private Sub t8_AfterUpdate()
m6 = DateAdd("m", 6, t8)
mohlatm6 = TotalDiff(txtToday, m6)
End Sub
2- اون default value برای mohlatm6 هم بنظر میاد لازم نیست.
نقل قول: فیلد محاسباتی در After Update
سلام بزرگوار
- default value برای mohlatm6 رو هم برداشتم ولی جواب نگرفتم.
- چون اول، تاریخ انقضا (m6) باید محاسبه بشه، کد زیر در خاصیت After Update فیلد قرارداد (t8)، جواب نمیده:
mohlatm6 = TotalDiff (txtToday, m6)
نقل قول: فیلد محاسباتی در After Update
سلام دوباره
الان منظور شما از جواب ندادن در (چون اول، تاریخ انقضا (m6) باید محاسبه بشه، کد زیر در خاصیت After Update فیلد قرارداد (t8)، جواب نمیده) مشخص نیست!
چون اون خط دوم کد پست 2 (محاسبه مهلت) مشکلی نداره و
بعد از خط اول (محاسبه تاریخ انقضا) اجرا میشه، و اگر مشکلی باشه باید در همون خط اول دیده بشه.
مشکل کد محاسبه تاریخ انقضا این هست که شما از تابع DateAdd که برای تاریخ میلادی (گرگوری) هست استفاده کردین؛
تعداد روزهای ماه های میلادی با تعداد روزهای ماه های ایرانی متناظر شون یکی نیست:
مثلا ماه های 7 و 8 میلادی (جولای و اگوست) 31 روزه ان ولی ماه های 7 و 8 ایرانی (مهر و آبان) 30 روزه
یا ماه 2 میلادی (فوریه) 28 یا 29 روزه است ولی ماه 2 ایرانی (اردیبهشت) همیشه 31 روزه است.
حالا اگر شما تاریخ قرارداد رو مثلا 30 اردیبهشت بذارین اون تابع DateAdd حتما خطا میگیره.
برای حل این مشکل 2 راه دارین:
1- در همین توابع کمکی تاریخ ایرانی که استفاده کردین بگردین ببینین تابع معادل داره یا نه و جایگزین کنین.
اگر نداشته باشه باید خودتون یکی بنویسین.
2- همون تابع DateAdd رو استفاده کنین، ولی تاریخ قرارداد رو بر اساس روز اول ماه بهش بدین
و بعد تاریخ بدست آمده رو با روز واقعی تاریخ قرارداد جمع کنین.
نقل قول: فیلد محاسباتی در After Update
سلام دوست عزیز
ممنون میشم در رابطه با راه حل دوم (همون تابع DateAdd رو استفاده کنین، ولی تاریخ قرارداد رو بر اساس روز اول ماه بهش بدین
و بعد تاریخ بدست آمده رو با روز واقعی تاریخ قرارداد جمع کنین) یک مثال بزنید.
نقل قول: فیلد محاسباتی در After Update
سلام دوباره
اجازه بدین اول این توابعی رو که برای تاریخ ایرانی استفاده کردین یک نگاهی بندازم
بعد تابعی رو نیاز دارین براتون آماده میکنم و روش کار رو هم توضیح میدم.
ممکنه یکی دو روزی زمان ببره.
نقل قول: فیلد محاسباتی در After Update
سپاس بزرگوار
نقل قول:
اگر تاریخ قرارداد رو مثلا 30 اردیبهشت بذارین اون تابع DateAdd حتما خطا میگیره.
اول ماه و کلا هر روزی رو هم خطا میده.
نقل قول: فیلد محاسباتی در After Update
خب من این روتین های ماژول DateShamsi رو بررسی کردم:
نه تنها بسیاری از توابع مورد نیاز رو نداره، بلکه نتایج محاسبات هم دارای اشتباه های بزرگی هست
و مطلقا غیرقابل اعتماده!
خود من هم تا خیلی سال پیش (یعنی پیش از پشتیبانی دات نت از Persian calendar)
توابع تبدیل تاریخ خودم رو داشتم (البته آلگوریتم محاسبات از رفرنس های علمی معتبر گرفته بودم)،
تو برنامه های قدیمی میگردم و اون رو براتون میذارم.
تا اون موقع تاپیک زیر رو هم ببینین (پست های 7 تا 13) :
حرفه ای: Mazoo Utils for VBA - کتابخانه ابزارهای سودمند برای VBA
نقل قول: فیلد محاسباتی در After Update
سلام دوست عزیز
نقل قول:
تو برنامه های قدیمی میگردم و اون رو براتون میذارم.
موفق شدید پیدا کنید؟
نقل قول: فیلد محاسباتی در After Update
سلام دوباره
آره - مشکل پیدا شدن نبود،
چند چیز در طولانی شدن پاسخ موثر بود:
1- بیشتر توابع تاریخ رو بعنوان متدهایی برای یک کلاس تاریخ ایرانی نوشته بودم،
(یعنی توابع مستقلی که مستقیما روی یک مقدار integer/long یا string بعنوان تاریخ کار کنن نیست)،
و ممکن بود کار با اون برای شما چندان ساده نباشه،
بنابراین لازم بود به شکل توابع جدا و ساده دربیاد (که انجام شده).
2- لازم بود یک بازنگری در کدها انجام و دستی به سر و روی اون کشیده بشه:
برخی چیزها باید حذف میشد (محاسبات مربوط به زمان: ساعت، دقیقه، ثانیه و یک سری توابع دیگه)،
کدها از نظر ظاهری و خوانایی نیاز به ویرایش داشت،
اینترفیس و پارامترها هم در بعضی جاها نیاز به تغییر داشت (اینها هم انجام شده)
3- هر کاری که بخواد روی تاریخ ایرانی انجام بشه نیازمند محاسبه درست روز اول سال و همچنین سالهای کبیسه هست.
الگوریتم درست (که astronomical هست) جای بحثش اینجا نیست،
ولی الگوریتم های تقریبی هم بوده که در یک دوره زمانی نتیجه دقیق دارن (توابعی که در برنامه شما بود همین رو هم رعایت نکرده بود!)
حالا:
کدهای محاسباتی برای روز اول سال و کبیسه ها سنگین و پیچیده است،
و ما معمولا در یک برنامه تجاری/اداری/مالی فقط با تاریخ هایی مثل سال مالی، تولد، مرگ، استخدام، قرارداد، ... سروکار داریم
و اینها هم در یک محدوده +/- 100 ساله نسبت تاریخ فعلی هست،
بنابراین پیاده سازی الگوریتم نجومی در یک برنامه متعارف منطقی نیست.
من 2 سری کد داشتم:
یکی برمبنای الگوریتم نجومی (برای کاربردهای علمی و تقریبا بدون محدودیت بازه)
و یکی هم بر مبنای یک الگوریتم بسیار سبک که در محدوده از سال 1200 تا 1500 کاملا دقیق عمل میکنه (و همین هم کافی هست).
با این وجود تصمیم گرفتم بجای این الگوریتم دوم از یک لیست پیش محاسبه شده استفاده کنم،
به این ترتیب همین کد (که اینجا برای بازه 1300 تا 1420 تعریف شده)، از سال 1 تا 9937 ایرانی هم درست هست - بدون نیاز به محاسبات پیچیده و فقط با ویرایش لیست (این هم انجام شده).
در همین یکی دو روز هم اینها رو در یک پست مستقل میارم،
و هم بر اساس همین فرم شما رو ویرایش میکنم.
2 ضمیمه
نقل قول: فیلد محاسباتی در After Update
با توجه به تاپیک:
آموزش: ساخت یک کلاس و توابع مورد نیاز برای کار تاریخ ایرانی Persian Date Class and Functions
برنامه شما میتونه به صورت زیر باشه:
Option Explicit
Option Compare Database
Private pNow As Long, ConDate As Long, ExpDate As Long
Private Sub ContractDate_AfterUpdate()
ConDate = ContractDate
ExpDate = AddMonths(ConDate, 6)
ExpireDate = FormatDate(ExpDate)
Deadline_days = DiffDays(pNow, ExpDate)
Dim ds As DateSpan
ds = DiffDateSpan(pNow, ExpDate)
Deadline_datespan = ds.Year & " سال و " & ds.Month & " ماه و " & ds.Day & " روز"
End Sub
Private Sub Form_Load()
pNow = FromGregorian(Now)
Today = FormatDate(pNow)
SpellToday = SpellFullDate(pNow)
End Sub
نقل قول: فیلد محاسباتی در After Update
بسیار بسیار ممنون
دقیقا همون چیزی که منظورم بود
سپاس فراوان
بزرگوار چطور میشه برای ششماه اول که 31 روزه هستند، اون یک روز اضاف رو در نظر گرفت؟
چون وقتی تاریخ قرارداد رو میزنم 1 شهریور، قانونا باید 6 ماه بعد بشه 29 بهمن (نه 1 اسفند)
همین طور وقتی روز 30 یا 31 ششماه اول رو انتخاب میکنم، برای هر دو تاریخ، یک روز (روز 30 ششماه دوم) رو نمایش میده (مثلا هم برای 30 مرداد، 30 بهمن در نظر میگیره و هم برای 31 مرداد همین تاریخ رو نشون میده).
نقل قول: فیلد محاسباتی در After Update
نقل قول:
نوشته شده توسط
arman2000
وقتی تاریخ قرارداد رو میزنم 1 شهریور، قانونا باید 6 ماه بعد بشه 29 بهمن (نه 1 اسفند)
نقل قول:
نوشته شده توسط
arman2000
همین طور وقتی روز 30 یا 31 ششماه اول رو انتخاب میکنم، برای هر دو تاریخ، یک روز (روز 30 ششماه دوم) رو نمایش میده (مثلا هم برای 30 مرداد، 30 بهمن در نظر میگیره و هم برای 31 مرداد همین تاریخ رو نشون میده).
اینها به تفسیر شما از 6 ماه مهلت و منطقی که در محاسبه به کار میبرین برمیگرده.
ولی رفتار و منطق اضافه کردن ماه یا سال به یک تاریخ (مهم نیست در چه نوع تقویمی: ایرانی، میلادی، چینی، ...)
اینجوری هست که پس از محاسبه ماه و سال، تعداد روزهای اون ماه در اون سال با روزِ ماه سال اولیه مقایسه میشه:
اگر مساوی یا بیشتر باشه که همون بعنوان روزِ ماه در نظر گرفته میشه
وگرنه تعداد روزِ ماه جدید جایگزین میشه.
مثال: اگر شما 3 ماه به 31 تیر 1404 اضافه کنین،
ماه تاریخ جدید میشه 7 که سی روزه هست و از 31 بیشتره
پس تاریخ جدید میشه 30 مهر 1404 .
ولی اگر همین 3 ماه رو به 1 تیر اضافه کنین میشه 1 مهر.
مشابه همین برای میلادی (تقویم گریگوری) هم هست:
اگر 1 ماه به 31 ژانویه 2024 اضافه کنین
میشه 29 فوریه 2024 - چون فوریه در اون سال 29 روزه هست (کبیسه)
ولی همین 1 ماه رو به 31 ژانویه 2025 اضافه کنین میشه 28 فوریه 2025 چون سال عادی هست و فوریه 28 روزه.
این منطق استاندارد کار با تاریخ هست و در همه زبانهای برنامه نویسی و همه تقویم ها همینه و باید رعایت بشه.
شما میتونین خواسته تون رو با ترکیبی از توابعی که در PersianDateHelper برای کم و اضافه کردن یک بخش از تاریخ (روز یا ماه یا سال) هست:
AddDays
AddMonths
AddYears
و کدهای خودتون پیاده کنین.