Function CheckValidShamsiDate(Dt) As Boolean
اگر فرمت بدین شکل باشد و / در فیلد ذخیره شود و سال هم چهار رقمی باشد 0000/00/00
((Y=Val(Mid(Dt,1,4
((M=val(Mid(Dt,6,2
((D=Val(Mid(Dt,9,2
If Y<1 And Y>2500 Then
CheckValidShamsiDate=False
End if
Select Case M
Case 1 To 6
If D>31 And D<1 Then
CheckValidShamsiDate=False
End if
Case 7 To 11
If D>30 And D<1 Then
CheckValidShamsiDate=False
End if
Case 12
If KabisehShamsi(Y)=True Then
If D>30 And D<1 Then CheckValidShamsiDate=False
Else if KabisehShamsi(Y)=False
If D>29 Abd D<1 Then CheckValidShamsiDate=False
End if
End Select
تابع بالا را میتوان در رویداد Exit تکست باکس نوشت که اگر False شد Cancel برابر True شود. چک کردن سال کبیسه ی شمسی هم مفصل در جای دیگر بحث شده.
برامون پیش اومده که وقتی فاکتور صادر می کنیم میخواهیم یه چیزی شبیه فاکتور باشه یا مثل اکسل ردیف ها را تا آخر در پرینت ببینیم ... فرض کنید شما تو فاکتورتون ۳ آیتم داریم ولی خط و خطوط باید تا پائین صفحه ی گزارش رسم بشه اگر نخواهید کنترل ها را بصورت Grow استفاده کنید ( منظور اگر شرح بیشتر شد از عرض کنترل اون کنترل تعریض یا اکسپند میشه تا محتویاتش رو راحت ببینیم ) می تونید امتحان کنید که در ارتفاع دیتیل در گزارش چقدر لاین جا می گیره به نسبتش یه کوئری ایجاد می کنید با آیدی از فرضا 1 تا ۴۰ و فیلدی که تماما خالیه بعد زمان باز شدن گزارش می گید که اون منبع گزارشتون با کوئری ساخته شده تجمیع بشه Union و بعد در شرط کوئری که ساختید و در یونیون استفاده می کنید می نویسید که آیدی هایی رو لیست کنه که کانت منبع گزارش ( با استفاده از تابع Dcount )
فرض مثال جدول فاکتور شامل فیلدهای زیر باشد
FactorNo PartNo Desc Qty UnitPrice Totals
ایجاد جدول بصورت بنام BlankFactor شامل فیلدهای
BlankId BlnkDesc
در یونیون حتما باید تعداد فیلدهای جدول یکی باشن اسامی فیلدها مهم نیست فقط دیتا تایپشون مغایرت نداشته باشه !!!
Select * From tblFactor
Union All
در سلکت زیر چون بایدتعداد فیلدها با تعداد فیلدهای سلکت بالائی یکی شود به تعداد باقیمانده از دابل کوتیشن استفاده کردیم
"","","","","",Select BlankDesc
Where BlankId>Dcount("*","tblFactor,"FactorID=" & tblFactor.FactorNo
در مثال فوق اگر شماره ی فاکتور را از باکسی در فرم بگیرد باید در شرط جای tblFactor.FactorNo آدرس کنترل در فرم یا سابفرم اعمال شود در اینجا شماره فاکتور ، دیتا تایپ نامبر گرفته شده که سرعت بالاتری در سرچ نسبت به دیتا تایپ تکست دارد
Forms!Form1!txtFactorNo
Report.NextRecord Property
Property NextRecord مشخص می کند که آیا سکشن مربوطه باید به رکورد بعدی پیش برود یا خیر که بصورت Boolean هست و در رویداد OnFormat قرار داده می شود .
پراپرتی مهم و کم کاربرد است
فرض کنید هر ۱۰ خط یا Line را در گزارش ( پرینت پرویو ) می خواهید جدا کنید ( توضیح واضح تر بعد از هر رکورد یک جای خالی باقی بگذارد یعنی به رکورد بعدی پیش نرود و بعد از آن لاین خالی دوباره رکوردها نمایش یابند ) یک کانتر در رویداد OnPrint دیتیل آن درست می کنید که اگر اون کانتر Mod ده برابر صفر شد NextRecord ترو شود PrintSection را هم می توانید ترو کنید ... برای ریست شدن کانتر از رویداد Format سکشن Header استفاده کنید که کانتر را صفر کند.
البته در مورد بالا باید یک نشانگر قرار دهید که اگر آن نشانگر برابر False شد آن سکشن رکوردها را طبق کانتر نمایش دهد و در صورتیکه به ۱۰ رسید به رکورد بعدی نرود و جای خالی بیاندازد یا بعبارتی رکورد بعد از لاین ۱۰ در خط بعد از آن جای خالی قرار گیرند. ( وقتی امتحان کنید لاین بعدی که نباید رکورد بعد از ده قرار گیرد همان تکرار رکورد ۱۰ است )
شی QueryDef یک تعریف ذخیره شده ای از کوئری در موتور دیتابیس اکسس هست که ازآن برای ساخت کوئری استفاده خواهد کرد . ( و حتی مقداردهی پارامتر )
Dim Qry As QueryDef
Set Qry=CurrentDb.CreateQueryDefs("Select * From
("Table1 Where Id>=14
استفاده از پارامتر
Dim qdf As QueryDef
("Set qdf = dbs.QueryDefs("myActionQuery
Set the value of the QueryDef's parameter'
تنظیم مقدار یا مقداردهی پارامتر
_ =qdf.Parameters("Organization").Value
"Microsoft"
....Docmd.Runcommand acCmd
acCmdZoom100
acCmdUndo
acCmdSelectRecord
acCmdSelectAll
acCmdSaveRecord
acCmdRowHeight
acCmdRemoveAllFilters
acCmdRefresh
acCmdRedo
برای سابفرم نه رکوردست از این فرامین استفاده می کنیم
acCmdRecordsGoToFirst
acCmdRecordsGoToLast
acCmdRecordsGoToNew
acCmdRecordsGoToNext
acCmdQueryTotals
acCmdPrintPreview
acCmdPrint
برای استفاده در شورت کات منوی ساخته شده در دیتا شیت توسط خودتان
acCmdCopy
acCmdCut
acCmdPaste
acCmdDelete
acCmdLayoutView
acCmdFind باکس Search Find
acCmdExportText
acCmdExportAccess
acCmdDesignView
acCmdDeleteRecord
acCmdDeleteRows
acCmdDataEntry
acCmdControlMarginsNarrow
acCmdCloseDatabase
acCmdCloseWindow
acCmdCloseAll
acCmdClearAll
acCmdChangeToComboBox
در دیزاین فقط میشود کنترلی را تغییر داد پس تلاش نکنید در ویو استفاده کنید
acCmdAppMaximize
acCmdAppMinimize
acCmdAppMove
acCmdAppRestore
شورتکات :
سه تا کامند باتن در کامندباربصورت MsoPopup برای پرینت ، رفرش و بستن فرم ContactList
اسم ماکروی بالا mcrAddShortcutMenu را در قسمت پراپرتی ShortCutMenu تایپ می شود با AddMenu در Add-In ریبون قابل مشاهده هست.
کامند باتن در CommandBar و ساب منو بهمراه کامند ها
بصورت زیر نمایان خواهد شد. برای ایجاد ساب منو در تصویر بالا از AddMenu استفاده شده و یک ماکروی با نام SubMenuCommands با فرمان ساب ماکرو داخلش ساخته شده و در MacroName اظهارشده .
در باکس ادیت SubMacro می توان از کلیدهایی برای انجام کارهائی استفاده کرد یا عملکرد آنها را غیر فعال کرد فرضا p^ منظور Ctrl+p هست فرضا شما می خواهید فرمان انجام نشود در نتیجه در خط بعدی CancelEvent را می توانید انتخاب و ماکرو را با عنوان AutoKeys ( فقط به این نام ) ذخیره کنید.
در سطح پیشرفته تر یعنی استفاده از Commandar.Controls Properties باید حتما از رفرنس Microsoft Object Library انتخاب شود تا بتوانید از پراپرتیهای آن استفاده نمائید.
https://docs.microsoft.com/en-us/office/vba/api/office.commandbar.controls
نمونه ای از سطح دسترسی
()Private Sub Form_LoadDim sPermit As StringDim iAccess As IntegerDim Ctl As Access.Control("Me.txtUser = Environ("usernameIf IsNothing(Me.txtUser) The"sPermit = "ReadOnlyElse"sPermit = "ReadOnlySelect Case sPermit(sPermit = GetPermission(Me.txtUserEnd IfiAccess = 3"Case "EditiAccess = 2"Case "AdminMe.txtLevel = iAccessCase ElseiAccess = 1End SubEnd Select()Private Sub Form_LoadIf Forms!frmMenu!txtLevel < 11 ThenMe.AllowEdits = FalseElseMe.AllowEdits = TrueEnd IfEnd Sub(Private Function GetPermission(sUser As String_ & "'= If (IsNothing(DLookup("Permissions", "tblStaff", "LoginForms!frmmenu!txtUser & "'"))) Then"GetPermission = "ReadOnlyElse_ & "'=GetPermission = DLookup("Permissions","tblStaff","Login"'" & Forms!frmmenu!txtUserEnd ifEnd Functionنمونه ی تصویری
مثال زیر از متغیر intSearch برای گرفتن مقدار ( عددی ) استفاده می کند که بعنوان integer یعنی حدود ۵ رقم نهایتا تعریف میشود اگر عدد بزرگتر باشد از Long استفاده کنید
نکته : در پنجره ی immediate window وقتی میخواهید عددی را در عدد دیگری ضرب کنید چون پیش فرض integer می گیرد پیغام Overflow را نمایش می دهد که باید آنرا به Long تبدیل یا Convert کنید فرضا 200 *(Clng(1356 ?
Dim intSearch As IntegerDim varX As VariantintSearch = 1_ ,"varX = DLookup("[CompanyName]", "Shippers("[ShipperID] = " & intSearch]"در مورد بالا نام کمپانی را از جدول/ کوئری Shippers درصورتیکه مقدار ShipperID آن برابر متغیر اظهارشده بود( یعنی یک ) بازیابی میکند اگر Null باشد ارور Null را بر می گرداند پس صحیح است که بعد ازآن به نمونه روش ذیل عمل کنیمIf IsNull(Varx) =False Or Varx<>"" ThenEnd ifاگر شرط مورد جستجو عدد نبود یعنی تکست یا به قولی متنی باید شرط بصورت زیر تغییر یعنی تک کوتیشن به اول و آخر عبارت اضافه میشود " ' عبارت ' ""'=Dlookup("CompanyName","Query1","FamilyName"'" & Me.TxtSearch &در مثال فوق اسم شرکت از کوئری یک را بازیابی می کند زمانیکه مقدار txtSearch که تکست هست با فیلد FamilyName برابر باشد. اگر txtSearch در سابفرم باشد باید به آن ارجاع داد فرضا فرم اصلی را MainForm و اسم سابفرمی که txtSearch در آن وجود دارد Sub1 درنظر بگیرید .& "'=FamilyName""'" & Forms!MainForm!Sub1.Form!TxtSearchبعد از Sub1 از Form استفاده کردیم چرا ؟ چون سابفرم خودش از دو لایه تشکیل شده لایه ی اول پراپرتی های مربوط به خود سابفرم است مثل LinkMaster یا LinkChild و شامل کنترهای مربوط به فرم نیست و بعدی مربوط به فرم که شامل سکشن ها منظور دیتیل و هدر و کنترل هاست
Byte — For integers that range from 0 to 255. Storage requirement is a single byte.
Integer — For integers that range from -32,768 to +32,767. Storage requirement is two bytes.
Long Integer — For integers that range from -2,147,483,648 to +2,147,483,647. Storage requirement is four bytes.
Docmd.Rename NewName,ObjectType,OldName
از متد Rename برای تغییر نام شئ دیتابیس مشخص شده مثل جدول یا کوئری بهره ببرید
Use the Rename method to rename a specified database object.
اگر ObjectType و آرگومان OldName خالی بمانند ( پس با توجه به این گفته هر دو Optional یا انتخابی هستند و می توانند خالی رها شوند - پیش فرض acDefault است یعنی هر چی که انتخاب شده بود ) اکسس آبجکت یا شئ انتخاب شده در پنجره دیتابیس ( سمت چپ که لیست فرم و جداول و ... است ) را تغییر نام می دهد. برای انتخاب شئ می توانید از متد SelectObject استفاده بنمائید با بهره گیری از آرگومان InDataBaseWindow و تنظیم آن به Yes ( True )
If you leave the ObjectType and OldName arguments blank (the default constant, acDefault, is assumed for ObjectType), Access renames the object selected in the Database window. To select an object in the Database window, you can use the SelectObject method with the InDatabaseWindow argument set to Yes (True).
Docmd.SelectObject ObjectType, ObjectName, InNavigationPane
دو تا آرگومان آخر انتخابی هستند و می توانند خالی بمانند آرگومان آخر برای شی باز است اگر False تنظیم شود. پیش فرض InnavigationPane ( در پنل راهبری که همان پنجره دیتابیس است ) نیز False است
DoCmd.Rename "Old Employees Table"
, acTable, "Employees"
Run-time error '7874':
Microsoft Access cant find the object 'Test'مایکروسافت اکسس نمی تواند آبجکت اشاره شده را پیدا کندیا تغییر نام دادید یا اصلا جدول یا کوئری یا فرم یا گزارشدر دیتابیس موجود نیستند.
با SelTop میشود مشخص کرد که کدام Row در بالاترین مستطیل انتخابی در جدول ، کوئری ، دیتاشیت یا کانتینوس ف رم وجود دارد ( منظور اگر چند سل را انتخاب کرده باشید شماره ی مستطیل اول را بیان میکند بصورت Long ) اگر کالمن انتخاب شود پراپرتی مربوطه را نمی توانید تغییر دهید.
درتصویر پائین رکوردها انتخاب شده میتوان با Me.SelHeight تعداد انتخاب شده ها را گرفت توسط ایونت MouseUpو ذخیره در متغیر عمومی و بعد برای نمایش مقادیر انتخاب شده
۱-ایجاد رکوردست با RecordSetClone
۲-رفتن به رکورد اول
۳-تغییر موقعیت در رکوردست با پراپرتی Move که Rows آن SelTop میشود.
۴-ایجاد حلقه از یک تا جائی که به Sel برسد یا ممکنه حتی Sel-1 در این حلقه میتوان از پراپرتی Fields اون رکوردست استفاده کرد تا با MsgBox مقداراون فیلد را برگرداند .
این روش ها درست است : فرضا اگر FLD1 کالمن اول رکوردست باشد منظور در جدول یا کوئری و از صفر شروع میشود.
("MsgBox RS.FIELDS("FLD1
( MsgBox RS(0
MsgBox RS!FLD1
با استفاده از پراپرتی های SelHeight و SelWidth فرم هم می توان سایز واقعی مستطیل انتخابی در دیتاشیت را مشخص نمود.
بعبارتی گوشه ی راست پائینی مستطیل انتخابی را تعیین میکند
SelTop و SelLeft هم گوشه ی بالائی چپ مستطیل انتخاب شده میتواند چند مستطیل باشد
مثل Delete یا Add
استفاده از متد Execute نه RunSql و بعد پراپرتی RecordsAffected از CurrentDb
لیست چندی از پراپرتی های اکسس ، پراپرتی CurrentDb.Properties
Name
Connect
Version
RecordsAffected شمارش رکوردهای تحت تاثیر اکشن کوئری ها فرضا دیلیت یا اپند
Connection
AccessVersion
StartUpForm در قسمت آپشن و این خصوصیت می توانید فرمی را برای بنمایش درآمدن در هنگام فعال کردن ماکروها اجرا کنید
StartUpShowDBWindow منظور همان NavigationPane هست
StartUpShowStatusBar نوار پائینی در آبجکت ها
AllowShortcutMenus برداشتن تیک در آپشن قسمت مربوطه یا کارنت دیتابیس یا کلاینت ستینگ باعث میشود که شورت کات هائی که در فرم یا گزارش وجود دارد و با کلیک راست اعمال می گردد غیرفعال شوند.
AllowFullMenus : فعال یا غیرفعال کردن منوهای اکسس منظور تب پیج های ریبون غیر از تب File که قابل حذف یا هاید کردن نیست
AllowBuiltInToolbars : در اکسس ۲۰۰۳ به پائین کاربرد داشت که ToolBar شما اعمال میشد منظور منوهایی که جای ریبون موجود در ۲۰۰۳ به بالا وجود دارند.
AllowToolbarChanges
AllowSpecialKeys : فعال یا غیرفعال کردن کلید ترکیبی Alt و F11
AppTitle عنوان برای اپلیکیشن در TitleBar
AppIcon آیکون برای اپلیکیشن که روی تمام آبجکت ها اعمال خواهد شد
بعضی از این پراپرتی ها با Docmd.SetOption قابل تنظیم است
مطالعهhttps://docs.microsoft.com/en-us/office/vba/api/access.application.setoption
از شی رکوردست برای دستکاری داده در دیتابیس در سطح رکورد استفاده میشود ( جدول یا کوئری )
چند تا تیپ داره یکیش SnapShot هست که ReadOnly است و قابل Edit نیست و بعدی Dynaset که Read و Write را دارد برای باز کردن رکوردست در دیتابیس جاری از متد OpenRecordset از CurrentDb استفاده میشود فرضا میخواهیم جدول یک را در رکوردست باز کنید
***اول اظهار متغیری بعنوان رکوردست
Dim Rs As DAO.Recordset ( اگر Object Library تیک نخورده باشد از Refrences ارور میدهد ).
***دوم ایجاد آن در بافر
(Set Rs=CurrentDb.OpenRecordset("Table1",dbOpenDynaset
-برای دستکاری دیتا در رکورد : برای دیلیت از Rs.Delete برای اضافه کردن از Rs.Add و برای ویرایش از Rs.Edit استفاده می کنیم و حتما باید بعد از اینها Rs.Update نوشته شود.
-برای رفتن به رکورد اول ، بعدی ، قبلی و آخر به ترتیب از
MoveLast MovePrevious MoveNext MoveFirst استفاده می کنیم بیشتر برای لوپ زدن داخل رکوردست استفاده میشود.
***سوم بعد از اتمام کار بستن رکوردست با Rs.Close و خالی کردن بافر از آن با Nothing
- Rs.Eof مقداری رو میده از نوع Boolean که آیا موقعیت رکورد جاری بعد از رکورد آخر هست یا خیر وقتی به آخرین رکورد برود و زمان رفتن به رکورد بعد از آن که چیزی نیست ارورمیدهد که به انتهای رکوردست رسیده زمان خاتمه به حلقه هم از آن استفاده میشود مثل
Do While Not Rs.Eof
("Debug.Print Rs.Field("FldName
Rs.MoveNext
Loop
-از Rs.Move برای انتقال پوزیشن رکورد جاری در شی رکوردست استفاده میشود که پارامتر اول آن Rows است
-از Rs.AbsolutePosition برای گرفتن شماره رکورد در آن شی رکوردست استفاده می شود.
-از Rs.FindFirst برای پیدا کردن مقدار یا عبارتی در رکوردست استفاد میشود و چک کردنش با پراپرتی بعدی یعنی NoMatch هست مثل
برای عدد Rs.FindFirst "FldName1=" & Me.txtValue
برای تکست "'" & Rs.FindFirst "FldName1='" & Me.txt1
-از Rs.NoMatch برای تطابق داده ی پیدا شده با استفاده از FindFirst استفاده میشود یعنی اگر توسط FindFirst پیدا شد چه عملی انجام دهد
"'" & Rs.FindFirst "FieldName='" & Me.TxtSearch
If Rs.NoMatch=False Then
DO Something '
End If
- از Rs.RecordCount برای شمارش رکورد در رکوردست باز شده استفاده میکنیم البته اول باید به رکورد آخر برویم و بعد رکورداول و بعد رکوردکانت را استفاده کنیم تا درست عمل نماید.
- از Rs.BookMark بعنوان نشانگری که به طور یونیک رکورد جاری را در شی رکوردست مشخص میکند استفاده میشود ... فرضا در ورد بعبارت ساده و قابل فهم ، عباراتی را بعنوان بوک مارک در نظر می گیرید ، زمان استفاده به آن صفحه ای که هست می رود . اینجا هم همینطور است فرضا در فرم رکوردی را اضافه میکنید و با استفاده از FindFirst و NoMatch و برابر قرار دادن BookMark فرم و BookMark رکوردست میتوان به همان رکورد در سابفرم رفت چون دیتای جدید بعد از رکورد آخر می آید
برای ایجاد RowNumber یا LineNo در فرم کانتینیوس نه سینگل هم بوک مارک رکوردست با بوک مارک فرم برابر میشود و از AbsolutePosition باضافه ی یک استفاده میکنیم برای برگشت مقدار تابع فرضا
(Function ROWNUM(FRM AS FORM
اگر کارنت رکورد فرم مخالف رکوردکانت رکوردست بود بوک مارک رکوردست برابر بوک مارک فرم شود
ROWNUM=RS.ABSOLUTEPOSITION+1
END IF
END FUNCTION
درنظر داشته باشید شماره ی رکورد در دیتا شیت اکسس با رکوردست یکی نیست !!!
در فرم اگر کمبوی مالتیپل داشته باشید طبق معمول برای تیک زدن یا برداشتن تیک به این روش عمل می کنید
۱-فوکس کردن روی کمبو
۲-انجام عمل دارپ داون با کلیک کردن روی فلش پائین سمت چپ کمبو که با بازشدن لیست باکس همراه هست و تیک زدن با لفت ماوس فرضا که اگر انتخاب شده باشد برداشه و اگر نشده باشد دوباره انتخاب می شود
روش کد نویسی
۱-SetFocus
2-DropDown
لیست باکس آن پراپرتی ListCount دارد.
3-پراپرتی (Selected(index کمبو یا لیست باکس برای تیک زدن یا برداشتن برابر True یا False
کمبو باکس از قسمت های زیر تشکیل شده :
ادیت باکس ، دراپ داون و لیست باکس
(Me.F.Selected(i)=Not Me.F.Selected(i
چون اکسس در بعضی سیستم ها ساعت را بصورت AmPm و نه حالت ۲۴ ساعته نشان می دهد بنابراین برای حل مشکل باید ماژولی نوشت که اگر Format اون Time جاری AM شد عدد ۱۲ به آن اضافه بنماید البته برای ساعات خیلی بالاتر باید ارور را رفع کرد بعد تبدیل ساعت و دقیقه به ثانیه و جمع کردن با خود ثانیه
فرضا اضافه کردن 520 ثانیه ( 8 دقیقه و 40 ثانیه ) به تایم زیر
1:14:20AM
Start ..... 131420
Dim H,M,S
(H=Mid(Start,1,2
(M=Mid(Start,3,2
(S=Mid(Start,5,2
در اینجا 13 در 3600 و 14 در 60 ضرب شده وبا 20 جمع می گردد و با عدد 520 ثانیه در بالا جمع میشود که عدد 48180 بدست می آید برای تبدیل این عدد به ساعت دقیقه و ثانیه اول 48180 را به 3600 تقسیم می کنیم که عدد 13 بدست می آید دوم Remainder ( یا باقیمانده ی تقسیم ) عدد 48180 بر 3600 را محاسبه می کنیم وبر 60 تقسیم می کنیم که عدد 23 میشود ( عدد دقیقه بدست آمد ) و ثانیه هم از Remainder عدد قبلی حاصل میشود یعنی 1380 منهای 22 در 60 : 0
AMPMhttps://www.languagecentre.ir/english/vocabulary/difference-between-pm-am
ساعت ( 13) دقیقه (23) ثانیه (0)
برای گرفتن ولیوهای داخل MultipleFieldValue باید از رکوردست ۲ استفاده کرد و پل زدن به آن فیلد و پراپرتی Value آن فرضا فیلد Rooz داریم و چند آیتم در آن وارد شده
۱-باز کردن رکوردست ۱ ( جدول )
۲-تنظیم رکوردست ۲ به فیلد رکوردست ۱ ( Rooz ) و پراپرتی ولیو (Value)
البته برای لیست شدن کلیه ی تیک خورده ها باید Loop زده شود و استفاده از MoveNext برای رفتن به رکورد بعدی در آن رکوردست
برای پرینت گرفتن ورد پی دی اف یا هر چیزی که قابلیت پرینت داشته باشد از طریق اکسس ارتباط با شل یا سا ختن آن (Shell.Application) است و استفاده از کامند ShellExecute که پارامتر اول آن نام و مسیر فایل است و پارامتر چهارم عبارت پرینت و آخری هم ویو است که فرضا VbHide یا VbNormalFocus و غیره است یا شماره ی آن که میشود در Immidiate Window Ctrl+G با علامت سوال قبل از آن ، عدد مربوطه رو گرفت
پرینت اوپن و ادیت را میتوان اعمال کرد در ShellExecute
پراپرتی هائی که در اکسس ایجاد نشده را میتوان از کالکشن DAO انتخاب و اضافه کرد جز کانکشن و ارورها مثل پراپرتی زیر برای بستن یا باز کردن شیفت True/False ، تا ایجاد نشن عمل نخواهند کرد و ارور هم داده خواهد شد پراپرتی نات فاوند اگر هم ایجاد بشه ارور قبلا ایجادشده را خواهد داد.
تایپ هم مهمه مثل پراپرتی زیر که Boolean هست ولی چیزهائی که عبارتی به آن ملحق میشه از نوع dbText هست مثل AppTitle
"Set Prp=CurrentDb.CreateProperty("AllowByPassKey
(dbBoolean,False,False,
CurrentDb.Properties.Append Prp
گاهی محاسبات بهم میریزد مثل ۷ خرداد ۱۳۹۸ که باید ۲۳ رمضان باشد ولی ۲۲ رمضان میشود چون ماه قبلی ۳۰ روزه شده ....
آیتم اول را اگر به ترتیب از اولین ماه قمری که 30 هست و یک درمیان 29 میشود کم کنیم تا مانده از تعداد روزهای ماه کوچکتر شود عدد 23 حاصل میشود
259−30−29−30−29−30−29−30−29=23
در این مثال می توان در ماژول نوشت اگر سال ۱۴۴۰ شد جای تعداد روزهای ماه ۸ و ماه ۹ قمری جابجاشوند تا ۲۳ رمضان به ۲۲ رمضان تبدیل شود
510,192+1−1,440×354−528+354=259
508,161+1−1,434×354−526+355=355
508515+1-1435×354-526+354=354
495323+1-1398×354-513+355=274
506627+1-1430×354-524+354=237
506714+1-1430×354-524+354=325
506393+1-1429×354-524=4
508870+1-1436×354-527+355=355
506743+1-1430×354-524+354=354
505,326+1−1,426×354−523+355=355
در مثال های بالا
عدد اول اختلاف 19 جولای 622 شروع قمری و تاریخ میلادی۱موردنظر است که به ترتیب 28 می 2019 ، 4 نوامبر 2013 ، 24 اکتبر 2014 ،11 سپتامبر 1978 ،23 اوت 2009 ، 18 نوامبر 2009 ، 1 ژانویه 2009 ، 14 اکتبر 2015 و 17 دسامبر 2009 ، 30 ژانویه 2006 می باشد
عدد دوم : یک واحد به اختلاف اضافه می شو
عدد سوم : حاصل ضرب 354 در ( تقسیم جمع عدد اول و دوم
(بر354 منهای یک است
عدد چهارم : تعداد کبیسه ی سپری شده تا عدد سوم است.
اگر عدد نهایی کوچکتر مساوی صفر شد اگر عدد سوم که سال است کبیسه بود با 355 اگر نه با 354 جمع میشود ، اگر عدد نهائی بزرگتر از صفر بود که یک واحد به سال اضافه میشود و ماه هم یک و یا بالاتر .
در جائی که عدد 354 یا 355 اضافه نشده یعنی عدد مثبت شده
لینک محاسباتhttps://keisan.casio.com/exec/system/1346122065 ذهنتون رو در گیر نکنید چون قمری هم قائده ی خاصی ندارد و دقیق ترین محاسبه باید نجومی باشد که آنهم نمیشود مال چند
سال دیگر را حدس زد
برای تبدیل شمسی به قمری تنها کافیه اختلاف تاریخ شمسی موردنظر تا تاریخ ۱/۱/۱ شمسی را بدست آوردید و منهای ۱۱۹
کنید ( اختلاف ۲۷ تیر یک شمسی تا ۱ول قمری ۱۱۹ است
فرضا اختلاف ۱ شمسی تا ۸ خرداد ۹۸ عدد ۵۱۰۳۱۲ عدد ۱۱۹ را که از آن کم کنیم میشود همان عدد ۵۱۰۱۹۳ و طبق مثال های بالا عمل
میکنیم
: آرایه
1 : 29 , 2 : 59 , 3 : 89 , 4 : 118 , 5 : 148 , 6 : 177 , 7 : 207
8 : 236 , 9 : 266 , 10 : 295 , 11 : 325 , 12 : 354
اگر سال کبیس شد ماه آخر در آرایه یعنی ۱۲ به ۳۵۵ تغییر می یابد
: معادله
510,193+1−1,440×354−528+354=260
چون سال ۱۴۴۰ قمری محاسبات را بهم زد و فرضا بجای ۲۳ رمضان ۲۲ رمضان شد در نتیجه در بالا می توانیم ا عداد ۸ و ۹ را عوض کنیم ( آرایه ی بالا ) در مورد ۲۶۰ در حالت عادی وقتی از ۲۳۶ کم می کنیم عدد روز قمری ۲۴ در می آید که طبق تغییرات در ماه قبل رمضان این روز ۲۳ رمضان خواهد شد نتیجتا باید در ماژول بنویسیم اگر سال ۱۴۴۰ قمری شد عدد ۸ به۲۳۷ و عدد ۹ به۲۶۵ تغییر یابد که اگر بدین منوال اقدام شود اختلاف عدد ۲۶۰ بدست
آمده و عدد۸ که ۲۳۷ شده ۲۳ می شود.
طبق تصویر پائین ماه های قمری ترتیب خاصی ندارد
19 جولای سال 622 شروع تاریخ قمری است و مصادف با 27 تیر سال یک شمسی
Dim D(12) As Long
D(1)=30 : D(2)=59 : D(3)=89 : D(4)=118 : D(5)=148 D(6)=177 : D(7)=207 : D(8)=236 : D(9)=266 : D(10)=295 : D(11)=325 : D(12)=354
یک در میان ماه ها ی قمری را بصورت قراردادی 29 مشخص کرده اند یعنی ماه اول که محرم است 30 روز و ماه بعدی 29 و با این منوال ماه های فرد را 30 روز و ماه های زوج را 29 روزه گرفته اند و در صورت کبیسه بودن سال طبق جدول ، روش رایج در گاه شمار قراردادی ماه آخر بجای 29 روزه 30 روزه در نظر خواهند گرفت.
در رایجترین تقویم هجری قمری حسابی طی یک دوره سی ساله کبیسه منظم از قرار زیر محاسبه شدهاست:
بر اساس این کبیسهگیری، چنانچه باقیماندهٔ حاصل تقسیم سال قمری به عدد ۳۰ یکی از اعداد (۲، ۵، ۷، ۱۰، ۱۳، ۱۶، ۱۸، ۲۱، ۲۴، ۲۶ و ۲۹) باشد، سال مذکور کبیسه و طول آن (۳۵۵ روزه) میباشد.
با کانتر براحتی میتوان تاریخ دقیق را بدست آورد اگر کبیسه دقیق و طبق جدول، روش رایج ،که اقتباس شده بدست آید ، ولی در فواصل طولانی حدودا ۳ ثانیه بازگشت بطول خواهد انجامید پس باید دنبال راهی باشید که کمترین زمان برگشتی را داشته باشد.
18 ژانویه سال 624 معادل 27 دی سال 2 ، اختلاف با تابع DateDiff اکسس بین 19 جولای 622 که شروع قمری است تا تاریخ 18 ژانویه ی 624 موردتبدیل ما 549 روز است که یک واحد به آن اضافه می کنیم .
در اینجا 550 از 354 بزرگتر است پس D12 را از آن کم میکنیم میشود 195 و سال هم بالطبع یک واحد بدان اضافه شده و 2 خواهد شد ، طبق آرایه ی بالا 195 بین D6 و D7 است پس کوچکتر از عدد 195 را انتخاب میکنیم 177-195 که میشود 18 ( روز ) و عدد آرایه ی 177 6 است که آنرا باضافه ی یک می کنیم که ماه عدد 7 می شود
بنابراین سال شد 2 ماه 7 و روز هم 18
2/4/14 - 6 جولای 623 و 28 ذی الحجه سال ۱ قمری ، 352
2/4/15 - 7 جولای 623 و 29 ذی الحجه سال ۱ قمری ، 353
2/4/16 - 8 جولای 623 و 1 محرم سال 2 قمری ، 354
2/4/17 - 9 جولای 623 و 2 محرم سال 2 قمری ، 355
۱۲ تیر سال ۵ شمسی معادل ۴ جولای ۶۲۶ و ۳۰ محرم (۱) سال ۵ ... اختلاف ۱۴۴۶ روز
۷ تیر سال ۵ شمسی معادل ۲۹ جون ۶۲۶ و ۲۵ محرم (۱) سال ۵ ... اختلاف ۱۴۴۱
۲۷ تیر سال یک شمسی آغار سال قمری و ۱۹ جولای ۶۲۲ آغاز سال قمری اختلاف ها با DateDiff
1446=("Dif=DateDiff("n","7/19/622","7/4/626
Ret=Dif=1446+1=1447
( If 1447>354 (True
Y=2 Ret=1447-354=1093
( If 1093>354 (True
2=Kabiseh Y=3 Ret=1093-355=738
( If 738>354 (True
3=NoKabiseh Y=4 Ret=738-354=384
( If 384>354 (True
4=Nokabiseh Y=5 Ret=384-354=30
(If 30>354 (False
(If Ret=D(1) , M=۰ : Ret=D(1
If Ret<D(1) , M=۰ : Ret=D(1)-Ret
... If
... If
M=M+1
تا زمانی لوپ ادامه می یابد که Ret کوچکتر مساوی (D(M شود
Ret=30 , M=1
Year : 5 , M : 1 , D : 30
۳۰ محرم سال ۵
باحسابhttps://www.bahesab.ir/time/conversion/
لینک بالا ۱۴۳۶ تا ۱۴۳۸ را کبیسه ی قمری نشان میدهد در حالیکه در تقویم های آنلاین دیگر ۱۴۳۶ کبیسه ولی ۱۴۳۷ کبیسه نیست ؟؟!!!! ولی ما بر حسب همان رایج استفاده می کنیم که قابل اعتمادتر است . انشالله باحساب توضیح قانع کننده برای کبیسه بودن ۳ سال پشت سر هم در سایتش داشته باشد ..( ۲۰ رمضان )
گاه شمار قمریhttps://fa.m.wikipedia.org/wiki/گاهشماری_هجری_قمری
از شکافتن هسته ی اتم هم ساده تر است اگر تلاش کنید محتاج چون منی نخواهید بود ( امام خمینی ره )
قسمت گاه شماری هجری قمری قراردادی جدول مربوطه ( رایج )
طبق رایج ... تعداد روزهای ماه های قمری یکی در میان ۲۹ یا ۳۰ روزه هستند و از ۲۹ روز شروع میشود اگر سال کبیسه بود ماه آخر بجای ۳۰ روزه ۲۹ روزه میشود با Mod میشود تعداد روزهای ماه قمری را مشخص کرد در لوپی که مانده باید از روزهای قمری کم شود
فرضا i mod 2 اگر صفرشود ماه ۳۰ روزه واگر یک شود ماه ۲۹ روزه است
تبدیل میلادی به قمری : ۲۶ می ۲۰۱۹ معادل ۵ خرداد ۹۸
اختلاف را با DateDiff اکسس میشود بدست آورد از ۱۹ جولای ۶۲۲ تا تاریخ میلادی درج شده .( روز اول در تابع DateDiff ثابت است )
که در اینجا اختلاف روزها را ۵۱۰۱۹۰ نشان میدهد
معادله البته اگر عدد منفی شد به سال بدست آمده اضافه نمیشود
سال را منهای یک کرده و در ۳۵۴ ضرب می کنیم تعداد کبیسه که اینجا ۵۲۸ است مربوط به یک قمری تا سال ۱۴۳۹ است ( ۳۵۴ جمع روزهای یکسال قمری در شرایط غیر کبیسه است )
۹۷-=۵۲۸-(۱۴۳۹×۳۵۴)-(۵۱۰۱۹۰-۳۵۳)
عدد منفی شده با ۳۵۳ جمع میکنیم ( عدد ۳۵۳ اختلاف روز یک قمری تا آخرماه همان سال است )
سال همان ۱۴۴۰ باقی می ماند
عدد آخر ۲۵۶ بدست می آید
از ماه اول قمری به همان شکل که گفته شد انقدر کم میکنیم تا از تعداد روز آن ماه کمتر یا مساوی باشد
۲۰=۲۵۶-۲۹-۳۰-۲۹-۳۰-۲۹-۳۰-۲۹-۳۰
خود تقویم سال ۹۸ یکشنبه ۵ اردیبهشت ۹۸ را ۲۱ رمضان چاپ کرده
https://fa.m.wikipedia.org/wiki/گاهشماری_رسمی_ایران
از قائده ی خاصی پیروی نمیکند لیست زیر طبق جدول لینک بالا از سال ۴ تا سال ۱۴۷۳ می باشد ، بعد از هر عدد یک کبیسه ی پنج ساله است و بعد از آن تا شروع عدد بعدی هر چهار واحدیک کبیسه ی چهارساله است.
اعداد زیر طبق جدول گاه شماری_رسمی_ایران ( لینک بالا ) استخراج شده .
ARRAY(4,37,66,99,132,165,198,231,264,297,326,359,392,425,458
491,524,553,586,619,656,685,718,751,784,817,850,883,916,
949,978,1011,1044,1077,1110,1143,1176,1209,1238,1275,
,1308,1341,1370,1403,1436,1473,1502,1535,1568,1601
1634,1667,1696,1733
اعداد بالا را در تابع Array قرار میدهیم بدون دابل کوتیشن فرضا اگر بخواهیم کبیسه بودن سال ۱۳۸۰ را بسنجیم
۱-عددی در آرایه را که از عدد ۱۳۸۰ کوچکتر باشد را پیدا میکنیم که در اینجا ۱۳۷۰ را نمایش خواهد داد
۲-همانطور که گفته شد بعد از اعداد یاد شده عدد بعدی باضافه ی ۵ کبیسه ی ۵ ساله میشود و اعداد بعدی آن هر چهار واحد اضافه کبیسه ی چهار ساله میشود . پس بین عدد ۱۳۷۰ تا ۱۳۸۰ لوپ میزنیم یا در همان دو لوپ ایجاد شده در لوپ اول یک C بعنوان کانتر میزنیم و میگوئیم C=C+1
لوپ اول هم در آرایه یکی یکی اعداد را میگیرد و بازه ی لوپ دوم عدد آرایه در لوپ اول و عدد بعد از آن خواهد شد .
قسمتی ازکد بقیه توسط الگوریتم باید انجام شود :
DO
.
DO
DEBUG.PRINT J
IF J>A+5 THEN J=J+4 ELSE J=J+5
(LOOP UNTIL J>=ARR(I+1 ؟؟؟ >
X=J
I=I+1
(LOOP UNTIL I=Ubound(J
لوپ دوم می تواند تا زمانی ادامه یابد که سال داخل تابع کوچکتر مساوی عدد داخل آرایه باشد. ( فرضا میخواهید چک کنید چند سال کبیسه را تا قبل از سال ۱۳۷۰ پشت سر گذاشته اید : برای اختلاف تاریخ شمسی حتما باید تعداد کبیسه تا یکسال قبل محاسبه شود ولی برای توتال روزهای گذشته از سال کنونی خود سال باید مشخص شود که کبیسه هست یا خیر .... عددی در آرایه که کوچکتر از ۱۳۷۰ باشد را میگیریم و طبق آنچه گفته شد ۵ سال به عدد آرایه اضافه می کنیم که کبیسه ی ۵ ساله است و کبیسه های بعدی چهار تا چهارتا اضافه میشود)
برای لیست کردن سال های کبیسه طبق آرایه ی بالا اگر Ubound و Lbound جواب دهد میتوان سال های کبیسه را لیست کرد چه در اکسل چه در اکسس طوری عمل میشود که عدد اول را باضافه ی ۵ میکند و بقیه را بعلاوه ی چهار تا به عدد بعدی در آرایه برسد اگر عدد آخر با pointer ( یا عدد بعدی آرایه ) برابر نبود عددها را چاپ کند ، فرضا
4+5=9 و بعد چهار تا چهارتا جلو میرود ۹+۴ ، ۱۳+۴ ، ۱۷+۴ ، ۲۱+۴
۲۵+۴ ، ۲۹+۴ ، ۳۳ +۴ که ۳۷ میشود
بدست آوردن دقیق کبیسه برای کسانیکه میخواهند تقویم دقیقی داشته باشند یا محاسبه ی دقیق از سال یک تا ۱۵۰۰ پیروی از این سبک الزامیست وگرنه اختلاف یک یا دو روز حداکثر حتمی است.
مرجع: گاه شماری_رسمی_ایران
سالهای کبیسه رسمی یک قرن اخیر با توجه به دورهها:
(دورهٔ ۳۳ساله): ۱۲۸۰ - ۱۲۸۴ - ۱۲۸۸ - ۱۲۹۲ - ۱۲۹۶ - ۱۳۰۰ - ۱۳۰۴ - ۱۳۰۸
(دورهٔ ۳۳ساله): ۱۳۱۳ - ۱۳۱۷ - ۱۳۲۱ - ۱۳۲۵ - ۱۳۲۹ - ۱۳۳۳ - ۱۳۳۷ - ۱۳۴۱
(دورهٔ ۲۹ساله): ۱۳۴۶ - ۱۳۵۰ - ۱۳۵۴ - ۱۳۵۸ - ۱۳۶۲ - ۱۳۶۶ - ۱۳۷۰
(دورهٔ ۳۳ساله): ۱۳۷۵ - ۱۳۷۹ - ۱۳۸۳ - ۱۳۸۷ - ۱۳۹۱ - ۱۳۹۵ - ۱۳۹۹ - ۱۴۰۳.
جدول زیر از وب گرفته شده و باید طبق جدول داخل لینک طبق ردیف هاچک کنید .
اختلاف بین ۱/۱/۱ تا ۱/۱۲/۲۹ عدد ۳۶۴ است که در اینجا عدد ثابتیست
عدد ۳۲۹ و ۳۱۵ کبیسه های از سال ۶۲۲ تا ۱۹۷۷ و ۱۹۲۰ هستند باید حتما با ۳۶۵ جمع شوند
این دست نویس ها ارزشمند هستند در صورت صفر شدن باید تغییر رویه داد