برای من راحت است که تاریخ شمسی را در اکسل و برنامه های دیگر به صورت یک عدد هشت رقمی ذخیره کنم. مثلا هشتم بهمن هزار و چهارصد و سه به شکل ۱۴۰۳۱۱۰۸ ذخیره می کنم.به این شکل می توان تاریخ شمسی را راحت تر مدیریت کرد چون به عنوان یک عدد هشت رقمی برای اکسل نمایان می شود.
برای اضافه کردن به تاریخ برای طول سال بایستی فرمولی باشد که بتواند هنگام رسیدن روز به ۳۰ یا ۳۱ عدد ماه را یک رقم اضافه کند و بعد از اینکه عدد ماه از ۱۲ عبور کند رقم یکان سال را یکی اضافه کند. فرمولی که در کادر زیر هست این کار را انجام می دهد. اول یک صفحه جدید باز کنید تاریخ دلخواه خود را به صورت هشت رقمی بدون فاصله یا کاراکتر در خانه A1 وارد کنید و در خانه A2 این فرمول را کپی کنید. تاریخ روز بعد اضافه خواهد شد. حالا با کشیدن مربع کوچک گوشه سلول A2 میتوان این سلول که فرمول را دارد ادامه داد…
=IF(RIGHT(A1,2)+1>
IF(MOD(INT(A1/100),100)<=6,31,IF(MOD(INT(A1/100),100)<=11,30,29)),
IF(MOD(INT(A1/100),100)=12,(INT(A1/10000)+1)*10000+101,INT(A1/100+1)*100+1),
A1+1)
این فرمول شش ماه اول را ۳۱ روزه و شش ماه دوم را ۳۰ روزه و اسفند را ۲۹ روزه محاسبه می کند.
توضیح مرحلهبهمرحلهٔ فرمول Excel
این فرمول برای افزایش (increment) یک تاریخ ذخیرهشده به شکل عددی YYYYMMDD در سلول A1 طراحی شده — یعنی تاریخ به صورت یک عدد هشترقمی (یا در برخی سالها/نمونهها عدد ۷ رقمی اگر صفرهای پیشرو حذف شده باشند) است. هدف: یک روز به تاریخ اضافه کند و در انتهای هر ماه ماه/سال را درست افزایش دهد. حال قدمبهقدم بررسی میکنیم چه اتفاقی میافتد.
۱) قسمتهای اصلی و توابع مورد استفاده
RIGHT(A1,2)→ دو کاراکتر آخر متن/عدد در A1؛ روز (DD). مقدار خروجی متنی است ولی هنگام عملگر+۱اکسل آن را به عدد تبدیل میکند.INT(A1/100)→ حذف دو رقم آخر (روز)؛ خروجی =YYYYMMبه صورت عدد (مثلاً از ۲۰۲۳۰۹۱۵ → ۲۰۲۳۰۹).MOD(…,۱۰۰)→ با گرفتنMOD(INT(A1/100),100)عملاً دو رقم آخرYYYYMMرا جدا میکند — یعنی ماه (MM).- توابع
IF(condition, value_if_true, value_if_false)برای تصمیمگیری استفاده شدهاند.
۲) منطق تعیین تعداد روزهای آخر هر ماه (بخش داخلی IF)
این بخش تعداد روزهای مجاز ماه جاری را برمیگرداند:
IF(MOD(INT(A1/100),100)<=6, 31,
IF(MOD(INT(A1/100),100)<=11, 30, 29))
توضیح:
- اگر ماه (
MM) ≤ ۶ → ماههای ۱ تا ۶: ۳۱ روز. - وگرنه اگر ماه ≤ ۱۱ → ماههای ۷ تا ۱۱: ۳۰ روز.
- در غیر این صورت (ماه = 12) → مقدار ۲۹ برگردانده میشود.
(این الگو دقیقاً با تقویم شمسی/جلالی مطابقت دارد: ۶ ماه اول ۳۱ روز، ماههای ۷–۱۱ هر کدام ۳۰، ماه ۱۲ معمولاً ۲۹ که در سال کبیسه ۳۰ میشود — نکته مهم: فرمول حاضر بررسی کبیسه بودن سال را انجام نمیدهد و همیشه ۲۹ در نظر میگیرد.)
۳) شرط اصلی: آیا روز + ۱ از آخرین روز ماه بزرگتر است؟
بخش بیرونی IF:
IF(RIGHT(A1,2)+1 > (maxDayOfMonth), then_rollover, A1+1)
RIGHT(A1,2)+1→ روز فعلی بهاضافهٔ ۱ (مثلاً ۳۱+۱ = 32).- اگر این عدد بزرگتر از
maxDayOfMonthباشد، یعنی باید به روز اول ماه بعد برویم (rollover). - وگرنه فقط عدد تاریخ را بهسادگی
A1 + 1افزایش میدهد (مثلاً از۲۰۲۳۰۹۱۴→۲۰۲۳۰۹۱۵).
نکته: A1+1 در قالب عدد YYYYMMDD کار میکند چون افزایش روز درون همان ماه (مثلاً ۱۴→۱۵) دقیقاً با +۱ عددی برابر است.
۴) اگر نیاز به تغییر ماه/سال باشد — بخش then_rollover
بخش then_rollover این است:
IF(MOD(INT(A1/100),100)=12,
(INT(A1/10000)+1)*10000 + 101,
INT(A1/100+1)*100 + 1)
توضیح دو حالت:
حالت (ماه = 12) — پایان سال
MOD(INT(A1/100),100)=12 یعنی اگر ماه جاری دوازدهم باشد:
INT(A1/10000)→ عدد سال (YYYY) را جدا میکند (حذف چهار رقم آخرMMDD).(INT(A1/10000)+1)*10000 + 101→ سال را یکی بیشتر میکند، سپس با *۱۰۰۰۰ و جمع۱۰۱عدد جدید را میسازد:- نتیجه =
NextYear * 10000 + 0101→ یعنیYYYY+1 01 01(اول فروردین/ماه ۰۱ روز ۰۱). - مثال: اگر A1 =
۱۴۰۰۱۲۲۹→INT(A1/10000)=1400→ +۱ = 1401 →۱۴۰۱*۱۰۰۰۰ + ۱۰۱ = 14010101.
- نتیجه =
حالت (ماه ≠ ۱۲) — فقط افزایش ماه
INT(A1/100+1)*100 + 1 — منظور افزایش ماه و تنظیم روز به ۰۱.
- توجه مهم به پرانتزها: آنچه نوشته شده
INT(A1/100+1)معنیاشINT( (A1/100) + 1 )است. معمولاً مقصود نویسنده این بوده کهINT(A1/100) + 1(یعنی ابتداYYYYMMرا بگیر و سپس یک واحد به آن اضافه کن تا ماه ++ شود). بهصورت عددی این دو اغلب برابرند، اما از نظر خوانایی بهتر استINT(A1/100) + 1نوشته شود. - سپس
... *۱۰۰ + ۱→ نتیجه را دوباره به شکلYYYYMMتبدیل میکند و+۱آخر میسازدYYYY (MM+1) 01.- مثال: اگر A1 =
۲۰۲۳۰۶۳۱(فرض) وقتی ماه ۰۶ و روز ۳۱ روز +۱ > 31 → وارد این شاخه میشود:INT(A1/100)=۲۰۲۳۰۶- +۱ →
۲۰۲۳۰۷ *100 + ۱→۲۰۲۳۰۷۰۱.
- مثال: اگر A1 =
۵) چند مثال عددی (برای فهم بهتر)
- مثال ساده، افزایش روز در همان ماه:
- A1 =
۲۰۲۳۰۹۱۴(۱۴ سپتامبر) RIGHT(A1,2)+1 = 15maxDayOfMonth(ماه ۰۹ → ماه ≤ ۱۱ و >۶) = 30- ۱۵ > 30 ؟ خیر → نتیجه =
A1+1 = 20230915.
- A1 =
- مثال پایان ماه (ماه با ۳۱ روز):
- A1 =
۲۰۲۳۰۱۳۱ - روز+۱ = 32،
maxDayOfMonth= 31 → ۳۲>۳۱ → باید ماه عوض شود - ماه = 01 (≠۱۲) → شاخهٔ افزایش ماه → خروجی
۲۰۲۳۰۲۰۱.
- A1 =
- مثال پایان سال:
- A1 =
۱۴۰۰۱۲۲۹(در تقویم شمسی؛ روز ۲۹ ماه ۱۲) - روز+۱ = 30،
maxDayOfMonthبراساس فرمول = 29 → ۳۰>۲۹ → شاخهٔ ماه=۱۲ برقرار - سال +۱ →
۱۴۰۱۰۱۰۱(اول فروردین سال بعد).
- A1 =
۶) محدودیتها و نکات مهم
- کبیسه (leap year): فرمول بالا هرگز سال کبیسه را در نظر نمیگیرد — ماه ۱۲ همیشه ۲۹ روز فرض شده. اگر لازم است ماه دوازدهم در سالهای کبیسه ۳۰ روز شود، باید شرط اضافی برای تشخیص کبیسهٔ تقویم مورد نظر (جلالی/شمسی) اضافه گردد.
- قالب ورودی: فرمول فرض میکند
A1یک عدد یا متن با قالبYYYYMMDDاست (دو رقم روز همیشه وجود دارد). اگر روز/ماه یک رقمی باشند و صفر پیشرو حذف شده باشد، تفکیک اشتباه میشود. - خوانایی و یکسانسازی: بهتر است بهجای
INT(A1/100+1)ازINT(A1/100)+1استفاده شود تا دقیقاً منظور «افزایشYYYYMM» روشن باشد. - نوع داده:
RIGHTخروجی متن میدهد ولی چون بعداً با+۱استفاده شده اکسل آن را به عدد تبدیل میکند — این رفتار معمولاً بدون اشکال است ولی بهتر است برای خوانایی ازVALUE(RIGHT(A1,2))استفاده کرد. - مثالهای تقویم: الگوی روزها (۶ ماه اول ۳۱ روز و…) نشان میدهد فرمول برای تقویم شمسی/جلالی نوشته شده، نه تقویم میلادی (گرگوری). لذا در صورت استفاده برای تقویم میلادی باید منطق ماهها و بهخصوص ماه ۲ (فوریه) و کبیسه را تغییر داد.
۷) پیشنهاد بهبود (نمونهٔ بازنویسی خواناتر)
برای خوانایی و ایمنی بیشتر، میتوانید فرمول را بازنویسی کنید مثلاً:
=IF(VALUE(RIGHT(A1,2))+1 >
IF(MOD(INT(A1/100),100)<=6,31,IF(MOD(INT(A1/100),100)<=11,30,29)),
IF(MOD(INT(A1/100),100)=12,
(INT(A1/10000)+1)*10000 + 101,
(INT(A1/100)+1)*100 + 1),
A1+1)
تفاوت مهم: در شاخهٔ افزایش ماه از (INT(A1/100)+1) استفاده شده که خواناتر و مطمئنتر است.
