PDA

View Full Version : حرفه ای: خارج از دستور - پرسشهایی از جنس دیگر



mazoolagh
چهارشنبه 19 آذر 1399, 20:49 عصر
اینجا پرسشهایی رو مطرح کنید که هدف اصلی اون الزاما حل یک مساله کاربردی و (شاید) از جنس دیتابیس هم نباشه، بلکه تمرین ذهن و به چالش کشیدن توان کدنویسی و گریزی از امور تکراری و کسالت بار هست.
البته این دست مسائل ممکنه در زبانهای دیگه راحت تر کدنویسی بشه و vba انتخاب اول نباشه ولی چون در اینجا مطرح شده مخصوصا محدود به همین اکسس (و آفیس بطور عام) هستیم.
بنابراین پاسخ به زبان دیگر وقتی قبول هست که ابتدا پاسخ در اکسس (آفیس) داده شده باشه.

چراغ اول رو هم خودم روشن میکنم، به امید اینکه از شرکت کنندگان مطلب جدیدی یاد بگیریم.

حساب ابجد - ماده تاریخ (https://barnamenevis.org/showthread.php?563684-%D8%AE%D8%A7%D8%B1%D8%AC-%D8%A7%D8%B2-%D8%AF%D8%B3%D8%AA%D9%88%D8%B1-%D9%BE%D8%B1%D8%B3%D8%B4%D9%87%D8%A7%DB%8C%DB%8C-%D8%A7%D8%B2-%D8%AC%D9%86%D8%B3-%D8%AF%DB%8C%DA%AF%D8%B1&p=2437839&viewfull=1#post2437839)

رسم نمودار ، گراف (https://barnamenevis.org/showthread.php?563684-%D8%AE%D8%A7%D8%B1%D8%AC-%D8%A7%D8%B2-%D8%AF%D8%B3%D8%AA%D9%88%D8%B1-%D9%BE%D8%B1%D8%B3%D8%B4%D9%87%D8%A7%DB%8C%DB%8C-%D8%A7%D8%B2-%D8%AC%D9%86%D8%B3-%D8%AF%DB%8C%DA%AF%D8%B1&p=2438376&viewfull=1#post2438376)

حرکت دایره در بیسیک (https://barnamenevis.org/showthread.php?563684-%D8%AE%D8%A7%D8%B1%D8%AC-%D8%A7%D8%B2-%D8%AF%D8%B3%D8%AA%D9%88%D8%B1-%D9%BE%D8%B1%D8%B3%D8%B4%D9%87%D8%A7%DB%8C%DB%8C-%D8%A7%D8%B2-%D8%AC%D9%86%D8%B3-%D8%AF%DB%8C%DA%AF%D8%B1&p=2438388&viewfull=1#post2438388)

نمودار پویا در اکسس (https://barnamenevis.org/showthread.php?563684-%D8%AE%D8%A7%D8%B1%D8%AC-%D8%A7%D8%B2-%D8%AF%D8%B3%D8%AA%D9%88%D8%B1-%D9%BE%D8%B1%D8%B3%D8%B4%D9%87%D8%A7%DB%8C%DB%8C-%D8%A7%D8%B2-%D8%AC%D9%86%D8%B3-%D8%AF%DB%8C%DA%AF%D8%B1&p=2438485&viewfull=1#post2438485)

Unbound Master-Detail Form (https://barnamenevis.org/showthread.php?563684-%D8%AE%D8%A7%D8%B1%D8%AC-%D8%A7%D8%B2-%D8%AF%D8%B3%D8%AA%D9%88%D8%B1-%D9%BE%D8%B1%D8%B3%D8%B4%D9%87%D8%A7%DB%8C%DB%8C-%D8%A7%D8%B2-%D8%AC%D9%86%D8%B3-%D8%AF%DB%8C%DA%AF%D8%B1&p=2439265&viewfull=1#post2439265)

RECORDSET/QUERY PAGING (https://barnamenevis.org/showthread.php?563684-%D8%AE%D8%A7%D8%B1%D8%AC-%D8%A7%D8%B2-%D8%AF%D8%B3%D8%AA%D9%88%D8%B1-%D9%BE%D8%B1%D8%B3%D8%B4%D9%87%D8%A7%DB%8C%DB%8C-%D8%A7%D8%B2-%D8%AC%D9%86%D8%B3-%D8%AF%DB%8C%DA%AF%D8%B1&p=2439699&viewfull=1#post2439699)

ADO Recordset Paging (https://barnamenevis.org/showthread.php?563684-%D8%AE%D8%A7%D8%B1%D8%AC-%D8%A7%D8%B2-%D8%AF%D8%B3%D8%AA%D9%88%D8%B1-%D9%BE%D8%B1%D8%B3%D8%B4%D9%87%D8%A7%DB%8C%DB%8C-%D8%A7%D8%B2-%D8%AC%D9%86%D8%B3-%D8%AF%DB%8C%DA%AF%D8%B1&p=2440198&viewfull=1#post2440198)

ایجاد نویگیشن باتن جهت تغییر صفحات گزارش (https://barnamenevis.org/showthread.php?571603)

کوئری برای ساخت رشته اعداد در یک محدوده مشخص Query to create a range of numbers (https://barnamenevis.org/showthread.php?563684-%D8%AE%D8%A7%D8%B1%D8%AC-%D8%A7%D8%B2-%D8%AF%D8%B3%D8%AA%D9%88%D8%B1-%D9%BE%D8%B1%D8%B3%D8%B4%D9%87%D8%A7%DB%8C%DB%8C-%D8%A7%D8%B2-%D8%AC%D9%86%D8%B3-%D8%AF%DB%8C%DA%AF%D8%B1&p=2462372&viewfull=1#post2462372)

پیدا کردن مسیر یک گره در یک ساختار پدر-فرزندی Path of a node in a hierarchical table (https://barnamenevis.org/showthread.php?563684-%D8%AE%D8%A7%D8%B1%D8%AC-%D8%A7%D8%B2-%D8%AF%D8%B3%D8%AA%D9%88%D8%B1-%D9%BE%D8%B1%D8%B3%D8%B4%D9%87%D8%A7%DB%8C%DB%8C-%D8%A7%D8%B2-%D8%AC%D9%86%D8%B3-%D8%AF%DB%8C%DA%AF%D8%B1&p=2462550&viewfull=1#post2462550)

صفحه بندی دیتا با افکت و انیمیشن در مرورگر وب Data-paging with transitions/animations in Web Browser (https://barnamenevis.org/showthread.php?563684&p=2463193&viewfull=1#post2463193)

محاسبات هندسی بدون دانستن یا داشتن فرمول Geometric Calculation (https://barnamenevis.org/showthread.php?563684-%D8%AE%D8%A7%D8%B1%D8%AC-%D8%A7%D8%B2-%D8%AF%D8%B3%D8%AA%D9%88%D8%B1-%D9%BE%D8%B1%D8%B3%D8%B4%D9%87%D8%A7%DB%8C%DB%8C-%D8%A7%D8%B2-%D8%AC%D9%86%D8%B3-%D8%AF%DB%8C%DA%AF%D8%B1&p=2469429&viewfull=1#post2469429)

mazoolagh
چهارشنبه 19 آذر 1399, 21:06 عصر
هدف نوشتن برنامه ای هست که با گرفتن یک عدد طبیعی به نام Number و یک عدد طبیعی بین 2 تا 15 به نام N ؛
تمام حالت های ممکن غیر تکراری ترکیب N عدد و همچنین معادل حرفی آن را، بشرطی که جمع اونها طبق حساب ابجد برابر Number باشه، رو بدست بیاره و در دو لیست باکس جدا نمایش بده.

جدول ارزش حرف در حساب ابجد رو میتونین از آدرس زیر پیدا کنین:
https://fa.wikipedia.org/wiki/%D8%A7%D8%A8%D8%AC%D8%AF#‎‎%D8%A7%D8%B1%D8%B2% D8%B4_%D8%AD%D8%B1%D9%88%D9%81

بعنوان مثال اگر Number=241 و N=3 باشه، جواب بصورت زیر خواهد بود:
1,40,200
ا م ر

و اگر Number=6 و N=2 باشه:
1,5
2,4
3,3

ا ه
ب د
ج ج

atf1379
پنج شنبه 20 آذر 1399, 11:24 صبح
هدف نوشتن برنامه ای هست که با گرفتن یک عدد طبیعی به نام Number و یک عدد طبیعی بین 2 تا 15 به نام N ؛
تمام حالت های ممکن غیر تکراری ترکیب N عدد و همچنین معادل حرفی آن را، بشرطی که جمع اونها طبق حساب ابجد برابر Number باشه، رو بدست بیاره و در دو لیست باکس جدا نمایش بده.

جدول ارزش حرف در حساب ابجد رو میتونین از آدرس زیر پیدا کنین:
https://fa.wikipedia.org/wiki/%D8%A7%D8%A8%D8%AC%D8%AF#‎‎‎‎‎‎‎‎% D8%A7%D8%B1%D8%B2%D8%B4_%D8%AD%D8%B1%D9%88%D9%81

بعنوان مثال اگر Number=241 و N=3 باشه، جواب بصورت زیر خواهد بود:
1,40,200
ا م ر

و اگر Number=6 و N=2 باشه:
1,5
2,4
3,3

ا ه
ب د
ج ج


ضمن سلام و عرض تشکر از جناب mazoolagh (https://barnamenevis.org/member.php?9893-mazoolagh) بخاطر ایجاد این تاپیک ارزشمند
در مورد این مسئله بنده یک ابهام دارم و اون اینکه آیا دو مثال پائین فرضی و مستقل از مسئله مطرح شده در نظر گرفته شده اند و ارتباطی با اصل سوال ندارد؟ یا اگر دارند چرا در مثال یک 3 عدد 1، 40 و 200 بدست آمده که جزء اعداد طبیعی بین 2 و 15 نمی باشند ؟ در سوال اشاره شده که N عددی طبیعی بین 2 و 15 میباشد ولی می بینیم در مثال یک 3 عدد مذکور جزء این مجموعه( بین 2 و 15) نمی باشند.
در مثال 2 هم عدد یک جزء مجموعه نمی باشد و ترکیب 3و3 هم بعلت تکراری بودن آنها قابل قبول نمی باشد.
بنظرم اگر لطف کنی قدری بیشتر در مورد سوال توضیح بدهین دوستان راحتتر به جواب میرسند
با تشکر

padide55
پنج شنبه 20 آذر 1399, 13:08 عصر
ضمن سلام و عرض تشکر از جناب mazoolagh (https://barnamenevis.org/member.php?9893-mazoolagh) بخاطر ایجاد این تاپیک ارزشمند
در مورد این مسئله بنده یک ابهام دارم و اون اینکه آیا دو مثال پائین فرضی و مستقل از مسئله مطرح شده در نظر گرفته شده اند و ارتباطی با اصل سوال ندارد؟ یا اگر دارند چرا در مثال یک 3 عدد 1، 40 و 200 بدست آمده که جزء اعداد طبیعی بین 2 و 15 نمی باشند ؟ در سوال اشاره شده که N عددی طبیعی بین 2 و 15 میباشد ولی می بینیم در مثال یک 3 عدد مذکور جزء این مجموعه( بین 2 و 15) نمی باشند.
در مثال 2 هم عدد یک جزء مجموعه نمی باشد و ترکیب 3و3 هم بعلت تکراری بودن آنها قابل قبول نمی باشد.
بنظرم اگر لطف کنی قدری بیشتر در مورد سوال توضیح بدهین دوستان راحتتر به جواب میرسند
با تشکر

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

در ریاضی و احتمالات داریم :
ابتدا مثال ساده تر
30دانش آموز را به چند روش میتوان سه تا سه تا چیدمان نمود و ....

در اینجا اعداد ابجد را به چند طریق میتوان بصورت سه تا سه تا مرتب نمود .
پس از مرتب کردن .
چند روش چیدمان سه تایی ایجاد شده جمعشان 241 میشود ؟

هدف بدست اوردن n=3 یعنی سه رقم هست که بدون تکرار جمعشان بشود number 241 و ضمنا در جدول ابجد موجود باشند .
1,40,200
اعداد ابجد متناظر با حروف هستند که جمعشان 241 میشود و تکرار هم نشده اند

«اَبْجَدْ - هَوََّزْ - حُطّی - کَلَمَنْ - سَعْفَصْ - قَرَشَتْ - ثَخَِّذْ - ضَظِغْ»
به ترتیب شماره میگیرند
1و2و3و4و5و6و7و8و9و10و20و30و40و50و60 70و80و90و100و200و300و400و500و600و700و80 0و900و1000

و عددهای پ ژ گ و چ هم برای فارسی به اینها با کدش اضافه میشه

حالا علی میشه
ع=70 +ل=30 +ی=10 70+30+10=110
طبق جدول
یا علی 70+30+10+10+1 =121

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

با بررسی زیاد اعداد متناظر با جدول ابجد را ایجاد نمودم . و چیدمان اعداد ابجد را ایجاد کردم .

مشکل در جمع سطر کوئری دارم که کل سطر رو جمع کنه که بشه مثلا 241 رو پیدا کرد .
دستی میتونم فرمول بدم
ولی اگر کد sql ایجاد کنم که جمع هر سطر رو بده . اون موقع سطر مورد نظر مطابق با عدد جمع 241 رو فیلتر میکنم و تمام.
نهایتا میرسیم به اعداد که تبدیل میکنیم به حرف متناظر در ابجد .
کار شدنی هست . فعلا نمونه تا این مرحله.................
خسته شدم :متفکر: :عصبانی++: :تشویق:

mazoolagh
جمعه 21 آذر 1399, 11:49 صبح
ضمن سلام و عرض تشکر از جناب mazoolagh (https://barnamenevis.org/member.php?9893-mazoolagh) بخاطر ایجاد این تاپیک ارزشمند
در مورد این مسئله بنده یک ابهام دارم و اون اینکه آیا دو مثال پائین فرضی و مستقل از مسئله مطرح شده در نظر گرفته شده اند و ارتباطی با اصل سوال ندارد؟ یا اگر دارند چرا در مثال یک 3 عدد 1، 40 و 200 بدست آمده که جزء اعداد طبیعی بین 2 و 15 نمی باشند ؟ در سوال اشاره شده که N عددی طبیعی بین 2 و 15 میباشد ولی می بینیم در مثال یک 3 عدد مذکور جزء این مجموعه( بین 2 و 15) نمی باشند.
در مثال 2 هم عدد یک جزء مجموعه نمی باشد و ترکیب 3و3 هم بعلت تکراری بودن آنها قابل قبول نمی باشد.
بنظرم اگر لطف کنی قدری بیشتر در مورد سوال توضیح بدهین دوستان راحتتر به جواب میرسند
با تشکر

سلام و روز خوش
جناب padide55 راهنمایی خیلی خوبی کردن که این در واقع یک مساله ترکیب آمار هست، با این وجود بیشتر توضیح میدم:

1- عدد N در واقع تعداد انتخابهای ما از مجموعه حروف ابجد هست (یک مجموعه از 28 حرف) ،
که در اینجا شرط گذاشتیم :

2<= N <=15
یعنی بین 2 تا 15 حرف انتخاب میکنیم و حروف انتخابی میتونه تکراری هم باشه

2- بعبارت دیگه مساله همون انتخاب N حرف از 28 حرف هست (ترکیب آماری) با این شرط که جمع حروف انتخابی برابر Number باشه.

3- منظور از اینکه پاسخ غیرتکراری یعنی ترتیب حروف اهمیت نداره، بنابراین وقتی Number=6 , N=2 هست {1,5} پاسخ هست ولی {5,1} نیست و {3,3} هم تکراری محسوب نمیشه.
اگر ترتیب حروف اهمیت داشت مساله تبدیل به ترتیب آماری (Arrangement) میشد.

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

mazoolagh
جمعه 21 آذر 1399, 11:52 صبح
در اینترنت سرچ کنید combination
فعلا نمونه تا این مرحله.................
خسته شدم :متفکر: :عصبانی++: :تشویق:

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

زمان بدین برنامه رو یک نگاه بندازم.

padide55
جمعه 21 آذر 1399, 12:21 عصر
سلام
با توجه به اینکه برنامه نویسی بلدنیستم ولی در کل سعی کردم با جستجو و بررسی به این نتیجه برسم .
اصل فرمول رو بر اساس نیاز از منابع مختلف جمع کردم

mazoolagh
جمعه 21 آذر 1399, 13:36 عصر
سلام
با توجه به اینکه برنامه نویسی بلدنیستم ولی در کل سعی کردم با جستجو و بررسی به این نتیجه برسم .
اصل فرمول رو بر اساس نیاز از منابع مختلف جمع کردم

سلام دوباره
کاش کدها رو همینجا هم پیوست میکردین و توضیح مختصری هم در مورد روش انتخابی میدادین، چون راستش متوجه نشدم برنامه دقیقا چکار میکنه.

این عبارت "برنامه نویسی بلد نیستم" رو هم میگذارم بحساب شکسته نفسی شما.

eb_1345
شنبه 22 آذر 1399, 02:06 صبح
هدف نوشتن برنامه ای هست که با گرفتن یک عدد طبیعی به نام Number و یک عدد طبیعی بین 2 تا 15 به نام N ؛
تمام حالت های ممکن غیر تکراری ترکیب N عدد و همچنین معادل حرفی آن را، بشرطی که جمع اونها طبق حساب ابجد برابر Number باشه، رو بدست بیاره و در دو لیست باکس جدا نمایش بده.

جدول ارزش حرف در حساب ابجد رو میتونین از آدرس زیر پیدا کنین:
https://fa.wikipedia.org/wiki/%D8%A7%D8%A8%D8%AC%D8%AF#‎‎‎‎‎%D8%A7%D8% B1%D8%B2%D8%B4_%D8%AD%D8%B1%D9%88%D9%81

بعنوان مثال اگر Number=241 و N=3 باشه، جواب بصورت زیر خواهد بود:
1,40,200
ا م ر

و اگر Number=6 و N=2 باشه:
1,5
2,4
3,3

ا ه
ب د
ج ج

سلام
بنظرم از طریق ایجاد دو آرایه که عناصر تشکیل دهنده آنها بترتیب اعداد و حروف ابجد و ایجاد یک حلقه for...next (البته در مواردی شاید حلقه های for...next تو در تو )بتوان به جواب رسید.
الآن ساعت یک و سی دقیقه نصف شبه ، زیاد نمیخواهم ذهنم رو درگیر فکر کردن به این موضوع بکنم ، چون تا صبح همش باید خواب آرایه و حلقه های تو در تو ببینم:لبخند:خل

padide55
شنبه 22 آذر 1399, 07:25 صبح
سلام
نمونه اعداد
مثلا ۱_۲_۳_۴_۵_۶
حالا
اگر سه تا سه تا چیدمان کنیم
۱_۲_۳
۱_۲_۴
۱_۲_۵
۱_۲_۶
۲_۳_۴
۲_۳_۵
۲_۳_۶
۳_۴_۴
۳_۴_۶
۴_۵_۶

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

فرمول
اگر سه تایی باشه n=3
d='mynumbe
c='count number


for i to eof of table
i=go first
i=1
arangei=di+(n-(i+1));di+(n-(i+2);di+(n+i+c3)
go next
i=i+1
to eof
loop


ببخشید .
این تقریبا کد مورد لزوم
اول باید بره به اولین رکورد
بعد ببینه چند تایی باید باشه
iهر رکورد و رکورد دوم و رکورد سوم با هم .
بعد رکورد اول و سوم و‌چهارم با هم
بعد رکورد سوم و‌پنجم با هم .

نگاه به اعداد نکنید .
فقط ترتیب رکوردها مشخص شد .عددش رو لیست کنه .
جمع هر سه تا دربیاد .اگر با جمع کل مورد نظر مساوی باشه addبه لیست .
بروید دنبال کد فرمول ان فاکتوریل n!

padide55
شنبه 22 آذر 1399, 11:42 صبح
این هم اعداد ابجد مورد نظر
بعد میرسیم به حروف ابجد متناظر

atf1379
شنبه 22 آذر 1399, 12:16 عصر
این هم اعداد ابجد مورد نظر
بعد میرسیم به حروف ابجد متناظر

عالیه :تشویق:
جستجوتون در اینترنت حرف نداره
این کدها رو از کدوم سایت دانلود کرده این ؟

mazoolagh
شنبه 22 آذر 1399, 13:26 عصر
سلام
بنظرم از طریق ایجاد دو آرایه که عناصر تشکیل دهنده آنها بترتیب اعداد و حروف ابجد و ایجاد یک حلقه for...next (البته در مواردی شاید حلقه های for...next تو در تو )بتوان به جواب رسید.
الآن ساعت یک و سی دقیقه نصف شبه ، زیاد نمیخواهم ذهنم رو درگیر فکر کردن به این موضوع بکنم ، چون تا صبح همش باید خواب آرایه و حلقه های تو در تو ببینم:لبخند:خل

سلام و روز خوش
بله، استفاده از آرایه و حلقه های تودرتو راه حل خیلی خوبی هست. ولی چون تعداد حلقه ها متغییر هست نیاز به ابداع یک روش ابتکاری برای پیاده سازی اون هست.

mazoolagh
شنبه 22 آذر 1399, 13:36 عصر
این هم اعداد ابجد مورد نظر
بعد میرسیم به حروف ابجد متناظر

در تست اولیه بنظر میاد جواب گرفتین و روش ابتکاری و قشنگی هم بکار بردین که جای تبریک داره.
فقط فرم یک مقدار نیاز به چکش کاری داره و همچنین کدها لازمه دستی به سر و روشون کشیده بشه - وگرنه هسته منطق برنامه بنظرم عالی هست بخصوص که در روش متعارف nested loop (که جناب eb-1345 هم اشاره کردن) مشکل پرفورمنس وقتی تعداد حلقه ها از 6و7 بالاتر میره محسوس هست و روش شما بمراتب سریعتر هست.

padide55
شنبه 22 آذر 1399, 13:49 عصر
عالیه :تشویق:
جستجوتون در اینترنت حرف نداره
این کدها رو از کدوم سایت دانلود کرده این ؟

سلام
سایتش رونمیدونم
ولی یک مشکل در کد دارم
3و3 رو نشون نمیده و تکراری در نظر میگیره .

دوم
میره تعداد ستون مورد نظر رو k در نظر میگیره
بعد همه رو با هم ذخیره مینه و یکجا به جدول انتقال میده
یعنی
برای هر ردیف یک integer با کد در نظرمیگیره

کل فرمول دو خطه

دوستان برنامه نویس شرح بیشتری بدن .

من فقط کد رو بدست اوردم و از روشش خوشم اومد




strSelect = "SELECT QN.N "
strFrom = "FROM QN "
strWhere = "WHERE QN_1.N > QN.N "

'--------------------------------runcode -search and --list of ehtemal -----------------
For intI = 1 To K - 1
strSelect = strSelect & ", QN_" & intI & ".N AS N" & intI & " "
strFrom = strFrom & ", QN AS QN_" & intI & " "
If intI < K - 1 Then
strWhere = strWhere & " AND QN_" & intI + 1 & ".N > QN_" & intI & ".N "

End If
Next



بقیه کدها برای ایجاد یک کوئری هست که از جدول ایجادشده جمع رو بدست بیاره و جمع مورد نظر رو فیلتر کنه.

eb_1345
شنبه 22 آذر 1399, 13:56 عصر
سلام و روز خوش
بله، استفاده از آرایه و حلقه های تودرتو راه حل خیلی خوبی هست. ولی چون تعداد حلقه ها متغییر هست نیاز به ابداع یک روش ابتکاری برای پیاده سازی اون هست.
سلام
فایل ضمیمه رو هم بررسی بفرمائید
البته در فایل نمونه استفاده از حلقه فقط برای ترکیب های دو تائی صورت گرفته و بدیهیست برای ترکیبهای بیشتر باید از از حلقه های تو در تو بیشتر استفاده شود
بنظرم برای نتیجه گیری بهتر میتوان روشی که بنده در نمونه فوق ارائه نموده ام با روشی که در فایل نمونه جناب padide55 (https://barnamenevis.org/member.php?263869-padide55) استفاده شده تلفیق نمود

eb_1345
شنبه 22 آذر 1399, 14:15 عصر
سلام
فایل ضمیمه رو هم بررسی بفرمائید
البته در فایل نمونه استفاده از حلقه فقط برای ترکیب های دو تائی صورت گرفته و بدیهیست برای ترکیبهای بیشتر باید از از حلقه های تو در تو بیشتر استفاده شود
بنظرم برای نتیجه گیری بهتر میتوان روشی که بنده در نمونه فوق ارائه نموده ام با روشی که در فایل نمونه جناب padide55 (https://barnamenevis.org/member.php?263869-padide55) استفاده شده تلفیق نمود
فایل نمونه آخرین بار در ساعت 13:29 ویرایش شده (https://barnamenevis.org/posthistory.php?p=2437903)
بمنظور متناظر شدن ترکیب حروف و اعداد جای x3 و x4 در کوئری تغییر دادم

mazoolagh
شنبه 22 آذر 1399, 20:06 عصر
سلام
فایل ضمیمه رو هم بررسی بفرمائید
البته در فایل نمونه استفاده از حلقه فقط برای ترکیب های دو تائی صورت گرفته و بدیهیست برای ترکیبهای بیشتر باید از از حلقه های تو در تو بیشتر استفاده شود
بنظرم برای نتیجه گیری بهتر میتوان روشی که بنده در نمونه فوق ارائه نموده ام با روشی که در فایل نمونه جناب padide55 (https://barnamenevis.org/member.php?263869-padide55) استفاده شده تلفیق نمود

time .....

eb_1345
شنبه 22 آذر 1399, 20:19 عصر
سلام
بنظر میرسد در تابع buildquery نمونه پست 11 چنانچه در خط strWhere بجای < از =< استفاده شود نتیجه دقیقتر بدست میآید




strWhere = "WHERE QN_1.N >= QN.N "
For intI = 1 To k - 1
strSelect = strSelect & ", QN_" & intI & ".N AS N" & intI & " "
strFrom = strFrom & ", QN AS QN_" & intI & " "
If intI < k - 1 Then
strWhere = strWhere & " AND QN_" & intI + 1 & ".N >= QN_" & intI & ".N "
End If

Next

eb_1345
یک شنبه 23 آذر 1399, 16:43 عصر
سلام
لطفاً نمونه جدیدتر رو از ضمیمه بررسی بفرمائید !

eb_1345
دوشنبه 24 آذر 1399, 05:56 صبح
سلام
لطفاً نمونه جدیدتر رو از ضمیمه بررسی بفرمائید !
بنظر میرسد در نمونه آخر که نام حروف ابجد در ستون های کوئری از طریق DLookup استخراج گردیده بتوان از طریق ایجاد حلقه FOR ...NEXT نیز بدست آورد( بجهت حرفه ای عمل کردن درخلاصه و کوتاه تر کردن کدها)

padide55
دوشنبه 24 آذر 1399, 08:15 صبح
بنظر میرسد در نمونه آخر که نام حروف ابجد در ستون های کوئری از طریق DLookup استخراج گردیده بتوان از طریق ایجاد حلقه FOR ...NEXT نیز بدست آورد( بجهت حرفه ای عمل کردن درخلاصه و کوتاه تر کردن کدها)

:تشویق: :تشویق: :تشویق: :تشویق: :تشویق:
سلام
این سوال کلا ذهنو درگیر کرده . خواب از سر برده .

اون فیلدها رو داخل فرم ایجاد کرده بودم که نتیجه کدهای ایجادشده رو ببینم.
بعد هم برشون نداشتم که نوع سرهم نمودن متن کوئری نمایش داده بشه تا خطای کار رو ببینم . اگر integerبه تنهایی به کار میبردم نمیدیدم چجوری میشه . اول از تکست باکس استفاده کردم . برای اون کسی که داره دانلود میکنه خوبه که سریع متوجه بشه قضیه چیه .


فرم زیبایی شده .
سرعت عملکرد هم عالیه .
موفق باشید.

mazoolagh
سه شنبه 25 آذر 1399, 14:20 عصر
بنظر میرسد در نمونه آخر که نام حروف ابجد در ستون های کوئری از طریق DLookup استخراج گردیده بتوان از طریق ایجاد حلقه FOR ...NEXT نیز بدست آورد( بجهت حرفه ای عمل کردن درخلاصه و کوتاه تر کردن کدها)

بسیار عالی!
واقعا دست مریزاد - باید وقت بگذارم و با بررسی این برنامه چیز جدید یاد بگیرم.
من هنوز نمونه کد خودم رو آماده نکردم (با vba منظورم هست) ؛ ولی دوستان اگر پرسش جالب جدیدی به ذهنشون میرسه لطفا مطرح کنن.

eb_1345
سه شنبه 25 آذر 1399, 14:56 عصر
بنظر میرسد در نمونه آخر که نام حروف ابجد در ستون های کوئری از طریق DLookup استخراج گردیده بتوان از طریق ایجاد حلقه FOR ...NEXT نیز بدست آورد( بجهت حرفه ای عمل کردن درخلاصه و کوتاه تر کردن کدها)

سلام
نمونه جدید که استخراج نام حروف متناظر اعداد ابجد از طریق حلقه for...next انجام و کد نویسی کوتاه تر گردید.

mazoolagh
جمعه 28 آذر 1399, 09:42 صبح
سلام
نمونه جدید که استخراج نام حروف متناظر اعداد ابجد از طریق حلقه for...next انجام و کد نویسی کوتاه تر گردید.

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

mazoolagh
جمعه 28 آذر 1399, 10:31 صبح
در هر دو برنامه نمونه که آقایان eb_1345 و Padide55 زحمتش رو کشیدن، از جدول و عملیات مربوط به اون استفاده شده.

یک نمونه هم من میگذارم که تمام کارها در حافظه انجام میشه (البته نهایتا نتایج رو در صورت نیاز میشه در جدول یا فایل هم ذخیره کرد).
یک خوبی این روش این هست که در ساده ترین محیط ها هم قابل پیاده سازی هست، کما اینکه سالها پیش این برنامه رو به FORTRAN نوشته بودم و همچنین با javascript مرورگر هم میشه نوشت.

چند نکته هست که توضیح میدم:
1- برای ساخت حلقه های تودرتو (Nested Loops) با تعداد حلقه متغییر، از یک آرایه برای نگهداری شمارنده حلقه ها استفاده کردیم.
پس از هر دور از عملیات، اگر شمارنده حلقه به مرز بالایی رسیده باشه اون رو 0 و شمارنده حلقه بیرونیش رو 1 اضافه میکنیم (همون کاری که Next انجام میده)
متغیر switch که میبینین برای همین منظور هست.
این یکی از روشهای ساخت Dynamic Nested Loops هست (بنظرم ساده ترینش)، برای دوستانی که مایل به یادگیری بیشتر و دونستن روشهای پیشرفته تر و ویژه زبانهای خاص هستن پیشنهاد میکنم همین عبارت رو گوگل کنن.

2- پس از پیدا کردن هر پاسخ، ابتدا آرایه پاسخV رو sort میکنیم و بعد اون رو با join به یک string تبدیل و در یک dictionary (اینجا متغییر D) میریزیم.
برای حذف پاسخ های تکراری کافی هست قبلش دیکشنری رو با متد exists چک کنیم.

mazoolagh
جمعه 28 آذر 1399, 10:44 صبح
3- در این مساله، درسته که عملیات هر حلقه سبک هست ولی تعداد حلقه ها خیلی راحت میتونه به چند 10 میلیون برسه.
برای همین چند تمهید دیده شده:

کنترل مرز بالایی هر حلقه با MaxIndex : فرضا اگر Number=21 , N=4 باشه هیچ مقدار بزرگتر 10 نمیتونه پاسخ باشه بنابراین مرز بالایی متغیر حلقه ها برابر 9 هست (موقعیت 10 در آرایه Values) و نه 27 (موقعیت 1000)
اگر جمع مقادیر بیشتر از Number باشه یعنی هیچ پاسخ دیگه ای در آرایش کنونی حلقه ها نمیتونه جواب باشه، پس درونی ترین حلقه رو پایان میدیم
برای اینکه برنامه به حالت freeze نره، از یک button برای متوقف کردن پروسه استفاده کردیم - همان روش استاندارد doevents

mazoolagh
جمعه 28 آذر 1399, 10:46 صبح
Option Compare DatabaseOption Explicit
Dim Values()
Dim V()
Dim Chars()
Dim C()
Dim A()
Dim Number As Integer
Dim N As Integer
Dim S As String
Dim i As Integer
Dim D As Dictionary
Dim Canceled As Boolean
Dim counter As Long

mazoolagh
جمعه 28 آذر 1399, 10:47 صبح
Private Sub Start_btn_Click()Me.Answers.SetFocus
Me.Start_btn.Enabled = False
Canceled = False
Me.Stop_btn.Visible = True


Dim Sum, MaxIndex As Integer
N = Me.N_cb
Number = Me.Number_tb
Me.Answers.RowSource = ""
For i = 0 To UBound(Values)
If Values(i) <= Number - N + 1 Then
MaxIndex = i
Else
Exit For
End If
Next i


ReDim A(N - 1)
ReDim V(N - 1)
ReDim C(N - 1)


For i = 0 To N - 1
A(i) = 0
Next i
Set D = New Dictionary
Dim switch As Boolean


counter = 0
Do While Not Canceled
For i = 0 To N - 1
V(i) = Values(A(i))
C(i) = Chars(A(i))
Next i
Sum = Array_Sum(V)
If Sum = Number Then
Sort V, 0, N - 1
AddAnswer
ElseIf Sum > Number Then
A(N - 1) = MaxIndex
End If
If Array_Sum(A) = N * MaxIndex Then Exit Do
switch = True
i = N - 1
Do While switch And i >= 0
A(i) = A(i) + 1
If A(i) > MaxIndex Then
A(i) = 0
switch = True
Else
switch = False
End If
i = i - 1
Loop
counter = counter + 1
If counter Mod 10000 = 0 Then DoEvents
Loop
Me.Answers.SetFocus
Me.Stop_btn.Visible = False
Me.Start_btn.Enabled = True
End Sub

mazoolagh
جمعه 28 آذر 1399, 10:48 صبح
Function Array_Sum(Q) As IntegerArray_Sum = 0
Dim i As Integer
For i = 0 To UBound(Q)
Array_Sum = Array_Sum + Q(i)
Next
End Function

mazoolagh
جمعه 28 آذر 1399, 10:48 صبح
Public Sub Sort(A As Variant, L As Integer, H As Integer)Dim Pivot, Swap
Dim Lx As Integer
Dim Hx As Integer


Lx = L
Hx = H
Pivot = A((L + H) \ 2)


While (Lx <= Hx)
While (A(Lx) < Pivot And Lx < H)
Lx = Lx + 1
Wend


While (Pivot < A(Hx) And Hx > L)
Hx = Hx - 1
Wend


If (Lx <= Hx) Then
Swap = A(Lx)
A(Lx) = A(Hx)
A(Hx) = Swap
Lx = Lx + 1
Hx = Hx - 1
End If
Wend


If (L < Hx) Then Sort A, L, Hx
If (Lx < H) Then Sort A, Lx, H
End Sub

mazoolagh
جمعه 28 آذر 1399, 10:49 صبح
Sub AddAnswer()S = Join(V, ",")
If Not D.Exists(S) Then
D.Add S, S
Me.Answers.AddItem D.Count & ";" & S & ";" & Join(C, " ")
Me.Answers = D.Count
End If
End Sub

mazoolagh
جمعه 28 آذر 1399, 10:53 صبح
152677

.............

mazoolagh
جمعه 28 آذر 1399, 10:55 صبح
برنامه نمونه:

بجای این برنامه، از نمونه اصلاح شده پست 36 (https://barnamenevis.org/showthread.php?563684-%D8%AE%D8%A7%D8%B1%D8%AC-%D8%A7%D8%B2-%D8%AF%D8%B3%D8%AA%D9%88%D8%B1-%D9%BE%D8%B1%D8%B3%D8%B4%D9%87%D8%A7%DB%8C%DB%8C-%D8%A7%D8%B2-%D8%AC%D9%86%D8%B3-%D8%AF%DB%8C%DA%AF%D8%B1&p=2438238&viewfull=1#post2438238) استفاده کنید.

atf1379
جمعه 28 آذر 1399, 17:00 عصر
و اگر Number=6 و N=2 باشه:
1,5
2,4
3,3

ا ه
ب د
ج ج


برنامه نمونه:
سلام جناب mazoolagh (https://barnamenevis.org/member.php?9893-mazoolagh)
در نمونه پست 24 که توسط eb_1345 (https://barnamenevis.org/member.php?424036-eb_1345) ارائه شده تعداد ترکیب ها برای تعداد 2 و جمع 6 سه ترکیب و در نمونه جنابعالی دو ترکیب بدست می آید . درحالیکه در مثال پست اولتون برای تعداد 2 و جمع 6 سه ترکیب بدست آورده بودین( نقل قول بالا)

mazoolagh
شنبه 29 آذر 1399, 10:05 صبح
برنامه اصلاح شده ، کد پست 29 بصورت زیر اصلاح شد:
If Values(i) <= Number - N + 1 Then

mazoolagh
شنبه 29 آذر 1399, 10:11 صبح
سلام جناب mazoolagh (https://barnamenevis.org/member.php?9893-mazoolagh)
در نمونه پست 24 که توسط eb_1345 (https://barnamenevis.org/member.php?424036-eb_1345) ارائه شده تعداد ترکیب ها برای تعداد 2 و جمع 6 سه ترکیب و در نمونه جنابعالی دو ترکیب بدست می آید . درحالیکه در مثال پست اولتون برای تعداد 2 و جمع 6 سه ترکیب بدست آورده بودین( نقل قول بالا)

سلام و روز خوش
خیلی ممنون بابت دقت نظر شما و اینکه بحث رو دنبال کردین.

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

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

mazoolagh
سه شنبه 02 دی 1399, 13:54 عصر
پرسش بعدی رو مطرح میکنم:

چه روشی رو برای ساخت و رسم نمودار (و شکل های پیچیده) مشابه تصاویر زیر پیشنهاد میکنید؟
راهنمایی اینکه flash نیست.

152727

152728

padide55
سه شنبه 02 دی 1399, 16:28 عصر
سلام
چند روزیه دنبال حرکت دایره در بیسیک بودیم .
به نتیجه رسیدیم .
این هم تاپیک مربوطه (https://barnamenevis.org/showthread.php?563364-%D8%AD%D8%B1%DA%A9%D8%AA-%D8%A7%D8%B4%DB%8C%D8%A7%D8%A1-%D8%A8%D8%A7-VB-%D8%A7%DA%A9%D8%B3%D8%B3&p=2438309&viewfull=1#post2438309)
فعلا برای اولین نمونه فایل مربوطه رو‌میگذارم .

حالا ما محور x را ثابت درنظربگیریم .
با توجه به ثابت شدن x در همین فرمول
شی ما حرکت بالا و پایین متناوب پیدا میکند .
تا اینجا همه چیز روبراه هست .
مرحله بعد کد جهت ایجاد حرکت نمودارهست .

دو راه داریم .
اول نقطه گذاری در صفحه و اینکه نقاط خاموش و روشن بشوند .شبیه انچه در تابلوهای روان داریم .


152730
حالا کدام نقاط روشن شوند
اینجا کلیک کنید (https://blog.faradars.org/intuitive-understanding-of-sine-waves/)
پیشنهاد من اینه که کد بدیم که شی در صفحه اتومات ایجاد بشه و بر اساس تایم اینتروال به اندازه هر x. به چپ بره .

بر اساس xوy. نمودار .

atf1379
سه شنبه 02 دی 1399, 16:28 عصر
پرسش بعدی رو مطرح میکنم:

چه روشی رو برای ساخت و رسم نمودار (و شکل های پیچیده) مشابه تصاویر زیر پیشنهاد میکنید؟
راهنمایی اینکه flash نیست.

152727

152728



.................................................. ..

padide55
چهارشنبه 03 دی 1399, 14:57 عصر
سلام
موقتا کمک میخوام

اول اینکه میخوام 360 عدد دایره درست کنم که به ترتیب چینش کنم
یعنی باتن شماره 1 تا 360
یعنی
for x to command360
me.commandX.move x ,3000
next
حالا محاسبه x رو با
dim ctl as control بدست بیاریم و چینش بشه یعنی 365 نقطه به فاصله 1 پیکسل از هم در ارتفاع 3000 ردیف شوند .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .

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



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

فعلا مرحله اول رو کمک میخوام
اندازه رو محاسبه میکنم بعدا

mazoolagh
چهارشنبه 03 دی 1399, 16:18 عصر
سلام
...


سلام و روز خوش
1- در مورد ساعت و بطور کلی انیمیشن روی فرم اکسس، متاسفانه همه روشهای متعارف نتیجه اش زمخت و چشم آزار از آب در میاد و این نه بخاطر ضعف کدنویس بلکه محدودیت ذاتی اکسس هست.
این ساعت که نمونه گذاشتم خارج از اکسس طراحی و اجرا میشه - فقط نتیجه روی فرم اکسس دیده میشه و حرکت هم بسیار روان هست.
کدنویسی هم بسیار راحتتر ولی البته vba نیست!

2- برای گراف و نمودار، مشکلات ردیف 1 رو نداریم، ولی محاسبات نمایش با vba و امکانات داخلی سختتر و از نظر ظاهری هم منحنی ها و خطوط هموار نیستن، ولی قابل قبول هست و شدنیه.
این گراف نمونه هم البته با vba نیست و همونطور که میبینین منحنی ها کاملا هموار هستن.
دقت کنید که در فرم اکسس نمیتونین point یا دایره رسم کنین، برای اینکار از ریپورت استفاده کنین.

3- در مورد ساخت 360 کنترل روی فرم، باید فرم رو با کد در مود طراحی باز کنین و با متد createcontrol هر چه که لازم دارین بسازین و به فرم اضافه و بعد فرم رو ذخیره کنین.

padide55
پنج شنبه 04 دی 1399, 11:48 صبح
سلام
نمونه دایره و حرکت را با نمودار اکسس در یک فرم ایجاد کردم .

نتیجه
بجای جدول دستی هم میشه خود سیستم بصورت اتومات سینوس مورد نظر را ایجاد و درجدول قراربده . البته اینجا فقط برای نمودار از جدول استفاده میشه . برای ایجاد حرکت هم سینوس 90 درجه کمتر و 90 درجه بیشتر از عدد مورد نظر رو وارد کردم که نمودار مقدار زاویه که در خط افقی میاد رو داشته باشه .
نمودارهای مورد نظر در تصویر هم به همون شکل ساخته میشه . فقط باید فرمول XY رو محاسبه نمود و آرایه Y , X رو در آورد . که اون هم با توجه به فرمول هر نمودار شدنیه .
ولی درکل روش نمودار همینه که اینجا اوردم . فقط نوع محاسبه داده ها فرق میکنه .
نمودار پویا در اکسس

eb_1345
پنج شنبه 04 دی 1399, 12:10 عصر
سلام
نمونه دایره و حرکت را با نمودار اکسس در یک فرم ایجاد کردم .

نتیجه
بجای جدول دستی هم میشه خود سیستم بصورت اتومات سینوس مورد نظر را ایجاد و درجدول قراربده . البته اینجا فقط برای نمودار از جدول استفاده میشه . برای ایجاد حرکت هم سینوس 90 درجه کمتر و 90 درجه بیشتر از عدد مورد نظر رو وارد کردم که نمودار مقدار زاویه که در خط افقی میاد رو داشته باشه .
نمودارهای مورد نظر در تصویر هم به همون شکل ساخته میشه . فقط باید فرمول XY رو محاسبه نمود و آرایه Y , X رو در آورد . که اون هم با توجه به فرمول هر نمودار شدنیه .
ولی درکل روش نمودار همینه که اینجا اوردم . فقط نوع محاسبه داده ها فرق میکنه .
نمودار پویا در اکسس


بابا ! تو دیگه کی هستی ؟! :لبخند::تشویق::تشویق::تشویق:: شویق::تشویق::تشویق::تشویق::ت ویق:

eb_1345
پنج شنبه 04 دی 1399, 12:23 عصر
...............................

eb_1345
پنج شنبه 04 دی 1399, 17:01 عصر
....................................

mazoolagh
دوشنبه 08 دی 1399, 12:41 عصر
....................................

نمیدونم چرا پست رو پاک کردین
ولی در ایمیل مشخص بود که به اکتیواکس codejoke اشاره کرده بودین.
با codejoke آشنایی ندارم، ولی به اصل مطلب این پرسش که برای هر کاری باید از ابزار صحیح اون استفاده کرد رسیدین و اینجا هم در کل مجبوریم از اکتیوایکس (ولی مناسب) استفاده کنیم.

mazoolagh
دوشنبه 08 دی 1399, 13:02 عصر
در مورد ساعت:
اگر هدف نمایش وقت هست که خود taskbar ساعت داره و نیازی نیست و کار بیهوده ای هست،
اگر هدف زیبایی فرم و ... هست که باز هم کار عبثی است!
اما اگر هدف چالش کدنویسی و محک زدن توانایی و ... است نتیجه اش همین هست که کار بیهوده ایست و بهتره وقتمون رو روی موارد مهمتر بگذاریم.

به هر حال چند راه وجود داره:
1- ساعت flash - که بهتره از اون اجتناب بشه، ولی ده ها طرح دیجیتال و آنالوگ ازش به راحتی در دسترس هست.
2- استفاده از فونت مناسب (بهترین روش)
3- استفاده از html5 در کنترل web browser
اون ساعت که نمونه اش رو فرستاده بودم در اصل یک فایل html بود که همینجا پیوست میکنم




<!DOCTYPE HTML>
<html>
<head>
<title>clock</title>
<style>
body {
background-color:#3084e2;
}
#cnv {
position:absolute;
top:50%;
left:50%;
width:500px;
height:500px;
margin:-250px 0 0 -250px;
}
</style>
</head>


<body onload="clock();">


<canvas id="cnv"></canvas>


<script>
function clock() {
var canvas = document.getElementById('cnv');

//guarantee canvas is supported
if (!canvas.getContext) {
alert('canvas not supported!');
return;
}

canvas.width = 500;
canvas.height = 500;
tick();
}


function tick() {
var d = new Date();
var h = d.getHours();
var m = d.getMinutes() + h * 60;
var s = d.getSeconds() + m * 60;
var ms = d.getMilliseconds();

//multiply by 6 to get basic sec angle, then add up to
//5.994 degrees (999 * 0.006) to account for milliseconds
var secAngle = -90 + s * 6 + ms * 0.006;

//multiply by 6 to get basic min angle, then add up to
//5.9 degrees (59 * 0.1) to account for seconds
var minAngle = -90 + s * 0.1;

//multiply by 30 to get basic hour angle, then add up to
//29.5 degrees (59 * 0.5) to account for minutes, and up to
//0.4916666667 degrees (59 * 1/120) to account for seconds
var hourAngle = -90 + (s / 120);

var canvas = document.getElementById('cnv');
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, 500, 500);

drawFace(ctx);

ctx.translate(250, 250);
drawTicks(ctx);
drawHourHand(ctx, hourAngle);
drawMinHand(ctx, minAngle);
drawSecHand(ctx, secAngle);
ctx.translate(-250, -250);
drawFace2(ctx);

setTimeout(tick, 31);
}


function drawFace(ctx) {
//outer black ring
ctx.beginPath();
ctx.arc(250, 250, 250, 0, 2 * Math.PI);
ctx.fillStyle = '#111';
ctx.fill();
ctx.closePath();

//next light grey ring
ctx.beginPath();
ctx.arc(250, 250, 248, 0, 2 * Math.PI);
ctx.fillStyle = '#bbb';
ctx.fill();
ctx.closePath();


//outer gradient bezel
var g1x1 = 250 + 246 * Math.cos(4/3*Math.PI);
var g1y1 = 250 + 246 * Math.sin(4/3*Math.PI)
var g1x2 = 250 + 246 * Math.cos(1/3*Math.PI);
var g1y2 = 250 + 246 * Math.sin(1/3*Math.PI);
var g1 = ctx.createLinearGradient(g1x1,g1y1,g1x2,g1y2);
g1.addColorStop(0, '#f4f4f4');
g1.addColorStop(1, '#000');

ctx.beginPath();
ctx.arc(250, 250, 246, 0, 2 * Math.PI);
ctx.fillStyle = g1;
ctx.fill();
ctx.closePath();


//next outer bezel
var g2x1 = 250 + 224 * Math.cos(4/3*Math.PI);
var g2y1 = 250 + 224 * Math.sin(4/3*Math.PI)
var g2x2 = 250 + 224 * Math.cos(1/3*Math.PI);
var g2y2 = 250 + 224 * Math.sin(1/3*Math.PI);
var g2 = ctx.createLinearGradient(g2x1,g2y1,g2x2,g2y2);
g2.addColorStop(0, '#000');
g2.addColorStop(1, '#777');

ctx.beginPath();
ctx.arc(250, 250, 224, 0, 2 * Math.PI);
ctx.fillStyle = g2;
ctx.fill();
ctx.closePath();


//tan clock face
ctx.beginPath();
ctx.arc(250, 250, 212, 0, 2 * Math.PI);
ctx.fillStyle = '#d5c595';
ctx.fill();
ctx.closePath();
}


function drawTicks(ctx) {
//radial lines
drawPath(ctx, 'M -108,-1 L 108,-1 108,1 -108,1 Z', '#baa77c', 0);
drawPath(ctx, 'M -108,-1 L 108,-1 108,1 -108,1 Z', '#baa77c', 30);
drawPath(ctx, 'M -108,-1 L 108,-1 108,1 -108,1 Z', '#baa77c', 60);
drawPath(ctx, 'M -108,-1 L 108,-1 108,1 -108,1 Z', '#baa77c', 90);
drawPath(ctx, 'M -108,-1 L 108,-1 108,1 -108,1 Z', '#baa77c', 120);
drawPath(ctx, 'M -108,-1 L 108,-1 108,1 -108,1 Z', '#baa77c', 150);


//triangle ticks
drawPath(ctx, 'M 154,0 L 178,-6 178,6 Z', '#111', 0);
drawPath(ctx, 'M 154,0 L 178,-6 178,6 Z', '#111', 90);
drawPath(ctx, 'M 154,0 L 178,-6 178,6 Z', '#111', 180);
drawPath(ctx, 'M 154,0 L 178,-6 178,6 Z', '#111', -90);

//long brown ticks
drawPath(ctx, 'M 156,-2 L 180,-2 180,2 156,2 Z', '#baa77c', 30);
drawPath(ctx, 'M 156,-2 L 180,-2 180,2 156,2 Z', '#baa77c', 60);
drawPath(ctx, 'M 156,-2 L 180,-2 180,2 156,2 Z', '#baa77c', 120);
drawPath(ctx, 'M 156,-2 L 180,-2 180,2 156,2 Z', '#baa77c', 150);
drawPath(ctx, 'M 156,-2 L 180,-2 180,2 156,2 Z', '#baa77c', -30);
drawPath(ctx, 'M 156,-2 L 180,-2 180,2 156,2 Z', '#baa77c', -60);
drawPath(ctx, 'M 156,-2 L 180,-2 180,2 156,2 Z', '#baa77c', -120);
drawPath(ctx, 'M 156,-2 L 180,-2 180,2 156,2 Z', '#baa77c', -150);

//text labels: 3,6,9,12
ctx.font = '24pt Georgia';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillStyle = '#444';
ctx.fillText('3', 140, -4);
ctx.fillText('6', 0, 138);
ctx.fillText('9', -140, -4);
ctx.fillText('12', 0, -140);

//big dot above 12
ctx.beginPath();
ctx.arc(0, -195, 4, 0, 2 * Math.PI);
ctx.fillStyle = '#444';
ctx.fill();
ctx.closePath();

for (var i = 0; i < 360; i += 30) {
//outer tick squares
drawPath(ctx, 'M 180,-3 L 184,-3 184,3 180,3 Z', 'rgba(68,68,68,0.8)', i);

//inner tick squares
drawPath(ctx, 'M 110,-3 L 120,-3 120,3 110,3 Z', 'rgba(68,68,68,0.8)', i);


//outer text labels
var lbl = '' + Math.round(i/6 + 15);
if (lbl == '60') lbl = '';
if (lbl == '65') lbl = '5';
if (lbl == '70') lbl = '10';
var x = 195 * Math.cos(i * Math.PI / 180.0);
var y = 195 * Math.sin(i * Math.PI / 180.0);
ctx.save();
ctx.translate(x,y);
ctx.rotate((i + 90 - (i > 0 && i < 180 ? 180 : 0)) * Math.PI / 180.0);
ctx.font = '9pt Georgia';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillStyle = 'rgba(68,68,68,0.8)';
ctx.fillText(lbl, 0, 0);
ctx.restore();

//far outer dots between labels
ctx.beginPath();
x = 195 * Math.cos((i+15) * Math.PI / 180);
y = 195 * Math.sin((i+15) * Math.PI / 180);
ctx.arc(x, y, 1.5, 0, 2 * Math.PI);
ctx.fillStyle = '#444';
ctx.fill();
ctx.closePath();

for (var j = 0; j < 25; j += 6) {
if (j != 0) {
//outer tick ring - long ticks
drawPath(ctx, 'M 174,-0.5 L 184,-0.5 184,0.5 174,0.5 Z', '#444', i+j);

//inner tick ring - short ticks
drawPath(ctx, 'M 114,-0.5 L 120,-0.5 120,0.5 114,0.5 Z', 'rgba(68,68,68,0.8)', i+j);
}

for (var k = 1.5; k < 5; k += 1.5) {
//outer tick ring - short ticks
drawPath(ctx, 'M 180,-0.3 L 184,-0.3 184,0.3 180,0.3 Z', 'rgba(68,68,68,0.5)', i+j+k);
}
}
}
}


function drawSecHand(ctx,ang) {
drawPath(ctx, 'M -50,0 L -45,-5 -25,-5 -22,-2 22,-2 25,-5 180,0 25,5 22,2 -22,2 -25,5 -45,5 Z', '#c21', ang);


ctx.beginPath();
ctx.arc(0, 0, 8, 0, 2 * Math.PI);
ctx.fillStyle = '#c21';
ctx.fill();
ctx.closePath();
}


function drawMinHand(ctx,ang) {
drawPath(ctx, 'M 0,0 L 1,-2 20,-2 22,-5 122,-5 124,-2 146,-2 168,0 146,2 124,2 122,5 22,5 20,2 1,2 0,0 24,0 24,2 120,2 122,0 120,-2 24,-2 24,0 Z', '#111', ang);
}


function drawHourHand(ctx,ang) {
drawPath(ctx, 'M 0,0 L 1,-3 14,-3 17,-7 97,-7 100,-3 112,-2 134,0 112,2 100,3 97,7 17,7 14,3 1,3 0,0 18,0 21,3 94,3 96,0 94,-3 21,-3 18,0 Z', '#000', ang);
}


function drawFace2(ctx) {
//outer center button ring
var g1x1 = 250 + 5 * Math.cos(4/3*Math.PI);
var g1y1 = 250 + 5 * Math.sin(4/3*Math.PI)
var g1x2 = 250 + 5 * Math.cos(1/3*Math.PI);
var g1y2 = 250 + 5 * Math.sin(1/3*Math.PI);
var g1 = ctx.createLinearGradient(g1x1,g1y1,g1x2,g1y2);
g1.addColorStop(0, '#999');
g1.addColorStop(1, '#333');

ctx.beginPath();
ctx.arc(250, 250, 5, 0, 2 * Math.PI);
ctx.fillStyle = g1;
ctx.fill();
ctx.closePath();

//inner center button
var g2x1 = 250 + 3 * Math.cos(4/3*Math.PI);
var g2y1 = 250 + 3 * Math.sin(4/3*Math.PI)
var g2x2 = 250 + 3 * Math.cos(1/3*Math.PI);
var g2y2 = 250 + 3 * Math.sin(1/3*Math.PI);
var g2 = ctx.createLinearGradient(g2x1,g2y1,g2x2,g2y2);
g2.addColorStop(0, '#ccc');
g2.addColorStop(1, '#aaa');

ctx.beginPath();
ctx.arc(250, 250, 3, 0, 2 * Math.PI);
ctx.fillStyle = g2;
ctx.fill();
ctx.closePath();

//highlight (gradient overlay)
var g3x1 = 250 + 212 * Math.cos(4/3*Math.PI);
var g3y1 = 250 + 212 * Math.sin(4/3*Math.PI)
var g3x2 = 250 + 212 * Math.cos(1/3*Math.PI);
var g3y2 = 250 + 212 * Math.sin(1/3*Math.PI);
var g3 = ctx.createLinearGradient(g3x1,g3y1,g3x2,g3y2);
g3.addColorStop(0, 'rgba(255,255,255,0.5)');
g3.addColorStop(1, 'rgba(255,255,255,0)');

ctx.beginPath();
ctx.arc(250, 250, 212, 0, 2 * Math.PI);
ctx.fillStyle = g3;
ctx.fill();
ctx.closePath();
}


/** Simple svg path parser that only understands M (move to) and L (line to). */
function drawPath(ctx,path,fill,ang) {
ctx.save();
ctx.rotate(ang == undefined ? 0 : ang * Math.PI / 180.0);
ctx.beginPath();

var parts = path.split(' ');
while (parts.length > 0) {
var part = parts.shift();
if (part == 'M') {
coords = parts.shift().split(',');
ctx.moveTo(coords[0], coords[1]);
} else if (part == 'L') {
continue;
} else if (part == 'Z') {
break;
} else if (part.indexOf(',') >= 0) {
coords = part.split(',');
ctx.lineTo(coords[0], coords[1]);
}
}

ctx.closePath();
ctx.fillStyle = (fill == undefined ? '#000' : fill);
ctx.fill();
ctx.restore();
}
</script>
</body>
</html>

mazoolagh
دوشنبه 08 دی 1399, 14:04 عصر
در مورد نمودار:
نمودار همانجور که قبلا گفتیم در خود اکسس قابل ساخت هست (با کدنویسی زیاد) ولی نتیجه جالبی بدست نمیاد.
یک راه مناسب استفاده از visio هست و کافی هست یک visio viewer در فرم اضافه بشه.
البته Html5 هم همیشه هست!


<!DOCTYPE HTML><html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}


</style>
</head>
<body data-rsssl=1>
<canvas id="myCanvas" width="800" height="500"></canvas>
<script>
function Graph(config) {
// user defined properties
this.canvas = document.getElementById(config.canvasId);
this.minX = config.minX;
this.minY = config.minY;
this.maxX = config.maxX;
this.maxY = config.maxY;
this.unitsPerTick = config.unitsPerTick;


// constants
this.axisColor = '#aaa';
this.font = '8pt Calibri';
this.tickSize = 20;


// relationships
this.context = this.canvas.getContext('2d');
this.rangeX = this.maxX - this.minX;
this.rangeY = this.maxY - this.minY;
this.unitX = this.canvas.width / this.rangeX;
this.unitY = this.canvas.height / this.rangeY;
this.centerY = Math.round(Math.abs(this.minY / this.rangeY) * this.canvas.height);
this.centerX = Math.round(Math.abs(this.minX / this.rangeX) * this.canvas.width);
this.iteration = (this.maxX - this.minX) / 1000;
this.scaleX = this.canvas.width / this.rangeX;
this.scaleY = this.canvas.height / this.rangeY;


// draw x and y axis
this.drawXAxis();
this.drawYAxis();
}


Graph.prototype.drawXAxis = function() {
var context = this.context;
context.save();
context.beginPath();
context.moveTo(0, this.centerY);
context.lineTo(this.canvas.width, this.centerY);
context.strokeStyle = this.axisColor;
context.lineWidth = 2;
context.stroke();


// draw tick marks
var xPosIncrement = this.unitsPerTick * this.unitX;
var xPos, unit;
context.font = this.font;
context.textAlign = 'center';
context.textBaseline = 'top';


// draw left tick marks
xPos = this.centerX - xPosIncrement;
unit = -1 * this.unitsPerTick;
while(xPos > 0) {
context.moveTo(xPos, this.centerY - this.tickSize / 2);
context.lineTo(xPos, this.centerY + this.tickSize / 2);
context.stroke();
context.fillText(unit, xPos, this.centerY + this.tickSize / 2 + 3);
unit -= this.unitsPerTick;
xPos = Math.round(xPos - xPosIncrement);
}


// draw right tick marks
xPos = this.centerX + xPosIncrement;
unit = this.unitsPerTick;
while(xPos < this.canvas.width) {
context.moveTo(xPos, this.centerY - this.tickSize / 2);
context.lineTo(xPos, this.centerY + this.tickSize / 2);
context.stroke();
context.fillText(unit, xPos, this.centerY + this.tickSize / 2 + 3);
unit += this.unitsPerTick;
xPos = Math.round(xPos + xPosIncrement);
}
context.restore();
};


Graph.prototype.drawYAxis = function() {
var context = this.context;
context.save();
context.beginPath();
context.moveTo(this.centerX, 0);
context.lineTo(this.centerX, this.canvas.height);
context.strokeStyle = this.axisColor;
context.lineWidth = 2;
context.stroke();


// draw tick marks
var yPosIncrement = this.unitsPerTick * this.unitY;
var yPos, unit;
context.font = this.font;
context.textAlign = 'right';
context.textBaseline = 'middle';


// draw top tick marks
yPos = this.centerY - yPosIncrement;
unit = this.unitsPerTick;
while(yPos > 0) {
context.moveTo(this.centerX - this.tickSize / 2, yPos);
context.lineTo(this.centerX + this.tickSize / 2, yPos);
context.stroke();
context.fillText(unit, this.centerX - this.tickSize / 2 - 3, yPos);
unit += this.unitsPerTick;
yPos = Math.round(yPos - yPosIncrement);
}


// draw bottom tick marks
yPos = this.centerY + yPosIncrement;
unit = -1 * this.unitsPerTick;
while(yPos < this.canvas.height) {
context.moveTo(this.centerX - this.tickSize / 2, yPos);
context.lineTo(this.centerX + this.tickSize / 2, yPos);
context.stroke();
context.fillText(unit, this.centerX - this.tickSize / 2 - 3, yPos);
unit -= this.unitsPerTick;
yPos = Math.round(yPos + yPosIncrement);
}
context.restore();
};


Graph.prototype.drawEquation = function(equation, color, thickness) {
var context = this.context;
context.save();
context.save();
this.transformContext();


context.beginPath();
context.moveTo(this.minX, equation(this.minX));


for(var x = this.minX + this.iteration; x <= this.maxX; x += this.iteration) {
context.lineTo(x, equation(x));
}


context.restore();
context.lineJoin = 'round';
context.lineWidth = thickness;
context.strokeStyle = color;
context.stroke();
context.restore();
};


Graph.prototype.transformContext = function() {
var context = this.context;


// move context to center of canvas
this.context.translate(this.centerX, this.centerY);


/*
* stretch grid to fit the canvas window, and
* invert the y scale so that that increments
* as you move upwards
*/
context.scale(this.scaleX, -this.scaleY);
};
var myGraph = new Graph({
canvasId: 'myCanvas',
minX: -10,
minY: -10,
maxX: 10,
maxY: 10,
unitsPerTick: 1
});


myGraph.drawEquation(function(x) {
return 5 * Math.sin(x);
}, 'green', 3);


myGraph.drawEquation(function(x) {
return x * x;
}, 'blue', 3);


myGraph.drawEquation(function(x) {
return 1 * x;
}, 'red', 3);


myGraph.drawEquation(function(x) {
return 7 * Math.sin(x)/x;
}, 'pink', 3);




</script>
</body>
</html>

eb_1345
سه شنبه 09 دی 1399, 20:05 عصر
نمیدونم چرا پست رو پاک کردین
ولی در ایمیل مشخص بود که به اکتیواکس codejoke اشاره کرده بودین.
با codejoke آشنایی ندارم، ولی به اصل مطلب این پرسش که برای هر کاری باید از ابزار صحیح اون استفاده کرد رسیدین و اینجا هم در کل مجبوریم از اکتیوایکس (ولی مناسب) استفاده کنیم.
سلام جناب mazoolagh (https://barnamenevis.org/member.php?9893-mazoolagh) عزیز !
ببخشید این پست شما رو ندیده بودم
بله ، همونطوری که بدرستی اشاره کردین مطلب حذف شده پست فوق در خصوص استفاده از کامپوننت codejoke برای اینکار بود .
علی ایحال مجدد نمونه را در لینک زیر قرار داده ام
در لینک یک نمونه که به زبان های VB ، VB.NETو C#‎‎‎‎‎‎‎.NET تهیه شده با اکتیوایکس مربوطه در پوشه Bin
https://s17.picofile.com/file/8419366818/FlowGraph.rar.html
تصویری از گراف نمونه تهیه شده در محیط vb6 :

eb_1345
سه شنبه 09 دی 1399, 21:29 عصر
بنده قبلا بیشتر از اکتیوایکس CommandBars ، CommandBarsDesigner و SkinFramework و چندمورد دیگر در برنامه هایم استفاده می کردم .
واقعاً کامپوننت های codejoke در نوع خودش بی نظیر هستند
کاربرانی که دنبال منوهای زیبا و پیشرفته و جذاب نمودن محیط برنامه خود هستند تمایلی شدیدی به استفاده از این کامپوننت های codejoke دارند .
ولی با این وجود با تمام جذابیت هائیکه که از استفاده از کامپوننت های Codejock مشاهده کرده ام اعتقاد دارم در محیط اکسس تاجائی که اجباری در کارنباشد از امکانات داخلی اکسس استفاده شود بهتراست . به هر حال استفاده از اکتیوایکس ها هم مشکلات و دردسرهای خاص خودش رو دارد .

mazoolagh
چهارشنبه 10 دی 1399, 11:13 صبح
اعتقاد دارم در محیط اکسس تاجائی که اجباری در کارنباشد از امکانات داخلی اکسس استفاده شود بهتراست . به هر حال استفاده از اکتیوایکس ها هم مشکلات و دردسرهای خاص خودش رو دارد .

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

mazoolagh
شنبه 20 دی 1399, 13:56 عصر
هدف پیدا کردن روش مؤثر یا پاسخ قطعی امکان ساخت فرم unbound روی 2 جدول مرتبط بصورت master-detail هست.
1- برای یکسان بودن شرایط و جلوگیری از پراکندگی بحث، دیتا نمونه پیوست شده و عملکرد و ظاهر فرم های unbound باید دقیقا کپی فرم های bound این دیتابیس باشد.
2- چنانچه شدنی است، توضیح کدها و آوردن آن در متن پست با تگ مناسب شایسته است!
3- چنانچه اینکار را نشدنی میدانید، توضیح مستدل نیاز است.

narpco
یک شنبه 21 دی 1399, 00:32 صبح
دوستان ببخشید من میام وسط بحث شما این موضوع
codejoke رو میشه توضیح بیشتر بفرمایید و اینکه در اکسس چطوری میشه دانلود و استفاده کرد ایا عکسی از نمونه کاربردهاش دارید ؟
تو گوگل که بیشتر برای محیط های غیر اکسس--Visual Studio--
من مطلب دیدم ....ممنون

mazoolagh
یک شنبه 21 دی 1399, 19:42 عصر
در همین تالار پیشتر چندین بار دیدم در مورد اکتیوایکس codejoke بحث شده و حتی آموزش هم گذاشته بودن.
جستجو رو از همینجا شروع میکردین احتمالا جواب گرفته بودین.
اونها که شما دیدین کمپوننت های دات نت از همین شرکت بودن.

هر موقع دیدین میزان خواسته هایی که اکسس مستقیما نمیتونه برآورده کنه از 2-3 تا رد شد، درجا برین سراغ راه حلی که اونها رو براحتی و بی دردسر انجام بده.
کل خاصیت اکسس در سادگی و سرعت ساخت برنامه است، اگر قرار باشه با وصله پینه و سنگین کردن کد و نیاز به رجیستر چند اکتیوایکس و برنامه نصب و ... همه اینها رو کنار بگذاریم، خب از همون اول اول میریم سراغ فرضا دات نت که خیلی سریعتر و راحتتر به خواسته مون میرسیم و تکنولوژی روز هم هست - برخلاف اکتیوایکس که سالهاست مرده محسوب میشه.

یک نمونه اش همین آخرین پرسشی هست که اینجا مطرح کردم و نشون میده که اکسس برای همه کاری حتی در زمینه دیتا الزاما ممکنه سریعترین و راحتترین راه نباشه!

narpco
یک شنبه 21 دی 1399, 23:48 عصر
در همین تالار پیشتر چندین بار دیدم در مورد اکتیوایکس codejoke بحث شده و حتی آموزش هم گذاشته بودن.
جستجو رو از همینجا شروع میکردین احتمالا جواب گرفته بودین.
اونها که شما دیدین کمپوننت های دات نت از همین شرکت بودن.

هر موقع دیدین میزان خواسته هایی که اکسس مستقیما نمیتونه برآورده کنه از 2-3 تا رد شد، درجا برین سراغ راه حلی که اونها رو براحتی و بی دردسر انجام بده.
کل خاصیت اکسس در سادگی و سرعت ساخت برنامه است، اگر قرار باشه با وصله پینه و سنگین کردن کد و نیاز به رجیستر چند اکتیوایکس و برنامه نصب و ... همه اینها رو کنار بگذاریم، خب از همون اول اول میریم سراغ فرضا دات نت که خیلی سریعتر و راحتتر به خواسته مون میرسیم و تکنولوژی روز هم هست - برخلاف اکتیوایکس که سالهاست مرده محسوب میشه.

یک نمونه اش همین آخرین پرسشی هست که اینجا مطرح کردم و نشون میده که اکسس برای همه کاری حتی در زمینه دیتا الزاما ممکنه سریعترین و راحتترین راه نباشه!


ممنون از توضیحات .....پس کلا موضوع خاصی برای کار در اکسس نیست و بهتره که حتی المکان از امکانات خود اکسس استفاده کنیم .....فک کنم استفاده از برنامه های بقول شما وصل پینه ای سرعت برنامه رو کاهش میده و حجم فایل رو هم افزایش میده .....در دات نت دیده بودم شبیه این codejoke رو که همه امکانات خود فرم ها رو در قالبی شکیل تر نشون میده .......به هر حال ممنون ....

mazoolagh
دوشنبه 06 بهمن 1399, 15:06 عصر
هدف پیدا کردن روش مؤثر یا پاسخ قطعی امکان ساخت فرم unbound روی 2 جدول مرتبط بصورت master-detail هست.
1- برای یکسان بودن شرایط و جلوگیری از پراکندگی بحث، دیتا نمونه پیوست شده و عملکرد و ظاهر فرم های unbound باید دقیقا کپی فرم های bound این دیتابیس باشد.
2- چنانچه شدنی است، توضیح کدها و آوردن آن در متن پست با تگ مناسب شایسته است!
3- چنانچه اینکار را نشدنی میدانید، توضیح مستدل نیاز است.

این پست فعلا اینجا میمونه تا یک کاربر باتجربه و دانش کافی پیدا بشه!

mazoolagh
دوشنبه 06 بهمن 1399, 15:11 عصر
یک پرسش ساده تر مطرح میکنم که احتمالا نمونه کد آماده هم برای اون شاید پیدا بشه.

هدف این هست که نتایج یک جدول/رکوردست/کوئری رو صفحه بندی کنیم.
تعداد رکورد در هر صفحه پارامتر هست و شماره صفحه/صفحه قبل/صفحه بعد/صفحه اول/صفحه آخر باید پیاده بشه.
خروجی روی فرم پیوسته یا لیست باکس هر دو قابل قبول هست.

ssadegh1365
دوشنبه 06 بهمن 1399, 15:50 عصر
از جناب Mazoolagh خواهشمندم به برنامه بنده در تالار اکسس درباره مشکل در انتخاب فیلد از جدول و نمایش در لیست باکس نگاهی بندازن .
درصورت امکان خواهشمندم درستش کنین.
هرکار کردم نتونستم. کسی نتونسته هنوز برام درستش کنه.
خیلی خیلی ببخشین

eb_1345
دوشنبه 06 بهمن 1399, 16:09 عصر
هرکار کردم نتونستم. کسی نتونسته هنوز برام درستش کنه.

دوست بزرگوار ! اینکه دوستان دیگری تا حالا به شما کمک نکرده اند دلیل بر این نیست که آنها هم توانائی انجام خواسته شما را نداشته باشند .
نمونه هائی تحت عنوان گزارش ساز در تالار موجوده .
موفق باشید

mazoolagh
دوشنبه 06 بهمن 1399, 16:51 عصر
از جناب Mazoolagh خواهشمندم به برنامه بنده در تالار اکسس درباره مشکل در انتخاب فیلد از جدول و نمایش در لیست باکس نگاهی بندازن .
درصورت امکان خواهشمندم درستش کنین.
هرکار کردم نتونستم. کسی نتونسته هنوز برام درستش کنه.
خیلی خیلی ببخشین
مشکلی نیست جناب صادق،
ولی راهنمایی کافی و وافی داده شده بود و باید قدری زحمت هم خودتون متحمل بشید یا اینکه صبر کنین دوستانی که راهنمایی کردن وقت آزاد داشته باشن.

mazoolagh
دوشنبه 06 بهمن 1399, 16:53 عصر
دوست بزرگوار ! اینکه دوستان دیگری تا حالا به شما کمک نکرده اند دلیل بر این نیست که آنها هم توانائی انجام خواسته شما را نداشته باشند .
نمونه هائی تحت عنوان گزارش ساز در تالار موجوده .
موفق باشید
حالا که زحمت کشیدین و تا اینجا اومدین خوشحال میشم روی paging هم نظر شما رو بدونم.

eb_1345
دوشنبه 06 بهمن 1399, 20:10 عصر
حالا که زحمت کشیدین و تا اینجا اومدین خوشحال میشم روی paging هم نظر شما رو بدونم.
سلام جناب mazoolagh (https://barnamenevis.org/member.php?9893-mazoolagh) !
راستش بنده تا حالا در خصوص کاربرد این موضوع (صفحه بندی نتایج یک جدول/رکوردست/کوئری) فکر نکرده ام
حالا اگر فکر می کنید این موضوع مهم وکاربردی است بفرمائید تا بر روی این موضوع تمرکز کنم .
فکر میکنم از طریق اسپلیت کردن تعداد رکورد برای هر صفحه بتوان به نتیجه رسید

eb_1345
دوشنبه 06 بهمن 1399, 21:59 عصر
سلام جناب mazoolagh (https://barnamenevis.org/member.php?9893-mazoolagh) !
راستش بنده تا حالا در خصوص کاربرد این موضوع (صفحه بندی نتایج یک جدول/رکوردست/کوئری) فکر نکرده ام
حالا اگر فکر می کنید این موضوع مهم وکاربردی است بفرمائید تا بر روی این موضوع تمرکز کنم .
فکر میکنم از طریق اسپلیت کردن تعداد رکورد برای هر صفحه بتوان به نتیجه رسید

با سلام مجدد
نمونه ضمیمه رو بررسی بفرمائید !
فقط ببخشین ! دیگر حال نداشتم توضیح کدها و متن آنها را در پست درج کنم:لبخندساده:

eb_1345
دوشنبه 06 بهمن 1399, 22:21 عصر
نمونه پست قبل اصلاح شد

mazoolagh
سه شنبه 07 بهمن 1399, 14:08 عصر
با سلام مجدد
نمونه ضمیمه رو بررسی بفرمائید !
فقط ببخشین ! دیگر حال نداشتم توضیح کدها و متن آنها را در پست درج کنم:لبخندساده:

سلام و روز خوش
... time

eb_1345
سه شنبه 07 بهمن 1399, 15:00 عصر
سلام
یک تغییر جزئی در کدها اعمال کردم
البته در کل بازهم امکان بهبودی و جمع و جور کردن کدها وجوددارد

mazoolagh
پنج شنبه 09 بهمن 1399, 12:42 عصر
سلام
یک تغییر جزئی در کدها اعمال کردم
البته در کل بازهم امکان بهبودی و جمع و جور کردن کدها وجوددارد

سلام و روز خوش
برنامه بروز شده رو الان دیدم.

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

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

اول از همه اینکه این روش کار میکنه، ولی چند مورد هست که مطرح میکنم:
1- نیاز به انجام تغییرات در جدول داره.
2- هنگام باز شدن فرم، محاسبه شماره صفحه پروسه زمانبری هست (با توجه به اینکه معمولا PAGING رو برای تعداد رکوردهای زیاد انجام میدیم)
3- انعطاف پذیری نداره و HARD-CODE هست، یعنی برای یک جدول دیگه نیاز به کدنویسی مجدد داریم
4- باحتمال زیاد پیاده سازی اون روی کوئری از جداول جوین شده، کار سخت و پیچیده ای خواهد بود.

الف- بنظرم اگر فقط با جدول سروکار داشته باشیم، بدون تغییر در طراحی اون و محاسبه اولیه هم میتونیم PAGING رو پیاده کنیم.
این مورد رو تست میکنم و سعی میکنم به جواب برسم.

ب- اونچه از پرسش مد نظر من هست یک روش کلی و ژنریک بدون نیاز به دانستن ساختار کوئری هست و برای همین هم به مورد الف فکر نکرده بودم.

mazoolagh
پنج شنبه 09 بهمن 1399, 12:49 عصر
مورد بعدی اینکه paging واقعا یک نیاز و روش مفید هست و یک مسئله انتزاعی یا چالش توانایی کدنویسی نیست:
هم سرعت لود شدن فرم رو بالا میبره و هم نیاز به اسکرول رو فقط که تعداد رکوردها زیاد هست مرتفع میکنه.

برای همین هم بیشتر database-engine این رو در نظر دارن، هم providerها و گاهی در سطح کنترل هایی مثل grid هم پیاده میشه.

eb_1345
جمعه 10 بهمن 1399, 02:25 صبح
البته در کل بازهم امکان بهبودی و جمع و جور کردن کدها وجوددارد




اول از همه اینکه این روش کار میکنه، ولی چند مورد هست که مطرح میکنم:
1- نیاز به انجام تغییرات در جدول داره.
2- هنگام باز شدن فرم، محاسبه شماره صفحه پروسه زمانبری هست (با توجه به اینکه معمولا PAGING رو برای تعداد رکوردهای زیاد انجام میدیم)
3- انعطاف پذیری نداره و HARD-CODE هست، یعنی برای یک جدول دیگه نیاز به کدنویسی مجدد داریم
4- باحتمال زیاد پیاده سازی اون روی کوئری از جداول جوین شده، کار سخت و پیچیده ای خواهد بود.

الف- بنظرم اگر فقط با جدول سروکار داشته باشیم، بدون تغییر در طراحی اون و محاسبه اولیه هم میتونیم PAGING رو پیاده کنیم.
این مورد رو تست میکنم و سعی میکنم به جواب برسم.

ب- اونچه از پرسش مد نظر من هست یک روش کلی و ژنریک بدون نیاز به دانستن ساختار کوئری هست و برای همین هم به مورد الف فکر نکرده بودم.

سلام
فایل نمونه پست 67 برای شروع کار و براساس خواسته اولیه جنابعالی که بدون شرط مطرح کرده بودید تهیه شده بود .
نمونه جدید رو بررسی بفرمائید !
در نمونه جدید فرض بر این است که تمام جداولی که بر اساس این روش نتایج رکوردست آنها صفحه بندی شود دارای یک فیلد ID که مقادیر آن متوالی است میباشد. بنا بر این فرض اگر فیلد فوق از نوع اتونامبر میباشد و رکوردی حذف میشود فیلد فوق قبل از عملیات صفحه بندی رکوردها باید ریست شود و اگر از نوع نامبر هم است باز هم بعد از حذف باید شماره گذاری مجدد صورت گیرد.

New Account
شنبه 11 بهمن 1399, 00:02 صبح
اون تاپیک خارج از دستور در واقع دون پاشی برای دوستانی مثل شما هست که به اونجا بیان و بتونم از دانسته هاشون بهره ببرم - البته به پیشگیری از آلزایمر هم بیربط نیست!
خاطرم هست که در چند مورد شما من رو از اشتباه درآوردین و خوشحال میشم هنوز هم به این کار ادامه بدین و من جزو اون گروه ناشایست که اشاره کردین نباشم.
هیچ مبحث بسته شده ای اونجا نیست و خوبیش اینه که اختلاف دیدگاه بین کسانی که صحبت هم رو میفهمن به راه های جدید منجر میشه و نه کدورت.

سلام mazoolagh
چوب کاری نفرمایید دوست من .
اختلاف نظرم با شما بر سر کلیات پست 55 هستش
ولی به دلایل ذیل در مبحث شرکت نکردم
1 – ممکن بود به اشتباه این شبه ایجاد بشه که قصد مقایسه اکسس با دیگر محیطهای توسعه وجود داره
2 – در خصوص مبحث اکتیو ایکس ها هم از اونجایی که نمی خواهم که شبه ای در خصوص ذی نفع بودنم در ذهن متبادر بشه , بر همین اساس ورود نکردم
البته قبلا در پستهایی مجزا در این خصوص مطالبی درج شده بود که به همونها استناد میکنم .

موفق باشید

mazoolagh
یک شنبه 12 بهمن 1399, 12:53 عصر
سلام
فایل نمونه پست 67 برای شروع کار و براساس خواسته اولیه جنابعالی که بدون شرط مطرح کرده بودید تهیه شده بود .
نمونه جدید رو بررسی بفرمائید !
در نمونه جدید فرض بر این است که تمام جداولی که بر اساس این روش نتایج رکوردست آنها صفحه بندی شود دارای یک فیلد ID که مقادیر آن متوالی است میباشد. بنا بر این فرض اگر فیلد فوق از نوع اتونامبر میباشد و رکوردی حذف میشود فیلد فوق قبل از عملیات صفحه بندی رکوردها باید ریست شود و اگر از نوع نامبر هم است باز هم بعد از حذف باید شماره گذاری مجدد صورت گیرد.


سلام و روز خوش
خب این نمونه بمراتب بهتر از نمونه اولیه هست (قطعا هم همینجور درسته و کارها بتدریج انجام میشه) و همچنین استفاده از id هم انتخاب کاملا منطقی و بجایی هست.
یک مورد هست که: فکر کنم الزامی نباشه نگران این باشین که همه idها بدون جاافتادگی باشن (البته اینجوری راحتتره) و فقط یکتا بودنش کفایت میکنه، البته در کد نیاز به تغییرات داره.

من هم یک نمونه آماده کردم که برای نظرخواهی همینجا پیوست میکنم (طبق عادت با عکس و تفصیلات)،
و بعد اگر مایل باشین این بخش رو ببندیم و بریم سراغ روش ژنریک و عمومی.

mazoolagh
یک شنبه 12 بهمن 1399, 13:18 عصر
سلام mazoolagh
چوب کاری نفرمایید دوست من .
اختلاف نظرم با شما بر سر کلیات پست 55 هستش
ولی به دلایل ذیل در مبحث شرکت نکردم
1 – ممکن بود به اشتباه این شبه ایجاد بشه که قصد مقایسه اکسس با دیگر محیطهای توسعه وجود داره
2 – در خصوص مبحث اکتیو ایکس ها هم از اونجایی که نمی خواهم که شبه ای در خصوص ذی نفع بودنم در ذهن متبادر بشه , بر همین اساس ورود نکردم
البته قبلا در پستهایی مجزا در این خصوص مطالبی درج شده بود که به همونها استناد میکنم .

موفق باشید

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

و در مورد کلیات پست 55 هم اونچه آمده نظر شخصی من بود، کما اینکه از api function هم تا حد امکان استفاده نمیکنم.
همیجور هر نوع دستکاری در سیستم کاربر و حتی به قفل هم اعتقادی ندارم - کلا این روش من بوده و هست: This the way.

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

باز هم ممنونم که پاسخ دادین و رفع ابهام شد.
کامیاب و کامروا باشین.

mazoolagh
یک شنبه 12 بهمن 1399, 13:51 عصر
Option Compare Database
Option Explicit
Const SQL = "SELECT TOP @PAGE_SIZE * FROM (SELECT TOP @P1 * FROM Products)" & _
" WHERE ProductID NOT IN (SELECT TOP @P2 ProductID FROM Products)"


Private DataSource As String
Private Page_ As Integer
Private PagesCount As Integer
Private RecordsCount As Long

Private Sub Form_Open(Cancel As Integer)
RecordsCount = DCount("*", "Products")
PageSize = 15
PageSize_AfterUpdate
End Sub

Private Sub GO_FIRST_Click()
Page_ = 1
BIND
End Sub

Private Sub GO_PREVIOUS_Click()
Page_ = Page_ - 1
BIND
End Sub

Private Sub GO_NEXT_Click()
Page_ = Page_ + 1
BIND
End Sub

Private Sub GO_LAST_Click()
Page_ = PagesCount
BIND
End Sub


Private Sub BIND()
If Page_ = 1 Then
DataSource = "SELECT TOP @PAGE_SIZE * FROM Products"
Else
DataSource = Replace(SQL, "@P1", PageSize * Page_)
DataSource = Replace(DataSource, "@P2", PageSize * (Page_ - 1))
End If
DataSource = Replace(DataSource, "@PAGE_SIZE", PageSize)
Set Me.Recordset = CurrentDb.OpenRecordset(DataSource)
Me.GO_FIRST.Enabled = Page_ > 1
Me.GO_PREVIOUS.Enabled = Page_ > 1
Me.GO_NEXT.Enabled = Page_ < PagesCount
Me.GO_LAST.Enabled = Page_ < PagesCount
Me.Indicator.Caption = "page " & Page_ & " of " & PagesCount
Me.PageNumber = Page_
End Sub


Private Sub PageNumber_AfterUpdate()
Page_ = Me.PageNumber
BIND
End Sub


Private Sub PageSize_AfterUpdate()
PagesCount = RecordsCount / PageSize
If PagesCount * PageSize < RecordsCount Then PagesCount = PagesCount + 1
Me.PageNumber.RowSource = ""
Dim i As Integer
For i = 1 To PagesCount
Me.PageNumber.AddItem (i)
Next i
GO_FIRST_Click
End Sub


Private Sub PageSize_NotInList(NewData As String, Response As Integer)
Response = acDataErrContinue
Me.PageSize = 15
End Sub

Private Sub PageNumber_NotInList(NewData As String, Response As Integer)
Response = acDataErrContinue
Me.PageNumber = 1
End Sub

mazoolagh
یک شنبه 12 بهمن 1399, 13:53 عصر
نمونه paging

ARData
یک شنبه 19 بهمن 1399, 10:20 صبح
سلام
سخت ترین فرمولی که من تا حالا نتونستم انجامش بدم و هربار به بن بست خوردم فرمول کاتینگ ورق برای برش طول و عرض های مورد نیاز بر اساس متریال ورق استاندارد موجود که کمترین پرت را داشته باشد - فقط یک شرکت هندی موفق شده این فرمول رو درست اجرا کنه
البته با توجه به نیاز بعد گرافیکی به اینکار ، در صورت کشف فرمول و ابعاد و اندازه نیازی به گرافیک نخواهد بود

mazoolagh
دوشنبه 20 بهمن 1399, 17:58 عصر
در ادامه بحث paging، الان که چند نمونه اولیه آورده شده و کلیت موضوع هم نشون داده شده، موقعیت مناسبی هست که روش اصولی رو معرفی و دنبال کنیم.
منظور از اصولی این هست که:
1- محاسبات paging رو از روی دوش خودمون برداریم و به دوش موتور دیتابیس یا provider بگذاریم (قطعا در اینها از هرنظر کدهای بهتری استفاده شده)
2- پیاده سازی اون راحت و ساده باشه و با عوض شدن دیتا نیاز به تغییراتی بیشتر از فیلدهای مورد نمایش نداشته باشیم (مثل هر فرم معمولی)

همونجور که در پست شماره 69 اشاره کرده بودم، بعضی providerها تمهیدات لازم رو برای اینکار آماده و کار ما رو راحت کردن.
در ado سه property برای رکوردست تعریف شده: PageSize , AbsolutePage , PageCount که در صورت تمایل میتونین مستندات اون رو بخونین.

mazoolagh
دوشنبه 20 بهمن 1399, 18:03 عصر
کوئری زیر رو درنظر بگیرین:
SELECT S.FullName AS Student, CT.CourseTitle AS Course, C.Year, C.Term, I.FullName AS Instructor, G.Final
FROM (((Courses AS C
INNER JOIN CourseTitles AS CT ON C.CourseTitleID = CT.CourseTitleID)
INNER JOIN Gradings AS G ON C.CourseID = G.CourseID)
INNER JOIN Instructors AS I ON C.InstructorID = I.InstructorID)
INNER JOIN Students AS S ON G.StudentID = S.StudentID


مشابه نمونه قبلی، اول یک فرم unbound با توجه به فیلدها میسازیم و کنترلهای paging رو هم اضافه میکنیم.

mazoolagh
دوشنبه 20 بهمن 1399, 18:08 عصر
Option Compare DatabaseOption Explicit
Private Page_ As Integer
Private PagesCount As Integer
Private RecordsCount As Long
Dim rs As ADODB.Recordset
Dim rsx As ADODB.Recordset

Private Sub Form_Close()
rs.Close
Set rs = Nothing
Set rsx = Nothing
End Sub

Private Sub Form_Open(Cancel As Integer)
Set rsx = New ADODB.Recordset
With rsx
.CursorLocation = adUseClient
.CursorType = adOpenKeyset
.LockType = adLockOptimistic
.Fields.Append "Row", adInteger, , adFldKeyColumn + adFldRowID
.Fields.Append "Student", adVarWChar, 100, adFldMayBeNull
.Fields.Append "Course", adVarWChar, 100, adFldMayBeNull
.Fields.Append "Instructor", adVarWChar, 100, adFldMayBeNull
.Fields.Append "Year", adInteger, , adFldMayBeNull
.Fields.Append "Term", adInteger, , adFldMayBeNull
.Fields.Append "Final", adInteger, , adFldMayBeNull
.ActiveConnection = Nothing
.Open
End With

PageSize = 15
Set rs = New ADODB.Recordset
rs.CursorLocation = adUseClient
rs.PageSize = PageSize
rs.Open "select * from Results", CurrentProject.Connection, adOpenDynamic, adLockOptimistic
RecordsCount = rs.RecordCount
PageSize_AfterUpdate
End Sub

Private Sub GO_FIRST_Click()
Page_ = 1
Bind
End Sub

Private Sub GO_PREVIOUS_Click()
Page_ = Page_ - 1
Bind
End Sub

Private Sub GO_NEXT_Click()
Page_ = Page_ + 1
Bind
End Sub

Private Sub GO_LAST_Click()
Page_ = PagesCount
Bind
End Sub

Private Sub Bind()
Set Me.Recordset = Nothing
Do While Not rsx.EOF
rsx.Delete
rsx.MoveFirst
Loop
rs.AbsolutePage = Page_
Dim i As Integer
For i = 1 To rs.PageSize
If rs.EOF Then Exit For
rsx.AddNew
rsx("Row") = rs.AbsolutePosition
rsx("Student") = rs("Student")
rsx("Course") = rs("Course")
rsx("Year") = rs("Year")
rsx("Term") = rs("Term")
rsx("Instructor") = rs("Instructor")
rsx("Final") = rs("Final")
rsx.Update
rs.MoveNext
Next
Set Me.Recordset = rsx
Me.GO_FIRST.Enabled = Page_ > 1
Me.GO_PREVIOUS.Enabled = Page_ > 1
Me.GO_NEXT.Enabled = Page_ < PagesCount
Me.GO_LAST.Enabled = Page_ < PagesCount
Me.PageNumber = Page_
End Sub

Private Sub PageNumber_AfterUpdate()
If Me.PageNumber > PagesCount Then Me.PageNumber = PagesCount
If Me.PageNumber < 1 Then Me.PageNumber = 1
Page_ = Me.PageNumber
Bind
End Sub

Private Sub PageSize_AfterUpdate()
rs.PageSize = PageSize
PagesCount = rs.PageCount
Me.PageNumber.RowSource = ""
Dim i As Integer
For i = 1 To PagesCount
Me.PageNumber.AddItem (i)
Next i
Me.Indicator.Caption = "of " & PagesCount
GO_FIRST_Click
End Sub

Private Sub PageSize_NotInList(NewData As String, Response As Integer)
Response = acDataErrContinue
Me.PageSize = 15
End Sub

Private Sub PageNumber_NotInList(NewData As String, Response As Integer)
Response = acDataErrContinue
Me.PageNumber = 1
End Sub

mazoolagh
دوشنبه 20 بهمن 1399, 18:15 عصر
اگر دقت کنین برای نمایش شماره ردیف یک فیلد Row به فیلدهای کوئری اضافه کردیم که برخلاف dao ، اینکار در ado خیلی راحت و شدنی هست.

153008

همچنین سرعت خوبی حتی در تعداد رکورد زیاد داریم.

mazoolagh
دوشنبه 20 بهمن 1399, 18:25 عصر
اگر در برنامه نمونه پیوست دقت کنین در واقع پاسخ اولیه مبحث Unbound Master/Detail Form رو هم پیدا میکنین!

دوستانی که مایل باشن میتونن عملیات insert/delete/update رو به فرم اضافه و در صورت تمایل با دیگران هم به اشتراک بگذارن.

mazoolagh
دوشنبه 20 بهمن 1399, 18:38 عصر
سلام
سخت ترین فرمولی که من تا حالا نتونستم انجامش بدم و هربار به بن بست خوردم فرمول کاتینگ ورق برای برش طول و عرض های مورد نیاز بر اساس متریال ورق استاندارد موجود که کمترین پرت را داشته باشد - فقط یک شرکت هندی موفق شده این فرمول رو درست اجرا کنه
البته با توجه به نیاز بعد گرافیکی به اینکار ، در صورت کشف فرمول و ابعاد و اندازه نیازی به گرافیک نخواهد بود

سلام و روز خوش
البته برنامه آماده cutting optimizer زیاد هست که mdfکار ها و برشکارها (فلز، پارچه، ...) از اون استفاده میکنن و حتی راه پارچه یا چوب رو هم میشه مشخص کرد.
در هر صورت اکسس ابزار مناسب این کار نیست، ولی شاید با visio بتونین یک کارهایی انجام بدین چون مستقیما ابجکت های گرافیکی سروکار دارهو
همچنین میتونین از addon های آماده autocad هم استفاده کنین یا خودتون بنویسن.

eb_1345
پنج شنبه 07 مهر 1401, 14:47 عصر
..........

eb_1345
سه شنبه 12 مهر 1401, 19:35 عصر
..........
سلام جناب استاد mazoolagh (https://barnamenevis.org/member.php?9893-mazoolagh) عزیز!
هفته قبل تغییراتی بر روی نمونه ارزشمند جنابعالی در پست 81 همین صفحه ایجاد کردم . لطفاً بررسی بفرمائین ایرادی داره یا نه !
بالاخره آخرین فعالیت بنده در سایت برنامه نویس و در این تالار برمیگرده به 20 ماه پیش و بعد از این مدت احساس می کنم بخاطر عدم تمرین نسبت به گذشته تسلط کافی در زمینه کد نویسی نداشته باشم

یا علی
https://barnamenevis.org/images/statusicon/user-offline.png

mazoolagh
چهارشنبه 13 مهر 1401, 11:29 صبح
سلام mazoolagh (https://barnamenevis.org/member.php?9893-mazoolagh) عزیز!
هفته قبل تغییراتی بر روی نمونه ارزشمند جنابعالی در پست 81 همین صفحه ایجاد کردم . لطفاً بررسی بفرمائین ایرادی داره یا نه !


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

چَشم، حتما - فقط چند روز فرصت بدین.

atf1379
چهارشنبه 13 مهر 1401, 20:17 عصر
سلام جناب استاد mazoolagh (https://barnamenevis.org/member.php?9893-mazoolagh) عزیز!
هفته قبل تغییراتی بر روی نمونه ارزشمند جنابعالی در پست 81 همین صفحه ایجاد کردم . لطفاً بررسی بفرمائین ایرادی داره یا نه !
بالاخره آخرین فعالیت بنده در سایت برنامه نویس و در این تالار برمیگرده به 20 ماه پیش و بعد از این مدت احساس می کنم بخاطر عدم تمرین نسبت به گذشته تسلط کافی در زمینه کد نویسی نداشته باشم

یا علی
https://barnamenevis.org/images/statusicon/user-offline.png


چقدر عالی!:تشویق:

atf1379
یک شنبه 17 مهر 1401, 10:08 صبح
سلام
بنظرم تاپیک ایجاد نویگیشن باتن جهت تغییر صفحات گزارش (https://barnamenevis.org/showthread.php?571603-%D8%A7%DB%8C%D8%AC%D8%A7%D8%AF-%D9%86%D9%88%DB%8C%DA%AF%DB%8C%D8%B4%D9%86-%D8%A8%D8%A7%D8%AA%D9%86-%D8%AC%D9%87%D8%AA-%D8%AA%D8%BA%DB%8C%DB%8C%D8%B1-%D8%B5%D9%81%D8%AD%D8%A7%D8%AA-%DA%AF%D8%B2%D8%A7%D8%B1%D8%B4) باید در اینجا ایجاد میشد . چون سوالی که در این تاپیک پرسیده شده واقعا از جنس دیگریست ومن مشابه این سوال و راهکاری که برای اون ارائه گردیده جائی ندیده ام

mazoolagh
یک شنبه 17 مهر 1401, 13:22 عصر
سلام
بنظرم تاپیک ایجاد نویگیشن باتن جهت تغییر صفحات گزارش (https://barnamenevis.org/showthread.php?571603-%D8%A7%DB%8C%D8%AC%D8%A7%D8%AF-%D9%86%D9%88%DB%8C%DA%AF%DB%8C%D8%B4%D9%86-%D8%A8%D8%A7%D8%AA%D9%86-%D8%AC%D9%87%D8%AA-%D8%AA%D8%BA%DB%8C%DB%8C%D8%B1-%D8%B5%D9%81%D8%AD%D8%A7%D8%AA-%DA%AF%D8%B2%D8%A7%D8%B1%D8%B4) باید در اینجا ایجاد میشد . چون سوالی که در این تاپیک پرسیده شده واقعا از جنس دیگریست ومن مشابه این سوال و راهکاری که برای اون ارائه گردیده جائی ندیده ام

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

mazoolagh
یک شنبه 17 مهر 1401, 13:31 عصر
هفته قبل تغییراتی بر روی نمونه پست 81 همین صفحه ایجاد کردم . لطفاً بررسی بفرمائین ایرادی داره یا نه !


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

eb_1345
یک شنبه 17 مهر 1401, 17:47 عصر
قطعا خودتو همه چک ها رو انجام دادین، منهم موردی ندیدم و مثل بنز کار میکنه.
فقط کاش همراه برنامه کدهاتون رو هم پیوست و یک توضیح هم اضافه کنین که کدوم بخشهای کد اولیه اصلاح و احتمالا بهینه شدن.
خوبی پیوست کردن کدها این هست که اگر کسی با یک بخش کد هم جستجو کنه میتونه بهش برسه.
سپاسگزارم استاد!
ممنون ازحسن نظرتون
در خصوص پیوست کردن کدها کاملاً درست میفرمائین ، متأسفانه این مورد جزء ایرادات همیشگی بنده بوده که در مورد کدهای استفاده شده توضیح نمیدم
علی ایحال اگه دوستان نسبت به هر بخش از کدها ابهامی داشتن اعلام بفرماین تا توضیح لازم ارائه بشه

mazoolagh
دوشنبه 29 آبان 1402, 14:11 عصر
هدف ساخت کوئری هست که 2 پارامتر از نوع long برای تعیین محدوده اعداد دریافت میکنه و خروجی اون همه اعداد در این محدوده است:
PARAMETERS Range_Start Long, Range_End Long;
SELECT ??? AS [Number]
FROM ???
WHERE ??? BETWEEN Range_Start AND Range_End;



محدوده اعداد بین 1 تا 99999 است.
اجازه استفاده از کد VBA نداریم!
اجازه ساخت جدول حتی بصورت موقت نداریم!


155048

155049

155050

atf1379
دوشنبه 29 آبان 1402, 22:06 عصر
هدف ساخت کوئری هست که 2 پارامتر از نوع long برای تعیین محدوده اعداد دریافت میکنه و خروجی اون همه اعداد در این محدوده است:
PARAMETERS Range_Start Long, Range_End Long;
SELECT ??? AS [Number]
FROM ???
WHERE ??? BETWEEN Range_Start AND Range_End;



محدوده اعداد بین 1 تا 99999 است.
اجازه استفاده از کد VBA نداریم!
اجازه ساخت جدول حتی بصورت موقت نداریم!




سلام استاد
یعنی برای ایجاد این کوئری جدول خاصی هم وجود نداره ؟
آیا انجام ساخت چنین کوئری ای بدون وجود جدول امکان پذیره ؟
البته با کد میشه یک جدول ایجاد کرد ولی اشاره کرده این که نه اجازه استفاده از کد VBA وجود داره نه اجازه ساخت جدول حتی بصورت موقت

mazoolagh
سه شنبه 30 آبان 1402, 18:52 عصر
سلام
یعنی برای ایجاد این کوئری جدول خاصی هم وجود نداره ؟
آیا انجام ساخت چنین کوئری ای بدون وجود جدول امکان پذیره ؟
البته با کد میشه یک جدول ایجاد کرد ولی اشاره کرده این که نه اجازه استفاده از کد VBA وجود داره نه اجازه ساخت جدول حتی بصورت موقت

سلام و روز خوش



شما از یک دیتابیس خالی Blank Database شروع میکنین،



میتونین هرچند کوئری که لازم دارین قبلش آماده کنین (اگر نیاز هست - شاید نباشه!)،


ساختار کوئری خواسته شده همین هست که در پست قبلی آمده، کافی هست پیدا کنین به جای ??? ها چی باید باشه،




ولی اجازه ساخت چیزی جز کوئری ندارین (جدول - شامل لینک شده هم میشه، فرم، گزارش، ماکرو، ماجول).

===========
با این وجود، جدولی رو که فکر میکنین نیاز دارین بگذارین تا در موردش بحث کنیم!

mazoolagh
جمعه 03 آذر 1402, 11:00 صبح
تا پاسخ پرسش قبلی رو پیدا میکنین روی این یکی هم فکر کنین:

دیتابیس پیوست یک لیست از تقسیمات کشوری هست که به شکل پدر-فرزند ساخته شده (سلسله مراتبی یا hierarchical)
و دارای 103682 رکورد در 5 سطح استان/شهرستان/بخش/شهر/روستا(آبادی) هست:

155058

هدف ساختن یک فرم جستجو هست که با گرفتن نام یک "جا" (Location) ،
مسیر همه جاهایی که شامل اون هستن رو به دو شکل مسیر IDها (Path) و مسیر Loacationها ($Path) نشون بده:

155059

دریافت دیتابیس (1.2 مگابایت) (https://drive.google.com/file/d/1CD84NE_GOBMUSqgjLTtnkkVvicOWoAKd/view?usp=sharing)

روش حل این مسئله در MS SQL (https://barnamenevis.org/showthread.php?576160-%D9%BE%DB%8C%D8%AF%D8%A7-%DA%A9%D8%B1%D8%AF%D9%86-%D9%88%D8%A7%D9%84%D8%AF-%D9%87%D8%A7%DB%8C-%DB%8C%DA%A9-%D9%81%D8%B1%D8%B2%D9%86%D8%AF&p=2461681&viewfull=1#post2461681)

eb_1345
شنبه 04 آذر 1402, 16:42 عصر
سلام و درود فراوان خدمت استادmazoolagh (https://barnamenevis.org/member.php?9893-mazoolagh)عزیز !
داده های دیتابیس شما رو در قالب treeview پیاده کردم
بخاطر زیاد بودن رکوردها تا حدودی با لود شدن اطلاعات بخصوص در هنگام باز شدن فرم مشکل دارم که سعی می کنم راهکاری براش پیدا کنم
در ضمن بلحاظ عدم مشارکت دوستان با اجازه شما فقط به ضمیمه نمودن دو تصویر از نمونه کار انجام شده اکتفا می کنم

eb_1345
شنبه 04 آذر 1402, 16:44 عصر
شرح مسیرها رو از طریق node.FullPath ایجاد کردم وسپس با استفاده از تابع Split اقدام به جداکردن سطوح مسیر که با علامت اسلش به همدیگر متصل شده اند نموده ا م و در مرحله آخر هم فراخوانی کد مربوط به شرح هر سطح از جدول و چسپاندن اونها به ترتیب سطوح شرح مسیر


TxtTitel.Value = node.FullPath
Pathsplit1 = Split(TxtTitel.Value, "\")(0) & "\"
TxtTitel.Value = Replace(TxtTitel.Value, Pathsplit1, "")
TxtTitel.Value = Replace(TxtTitel.Value, "\", "/")

CountWord1 = Len(TxtTitel.Value) - Len(Replace(TxtTitel.Value, "/", ""))
If CountWord1 = 0 Then
Strcode1 = DLookup("id", "TblLocations", "Location='" & Split(TxtTitel.Value, "/")(0) & "'")
TxtOstanCode = Strcode1
ElseIf CountWord1 = 1 Then
Strcode1 = DLookup("id", "TblLocations", "Location='" & Split(TxtTitel.Value, "/")(0) & "'")
Strcode2 = DLookup("id", "TblLocations", "Location='" & Split(TxtTitel.Value, "/")(1) & "'")
TxtOstanCode = Strcode2 & "/" & Strcode1
ElseIf CountWord1 = 2 Then
Strcode1 = DLookup("id", "TblLocations", "Location='" & Split(TxtTitel.Value, "/")(0) & "'")
Strcode2 = DLookup("id", "TblLocations", "Location='" & Split(TxtTitel.Value, "/")(1) & "'")
Strcode3 = DLookup("id", "TblLocations", "Location='" & Split(TxtTitel.Value, "/")(2) & "'")
TxtOstanCode = Strcode3 & "/" & Strcode2 & "/" & Strcode1
ElseIf CountWord1 = 3 Then
Strcode1 = DLookup("id", "TblLocations", "Location='" & Split(TxtTitel.Value, "/")(0) & "'")
Strcode2 = DLookup("id", "TblLocations", "Location='" & Split(TxtTitel.Value, "/")(1) & "'")
Strcode3 = DLookup("id", "TblLocations", "Location='" & Split(TxtTitel.Value, "/")(2) & "'")
Strcode4 = DLookup("id", "TblLocations", "Location='" & Split(TxtTitel.Value, "/")(3) & "'")
TxtOstanCode = Strcode4 & "/" & Strcode3 & "/" & Strcode2 & "/" & Strcode1
ElseIf CountWord1 = 4 Then
Strcode1 = DLookup("id", "TblLocations", "Location='" & Split(TxtTitel.Value, "/")(0) & "'")
Strcode2 = DLookup("id", "TblLocations", "Location='" & Split(TxtTitel.Value, "/")(1) & "'")
Strcode3 = DLookup("id", "TblLocations", "Location='" & Split(TxtTitel.Value, "/")(2) & "'")
Strcode4 = DLookup("id", "TblLocations", "Location='" & Split(TxtTitel.Value, "/")(3) & "'")
Strcode5 = DLookup("id", "TblLocations", "Location='" & Split(TxtTitel.Value, "/")(4) & "'")
TxtOstanCode = Strcode5 & "/" & Strcode4 & "/" & Strcode3 & "/" & Strcode2 & "/" & Strcode1
End If

اگه بشه با ایجاد یک حلقه و استفاده از تعداد علامت های اسلش بکار رفته شده در شرح مسیر چند خط کد بالا رو به دوسه خط تبدیل کنم خیلی خوب میشه
مثلاً بصورت زیر:
For i = 0 To CountWord1
TxtOstanCode = DLookup("id", "TblLocations", "Location='" & Split(TxtTitel.Value, "/")(i) & "'")
Next
ولی ظاهراً یک شرطی باید در این حلقه اعمال کنم که نتیجه درست از آب دربیاد
فعلاً موضوعی دیگه ذهنم رو درگیر خودش کرده و نمیتونم درست و حسابی رو این موضوع تمرکز کنم

atf1379
شنبه 04 آذر 1402, 19:46 عصر
سلام
کاش استاد mazoolagh (https://barnamenevis.org/member.php?9893-mazoolagh) کدهائی که در قسمت MS SQL (https://barnamenevis.org/showthread.php?576160-%D9%BE%DB%8C%D8%AF%D8%A7-%DA%A9%D8%B1%D8%AF%D9%86-%D9%88%D8%A7%D9%84%D8%AF-%D9%87%D8%A7%DB%8C-%DB%8C%DA%A9-%D9%81%D8%B1%D8%B2%D9%86%D8%AF&p=2461681&viewfull=1#post2461681) بکار برده ان در اینجا تبدیل به کد sql که قابل اجرا در محیط اکسس باشه میکردن !
منظورم کدهای زیره:



USE [Iran]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[GetParents]
@ID int
AS
BEGIN
SET NOCOUNT ON;

WITH All_Parents(ID) AS
(
SELECT ParentID FROM Locations WHERE ID=@ID
UNION ALL
SELECT L.ParentID
FROM All_Parents
INNER JOIN Locations AS L
ON All_Parents.ID=L.ID
)

SELECT L.ID, L.ParentID, L.[Location]
FROM All_Parents
INNER JOIN Locations AS L
ON All_Parents.ID = L.ID
END
GO






USE [Iran]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[GetParentsPath]
@ID int
AS
BEGIN
SET NOCOUNT ON;

WITH All_Parents(ID) AS
(
SELECT ParentID FROM Locations WHERE ID=@ID
UNION ALL
SELECT L.ParentID
FROM All_Parents
INNER JOIN Locations AS L
ON All_Parents.ID=L.ID
)

SELECT
STRING_AGG (RESULTS.ID , '/') AS [PATH],
STRING_AGG (RESULTS.[Location] , '/') AS [PATH$]
FROM
(SELECT L.ID AS ID, L.ParentID, L.[Location]
FROM All_Parents
INNER JOIN Locations AS L
ON All_Parents.ID = L.ID) AS RESULTS

END
GO

mazoolagh
یک شنبه 05 آذر 1402, 13:52 عصر
سلام و درود فراوان خدمت mazoolagh (https://barnamenevis.org/member.php?9893-mazoolagh)عزیز !
داده های دیتابیس شما رو در قالب treeview پیاده کردم
بخاطر زیاد بودن رکوردها تا حدودی با لود شدن اطلاعات بخصوص در هنگام باز شدن فرم مشکل دارم که سعی می کنم راهکاری براش پیدا کنم
در ضمن بلحاظ عدم مشارکت دوستان با اجازه شما فقط به ضمیمه نمودن دو تصویر از نمونه کار انجام شده اکتفا می کنم


شرح مسیرها رو از طریق node.FullPath ایجاد کردم وسپس با استفاده از تابع Split اقدام به ایجاد کد مسیرها نمودم

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

این که همه 103 هزار و اندی رکورد را گذاشتم 2 دلیل داشت:
1- دیتابیس کامل باشه شاید در جای دیگه ای نیاز کسی رو برآورده کنه.
2- بشه پرفورمنس و زمان پاسخ برنامه رو محک زد.

دیتابیس کامل (شامل Path و $Path های ساخته شده) رو خدمت شما و دیگر دوستان به پیوست تقدیم میکنم.
توجه داشته باشید که حجم فایل دانلودی 2.1 مگابایت هست که پس از بازکردن یک دیتابیس 86 مگابایتی خواهید داشت.

لطفا با این هم تست کنین .

دریافت دیتابیس کامل همراه با مسیرها (https://drive.google.com/file/d/1WAKadpxPIQWqyB0FvH-MXIz0cZL6xgjZ/view?usp=sharing)

mazoolagh
یک شنبه 05 آذر 1402, 14:09 عصر
سلام
کاش mazoolagh (https://barnamenevis.org/member.php?9893-mazoolagh) کدهائی که در قسمت MS SQL (https://barnamenevis.org/showthread.php?576160-%D9%BE%DB%8C%D8%AF%D8%A7-%DA%A9%D8%B1%D8%AF%D9%86-%D9%88%D8%A7%D9%84%D8%AF-%D9%87%D8%A7%DB%8C-%DB%8C%DA%A9-%D9%81%D8%B1%D8%B2%D9%86%D8%AF&p=2461681&viewfull=1#post2461681) بکار برده ان در اینجا تبدیل به کد sql که قابل اجرا در محیط اکسس باشه میکردن !

سلام و روز خوش
من هنوز برای حل این مساله در اکسس فکر نکردم!

فعلا جناب بهرامی 2 هیچ از همه ما جلوتر هستن.

mazoolagh
یک شنبه 05 آذر 1402, 19:32 عصر
فرض کنید که یک جدول (یا کوئری)از همه اعداد مجاز long integer به اسم All_Numbers داشته باشیم:
minimum long integer = -(2^31) = -2,147,483,648
maximum long integer = 2^31 -1 = +2,147,483,647
البته منطقی نیست چون این جدول (یا کوئری) 4,294,967,296 رکورد خواهد داشت، ولی برای حل مسئله این فرض مشکلی ایجاد نمیکنه.


در اینصورت خیلی ساده کافی بود کوئری رو به شکل زیر میساختیم:
PARAMETERS Range_Start Long, Range_End Long;
SELECT N AS [Number]
FROM All_Numbers
WHERE N BETWEEN Range_Start AND Range_End;
که N اسم فیلد هست.

خب البته این کار شدنی نیست (منطقی و عملی) ،
ولی از ریاضی دبستان به یاد داریم که در سیستم شمارش دهدهی هر عددی را میتونیم با ارقام 0 تا 9 بسازیم،
به این صورت که دسته های یکی، ده تایی، سد تایی، هزار تایی، .... بسازیم (همون یکان، دهگان، سدگان، هزارگان، ...)

حالا کافی هست به جای یک جدول (کوئری) با بیش از 4 میلیارد رکورد،
برای هر دسته یک جدول (کوئری) فقط با 10 رکورد داشته باشیم. به عنوان مثال:
D با 10 رکورد از 0 تا 9
D10 با 10 رکورد از 0 تا 90
D100 با 10 رکورد از 0 تا 900
D1K با 10 رکورد از 0 تا 9000
D10K با 10 رکورد از 0 تا 90000

پس کوئری ما به شکل زیر میشه:
PARAMETERS Range_Start Long, Range_End Long;
SELECT (D.N + D10.N + D100.N + D1K.N + D10K.N) AS [Number]
FROM D,
D10,
D100,
D1K,
D10K
WHERE (D.N + D10.N + D100.N + D1K.N + D10K.N)
Between Range_Start And Range_End;

اما هنوز میتونیم کارها رو ساده تر کنیم،
به این صورت که فقط یک جدول(کوئری) D داشته باشیم ولی کوئری رو به شکل زیر بنویسیم:
PARAMETERS Range_Start Long, Range_End Long;
SELECT (D.N + 10*D10.N + 100*D100.N + 1000*D1K.N + 10000*D10K.N) AS [Number]
FROM D,
D AS D10,
D AS D100,
D AS D1K,
D AS D10K
WHERE (D.N + 10*D10.N + 100*D100.N + 1000*D1K.N + 10000*D10K.N)
BETWEEN Range_Start AND Range_End;

mazoolagh
یک شنبه 05 آذر 1402, 19:58 عصر
خب، الان دیگه فقط میمونه چجوری بدون این که جدولی بسازیم این کوئری D رو طراحی کنیم.

راستش ساختن این کوئری بدون داشتن یک جدول واقعی در دیتابیس شدنی نیست!
ولی خوشبختانه هر دیتابیس خودش یک سری جدول سیستمی داره که همین برای ما کافی هست.

2 راه داریم:

1- بدون توجه به دیتا جدول سیستمی، کوئری D رو بسازیم (فقط از اسمش استفاده کنیم):
SELECT TOP 1 (0) AS N FROM MSysAccessStorage
UNION
SELECT TOP 1 (1) AS N FROM MSysAccessStorage
UNION
SELECT TOP 1 (2) AS N FROM MSysAccessStorage
UNION
SELECT TOP 1 (3) AS N FROM MSysAccessStorage
UNION
SELECT TOP 1 (4) AS N FROM MSysAccessStorage
UNION
SELECT TOP 1 (5) AS N FROM MSysAccessStorage
UNION
SELECT TOP 1 (6) AS N FROM MSysAccessStorage
UNION
SELECT TOP 1 (7) AS N FROM MSysAccessStorage
UNION
SELECT TOP 1 (8) AS N FROM MSysAccessStorage
UNION
SELECT TOP 1 (9) AS N FROM MSysAccessStorage;

که در اینجا MSysAccessStorage یکی از جدول های سیستمی هست و میتونه هر کدوم از اون ها باشه،
چون ما به دیتا اون نیاز نداریم. بلکه اکسس هست که در UNION ما رو وادار به استفاده از FROM میکنه.
از TOP 1 هم برای بهتر کردن پرفورمنس استفاده کردیم که هر SELECT فقط یک رکورد برگردونه،
وگرنه هر SELECT به تعداد رکوردهای اون جدول مقدار 0 (تا 9) برمیگردونه که البته خود UNION تکراری ها رو کنار میگذاره و اینجا ما کارش رو راحت کردیم.


2- از دیتا خود جدول استفاده کنیم.
چند جدول سیستمی داریم که من بررسی کردم دیتا اون ها رو.
همین جدول MSysAccessStorage برای کار ما مناسب هست (خوشبختانه)

SELECT *FROM MSysAccessStorage

155074

همینجور که میبینین فیلد ID کاملا مناسب کار ما هست،
پس خیلی ساده کوئری D به شکل زیر درمیاد:
SELECT (ID-1) AS N
FROM MSysAccessStorage
WHERE ID BETWEEN 1 AND 10
ORDER BY ID

پرسش برای بحث و تبادل نظر و ارائه شیوه های دیگه باز هست.

eb_1345
یک شنبه 05 آذر 1402, 21:46 عصر
به سهم خودم بابت همه چیزهایی که از شما یاد گرفتم سپاسگزارم.

با سلام مجدد حضور استاد عزیز و دوست داشتنی!
سپاسگزارم !
یقیناً عنوان کردن این مطلب که چیزهائی از بنده یاد گرفته این بخاطر تواضع و فروتنی همیشگی شماست چرا که این مختصر علم و دانشی که بنده در زمینه کد نویسی آنهم صرفاً در محیط اکسس دارم از بزرگانی همچون جنابعالی یاد گرفته ام
در هر حال سپاسگزارم از لطف و محبتی که نسبت به این حقیر دارین
و اما در خصوص نکته ای که در خصوص پیدا کردن راهکاری برای کم کردن کدهای پست 96 اشاره کردم باید عرض کنم در کدهای فوق متوجه یک ایراد اساسی شدم و اون اینکه همونطور که در پست فوق اشاره کردم بدست آوردن مسیرکامل 5 سطح استان/شهرستان/بخش/شهر/روستا(آبادی) با استفاده از node.FullPath کار راحتیست و نیاز به هیچ کد نویسی ای نداره ولی بدست آوردن کدهای سطوح فوق نیازمند کدنویسی میباشد . در کدهای پست 96 بنده کد هر سطح رو با توجه به عنوان اون سطح در جدول بدست میاوردم و در شرح کامل 5 سطح ممکنه نام بعضی از سطوح کاملاً مشابه هم باشد . بعنوان مثال چهار سطح مسیر استان آذربایجان شرقی بصورت زیر میباشد :

آذربایجان شرقی/آذرشهر/حومه/آذرشهر
همانطور که ملاحظه میفرمائید عناوین سطح دوم و سوم کاملاً مشابه هم هستن و اگر بخواهیم از طریقDLookup کد عناوین فوق رو بدست بیاوریم برای هر دو عنوان یک کد مشابه خواهیم داشت
به همین لحاظ به دنبال راهکار دیگری گشتم . تا اینکه متوجه شدم که با توجه به سلسله مراتبی پدر و فرزندی در treeview آبجکت node در جایگاه فرزند داری یک node پدر میباشد و اون node پدر هم بسته به سطحی که در آن قرار دارد ممکنه خود فرزند باشه که خود دارای یک نود پدر باشد و به همین ترتیب . در ابزار تری ویو node پدر رو بصورت node.Parent شناسائی می کنیم و همین طور node پدر پدر (یا پدر بزرگ)رو بصورت و node.Parent.Parent
این خاصیت جالب ابزار تری ویو بنده رو بفکر واداشت که وقتی بر روی تری ویو کلیک می کنیم و node (گره) خاصی رو انتخاب می کنیم میتوانیم ضمن بدست آوردن کلید اون node کلید node های قبلی اون سطح رو هم استخراج کنیم
برای اینکار بنده اومدم 5 متغییر از نوع رشته با عناوین StrNode1 و StrNode2 و ..... تعریف کردم و هر کدوم از این متغییرها رو مساوی کلید گره جاری و گره های قبلی خود کردم
بصورت زیر:





StrNode1 = Right(Node.Key, Len(Node.Key) - 1)
StrNode2 = Right(Node.Parent.Key, Len(Node.Parent.Key) - 1)
StrNode3 = Right(Node.Parent.Parent.Key, Len(Node.Parent.Parent.Key) - 1)
StrNode4 = Right(Node.Parent.Parent.Parent.Key, Len(Node.Parent.Parent.Parent.Key) - 1)
StrNode5 = Right(Node.Parent.Parent.Parent.Parent.Key, Len(Node.Parent.Parent.Parent.Parent.Key) - 1)



در کلید هر گره یک حرف لاتین در سمت راست قرار دارد که بنده با استفاده از تابع Right این حرف رو حذف کردم
باید متذکر بشم که امکان اینکه این کلیدها رو فقط در یک متغییر قرار داد وجود داشت ولی بنده برای فهم دقیقتر کلید هر گرهی رو در یک متغییر جداگانه قرار داده ام و در نهایت گره ها بصورت سلسله مراتبی در کنار هم و با قرار دادن علامت"/" به هم چسبانده و در تکست باکس PathCode = StrNode1 & "/" & StrNode2 & "/" & StrNode3 & "/" & StrNode4 & "/" & StrNode5
که برای مسیر کدها ایجاد شده قرار دادم
بصورت زیز :


PathCode = StrNode1 & "/" & StrNode2 & "/" & StrNode3 & "/" & StrNode4 & "/" & StrNode5

از آنجائیکه اگر در هنگام کلیک کردن برروی treeview بطور مثال بر روی سطح 3 کلیک کنیم در اینجا متغییر های StrNode4 و StrNode5 خالی می مانند که در نهایت با استفاده از تابع Replace میتوان علامت "/" مربوط به جاهای خالی رو حذف کرد

کدهائی که در رویداد کلیک treeview برای بدست آورن مسیر سطوح بکار رفته بشرح زیر است:



Private Sub treeview1_NodeClick(ByVal Node As Object)
On Error Resume Next
Dim i As Integer
PathCode = ""
PathText = ""
StrNode1 = ""
StrNode2 = ""
StrNode3 = ""
StrNode4 = ""
StrNode5 = ""
PathText.value = Node.FullPath
Pathsplit = Split(PathText.value, "\")(0) & "\"
PathText.value = Replace(PathText.value, Pathsplit, "")
PathText.value = Replace(PathText.value, "\", "/")
StrNode1 = Right(Node.Key, Len(Node.Key) - 1)
StrNode2 = Right(Node.Parent.Key, Len(Node.Parent.Key) - 1)
StrNode3 = Right(Node.Parent.Parent.Key, Len(Node.Parent.Parent.Key) - 1)
StrNode4 = Right(Node.Parent.Parent.Parent.Key, Len(Node.Parent.Parent.Parent.Key) - 1)
StrNode5 = Right(Node.Parent.Parent.Parent.Parent.Key, Len(Node.Parent.Parent.Parent.Parent.Key) - 1)
PathCode = StrNode1 & "/" & StrNode2 & "/" & StrNode3 & "/" & StrNode4 & "/" & StrNode5
PathCode = Replace(PathCode, "//", "")
PathCode = Replace(PathCode, "/0/", "")
PathCode = Replace(PathCode, "/0", "")
End Sub






البته همونطور که جناب mazoolagh (https://barnamenevis.org/member.php?9893-mazoolagh) در اولین پست این تاپیک اشاره کردند هدف اصلی طرح مسائل و حل اون در این تاپیک شاید الزاما حل یک مساله کاربردی نباشه بلکه یک تمرین ذهنی و به چالش کشیدن توان کدنویسی و همچنین گریزی از امور تکراری و کسالت بار باشه وگرنه در حالت نمایش اطلاعات این دیتابیس بر روی فرم شاید اصلاً نیازی به نمایش کد مسیرها نباشه که بخاطر اون بخواهیم خودمون رو به زحمت بیندازیم و چند خط کد بنویسیم

atf1379
دوشنبه 06 آذر 1402, 01:15 صبح
پرسش برای بحث و تبادل نظر و ارائه شیوه های دیگه باز هست.
با سلام
سوالی که ممکنه برای خیلی از دوستان مطرح باشه انست که با توجه به ایجاد راحت و بی دردسر کوئری از انواع جداول چه نیازی به ساخت چنین کوئری ای داریم که ایجاد اون آنچنان هم راحت نیست .
در کل استفاده از این نوع کوئری در کجا و چه حالتی مفیده ؟
با تشکر

mazoolagh
سه شنبه 07 آذر 1402, 19:59 عصر
البته همونطور که جناب mazoolagh (https://barnamenevis.org/member.php?9893-mazoolagh) در اولین پست این تاپیک اشاره کردند هدف اصلی طرح مسائل و حل اون در این تاپیک شاید الزاما حل یک مساله کاربردی نباشه بلکه یک تمرین ذهنی و به چالش کشیدن توان کدنویسی و همچنین گریزی از امور تکراری و کسالت بار باشه وگرنه در حالت نمایش اطلاعات این دیتابیس بر روی فرم شاید اصلاً نیازی به نمایش کد مسیرها نباشه که بخاطر اون بخواهیم خودمون رو به زحمت بیندازیم و چند خط کد بنویسیم

در مورد مسیریابی معمولا برعکس این مسئله است که اینجا مطرح شده؛
یعنی مسیر رو داریم و دنبال گره(ها) میگردیم.
و این همون کاری هست که XML/HTML Parser ها انجام میدن.
با اینحساب همین پرسش رو با JavaScript هم باید بتونیم انجام بدیم.

mazoolagh
سه شنبه 07 آذر 1402, 21:03 عصر
برای حل این مسئله ابتدا در نظر داشتم که نتایج رو در یک ListBox نمایش بدم (unbound - value list)

ولی چون اندازه دیتا ممکن هست از حداکثر طول رشته RowSource بیشتر باشه،
یک جدول به اسم Results برای نگهداری نتایج جستجو ساختم:

155082

برای جستجو Location از روش استاندارد SELECT ... LIKE
و برای ساختن مسیرها هم از حلقه معمولی استفاده کردم.
کلا نکته خاصی برای توضیح بیشتر نیست.

Option Compare Database
Option Explicit


Private Type Path
IDs As String
Locations As String
End Type

Private rsL As Recordset

Const SQL = "SELECT ID, ParentID, Location FROM Locations WHERE Location LIKE '*@LOC*'"

Private Function GetPath(ID As Long) As Path
Dim P As Path
Const BackSlash = ""
Const EmptyPath = "-"
Dim Delimeter As String
Do While True
rsL.Seek "=", ID
ID = rsL("ParentID")
If ID = -1 Then
Exit Do
Else
P.Locations = P.Locations + Delimeter + rsL("Location")
P.IDs = P.IDs + Delimeter + CStr(ID)
Delimeter = BackSlash
End If
Loop
If P.Locations = "" Then
P.IDs = EmptyPath
P.Locations = EmptyPath
End If
GetPath = P
End Function

Private Sub BTN_Search_Click()
If Nz(TB_Search, "") = "" Then Exit Sub
If Len(Trim(TB_Search)) < 2 Then Exit Sub
Debug.Print Now
Dim rs As Recordset
Set rs = CurrentDb.OpenRecordset(Replace(SQL, "@LOC", TB_Search), dbOpenSnapshot, dbReadOnly)
If rs.EOF Then GoTo Exit_Sub
DoCmd.Hourglass True
DoCmd.RunSQL "DELETE FROM RESULTS"
Dim N, Row As Long
rs.MoveLast
rs.MoveFirst
N = rs.RecordCount
SysCmd acSysCmdInitMeter, N & " Records found ...", N
Dim rsR As Recordset
Set rsR = CurrentDb.OpenRecordset("Results")
Do While Not rs.EOF
Row = rs.AbsolutePosition + 1
Dim P As Path
P = GetPath(rs("ID"))
rsR.AddNew
rsR("Row") = Row
rsR("Location") = rs("Location")
rsR("ID") = rs("ID")
rsR("Path$") = P.Locations
rsR("Path") = P.IDs
rsR.Update
SysCmd acSysCmdUpdateMeter, Row
rs.MoveNext
DoEvents
Loop
rsR.Close: Set rsR = Nothing
SysCmd acSysCmdRemoveMeter
DoCmd.Hourglass False
Debug.Print Now
DoCmd.OpenForm "Results", , , , , acDialog, "(" & TB_Search & ") " & N & " رکورد"
Exit_Sub:
rs.Close: Set rs = Nothing
End Sub

Private Sub Form_Close()
rsL.Close
Set rsL = Nothing
End Sub

Private Sub Form_Load()
Set rsL = CurrentDb.OpenRecordset("Locations", dbOpenTable, dbReadOnly)
rsL.Index = "PrimaryKey"
End Sub

155083

mazoolagh
سه شنبه 07 آذر 1402, 21:13 عصر
با سلام
سوالی که ممکنه برای خیلی از دوستان مطرح باشه انست که با توجه به ایجاد راحت و بی دردسر کوئری از انواع جداول چه نیازی به ساخت چنین کوئری ای داریم که ایجاد اون آنچنان هم راحت نیست .
در کل استفاده از این نوع کوئری در کجا و چه حالتی مفیده ؟
با تشکر

سلام و روز خوش
بخش بزرگی از پاسخ رو جناب بهرامی پایین پست شماره 102 آوردن و دیگه تکرار نمیکنم.
ولی این مسئله (که اتفاقا خیلی هم هم راحت هست - کلا 2 کوئری 4-5 خطی بیشتر نیست) راهی بجز این نداره.

شما حتی اگر اجازه ساخت جدول رو هم میداشتین نهایتا برای D مفید بود،
باز باید از این کوئری استفاده میکردین.

اما در مورد کاربردش؛
این رو به عهده زمان میگذارم - دیر یا زود برخورد میکنین؛
شاید دقیقا خود این نباشه ولی روش همین خواهد بود.

mazoolagh
دوشنبه 27 آذر 1402, 10:22 صبح
عنوان به اندازه گافی گویا هست:
میخواهیم دیتا جدول/کوئری رو صفحه بندی کنیم و هر صفحه رو پس از مدت زمان معینی نمایش بدیم.

1- ابتدا یک فرم باید باز بشه که در اون امکان انتخاب موارد زیر باشه:
2- لیست جدول ها و کوئری ها (چه جدول های local و چه linked)
3- انتخاب شماره رکوردها در هر صفحه
4- انتخاب زمان نمایش هر صفحه
5- انتخاب نوع انیمیشن یا افکت هنگام عوض شدن صفحه (مثلا fade-in/fade-out یا zoom-in/zoom-out و ...)
6- انتخاب مدت زمان هر افکت
7- انتخاب نمایش ساعت (بر اساس گاهشمار ایرانی) در پایین صفحه
8- بهتر هست دست کم یک تم theme برای نمایش نتایج وجود داشته باشه.
9- یک progress باید برای نمایش وضعیت وجود داشته باشه : هم متنی به صورت صفحه ... از .. و هم گرافیک
10 - پس از آن با زدن یک باتن محاسبات انجام و نتایج در یک فایل html ساخته شده و فرمی که دارای کنترل web browser هست اون رو نمایش میده.

----------
بهتر هست یادآوری کنم که این پرسش جنبه عملی چندانی نداره!
چون دیتا نمایش داده استاتیک هست،
و این که از 30 سال پیش با asp معمولی هم میشد این رو ساخت (البته بدون افکت و ...)

ولی چالشی هست که چگونه با کنترل web browser که بر مبنای ie7 هست و در حالت عادی این امکانات رو نداره جواب بگیریم.

و این که برای نوشتن این برنامه لازم هست به HTML/CSS/JavaScript مسلط باشین (آشنایی کافی نیست - ولی لازم هست)

atf1379
سه شنبه 28 آذر 1402, 20:52 عصر
عنوان به اندازه گافی گویا هست:
میخواهیم دیتا جدول/کوئری رو صفحه بندی کنیم و هر صفحه رو پس از مدت زمان معینی نمایش بدیم.

1- ابتدا یک فرم باید باز بشه که در اون امکان انتخاب موارد زیر باشه:
2- لیست جدول ها و کوئری ها (چه جدول های local و چه linked)
3- انتخاب شماره رکوردها در هر صفحه
4- انتخاب زمان نمایش هر صفحه
5- انتخاب نوع انیمیشن یا افکت هنگام عوض شدن صفحه (مثلا fade-in/fade-out یا zoom-in/zoom-out و ...)
6- انتخاب مدت زمان هر افکت
7- انتخاب نمایش ساعت (بر اساس گاهشمار ایرانی) در پایین صفحه
8- بهتر هست دست کم یک تم theme برای نمایش نتایج وجود داشته باشه.
9- یک progress باید برای نمایش وضعیت وجود داشته باشه : هم متنی به صورت صفحه ... از .. و هم گرافیک
10 - پس از آن با زدن یک باتن محاسبات انجام و نتایج در یک فایل html ساخته شده و فرمی که دارای کنترل web browser هست اون رو نمایش میده.

----------
بهتر هست یادآوری کنم که این پرسش جنبه عملی چندانی نداره!
چون دیتا نمایش داده استاتیک هست،
و این که از 30 سال پیش با asp معمولی هم میشد این رو ساخت (البته بدون افکت و ...)

ولی چالشی هست که چگونه با کنترل web browser که بر مبنای ie7 هست و در حالت عادی این امکانات رو نداره جواب بگیریم.

و این که برای نوشتن این برنامه لازم هست به HTML/CSS/JavaScript مسلط باشین (آشنایی کافی نیست - ولی لازم هست)

با این توضیحاتی که استاد اشاره کرده ان قطعاً نمونه جالب و جذابی خواهد بود:تشویق::تشویق::تشویق:

mazoolagh
شنبه 02 دی 1402, 21:06 عصر
کاملا مشخص هست که هیچکس به این مسئله اصلا فکر نکرده!

همون مورد 2 ( لیست جدول ها و کوئری ها (چه جدول های local و چه linked) ) به تنهایی یک پرسش نه چندان ساده است.

atf1379
یک شنبه 03 دی 1402, 00:55 صبح
........................................

eb_1345
یک شنبه 03 دی 1402, 02:06 صبح
کاملا مشخص هست که هیچکس به این مسئله اصلا فکر نکرده!

همون مورد 2 ( لیست جدول ها و کوئری ها (چه جدول های local و چه linked) ) به تنهایی یک پرسش نه چندان ساده است.

سلام
در ارتباط با مورد 2 فکر کنم نمونه ضمیمه بدرد بخوره

eb_1345
یک شنبه 03 دی 1402, 07:11 صبح
با کدهای زیر نام جداول (غیر از جداول سیستمی ) به لیست باکس اضافه میشه :


Dim tbl As TableDef
For Each tbl In CurrentDb.TableDefs
If Left(tbl.Name, 4) <> "Msys" Then
List.RowSource = List.RowSource & ";" & tbl.Name
End If
Next
List.RowSource = Mid(List.RowSource, 2)

و با کدهای زیر نام کوئری ها به لیست باکس اضافه میشه :


Dim qdf As QueryDef
For Each qdf In CurrentDb.QueryDefs
If Left(qdf.Name, 1) <> "~" Then
List.RowSource = List.RowSource & ";" & qdf.Name
End If
Next
List.RowSource = Mid(List.RowSource, 2)

mazoolagh
دوشنبه 04 دی 1402, 11:14 صبح
سلام
در ارتباط با مورد 2 فکر کنم نمونه ضمیمه بدرد بخوره

سلام دوباره و روز شما خوش
بسیار عالی و دقیق!

من جدولی که شما زحمتش رو کشیدین همینجا پیوست میکنم و
یک توضیح مختصر هم میدم در موردش:
اطلاعات آبجکت های اکسس در جدول MsysObjects (همراه با چند جدول سیستمی دیگه) نگه داری میشه ولی اصلی همین MsysObjects ه.
مایکروسافت به دلایل کاملا مشخص، اطلاعات اینها رو مستند نکرده و این جدول tblSysObjectTypesکه جناب بهرامی زحمتش رو کشیدن یکی از بهترین هاست،
چون تمام آبجکت ها رو در بر میگیره و کار رو بسیار راحت میکنه و دیگه نیازی نیست خودمون در MsysObjects بگردیم.
بخصوص که انواع کوئری رو هم در بر میگیره و خیلی جاها مهم هست که بدونیم کوئری ما رکورد برمیگردونه یا نه (یکیش همین پرسش پست 107)

پیشنهاد میکنم هر کس این تاپیک رو میخونه پیوست پست 111 رو دانلود کنه و یک جایی نگه داره چون دیر یا زود بهش نیاز پیدا میکنه.



Object
Type
SubType
Flags
Hidden
System


Form
-32768


0
0
0


Macro
-32766


0
0
0


Report
-32764


0
0
0


Module
-32761


0
0
0


Users
-32758




0
-1


Document
-32757




0
-1


Data Access Page
-32756




0
0


Table
1
Local
8
-1
0


Table
1
System


0
-1


Table
1
Local
0
0
0


Database
2




0
-1


Container
3




0
-1


Table
4
Linked SQL
537919496
-1
0


Table
4
Linked SQL
537919488
0
0


Query
5
Append
72
-1
0


Query
5
Append
64
0
0


Query
5
Crosstab
24
-1
0


Query
5
Crosstab
16
0
0


Query
5
Data Definition
96
0
0


Query
5
Data Definition
104
-1
0


Query
5
Delete
40
-1
0


Query
5
Delete
32
0
0


Query
5
Make Table
80
0
0


Query
5
Make Table
88
-1
0


Query
5
Pass Through
112
0
0


Query
5
Pass Through
120
-1
0


Query
5
Select
8
-1
0


Query
5
Select
0
0
0


Form/Report Module
5


3
0
0


Query
5
Union
128
0
0


Query
5
Union
136
-1
0


Query
5
Update
56
-1
0


Query
5
Update
48
0
0


Table
6
Linked Access
538968064
0
0


Table
6
Linked Text / CSV
10485760
0
0


Table
6
Linked Excel
11534336
0
0


Table
6
Linked Excel
11534344
-1
0


Table
6
Linked Text / CSV
10485768
-1
0


Table
6
Linked Access
538968072
-1
0


Table
6
Linked Access
2097152
0
0


SubDatasheet
8




0
-1


Table
1
System
-2147483648
0
-1


Table
1
System
-2147287040
-1
-1


Relationships
8


0
0
0

mazoolagh
دوشنبه 04 دی 1402, 12:31 عصر
خب، با توجه به پست بالا برای حل پرسش پست 107 باید آبجکت هایی از جدول MSysObjects رو لیست کنیم که:

Name اون ها با MSys شروع نمیشه (سیستمی)
Name اون ها با ~ شروع نمیشه (موقت temp)
Type=1 با flag>=0 (جدول لوکال)
Type=4 (جدول لینک شده ODBC)
Type=6 (جدول لینک شده)
Type=5 با flag=0,8,16,24,128,136 (کوئری select, crosstab, union)


توضیح این که آبجکت های مخفی در flag شون 8 تا با معمولی تفاوت دارن.

پس کوئری ما چیزی شبیه به زیر میشه:
SELECT [NAME], [TYPE], [FLAGS]
FROM MSYSOBJECTS
WHERE [NAME] NOT LIKE "MSYS*" AND
[NAME] NOT LIKE "~*" AND
( ([TYPE] IN (1,4,6) AND [FLAGS]>=0) OR
[TYPE]=5 AND FLAGS IN(0,8,16,24,128,136) )
ORDER BY [TYPE], [NAME];

نتیجه تست کوئری :

155175

155176

mazoolagh
دوشنبه 04 دی 1402, 12:38 عصر
با کدهای زیر نام جداول (غیر از جداول سیستمی ) به لیست باکس اضافه میشه :


Dim tbl As TableDef
For Each tbl In CurrentDb.TableDefs
If Left(tbl.Name, 4) <> "Msys" Then
List.RowSource = List.RowSource & ";" & tbl.Name
End If
Next
List.RowSource = Mid(List.RowSource, 2)

و با کدهای زیر نام کوئری ها به لیست باکس اضافه میشه :


Dim qdf As QueryDef
For Each qdf In CurrentDb.QueryDefs
If Left(qdf.Name, 1) <> "~" Then
List.RowSource = List.RowSource & ";" & qdf.Name
End If
Next
List.RowSource = Mid(List.RowSource, 2)



خیلی خوب شد که این رو هم مطرح کردین.

استفاده از tabledefs/querydefs نسبت به چرخیدن در MSysObjects راه تمیزتری هست و Hacky هم نیست!

در برنامه نهایی هر دو روش هست برای مقایسه و یادگیری.

mazoolagh
چهارشنبه 13 دی 1402, 21:12 عصر
با توجه به آموزش لیست همه جدول‌ها / کوئری‌ها و فیلدهای آنها List of All Tables/Queries and their Fields (https://barnamenevis.org/showthread.php?577500) ،
گام اول که پر کردن لیست باکس های data source و fields هست به سادگی انجام میشه:

155207

Option Compare Database
Option Explicit

Private DataSources As New Collection


Private Sub Form_Close()
Set DataSources = Nothing
End Sub


Private Sub Form_Load()
Dim CountTables As Integer
Dim CountLinkedTables As Integer
Dim CountQueries As Integer
Dim i As Integer
Dim x As New Collection

Set x = GetTables
For i = 1 To x.Count
DataSources.Add x.Item(i)
Me.LB_Sources.AddItem x.Item(i).SourceName & ";" & x.Item(i).SourceType
If x.Item(i).SourceType = "Table" Then
CountTables = CountTables + 1
Else
CountLinkedTables = CountLinkedTables + 1
End If
Next

Set x = GetQueries
For i = 1 To x.Count
With x.Item(i)
If .Fields.Count > 0 Then
DataSources.Add x.Item(i)
Me.LB_Sources.AddItem .SourceName & ";" & .SourceType
CountQueries = CountQueries + 1
End If
End With
Next

With Me.LB_Sources
If .ListCount > 1 Then
.Value = .ItemData(0)
LB_Sources_AfterUpdate
End If
End With


Me.LBL_Sources_Summary.Caption = _
"Tables=" & CountTables & _
" ; Linked Tables=" & CountLinkedTables & _
" ; Queries=" & CountQueries
End Sub


Private Sub LB_Sources_AfterUpdate()
Dim index As Integer
index = Me.LB_Sources.ListIndex
Dim i As Integer
With DataSources.Item(index + 1)
Me.LB_Fields.RowSource = .FieldsString
Me.LBL_Connect.Caption = .connect
Me.LBL_Fields_Summary.Caption = "Fields Count=" & .Fields.Count & " , Records Count=" & DCount("*", .SourceName)
End With
End Sub

mazoolagh
شنبه 16 دی 1402, 20:30 عصر
در گام بعدی امکانات انتخاب فیلدها از بین فیلدهای data source و ترتیب ستون بندی (نه ترتیب سورت!) رو اضافه میکنیم:



Private Sub BTN_None_Click()
Me.LB_SelectedFields.RowSource = ""
End Sub


Private Sub BTN_All_Click()
Me.LB_SelectedFields.RowSource = ""
Dim index As Integer
index = Me.LB_Sources.ListIndex
Dim i As Integer
Dim FieldsCount As Integer
With DataSources.Item(index + 1).Fields
FieldsCount = .count
For i = 1 To FieldsCount
If Not (.Item(i).FieldType Like "*Binary*" Or .Item(i).FieldType = "Attachment") Then
Me.LB_SelectedFields.AddItem .Item(i).FieldName
End If
Next
End With
End Sub


Private Sub BTN_Add_Click()
Dim SelectedField As String
Dim FieldType As String
Dim i As Integer

With Me.LB_Fields
If .ListIndex < 0 Then
.Value = .ItemData(0)
End If
SelectedField = .Value
FieldType = .Column(1)

If (FieldType Like "*Binary*" Or FieldType = "Attachment") Then
MsgBox "Attachment and Binary fields not allowed!", vbExclamation, "Invalid field type"
Exit Sub
End If

For i = 0 To .ListCount - 1
If Me.LB_SelectedFields.ItemData(i) = SelectedField Then Exit Sub
Next
Me.LB_SelectedFields.AddItem SelectedField
Me.LB_SelectedFields.Value = SelectedField
If .ListIndex < .ListCount - 1 Then
.Value = .ItemData(.ListIndex + 1)
End If
End With
End Sub


Private Sub BTN_Remove_Click()
Dim index As Integer
With Me.LB_SelectedFields
If .ListIndex < 0 Then
.Value = .ItemData(0)
End If
index = .ListIndex
.RemoveItem (index)
If index > .ListCount - 1 Then
index = .ListCount - 1
End If
.Value = .ItemData(index)
End With
End Sub


Private Sub BTN_Up_Click()
Dim index As Integer
With Me.LB_SelectedFields
index = .ListIndex
If index <= 0 Or .ListCount = 1 Then Exit Sub
Dim vlu As String
vlu = .Value
.RemoveItem (index)
.AddItem vlu, index - 1
.Value = vlu
End With
End Sub


Private Sub BTN_Down_Click()
Dim index As Integer
With Me.LB_SelectedFields
index = .ListIndex
If index = .ListCount - 1 Then Exit Sub
Dim vlu As String
vlu = .Value
.RemoveItem (index)
.AddItem vlu, index + 1
.Value = vlu
End With
End Sub

155211

mazoolagh
یک شنبه 17 دی 1402, 22:03 عصر
در مرحله آخر بخش مربوط به انتخاب پارامترها رو اضافه میکنیم:

نوع انیمیشن
زمان انیمیشن
تعداد رکورد در هر صفحه (در کد اگر از 100 بیشتر بشه اون رو به 100 محدود کردیم که حجم فایل html و البته زمان ساخت طولانی نباشه)
زمان نمایش هر صفحه
تم
نحوه نمایش مقادیر Boolean
اضافه کردن شماره ردیف


155217

نوع انیمیشن:
155218

تم:
155219

mazoolagh
یک شنبه 17 دی 1402, 22:10 عصر
نحوه نمایش فیلدهای Boolean:

155221

checkbox
155222

toggle button
155223

radio button
155224

on/off
155225

mazoolagh
یک شنبه 17 دی 1402, 22:14 عصر
yes/no
155226

true/false
155227

row number
155228

date/time
155229

mazoolagh
یک شنبه 17 دی 1402, 22:17 عصر
کد کامل فرم Main

Option Compare Database
Option Explicit

Private DataSources As New Collection
Private RecordsCount As Long


Private Sub Form_Close()
Set DataSources = Nothing
End Sub


Private Sub Form_Load()
Dim CountTables As Integer
Dim CountLinkedTables As Integer
Dim CountQueries As Integer
Dim i As Integer
Dim x As New Collection

Set x = GetTables
For i = 1 To x.count
DataSources.Add x.Item(i)
Me.LB_Sources.AddItem x.Item(i).SourceName & ";" & x.Item(i).SourceType
If x.Item(i).SourceType = "Table" Then
CountTables = CountTables + 1
Else
CountLinkedTables = CountLinkedTables + 1
End If
Next

Set x = GetQueries
For i = 1 To x.count
With x.Item(i)
If .Fields.count > 0 Then
DataSources.Add x.Item(i)
Me.LB_Sources.AddItem .SourceName & ";" & .SourceType
CountQueries = CountQueries + 1
End If
End With
Next

With Me.LB_Sources
If .ListCount > 1 Then
.Value = .ItemData(0)
LB_Sources_AfterUpdate
End If
End With


Me.LBL_Sources_Summary.Caption = _
"Tables=" & CountTables & _
" ; Linked Tables=" & CountLinkedTables & _
" ; Queries=" & CountQueries
End Sub


Private Sub LB_Sources_AfterUpdate()
Dim index As Integer
index = Me.LB_Sources.ListIndex
Me.LB_SelectedFields.RowSource = ""
With DataSources.Item(index + 1)
RecordsCount = DCount("*", .SourceName)
Me.LB_Fields.RowSource = .FieldsString
Me.LBL_Connect.Caption = .connect
Me.LBL_Fields_Summary.Caption = "Fields Count=" & .Fields.count & " , Records Count=" & RecordsCount
End With
Validate
End Sub


Private Sub BTN_None_Click()
Me.LB_SelectedFields.RowSource = ""
Validate
End Sub


Private Sub BTN_All_Click()
Me.LB_SelectedFields.RowSource = ""
Dim index As Integer
index = Me.LB_Sources.ListIndex
Dim i As Integer
Dim FieldsCount As Integer
With DataSources.Item(index + 1).Fields
FieldsCount = .count
For i = 1 To FieldsCount
If Not (.Item(i).FieldType Like "*Binary*" Or .Item(i).FieldType = "Attachment") Then
Me.LB_SelectedFields.AddItem .Item(i).FieldName
End If
Next
End With
Validate
End Sub


Private Sub BTN_Add_Click()
Dim SelectedField As String
Dim FieldType As String
Dim i As Integer

With Me.LB_Fields
If .ListIndex < 0 Then
.Value = .ItemData(0)
End If
SelectedField = .Value
FieldType = .Column(1)

If (FieldType Like "*Binary*" Or FieldType = "Attachment") Then
MsgBox "Attachment and Binary fields not allowed!", vbExclamation, "Invalid field type"
Exit Sub
End If

For i = 0 To .ListCount - 1
If Me.LB_SelectedFields.ItemData(i) = SelectedField Then Exit Sub
Next
Me.LB_SelectedFields.AddItem SelectedField
Me.LB_SelectedFields.Value = SelectedField
If .ListIndex < .ListCount - 1 Then
.Value = .ItemData(.ListIndex + 1)
End If
End With
Validate
End Sub


Private Sub BTN_Remove_Click()
Dim index As Integer
With Me.LB_SelectedFields
If .ListIndex < 0 Then
.Value = .ItemData(0)
End If
index = .ListIndex
.RemoveItem (index)
If index > .ListCount - 1 Then
index = .ListCount - 1
End If
.Value = .ItemData(index)
End With
Validate
End Sub


Private Sub BTN_Up_Click()
Dim index As Integer
With Me.LB_SelectedFields
index = .ListIndex
If index <= 0 Or .ListCount = 1 Then Exit Sub
Dim vlu As String
vlu = .Value
.RemoveItem (index)
.AddItem vlu, index - 1
.Value = vlu
End With
End Sub


Private Sub BTN_Down_Click()
Dim index As Integer
With Me.LB_SelectedFields
index = .ListIndex
If index = .ListCount - 1 Then Exit Sub
Dim vlu As String
vlu = .Value
.RemoveItem (index)
.AddItem vlu, index + 1
.Value = vlu
End With
End Sub


Private Sub Validate()
Me.BTN_Go.Enabled = (RecordsCount > 0 And Me.LB_SelectedFields.ListCount > 0)
End Sub


Private Sub BTN_Go_Click()
Dim fso As New FileSystemObject
Dim fl As TextStream
Dim rs As Recordset
Dim n As Long
Dim i As Integer
Dim j As Integer
Dim k As Integer
Dim m As Integer
Dim Path As String
Dim PageSize As Integer
Dim PagesCount As Integer
Dim AnimationType As String
Dim SQL As String

AnimationType = Replace(Me.CB_AnimationType, " ", "")

Path = CurrentProject.Path + "\html"
PageSize = Me.CB_PageSize

Dim x As Variant
x = Split(Me.LB_SelectedFields.RowSource, ";")
For i = LBound(x) To UBound(x)
x(i) = "[" & x(i) & "]"
Next
SQL = "SELECT " & Join(x, ",") & " FROM [" & Me.LB_Sources & "]"
Set rs = CurrentDb.OpenRecordset(SQL, dbOpenDynaset, dbSeeChanges + dbReadOnly)
rs.MoveLast
rs.MoveFirst
n = rs.RecordCount
PagesCount = n / PageSize

If PagesCount > 100 Then
PagesCount = 100
' limit the page to a maximum of 100 to keep the html file at a reasonable size
ElseIf PagesCount * PageSize < n Then
PagesCount = PagesCount + 1
End If

If Not fso.FolderExists(Path) Then
fso.CreateFolder (Path)
End If
Set fl = fso.CreateTextFile( _
FileName:=Path + FileName, _
overwrite:=True, _
unicode:=True)

fl.write HTML_Start
m = 0
For i = 1 To PagesCount
If AnimationType = "None" Then
If i = 1 Then
fl.WriteLine "<div id='page_1' class='page visible'>"
Else
fl.WriteLine "<div id='page_" + Trim(i) + "' class='page hidden'>"
End If
Else
If i = 1 Then
fl.WriteLine "<div id='page_1' class='page visible " & AnimationType & "_in'>"
Else
fl.WriteLine "<div id='page_" + Trim(i) + "' class='page hidden " & AnimationType & "_out'>"
End If
End If

Select Case Me.CB_Theme
Case "Mixed"
Select Case i Mod 4
Case 0
fl.WriteLine "<table class='orange'>"
Case 1
fl.WriteLine "<table class='green'>"
Case 2
fl.WriteLine "<table class='blue'>"
Case 3
fl.WriteLine "<table class='black'>"
End Select
Case Else
fl.WriteLine "<table class='" & LCase(Me.CB_Theme) & "'>"
End Select

fl.write "<thead><tr>"
If Me.CHK_RowNumber Then
fl.write "<th>#</th>"
End If
For j = 1 To rs.Fields.count
fl.write "<th>" + rs.Fields(j - 1).Name + "</th>"
Next
fl.write "</tr>"
fl.WriteLine "</thead>"
fl.WriteLine "<tbody>"
For j = 1 To PageSize
If rs.EOF Then Exit For
If Me.CHK_RowNumber Then
m = m + 1
fl.write "<tr><td>" + Trim(m) + "</td>"
End If
For k = 1 To rs.Fields.count
If rs.Fields(k - 1).Type = dbBoolean Then
Select Case Me.CB_Booleans
Case "CheckBox"
If rs.Fields(k - 1).Value Then
fl.write "<td><input type='checkbox' checked></td>"
Else
fl.write "<td><input type='checkbox'></td>"
End If
Case "Toggle"
If rs.Fields(k - 1).Value Then
fl.write "<td><label class='switch'><input type='checkbox' checked><span class='slider'></span></label></td>"
Else
fl.write "<td><label class='switch'><input type='checkbox'><span class='slider'></span></label></td>"
End If
Case "Radio"
If rs.Fields(k - 1).Value Then
fl.write "<td><input type='radio' checked></td>"
Else
fl.write "<td><input type='radio'></td>"
End If
Case "Yes/No"
If rs.Fields(k - 1).Value Then
fl.write "<td>Yes</td>"
Else
fl.write "<td>No</td>"
End If
Case "On/Off"
If rs.Fields(k - 1).Value Then
fl.write "<td>On</td>"
Else
fl.write "<td>Off</td>"
End If
Case Else ' default True/False
fl.write "<td>" & rs.Fields(k - 1) & "</td>"
End Select
Else
fl.write "<td>" & rs.Fields(k - 1).Value & "</td>"
End If
Next
fl.WriteLine "</tr>"
rs.MoveNext
Next
fl.WriteLine "</tbody>"
fl.WriteLine "</table>"
fl.WriteLine "</div>"
DoEvents
Next
rs.Close
Set rs = Nothing
Dim xEnd As String
xEnd = Replace(HTML_End, "@PAGE_LIFE", 1000 * Me.CB_PageLife)
If AnimationType = "None" Then
xEnd = Replace(xEnd, "@ANIMATION_DURATION", "0s")
xEnd = Replace(xEnd, "@ANIMATION_TYPE_in", "")
xEnd = Replace(xEnd, "@ANIMATION_TYPE_out", "")
Else
xEnd = Replace(xEnd, "@ANIMATION_DURATION", Me.CB_AnimationDuration & "s")
xEnd = Replace(xEnd, "@ANIMATION_TYPE", AnimationType)
End If

fl.write xEnd
fl.Close
Set fso = Nothing

DoCmd.OpenForm "Browser"
End Sub

mazoolagh
یک شنبه 17 دی 1402, 22:19 عصر
کد کامل فرم Browser

Option Compare Database
Option Explicit


Private Sub Form_Load()
DoCmd.Maximize
WB.ControlSource = "=""" & CurrentProject.Path & "\html" & FileName & """"
End Sub


Private Sub Form_Resize()
WB.width = Me.InsideWidth
WB.Height = Me.InsideHeight
End Sub

mazoolagh
یک شنبه 17 دی 1402, 22:20 عصر
HTML Module

Option Compare Database
Option Explicit

Public Const FileName = "pager.html"

Public Const Script = _
"<script>" + vbCrLf + _
"const pages = document.querySelectorAll('[id^=page_]');" + vbCrLf + _
"const bar = document.getElementById('bar');" + vbCrLf + _
"const bartext = document.getElementById('bar-text');" + vbCrLf + _
"const clock = document.getElementById('clock');" + vbCrLf + _
"const timeOptions = {year:'numeric',month:'long',day:'numeric',weekday :'long',hour:'2-digit',minute:'2-digit',second:'2-digit'};" + vbCrLf + _
"const n = pages.length;" + vbCrLf + _
"setClock();" + vbCrLf + _
"bar.style.transitionDuration = '@ANIMATION_DURATION';" + vbCrLf + _
"for (i = 0; i < n; i++) { pages[i].style.transitionDuration = '@ANIMATION_DURATION'; };" + vbCrLf + _
"var i = 0;" + vbCrLf + _
"setBar(i);" + vbCrLf + _
"setInterval(setClock, 1000);" + vbCrLf + _
"setInterval(function () {" + vbCrLf + _
"pages[i].className = 'page hidden @ANIMATION_TYPE_out';" + vbCrLf + _
"i = (i == (n - 1)) ? 0 : i + 1;" + vbCrLf + _
"pages[i].className = 'page visible @ANIMATION_TYPE_in';" + vbCrLf + _
"setBar(i);}, @PAGE_LIFE);" + vbCrLf + _
"function setBar(x) {" + vbCrLf + _
"bar.style.width = (100 * (x + 1) / n).toFixed() + '%';" + vbCrLf + _
"bartext.innerText = (x + 1) + ' of ' + n;};" + vbCrLf + _
"function setClock() { clock.innerText = new Date().toLocaleString('fa', timeOptions) };" + vbCrLf + _
"</script>"

Public Const HTML_Start = _
"<!DOCTYPE html>" + vbCrLf + _
"<!-- saved from url=(0016)http://localhost -->" + vbCrLf + _
"<html lang='en'>" + vbCrLf + _
"<head>" + vbCrLf + _
"<title title='Data-Paging with visual effects'></title>" + vbCrLf + _
"<meta http-equiv='X-UA-Compatible' content='IE=edge' />" + vbCrLf + _
"<meta charset='utf-8' />" + vbCrLf + _
"<meta name='viewport' content='width=device-width, initial-scale=1'>" + vbCrLf + _
"<link rel='stylesheet' href='../css/styles.css' type='text/css'>" + vbCrLf + _
"<link rel='stylesheet' href='../css/themes.css' type='text/css'>" + vbCrLf + _
"</head>" + vbCrLf + _
"<body>" + vbCrLf + _
"<div id='progress'>" + vbCrLf + _
"<div id='bar-box'>" + vbCrLf + _
"<span id='bar-text'></span>" + vbCrLf + _
"<div id='bar'></div>" + vbCrLf + _
"</div>" + vbCrLf + _
"</div>" + vbCrLf + _
"<div id='data'>" + vbCrLf

Public Const HTML_End = _
"</div>" + vbCrLf + _
"<div id='clock'></div>" + vbCrLf + _
Script + vbCrLf + _
"</body>" + vbCrLf + _
"</html>"

mazoolagh
یک شنبه 17 دی 1402, 22:24 عصر
themes.css

table.green, table.blue, table.orange, table.black {
font-family: Tahoma;
font-size: small;
text-align: center;
border-collapse: collapse;
width: 100%;
height: 100%;
background-color: ghostwhite;
}


table.green {
border: 2px solid darkgreen;
}


table.blue {
border: 2px solid darkblue;
}


table.orange {
border: 2px solid darkorange;
}


table.black {
border: 2px solid black;
}


table.green thead {
background-color: green;
box-shadow: inset 1px 6px 12px lightgreen, inset -1px -10px 5px darkgreen, 1px 2px 1px black;
}


table.blue thead {
background-color: blue;
box-shadow: inset 1px 6px 12px lightblue, inset -1px -10px 5px darkblue, 1px 2px 1px black;
}


table.orange thead {
background-color: darkorange;
box-shadow: inset 1px 6px 12px orange, inset -1px -10px 5px red, 1px 2px 1px black;
}


table.black thead {
background-color: black;
box-shadow: inset 1px 3px 3px darkgray, inset -1px -3px 3px darkgray, 1px 2px 1px black;
}


table.green thead th, table.blue thead th, table.orange thead th, table.black thead th {
color: white;
text-align: center;
}


table.green td, table.green th {
border: 1px solid darkgreen;
padding: 3px 2px;
}


table.blue td, table.blue th {
border: 1px solid darkblue;
padding: 3px 2px;
}


table.orange td, table.orange th {
border: 1px solid darkorange;
padding: 3px 2px;
}


table.black td, table.black th {
border: 1px solid black;
padding: 3px 2px;
}


table.green td, table.blue td, table.orange td, table.black td {
}


table.green tbody td {
color: darkgreen;
}


table.blue tbody td {
color: darkblue;
}


table.orange tbody td {
color: maroon;
}


table.black tbody td {
color: black;
}


table.green tr:nth-child(even) {
background-color: #CEE0CC;
}


table.blue tr:nth-child(even) {
background: #95BCE0;
}


table.orange tr:nth-child(even) {
background: #F5D08C;
}


table.black tr:nth-child(even) {
background: #D0D0D0;
}

mazoolagh
یک شنبه 17 دی 1402, 22:26 عصر
styles.css

html {
width: 100%;
height: 100%;
overflow: clip;
}


body {
background: linear-gradient(#EEEEEE,#6a6552);
}


#progress {
position: relative;
margin-left: 5%;
margin-right: 5%;
width: 90%;
}


#bar-box {
width: 100%;
padding: 4px;
background: rgba(0, 0, 0, 0.25);
border-radius: 6px;
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.25), 0 1px rgba(255, 255, 255, 0.08);
}


#bar {
height: 20px;
border-radius: 4px;
background-color: #252e43;
background-image: linear-gradient(to right, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.35));
transition: 1s linear;
transition-property: width, background-color;
box-shadow: 0 0 1px 1px rgba(0, 0, 0, 0.25), inset 0 1px rgba(255, 255, 255, 0.1);
}


#bar-text {
position: absolute;
width: 100%;
text-align: center;
font-family: Tahoma;
color: aliceblue;
text-shadow: 2px 2px 4px black;
}


#clock {
position: fixed;
bottom: 1%;
right: 1%;
direction: rtl;
font-family: 'Courier New';
font-size: large;
font-weight: bold;
padding: 4px;
border-radius: 6px;
color: gold;
box-shadow: rgba(0, 0, 0, 0.25) 0px 14px 28px, rgba(0, 0, 0, 0.22) 0px 10px 10px;
}


#data {
position: relative;
margin-top: 1%;
margin-left: 1%;
margin-right: 1%;
width: 98%;
height: 90vh;
overflow: hidden;
}


.page {
transition: ease-in-out all 1s;
position: absolute;
width: 100%;
display: table-row;
box-shadow: rgba(0, 0, 0, 0.7) 0px 5px 15px;
}


.switch {
position: relative;
display: inline-block;
width: 50px;
height: 20px;
}


.switch input {
opacity: 0;
width: 0;
height: 0;
}


.slider {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: red;
border-radius: 20px;
}


.slider:before {
position: absolute;
content: "";
height: 14px;
width: 14px;
left: 3px;
bottom: 3px;
background-color: white;
border-radius: 50%;
}


input:checked + .slider {
background-color: lightgreen;
}


input:checked + .slider:before {
transform: translateX(28px);
}


.visible {
opacity: 1;
}


.hidden {
opacity: 0;
}


.Fade_in {
}


.Fade_out {
}


.SlideRight_in {
right: 0px;
}


.SlideRight_out {
right: 120%;
}


.SlideLeft_in {
left: 0px;
}


.SlideLeft_out {
left: 120%;
}


.SlideUp_in {
margin-top: 0px;
}


.SlideUp_out {
margin-top: 120%;
}


.SlideDown_in {
margin-top: 0px;
}


.SlideDown_out {
margin-top: -120%;
}


.Zoom_in {
transform: scale(1);
}


.Zoom_out {
transform: scale(.1);
}


.RotateX_in {
transform: rotateX(0deg);
}


.RotateX_out {
transform: rotateX(180deg);
}


.RotateY_in {
transform: rotateY(0deg);
}


.RotateY_out {
transform: rotateY(180deg);
}


.Rotate_in {
transform: rotate(0deg);
}


.Rotate_out {
transform: rotate(180deg);
}

mazoolagh
یک شنبه 17 دی 1402, 22:32 عصر
برنامه نهایی:

خروجی برنامه یک فایل به نام pager.html است (در فولدر html) که میتونین مستقل از برنامه در هر مرورگری اون رو باز کنین.
یک خروجی نمونه برای تست در این فولدر هست که با هر بار اجرا برنامه با نتایج جدید جایگزین میشه.

و این که فایلهای فولدر css برای نمایش درست نتیجه ضروری هست!

amirzazadeh
دوشنبه 18 دی 1402, 18:57 عصر
برنامه نهایی:

خروجی برنامه یک فایل به نام pager.html است (در فولدر html) که میتونین مستقل از برنامه در هر مرورگری اون رو باز کنین.
یک خروجی نمونه برای تست در این فولدر هست که با هر بار اجرا برنامه با نتایج جدید جایگزین میشه.

و این که فایلهای فولدر css برای نمایش درست نتیجه ضروری هست!

خیلی عالی و ستودنی، واقعا دستتون درد نکنه. :تشویق::تشویق::تشویق:

mazoolagh
دوشنبه 18 دی 1402, 19:28 عصر
خیلی عالی و ستودنی، واقعا دستتون درد نکنه

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

amirzazadeh
سه شنبه 19 دی 1402, 17:18 عصر
ممنون از لطف شما
لطفا با دقت و کامل همه جوانب رو چک و اگر اشکالی هست گوشزد کنین،
همچنین اگر پیشنهادی در جهت بهتر شدن اون هست خوشحال میشم مطرح یا اگر وقت و حوصله دارین آپگرید کنین.
سلام و عرض ادب
تنها موردی که در حال حاضر به ذهن من میرسه در خصوص پروگرس بار هست که بعد از پایان دور اول و در آغاز لوپ دوم به جای آغاز از صفر به عقب برمیگرده، ولی چون تسلط کافی بر کدهای جاوا اسکریپت ندارم نتونستم کد رو اصلاح کنم.

eb_1345
سه شنبه 19 دی 1402, 22:13 عصر
دست مریزاد استاد!
فقط اگه براتون امکان داره یک نمونه هم که دارای دیتای(جدول) HTML باشه و از تغییر تم و افکت های در نظر گرفته شده در فرم Main استفاده کرد قرار بدهید.
ممنون

mazoolagh
چهارشنبه 20 دی 1402, 19:08 عصر
سلام و عرض ادب
تنها موردی که در حال حاضر به ذهن من میرسه در خصوص پروگرس بار هست که بعد از پایان دور اول و در آغاز لوپ دوم به جای آغاز از صفر به عقب برمیگرده، ولی چون تسلط کافی بر کدهای جاوا اسکریپت ندارم نتونستم کد رو اصلاح کنم.

سلام دوباره
و تشکر بخاطر دقت نظر شما

این پروگروس بار منطق پشتش قدری با کارهای دیگه متفاوت هست:
در جاهای دیگه وقتی یه پروسه رو شروع میکنیم، مقدار بار رو 0 میگذاریم و با هر مرحله مقدار رو تغییر میدیم.
مثلا اگر کلا 5 مرحله باشه مقدار اولیه اش 0 هست، بعد به ترتیب %20 و %40 و ... تا %100 - و دیگه کار تموم و بار هم بسته میشه.

اما اینجا ما قبل از شروع همه کارها رو آماده کردیم و اگر کلا 5 صفحه داریم در شروع کار در صفحه 1 هستیم پس مقدار اولبه بار %20 هست و نه 0.
وقتی در صفحه آخر (5) هستیم و مقدار بار هم %100 هست، مرحله بعدی ما دوباره صفحه 1 یا همون %20 میشه و هیچوقت 0 نداریم.

mazoolagh
چهارشنبه 20 دی 1402, 19:33 عصر
سلام و عرض ادب
تنها موردی که در حال حاضر به ذهن من میرسه در خصوص پروگرس بار هست که بعد از پایان دور اول و در آغاز لوپ دوم به جای آغاز از صفر به عقب برمیگرده، ولی چون تسلط کافی بر کدهای جاوا اسکریپت ندارم نتونستم کد رو اصلاح کنم.

در مورد این که چرا به عقب برمیگرده:
اگر افکت برای پروگروس بار تعریف نکرده باشیم، این حرکت رو به عقب دیده نمیشه و فقط مقدار بار درجا از %100 به مثلا %20 تغییر میکنه.
ولی اینجا یک transition برای بار تعریف شده (برای زیبایی) و این گذر روی سایز بار هم فعال هست برای همین حرکت رو به عقب دیده میشه،
البته معنی دار هم هست چون واقعا دوباره لوپ ریست میشه.

ولی میشه:
1- نمایش پروگروس رو بار رو با یک checkbox در فرم main بعنوان یک Option در اختیار کاربر قرار داد
2- داشتن transition رو برای پروگرس بار با یک چک باکس دیگه مشخص کرد

اگر اینها مفید هست لطفا اطلاع بدین تا پیاده کنم.

mazoolagh
چهارشنبه 20 دی 1402, 19:46 عصر
دست مریزاد !
فقط اگه براتون امکان داره یک نمونه هم که دارای دیتای(جدول) HTML باشه و از تغییر تم و افکت های در نظر گرفته شده در فرم Main استفاده کرد قرار بدهید.
ممنون

سلام دوباره
حتما

من برای تست همه حالت ها یک جدول لینک شده HTML هم داشتم (Customers_HTML)
که در پست شماره 116 هم در تصویر دیده میشه.

اون جدول رو همینجا پیوست میکنم،
چند رکورد اولش اینجوری هست:
<HTML>
<HEAD>
<TITLE>Customers</TITLE>
</HEAD>
<BODY>
<TABLE>
<CAPTION>Customers</CAPTION>
<TR>
<TD>ALFKI</TD>
<TD>Alfreds Futterkiste</TD>
<TD>Maria Anders</TD>
<TD>Sales Representative</TD>
<TD>Obere Str. 57</TD>
<TD>Berlin</TD>
<TD></TD>
<TD>12209</TD>
<TD>Germany</TD>
<TD>030-0074321</TD>
<TD>030-0076545</TD>
</TR>
<TR>
<TD>ANATR</TD>
<TD>Ana Trujillo Emparedados y helados</TD>
<TD>Ana Trujillo</TD>
<TD>Owner</TD>
<TD>Avda. de la Constituci&oacute;n 2222</TD>
<TD>México D.F.</TD>
<TD></TD>
<TD>05021</TD>
<TD>Mexico</TD>
<TD>(5) 555-4729</TD>
<TD>(5) 555-3745</TD>
</TR>
<TR>
<TD>ANTON</TD>
<TD>Antonio Moreno Taquer&iacute;a</TD>
<TD>Antonio Moreno</TD>
<TD>Owner</TD>
<TD>Mataderos 2312</TD>
<TD>México D.F.</TD>
<TD></TD>
<TD>05023</TD>
<TD>AROUT</TD>
<TD>Around the Horn</TD>
<TD>Thomas Hardy</TD>
<TD>Sales Representative</TD>
<TD>120 Hanover Sq.</TD>
<TD>London</TD>
<TD></TD>
<TD>WA1 1DP</TD>
<TD>UK</TD>
<TD>(171) 555-7788</TD>
<TD>(171) 555-6750</TD>
</TR>
</TABLE>
</BODY>
</HTML>

امیدوارم درست گرفته باشم منظور شما رو.

amirzazadeh
چهارشنبه 20 دی 1402, 19:53 عصر
سلام دوباره
و تشکر بخاطر دقت نظر شما

این پروگروس بار منطق پشتش قدری با کارهای دیگه متفاوت هست:
در جاهای دیگه وقتی یه پروسه رو شروع میکنیم، مقدار بار رو 0 میگذاریم و با هر مرحله مقدار رو تغییر میدیم.
مثلا اگر کلا 5 مرحله باشه مقدار اولیه اش 0 هست، بعد به ترتیب %20 و %40 و ... تا %100 - و دیگه کار تموم و بار هم بسته میشه.

اما اینجا ما قبل از شروع همه کارها رو آماده کردیم و اگر کلا 5 صفحه داریم در شروع کار در صفحه 1 هستیم پس مقدار اولبه بار %20 هست و نه 0.
وقتی در صفحه آخر (5) هستیم و مقدار بار هم %100 هست، مرحله بعدی ما دوباره صفحه 1 یا همون %20 میشه و هیچوقت 0 نداریم.

سلام و وقت به خیر، ممنون به خاطر توضیحات کامل وجامع.

eb_1345
چهارشنبه 20 دی 1402, 21:12 عصر
من برای تست همه حالت ها یک جدول لینک شده HTML هم داشتم (Customers_HTML)
که در پست شماره 116 هم در تصویر دیده میشه.

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


بسیار عالی :تشویق::تشویق::تشویق:

moustafa
دوشنبه 02 بهمن 1402, 20:03 عصر
در مورد ساعت:
اگر هدف نمایش وقت هست که خود taskbar ساعت داره و نیازی نیست و کار بیهوده ای هست،
اگر هدف زیبایی فرم و ... هست که باز هم کار عبثی است!
اما اگر هدف چالش کدنویسی و محک زدن توانایی و ... است نتیجه اش همین هست که کار بیهوده ایست و بهتره وقتمون رو روی موارد مهمتر بگذاریم.

به هر حال چند راه وجود داره:
1- ساعت flash - که بهتره از اون اجتناب بشه، ولی ده ها طرح دیجیتال و آنالوگ ازش به راحتی در دسترس هست.
2- استفاده از فونت مناسب (بهترین روش)
3- استفاده از html5 در کنترل web browser
اون ساعت که نمونه اش رو فرستاده بودم در اصل یک فایل html بود که همینجا پیوست میکنم




[/CODE]
با سلام
چطوری کانکت میشه به وب بروزر با این کدها نشد یه نوتیفیکیشن زرد رنگ ریسک میده بعد از اجازه دوباره پی ام میده که canvce ساپورت نمیشه


Path = CurrentProject.Path & "\html\clock.html"
Forms!frmMain!wbroclock.Navigate (Path)

mazoolagh
سه شنبه 03 بهمن 1402, 21:24 عصر
با سلام
چطوری کانکت میشه به وب بروزر با این کدها نشد یه نوتیفیکیشن زرد رنگ ریسک میده بعد از اجازه دوباره پی ام میده که canvce ساپورت نمیشه


Path = CurrentProject.Path & "\html\clock.html"
Forms!frmMain!wbroclock.Navigate (Path)

سلام و روز خوش
1- درست در اول فایل html و قبل از هر چیزی (یعنی قبل از تگ <html>) این کد رو بگذارین:

<!DOCTYPE html>
<!-- saved from url=(0016)http://localhost -->
به طور ساده و خلاصه: کد خط دوم به مرورگر IE میفهمونه که داکیومنت شما trusted هست - دقت کنین که کنترل web browser بر اساس IE7 بنا شده!
در نتیجه نوار زرد رنگ رو دیگه نباید ببینین.

2- در بخش head فایل html اینها رو اضافه کنین:

<meta http-equiv='X-UA-Compatible' content='IE=edge' />
<meta charset='utf-8' />
<meta name='viewport' content='width=device-width, initial-scale=1'>
به طور ساده و خلاصه: کد خط اول برای رندر (render) شدن درست کدهای html/css هست که IE7 پشتیبانی نمیکنه،
به این صورت که وب بروزر رو هدایت میکنه که از انجین (engine) مرورگر مدرن edge استفاده کنه (کرومیوم).

==========

برای نمونه:
میتونین فایل pager.html برنامه پیوست مبحث "صفحه بندی دیتا با افکت و انیمیشن در مرورگر وب Data-paging with transitions/animations in We" رو بررسی کنین،
یا
در پست شماره 123 به تعریف html_start دقت کنین.

moustafa
شنبه 07 بهمن 1402, 16:41 عصر
سلام و روز خوش
1- درست در اول فایل html و قبل از هر چیزی (یعنی قبل از تگ <html>) این کد رو بگذارین:

<!DOCTYPE html>
<!-- saved from url=(0016)http://localhost -->
به طور ساده و خلاصه: کد خط دوم به مرورگر IE میفهمونه که داکیومنت شما trusted هست - دقت کنین که کنترل web browser بر اساس IE7 بنا شده!
در نتیجه نوار زرد رنگ رو دیگه نباید ببینین.

2- در بخش head فایل html اینها رو اضافه کنین:

<meta http-equiv='X-UA-Compatible' content='IE=edge' />
<meta charset='utf-8' />
<meta name='viewport' content='width=device-width, initial-scale=1'>
به طور ساده و خلاصه: کد خط اول برای رندر (render) شدن درست کدهای html/css هست که IE7 پشتیبانی نمیکنه،
به این صورت که وب بروزر رو هدایت میکنه که از انجین (engine) مرورگر مدرن edge استفاده کنه (کرومیوم).

==========

برای نمونه:
میتونین فایل pager.html برنامه پیوست مبحث "صفحه بندی دیتا با افکت و انیمیشن در مرورگر وب Data-paging with transitions/animations in We" رو بررسی کنین،
یا
در پست شماره 123 به تعریف html_start دقت کنین.
دست شما درد نکنه از این همه حوصله ومرام :تشویق::تشویق:واگه بخوایم فیت WebBrowser بشه چطور ؟ میشه ازش ایده گرفت برای گزارش سازی کدهای css و html5و js با کدهای vbaدست کاری بشن

mazoolagh
دوشنبه 09 بهمن 1402, 19:15 عصر
دست شما درد نکنه از این همه حوصله ومرام
ممنون از لطف شما


واگه بخوایم فیت WebBrowser بشه چطور ؟
در html چند راه برای تعیین اندازه ها داریم:

اندازه گیری مطلق مانند پیکسل px ، سانتیمتر cm ، میلیمتر mm ، ...
اندازه گیری نسبی که براساس درسد % بیان میشه و میتونه نسبت به ابعاد المان parent ، المان root ، اندازه فونت، ابعاد viewport و ... باشه.


در همین فایل pager.html اگر دقت کنین یک کانتینر اصلی داریم که id اون data هست و همه المانها درون اون هستن

<div id='data'>

داخل data تعدادی کانتینر دیگه داریم (هر کدام برای یک page از pager) که پشت سر هم چیده شدن
ولی هر بار فقط یکی نشون داده میشه - به جز زمان عوض شدن صفحه و اجرای افکت ها
و داخل هر کدون از این کانتینرها یک جدول table برای نمایش دیتا هر page داریم که تم اون رو با یک کلاس class تعریف کردیم

<div id='page_1' class='page visible Fade_in'>
<table class='black'>
...
</table>
</div>
<div id='page_2' class='page hidden Fade_out'>
<table class='blue'>
...
</table>
</div>

حالا برای دیدن چگونگی تعیین اندازه ها در فایل styles.css دقت کنین:
#data {
position: relative;
margin-top: 1%;
margin-left: 1%;
margin-right: 1%;
width: 98%;
height:90vh;
overflow:hidden;
}
یعنی که پهنای اون 98% برابر پهنای parent element (که میشه body) هست،
و 1% از چپ و راست margin داره (که میشه وسط-چین)،
و 1% از بالا margin داره که چون موقعیتش نسبی تعریف شده (position:relative) یعنی 1% از المان خواهرش (قبلی که میشه کانتینر progress)
و قدش هم 90% قد viewport هست.

یعنی وقتی شما اندازه مرورگر رو تغییر میدین،
پهنای کانتینر data همیشه به صورت خودکار 98% پهنای body
و قدش همیشه 90% قد viewport تنظیم میشه.

و برای هر page :
.page {
transition: ease-in-out all 1s;
position: absolute;
width: 100%;
display: table-row;
box-shadow: rgba(0, 0, 0, 0.7) 0px 5px 15px;
}

پهنای اون همیشه 100% پهنای data هست

و برای هر table
table.green, table.blue, table.orange, table.black {
font-family: Tahoma;
font-size:small;
text-align: center;
border-collapse: collapse;
width: 100%;
height: 100%;
background-color: ghostwhite;
}

همیشه اندازه اش به صورت خودکار تمام فضای در دسترس page رو پر میکنه (100%)


یا در مورد کانتینر clock که همیشه گوشه پایین دست راست قرار میگیره:
#clock {
position: fixed;
bottom: 1%;
right: 1%;
direction: rtl;
font-family: 'Courier New';
font-size: large;
font-weight: bold;
padding: 4px;
border-radius: 6px;
color: gold;
box-shadow: rgba(0, 0, 0, 0.25) 0px 14px 28px, rgba(0, 0, 0, 0.22) 0px 10px 10px;
}

با تعیین right و bottom به اندازه 1% از body انجام میشه،
و چون position اون fixed هست اگر قد مرورگر کافی نباشه میفته روی بخش های دیگه


میشه ازش ایده گرفت برای گزارش سازی کدهای css و html5و js با کدهای vbaدست کاری بشن
دقیقا هدف از این گفتگو هم همین بوده.
شما میتونین هر گزارشی رو که در اکسس ساختنش نشدنی هست رو با این روش بسازین.

در واقع کارهای بیشتری هم میتونین انجام بدین.
اینگونه نیست که فقط برای خروجی (گزارش سازی) استفاده بشه،
میتونین با کنترل مرورگر تعامل دو طرفه داشته باشین و فرم هم بسازین.

این فرم میتونه یک فرم unbound باشه مثل فرم login یا data entry ،
و با صرف وقت و حوصله و کدنویسی حتی میشه از نظر کار مثل فرم Bound باشه.

آموزش ساخت فرم unbound با کنترل وب بروزر و نحوه کار با رخدادهای این کنترل رو در برنامه دارم.

amirzazadeh
دوشنبه 09 بهمن 1402, 21:24 عصر
دقیقا هدف از این گفتگو هم همین بوده.
شما میتونین هر گزارشی رو که در اکسس ساختنش نشدنی هست رو با این روش بسازین.

در واقع کارهای بیشتری هم میتونین انجام بدین.
اینگونه نیست که فقط برای خروجی (گزارش سازی) استفاده بشه،
میتونین با کنترل مرورگر تعامل دو طرفه داشته باشین و فرم هم بسازین.

این فرم میتونه یک فرم unbound باشه مثل فرم login یا data entry ،
و با صرف وقت و حوصله و کدنویسی حتی میشه از نظر کار مثل فرم Bound باشه.

آموزش ساخت فرم unbound با کنترل وب بروزر و نحوه کار با رخدادهای این کنترل رو در برنامه دارم.

با سلام و عرض ادب، بی صبرانه منتظر پست های بعدی این تاپیک هستم.

moustafa
چهارشنبه 11 بهمن 1402, 14:34 عصر
ممنون از لطف شما



دقیقا هدف از این گفتگو هم همین بوده.
شما میتونین هر گزارشی رو که در اکسس ساختنش نشدنی هست رو با این روش بسازین.

در واقع کارهای بیشتری هم میتونین انجام بدین.
اینگونه نیست که فقط برای خروجی (گزارش سازی) استفاده بشه،
میتونین با کنترل مرورگر تعامل دو طرفه داشته باشین و فرم هم بسازین.

این فرم میتونه یک فرم unbound باشه مثل فرم login یا data entry ،
و با صرف وقت و حوصله و کدنویسی حتی میشه از نظر کار مثل فرم Bound باشه.

آموزش ساخت فرم unbound با کنترل وب بروزر و نحوه کار با رخدادهای این کنترل رو در برنامه دارم.
بسیار سپاسگذارم . فقط کنجکاو شدم با اینهمه مهارت و زحمات چرا تو اکسس و الکترون جی اس نه ؟ وقتی اینهمه مهارت در این سه مورد داشته باشین با ری اکت نیتیو می تونید برنامه موبایل بسازین با نود جی اس یک اند سایت و در یونیتی گیم و ... خیلی کارای دیگه .من خیلی وقتیه که فکرمیکردم اکسس تموم شده است علی الخصوص که الان همچی وب بیس محور شده

mazoolagh
شنبه 14 بهمن 1402, 20:14 عصر
بسیار سپاسگذارم . فقط کنجکاو شدم با اینهمه مهارت و زحمات چرا تو اکسس و الکترون جی اس نه ؟ وقتی اینهمه مهارت در این سه مورد داشته باشین با ری اکت نیتیو می تونید برنامه موبایل بسازین با نود جی اس یک اند سایت و در یونیتی گیم و ... خیلی کارای دیگه .من خیلی وقتیه که فکرمیکردم اکسس تموم شده است علی الخصوص که الان همچی وب بیس محور شده

هر چیزی جایگاه خودش رو داره،
اکسس هم مثل اپلیکیشن های دیگه آفیس هیچ رقیب و مشابهی نداره،
و با این اندازه برنامه در حال کار به این زودی ها کنار گذاشته نمیشه.
حتی سی سال هم پیش که اکسس تازه آمده بود و چند رقیب جدی جا افتاده داشت کنار نرفت - الان که دیگه هیچ جایگزینی براش نیست.

ولی چون اکسس یک ابزار هست - و برای حل یک مسئله ممکنه ابزارهای مختلفی بشه استفاده کرد - باید ببینیم در یک مسئله بخصوص اکسس ابزار مناسبی هست یا نه.

mazoolagh
یک شنبه 13 خرداد 1403, 00:02 صبح
چالش امروز واقعا خارج از دستور هست،
فرض کنید شکل هندسی زیر رو داریم و نیاز هست که:
1- مساحت
2- پیرامون
3- گرانیگاه (یا مرکز جرم)
اونها رو بدست بیاریم (همه اندازه ها به سانتیمتر).

155774

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

گرچه این شکل محاسبات نسبتا ساده ای داره و میشه خواسته ها رو با فرمول های معمولی بدست آورد،
ولی موضوع این هست که در حل این مسئله هیچ دانش هندسه نداریم،
یعنی قرار نیست اندازه ها رو فرموله کنیم و برنامه ای برای محاسبه خواسته ها بنویسیم.
قرار هست یک راه بهتر پیدا کنیم که این محاسبات رو برای ما انجام بده.

برای درک بهتر این که چرا قرار نیست هندسه مسئله رو خودمون حل کنیم،
فرض کنید همین خواسته برای شکل زیر بود (البته اینجا نیست - مگر کسی که علاقه داشته باشه):

155775

تنها محدودیتی که داریم این هست که باید از vba و از اکسس (یا اکسل) استفاده کنیم.

و مهم این که اشاره به روش کافی نیست!
کدهای کامل حل مسئله و توضیح کارها هم نیاز هست.

mazoolagh
شنبه 26 خرداد 1403, 21:18 عصر
راهنمایی:
باید autocad روی سیستم نصب شده باشه!