ورود

View Full Version : آموزش: ماژول برای فیلتر کردن کمبوباکس براساس حروف وارد شده



Abbas Amiri
جمعه 16 دی 1390, 20:23 عصر
استفاده از کدهای زیر کار را برای فیلتر کردن لیست نمایش داده شده در کمبو آسانتر می کند. فقط کافیست در روال رویداد Change مربوط به کمبو به روش زیر عمل کنید: SmartSourceCombo Combo ,ColumnIndex اگر تعداد ستونهای کمبو یکی باشد ویا فیلدی که در کمبو نمایش داده میشود ، اولین فیلدکوئری مربوط به کمبو باشد، احتیاجی به درج ColumnIndex نیست.



Private Sub MyCombo_Change()
SmartSourceCombo MyCombo, 1
End Sub



کدهای زیر را در یک ماژول کپی کنید.


Public Function SmartSourceCombo(cbo As ComboBox, Optional fldColumnIdx As Integer = 0) As String
Dim sFilter As String, strRowSource As String, k As Integer, j As Integer, str1 As String, str2 As String
Dim SQL_WHERE As String, SQL_HAVING As String
strRowSource = Trim(cbo.RowSource)
If strRowSource = "" Then Exit Function
If InStr(strRowSource, ";") = 0 Then strRowSource = strRowSource & ";"
sFilter = Nz(Left(cbo.Text, Len(cbo.Text) - cbo.SelLength), "")
If SplitSQL(strRowSource, "WHERE") <> "" Then
str1 = SplitSQL(strRowSource, "WHERE")
k = InStr(str1, CompleteFieldName(strRowSource, fldColumnIdx) & " LIKE '*")
If k Then
str1 = Left(str1, k - 1)
str2 = CompleteFieldName(strRowSource, fldColumnIdx)
k = InStr(SplitSQL(strRowSource, "SELECT"), str2)
k = InStrRev(SplitSQL(strRowSource, "SELECT"), " ", k)
str2 = str1 & CompleteFieldName(strRowSource, fldColumnIdx) & " LIKE '*" & sFilter & "*' "
Else
str2 = str1 & " AND " & CompleteFieldName(strRowSource, fldColumnIdx) & " LIKE '*" & sFilter & "*' "
End If
SQL_WHERE = str2
'ElseIf SplitSQL(strRowSource, "HAVING") <> "" And InStr(str1, fldName(strRowSource, fldColumnIdx)) > 0 Then
' str1 = SplitSQL(strRowSource, "HAVING")
' k = InStr(str1, CompleteFieldName(strRowSource, fldColumnIdx) & " LIKE '*")
' If k Then
' str1 = Left(str1, k - 1)
' str2 = str1 & CompleteFieldName(strRowSource, fldColumnIdx) & " LIKE '*" & sFilter & "*' "
' Else
' str2 = str1 & " AND " & CompleteFieldName(strRowSource, fldColumnIdx) & " LIKE '*" & sFilter & "*' "
' End If
' SQL_HAVING = str2
Else
str2 = " WHERE " & CompleteFieldName(strRowSource, fldColumnIdx) & " LIKE '*" & sFilter & "*' "
SQL_WHERE = str2
End If
strRowSource = SplitSQL(strRowSource, "SELECT") & SplitSQL(strRowSource, "FROM") & _
IIf(SQL_WHERE <> "", SQL_WHERE, SplitSQL(strRowSource, "WHERE")) & _
SplitSQL(strRowSource, "GROUP BY") & _
SplitSQL(strRowSource, "HAVING") & SplitSQL(strRowSource, "ORDER BY")
cbo.RowSource = strRowSource
cbo.Dropdown
SmartSourceCombo = strRowSource
End Function

Private Function fldName(ByVal sSource As String, idxfld As Integer) As String
On Error GoTo errFldName
Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset(sSource)
fldName = rs.Fields(idxfld).Name
rs.Close
Set rs = Nothing
Exit Function
errFldName:
fldName = "Error"
End Function

Private Function GetSection(strSearch As String, Delemiter As String, Optional Nth As Integer = 1) As String
Dim workTb() As String, k As Integer, j As Integer
workTb = Split(strSearch, Delemiter)
k = UBound(workTb)
If k < Nth - 1 Then Exit Function
GetSection = workTb(Nth - 1)
End Function

Private Sub SortStringsByLenght(ByRef str)
Dim k As Integer, j As Integer, tmp As String
For k = 0 To UBound(str) - 1
For j = k + 1 To UBound(str)
If Len(str(k)) > Len(str(j)) Then
tmp = str(k)
str(k) = str(j)
str(j) = tmp
End If
Next
Next
End Sub

Private Function SplitSQL(ByVal strSQL As String, ByVal SQLSection As String)
Dim Sections(5) As String, k As Integer, j As Integer, s As String
Dim SectionList As Variant, tmp
SectionList = Array("FROM", "WHERE", "GROUP BY", "HAVING", "ORDER BY", ";")
j = Len(strSQL)
For k = 0 To 5
Sections(k) = GetSection(strSQL, CStr(SectionList(k)))
If Len(Sections(k)) < j Then
Else
Sections(k) = ""
End If
Next
SortStringsByLenght Sections
tmp = Sections
For k = 0 To 5
If Sections(k) <> "" Then
If k Then Sections(k) = Right(Sections(k), Len(Sections(k)) - Len(tmp(k - 1)))
If StrComp(Left(Sections(k), Len(SQLSection)), SQLSection, vbTextCompare) = 0 Then
SplitSQL = Sections(k)
Exit Function
End If
End If
Next
End Function

Private Function CompleteFieldName(strSQL As String, Optional idx As Integer = 0) As String
Dim k As Integer
Dim str1 As String, str2 As String
str2 = fldName(strSQL, idx)
str1 = SplitSQL(strSQL, "SELECT")
k = InStr(str1, str2)
j = InStrRev(str1, " ", k) + 1
str1 = Mid(str1, j, k - j)
CompleteFieldName = str1 & str2
End Function

royasaz_bam
جمعه 16 دی 1390, 20:30 عصر
اگر ممکنه تابع را د قالب یک نمونه پیوست کن زیرا جهت کپی کردن مشکل دارم

Abbas Amiri
جمعه 16 دی 1390, 21:20 عصر
لازم به تذکر است برای اسامی Alias این تابع جواب نمی دهد وباید در ساختار آن تغییراتی ایجاد شود که خودم ویا هرکدام ازدوست در حوصله اشان بود انجام دهند. " مانند Sum(Amount) AS SomOfAmount "
نمونه فایل:

najafi87
چهارشنبه 20 اردیبهشت 1391, 23:22 عصر
عباسجون الحق که امیری...
خیر ببینی ایشالله...

hf.farhadi
شنبه 23 اردیبهشت 1391, 23:52 عصر
با سلام آقای امیری عزیز و سپاس فراوان بابت حضور فعال و مثبتتون

در نمونه ضمیمه شده من در یه کمبو باکس مجبورم که اطلاعات مربوط به هر بخش رو فیلتر کنم و همزمان میخوام از ماژول شما استفاده کنم

چون برای ثبت اطلاعات، کاربر باید شماره پرسنلی افراد رو وارد کنه .وقتی تعداد پرسنل زیاد میشه جهت پیدا کردن این شماره به مشکل میخوره

ماژول جنابعالی تا حد زیادی این مشکل رو حل میکنه اما مشکل اینجاست که همزمان باید یه فیلتر دیگه هم اعمال بشه . آیا راهی برای حل این مشکل وجود داره ؟
سپاس

najafi87
شنبه 30 اردیبهشت 1391, 00:08 صبح
عذر خواهی میکنم
آیا راهی هست که وقتی کمبو به صورت ریلی باز شد با کلید های جهت دار بهتر بتونیم بین گزینه ها حرکت کنیم و یا وقتی با موس روی اون کلیک میکنیم واکنش بهتری نشون بده. برنامه رو اگه تست کنید متوجه میشید.

Abbas Amiri
پنج شنبه 04 خرداد 1391, 12:37 عصر
لطفا به تاپیک زیر مراجعه کنید
http://barnamenevis.org/showthread.php?342716-%D8%AF%D8%B1%D8%AE%D9%88%D8%A7%D8%B3%D8%AA-%D8%AA%D8%B5%D8%AD%DB%8C%D8%AD-%DA%A9%D8%AF-%D8%A8%D8%B1%D8%A7%DB%8C-combo

hf.farhadi
پنج شنبه 04 خرداد 1391, 19:07 عصر
با سلام آقای امیری عزیز و ممنون بابت پاسختون

مشکل فایل با راهنمایی شما کمی حل شده اما برخی مشکلات همچنان به حرمت خود باقی هست

من میخوام وقتی در کمبو شماره پرسنلی , اسم یه شخص رو تایپ میکنم , اسامی فیلتر بشه و هنگام انتخاب گزینه از ریل باز شده , فیلد باند بشه به شماره پرسنلی

ممنون میشم یه نگاه به فایل ضمیمه بندازین و در صورت امکان اصلاح بفرمایین

Abbas Amiri
پنج شنبه 04 خرداد 1391, 23:33 عصر
تغییرات انجام شد.

hf.farhadi
جمعه 05 خرداد 1391, 00:08 صبح
آقای امیری باتشکر
همانطور که خدمتتون عرض کردم ,


من میخوام وقتی در کمبو شماره پرسنلی , اسم یه شخص رو تایپ میکنم , اسامی فیلتر بشه و هنگام انتخاب گزینه از ریل باز شده , فیلد باند بشه به شماره پرسنلی

وقتی گزینه رو انتخاب میکنی شماره پرسنلی شخص در کادر نیست یعنی میخوام شماره پرسنلی شخص پس از انتخاب گزینه در کمبو بشینه(العان اسم شخص میشینه)
چون این شماره بودنش در فرم خیلی ضروریه . لطفاً این مشکل رو هم راهنمایی بفرمایین

Abbas Amiri
جمعه 05 خرداد 1391, 00:25 صبح
اگر به خصوصیت BoundColumn کمبو توجه کنید مقدار یک دارد . یعنی درجدول شماره آن درج خواهدشد .چنانچه الزام به نمایش آن دارید ، یک تکست باکس اضافه ودر روال AfterUpdate کمبو مقدارتکست باکس را مساوی txtID=Combo0 قراردهید

Abbas Amiri
جمعه 05 خرداد 1391, 00:33 صبح
البته اضافه کردن کدهای زیرهم راه خوبی است


Private Sub Combo0_LostFocus()
Combo0.ColumnWidths = "2cm;4.064cm;2.542cm"
End Sub
Private Sub Combo0_GotFocus()
Combo0.ColumnWidths = "0cm;4.064cm;2.542cm"
End Sub

hf.farhadi
یک شنبه 21 خرداد 1391, 23:59 عصر
با سلام آقای امیری عزیز
من ماژول شما رو در یه برنامه تحت شبکه دارم استفاده میکنم و بابت زحمتی که کشیدین مجدداً سپاسگذارم.

فقط یه مشکلی که هست اینه که در بعضی مواقع (که دقیقاً نتونستم پیدا کنم که در چه رویدادی اتفاق میفته) وقتی گزینه رو انتخاب میکنی کلید Num Lock خاموش میشه و کار رو برای کاربر که مجبور به وارد کردن عدد هست سخت میکنه .
البته من این موضوع رو بر روی چندین سیستم تست کردم.
با تشکر

Abbas Amiri
دوشنبه 22 خرداد 1391, 01:02 صبح
شخصا به چنین موردی برخوردنکردم برای همین تنها راهی که میتوان پیشنهاد کنم چک کردن وضعیت NumLock ودر صورت خاموش بودن ، ست کردن آن است تابع Api و بعدی را دریک ماژول کپی کنید:


Private Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer

Function GetNumlock() As Boolean
GetNumlock = Not CBool(GetKeyState(vbKeyNumlock))
End Function


ودر رویداد Change کمبو وارد کنید:


If Not GetNumlock Then SendKeys "{NUMLOCK}"

mehr84
چهارشنبه 24 خرداد 1391, 10:16 صبح
دوست عزیز: با تشکر از زحمتی که کشیده اید من به هیچ عنوان نتوانستم روی فرم اکسس 2007 آن را اجرا کنم و کد در خط
j = InStrRev(str1, " ", k) + 1 خطا می دهد. اسامی که می خواهم فیلتر کنم فارسی است و دارای فاصله هم هست مثل "شرکت آریانا"

Abbas Amiri
چهارشنبه 24 خرداد 1391, 17:48 عصر
عبارت RowSource کمبو شما چیست؟

alireza6211
جمعه 31 شهریور 1391, 13:34 عصر
سلام
من میخوام روی یک تکست باکس این رو پیاده بکنم نه کمبو باکس ..یعنی مثل اکسل نوشته های قبلی رو نیاز نباشه دوباره تایپ کنی .. برای کاربر هم راحت می شه

Abbas Amiri
جمعه 31 شهریور 1391, 16:06 عصر
سلام تابع زیر را دریک ماژول کپی کنید


Public Function SmartText(ctlText As TextBox, tdf As String, fld As String, kp As Integer) As String
Dim strText As String, k As Integer
k = ctlText.SelStart
strText = Nz(ctlText.Text)
If strText = "" Then
ctlText = ""
Exit Function
Else
strText = Nz(DLookup(fld, tdf, fld & " LIKE '" & strText & "*'"))
End If
k = IIf(k > 0, k, 1)
If kp = 8 Then strText = Left(strText, k - 1)
If kp = 46 Then
If ctlText.SelStart Then
strText = Left(strText, k - 1)
Else
strText = Left(strText, k - 1) & Right(strText, Len(strText) - k + 1)
End If
End If
If strText <> "" Then ctlText = strText
ctlText.SelStart = k
k = Len(strText) - k
ctlText.SelLength = IIf(k > 0, k, 1)

End Function



بعد در رویدادهای Change و KeyDown تکست باکس خود کدهای زیر را وارد کنید


Dim kp As Integer

Private Sub Text0_Change()
SmartText Text0, "TableName", "FieldName", kp
End Sub

Private Sub Text0_KeyDown(KeyCode As Integer, Shift As Integer)
kp = KeyCode
End Sub



توجه داشته باشید در عبارت SmartText Text0, "TableName", "FieldName", kp

Text0 نام تکست باکس ، TableName نام جدول و FieldName نام فیلد مربوط به تکست باکس است

alireza6211
شنبه 01 مهر 1391, 12:18 عصر
از راهنمائی تون خیلی ممنون آقای امیری

ماژول رو کپی کردم و تکست باکس را در قسمت EVENT در on change و key down در قسمت code builder کدهای شما رو وارد کردم ولی خطا داد

آیا در انجامش اشتباهی کردم ؟

Abbas Amiri
دوشنبه 03 مهر 1391, 17:54 عصر
برای ایجاد رویداد جهت کنترلها ازمراحل استفاده کنید

93216

میتوانید بعد ازمراحل فوق که به محیط VBE وارد شدید کدهای بالا را در صفحه رویداد بازشده کپی کنید.

alireza6211
شنبه 08 مهر 1391, 08:55 صبح
سلام آقای امیری

برنامه ای که میخواستم آماده کنم این بود .. نمیدونم چرا با وارد کردن کد ها کار نکرد ..

در صورت امکان خواهش می کنم یه بررسی بفرمائید که در کل آیا بدرد می خوره یا نه.. بی نهایت متشکرم

Abbas Amiri
شنبه 08 مهر 1391, 19:24 عصر
با سلام
فایل اصلاح شد

G.hemati
سه شنبه 29 مرداد 1392, 19:51 عصر
با سلام خدمت اساتید گرامی مخصوصاً استاد امیری عزیز بابت آموزش خوبشون

من در نمونه پیوست تمامی کدهای مربوطه رو قرار دادم ولی نمیدونم چرا کمبو باکس عمل فیلتر رو انجام نمیده . ممنون میشم راهنمایی بفرمایین

vahidmasoudi1391
چهارشنبه 30 مرداد 1392, 07:02 صبح
سلام
لطفا" نمونه را ملاحظه فرمایید
با تشکر

G.hemati
چهارشنبه 30 مرداد 1392, 14:11 عصر
با سلام
دوست عزیز به نام تاپیک و آموزش استاد امیری توجه نمایید

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



در این ماژول با وارد کردن هر حرفی از هر قسمت متن فیلتر انجام میشود مثلاً با وارد کردن نام رضا ، اسامی مانند محمد رضا ، رضا ، محمد رضایی ، علیرضا ، احمد رضاپور و ... رو فیلتر میکنه

در صورتی که نمونه ای که زحمت کشیدین ، خاصیت ابتدایی یک کمبو باکس را هم دارا نمیباشد

hamid-nice
چهارشنبه 30 مرداد 1392, 17:36 عصر
لازم به تذکر است برای اسامی Alias این تابع جواب نمی دهد وباید در ساختار آن تغییراتی ایجاد شود که خودم ویا هرکدام ازدوست در حوصله اشان بود انجام دهند. " مانند Sum(Amount) AS SomOfAmount "
نمونه فایل:
با سلام
برای کمبو هایی که در اسمشان فاصله وجود دارد چگونه باید عمل کرد چون من از کروشه و underline هم که استفاده کردم کار نکرد
در ضمن اگه ممکنه لطفا در مورد توابع Alias که چی هستند لطفا توضیحی دهید
با تشکر

Abbas Amiri
چهارشنبه 30 مرداد 1392, 17:51 عصر
با سلام خدمت اساتید گرامی مخصوصاً استاد امیری عزیز بابت آموزش خوبشون

من در نمونه پیوست تمامی کدهای مربوطه رو قرار دادم ولی نمیدونم چرا کمبو باکس عمل فیلتر رو انجام نمیده . ممنون میشم راهنمایی بفرمایین

استفاده نکردن از کلمات رزرو شده بجای اسامی فیلدها مشکل شمار رو حل میکنه . البته درصورتی که در تابع مربوطه اسامی فیلدها با کروشه برگردانده شود ، این مشکل بوجود نخواهد آمد.

Abbas Amiri
چهارشنبه 30 مرداد 1392, 17:55 عصر
با سلام
برای کمبو هایی که در اسمشان فاصله وجود دارد چگونه باید عمل کرد چون من از کروشه و underline هم که استفاده کردم کار نکرد
در ضمن اگه ممکنه لطفا در مورد توابع Alias که چی هستند لطفا توضیحی دهید
با تشکر

برای استفاده از اسامی چند بخشی باید اصلاحاتی در تابع ایجاد شود ، تا نام فیلدها رو با کروشه بدست بیاورد

G.hemati
چهارشنبه 30 مرداد 1392, 19:09 عصر
با سلام

استفاده نکردن از کلمات رزرو شده بجای اسامی فیلدها مشکل شمار رو حل میکنهمن اسمهای رزرو شده مانند Date , Time رو در نام فیلدهام استفاده نمیکنم ولی نمیدونستم که Name هم جزء همین اسمهاست .

ممنون میشم کل این اسامی (اسمهای رزرو شده ) رو دوستان ارائه نمایند تا مبتدیانی چون من ، ضایع بازی در نیاریم

من نام فیلد و جدول را نیز تغییر دادم ولی همچنان درست کار نمیکنه . ممنون میشم راهنمایی بفرمایین

hamid-nice
چهارشنبه 30 مرداد 1392, 19:59 عصر
با سلام
ممنون از پاسختون مشکلم با کروشه حل شد و جواب داد
اما نمی دونم چرا کلا تابع فوق رو نتونستم بکار ببرم در زیر یک نمونه گذاشتم رو کامپیوتر من جواب نمیده و هنگام تایپ در کمبو error میده اگه ممکنه ایرادش را بررسی بفرمایید
با تشکر

hashemi.hanieh
پنج شنبه 31 مرداد 1392, 10:15 صبح
دوست عزیز: با تشکر از زحمتی که کشیده اید من به هیچ عنوان نتوانستم روی فرم اکسس 2007 آن را اجرا کنم و کد در خط
j = InStrRev(str1, " ", k) + 1 خطا می دهد. اسامی که می خواهم فیلتر کنم فارسی است و دارای فاصله هم هست مثل "شرکت آریانا"

مشکل من هم دقیقا همین هست... امکانش هست راهنمایی کنید؟

hamid-nice
جمعه 01 شهریور 1392, 13:33 عصر
http://barnamenevis.org/images/misc/quote_icon.png نوشته شده توسط mehr84 http://barnamenevis.org/images/buttons/viewpost-left.png (http://barnamenevis.org/showthread.php?p=1525295#post1525295)
دوست عزیز: با تشکر از زحمتی که کشیده اید من به هیچ عنوان نتوانستم روی فرم اکسس 2007 آن را اجرا کنم و کد در خط
j = InStrRev(str1, " ", k) + 1 خطا می دهد. اسامی که می خواهم فیلتر کنم فارسی است و دارای فاصله هم هست مثل "شرکت آریانا"
با سلام
در ضمیمه ای که در پست 3# گذاشتم و به طور کلی از ماژول بسیار ارزنده و کاربردی که جناب امیری عزیز زحمت کشیدند و قرار دادند ضمن تشکر از ایشان نکات زیر حتما باید رعایت شود و گرنه error های اینچنینی رخ میدهد :
1- حتما باید وقتی در قسمت RowSource Type فرم table/query انتخاب می شود در جدولی که در قسمت RowSource قرار میدهیم قسمت sort یکی از فیلدها را وارد کنیم (یعنی نباید برای همه فیلدها sort خالی بماند )
2-اگر در بند فوق تنها یک فیلد را در جدولی که در قسمت RowSource انتخاب کردهایم ،قرار دهیم حتما کدی که در رویداد on change می نویسیم باید بدون عدد باشد یعنی به صورت SmartSourceCombo Combo0 ( نام combo0 را به نام کمبو خودتان تغییر دهید )

فایل اصلاح شده پست 30# در ضمیمه قرار دادم تا بتوانید مقایسه لازم را انجام دهید
موفق باشید

G.hemati
جمعه 01 شهریور 1392, 17:54 عصر
با سلام

من نام فیلد و جدول را نیز تغییر دادم ولی همچنان درست کار نمیکنه . من همه مراحل شما رو انجام دادم ولی نتونستم جواب بگیرم

وقتی برای بار اول کمبو رو باز میکنیم مقادیر را دارا میباشد .

ولی به محض اینکه یک گزینه انتخاب میکنی و اون رو میخوای Delete کنی تصویر شماره 2 ظاهر میشه

ممنون میشم یه نگاه به نمونه پست 29 بندازین . و راهنمایی بفرمایین

G.hemati
یک شنبه 03 شهریور 1392, 10:13 صبح
دوستان لطفا راهنمایی بفرمایین

G.hemati
دوشنبه 04 شهریور 1392, 17:32 عصر
با سلام
بالاخره با کلی سر و کله زدن با نمونه پست 29 ، یه روشی پیدا کردم که مشکل فعلا بر طرف شده . فقط میخواستم بدونم علت این موضوع چیه

وقتی تنها یک فیلد را در جدولی که در قسمت RowSource انتخاب کرده ایم ،به کمبو باکس اضافه میکنیم و همزمان کدهایی که جناب امیری در پست 7 لینکشو گذاشتن ،استفاده میکنیم. اشکال تصویر پست بالا رو میگیره .

برای حل مشکل من نام جدول رو با نام فیلدی که در کمبو باکس استفاده میکنیم یکی کردم . یعنی نام جدول من TblTxtChap است و نام فیلدم را هم که TxtChap بود به TblTxtChap تغییر دادم .

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

سپاس