<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های ابراهیم حمزه</title>
        <link>https://virgool.io/feed/@pranc14</link>
        <description>full stack web Developer- علاقه‌مند به SQL Server و چالش افزایش سرعت- علاقه‌مند به After Effect  و Adobe Audition</description>
        <language>fa</language>
        <pubDate>2026-06-16 20:53:14</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/53358/avatar/avatar.png?height=120&amp;width=120</url>
            <title>ابراهیم حمزه</title>
            <link>https://virgool.io/@pranc14</link>
        </image>

                    <item>
                <title>افزایش سرعت SQL SERVER قسمت ۳ (مفاهیم اولیه Page و DBCC)</title>
                <link>https://virgool.io/@pranc14/%D8%A7%D9%81%D8%B2%D8%A7%DB%8C%D8%B4-%D8%B3%D8%B1%D8%B9%D8%AA-sql-server-%D9%82%D8%B3%D9%85%D8%AA-%DB%B3-%D9%85%D9%81%D8%A7%D9%87%DB%8C%D9%85-%D8%A7%D9%88%D9%84%DB%8C%D9%87-page-%D9%88-dbcc-zjinnlr8fa5x</link>
                <description>این قسمت می‌خوایم کمی عملی کار کنیم تا شاید کمی دوره جزاب بشهدر ابتدا بگم که من از SQL SERVER 2019 استفاده می‌کنم در کنار آن از SQL Server Management Studio 15. اما تمام دستورات از SQL SERVER 2008 به بعد قابل اجرا هستند و فکر می‌کنم 2005 آن هم بتونه این موارد اجرا کنه. و این هم بگم که من نسخه اصلی دارم و CE یا Express نیست.برای ایجاد دیتابیس از دستور زیر استفاده می‌کنیم.CREATE DATABASE SqlSample01خوب دستور ساده است و نیاز به توضیح نداره فقط به یاد داشته باشید همیشه دستورات سیستم SQL با حروف بزرگ بنویسید. و تا جایی هم که می‌تونید روش دستوراری انجام عملیات یاد بگیرید.دستور بعدی sys.sysfiles که یک جدول سیستمی است و هر دیتابیس این جدول داره. اما اگر من دستور زیر اجرا کنم.همون طور که می‌بینید داره اطلاعات دیتابیس master به من میده در صورتی که من SqlSample01 می‌خوام. برای رفع این مشکل از دستور زیر در ابتدا بعد از ایجاد دیتابیس استفاده می‌کنم.البته از SP_HELPFILE  میتونید استفاده کنید که خود یک SP سیستمی میباشد و اطلاعات جمع و جور‌تری نسبت به sys.sysfiles به ما میدهشما در خروجی می‌توانید هر دو فایل پیش‌فرض دیتابیس مشاهده کنید و حجم اون‌هارو ببینید. این دقت داشته باشید که یادگیری این دستورات به شما کمک می‌کند تا در آینده کدهای سیستمی‌تری بنویسید و هر آنچه در ذهن دارید با آن‌ها پیاده کنید. مثلا خذف لوگ‌ها بعد از رسیدن به حجم خواست یا انجام یک عملیات خواست و... . شما می‌توایند با کد‌های بالا میزان این کار را سنجش کنید و با توجه به شرط‌ها لایه بیزینس برنامه، واکنش‌های مناسب نشان دهید.در دستور دیگر جدول Customer‌ها را ایجاد می‌کنیم.CREATE TABLE Customers(
	[CustomerID] [nchar](5),
	[CompanyName] [nvarchar](40),
	[ContactName] [nvarchar](30),
	[ContactTitle] [nvarchar](30),
)
GOنکته: اگر دستور بالا را اجزا کنید با صفحه‌ی زیر روبرو می‌شوید. احتمالا کمی برای شما آزاردهنده است(اگر اهل کیبورد باشید و کمتر با ماوس کار کنید که دیگر هیچ). برای مخفی کردن آن می‌توانید از کلید میانبر Ctrl + R استفاده کنید.دستور درج اطلاعاتINSERT INTO Customers (CustomerID, CompanyName, ContactName, ContactTitle)     
VALUES 
	 (1, &#039;CompanyName1&#039;, &#039;ContactName1&#039;, &#039;ContactTitle1&#039;),
	 (2, &#039;CompanyName2&#039;, &#039;ContactName2&#039;, &#039;ContactTitle2&#039;),
	 (3, &#039;CompanyName3&#039;, &#039;ContactName3&#039;, &#039;ContactTitle3&#039;),
	 (4, &#039;CompanyName4&#039;, &#039;ContactName4&#039;, &#039;ContactTitle4&#039;),
	 (5, &#039;CompanyName5&#039;, &#039;ContactName5&#039;, &#039;ContactTitle5&#039;)
GOخوب تمام این موارد گام به گام با هم اومدیم تا درباره‌ی درستور زیر با هم صحبت کنیم.DBCC IND (&#039;SqlSample01&#039;,  &#039;Customers&#039;,  1)DBCC دستور پر کاردی است و ما هم در آینده بیشتر ازش استفاده می‌کنیم چون اطلاعات زیادی درباره‌ی موارد مورد نیاز ما به ما می‌دهد. اما ما در اینجا با کمک این دستور می‌خواهیم بررسی کنیم جدول ایجاد شده ما در چند  Page قرار گرفته و اطلاعات به چه شکلی درش ذخیره شده. اطلاعات بیشتر پارامتر اول این دستور، نام دیتابیس را دریافت می‌کند و پارامتر دوم نام جدول را اما پارامتر سوم پیش‌فرض این دستور است.می‌بینید که جدول ما از دو Page تشکیل شده یک سطر اول آن مربوط به Index‌هاست اما سطر دوم مشخص کنند ثبت اطلاعات ما در یک صفحه است و به صفحه‌ی بعدی کشیده نشده است.درباره‌ی دستورات DBCC سرچ کنید و از مستندات مایکروسافت استفاده کنید حتما.حال که ما متوجه شدیم جدول مورد استفاده‌ی ما یک Page دارد، برای مشاهده‌ی محتوای آن Page باید از دستور زیر استفاده کرد.DBCC PAGE (&#039;SqlSample01&#039;, 1, 264, 3)پارامتر اول آن نام دیتابیس است و پارامتر دوم آن Page File Id است(یا PagePID) که ما از طریق دستور قبل به آن‌ها رسیدیم. پارامتر سوم آن نیز PagePID و پارمتر چهارم آن نمایان‌گر درخواست ما برای واکشی اطلاعات به حافظه است. اما اجرای آن با پیام زیر روبرو می‌شود.DBCC execution completed. If DBCC printed error messages, contact your system administrator.برای رفع آن و امکان مشاهده اطلاعات اصلی باید از Flag زیر استفاده کرد تا بتوانیم اطلاعات را ردیابی کنیم.DBCC TRACEON(3604)با اجرای این دستور و بعد اجرای دستور قبل با خروجی باینری روبرو می‌شویم. آن هم همان اطلاعاتی است که خود SQL SERVER از آن استفاده می‌کند و بیشتر برای او قابل فهم است تا برای ما. البته می‌توایند اطلاعات ذخیره شده‌ی ما را هم آن‌جا پیدا کنید اما اطلاعات پراکنده شده‌اند.PAGE: (1:264)
BUFFER:
BUF @0x0000019AF63B1140
bpage = 0x0000019AD2AA8000          bPmmpage = 0x0000000000000000       bsort_r_nextbP = 0x0000019AF63B2A10
bsort_r_prevbP = 0x0000019AF63B2A00 bhash = 0x0000000000000000          bpageno = (1:264)
bpart = 0                           ckptGen = 0x0000000000000000        bDirtyRefCount = 0
bstat = 0x10b                       breferences = 0                     berrcode = 0
bUse1 = 9206                        bstat2 = 0x0                        blog = 0x212121cc
bsampleCount = 0                    bIoCount = 0                        resPoolId = 0
bcputicks = 0                       bReadMicroSec = 15313               bDirtyContext = 0x0000019AEE55D2C0
bDbPageBroker = 0x0000000000000000  bdbid = 8                           bpru = 0x0000019ADBD10040
PAGE HEADER:
Page @0x0000019AD2AA8000
m_pageId = (1:264)                  m_headerVersion = 1                 m_type = 1
m_typeFlagBits = 0x0                m_level = 0                         m_flagBits = 0x8000
m_objId (AllocUnitId.idObj) = 179   m_indexId (AllocUnitId.idInd) = 256 
Metadata: AllocUnitId = 72057594049658880
Metadata: PartitionId = 72057594043170816
Metadata: IndexId = 0
Metadata: ObjectId = 581577110      m_prevPage = (0:0)                  m_nextPage = (0:0)
pminlen = 14                        m_slotCnt = 5                       m_freeCnt = 7591
m_freeData = 591                    m_reservedCnt = 0                   m_lsn = (37:397:31)
m_xactReserved = 0                  m_xdesId = (0:0)                    m_ghostRecCnt = 0
m_tornBits = 0                      DB Frag ID = 1
Allocation Status
GAM (1:2) = ALLOCATED               SGAM (1:3) = NOT ALLOCATED          PFS (1:1) = 0x41 ALLOCATED  50_PCT_FULL
DIFF (1:6) = CHANGED                ML (1:7) = NOT MIN_LOGGED
Slot 0 Offset 0x60 Length 99
Record Type = PRIMARY_RECORD        Record Attributes =  NULL_BITMAP VARIABLE_COLUMNS
Record Size = 99
Memory Dump @0x0000005CF6778060
0000000000000000:   30000e00 31002000 20002000 20000400 00030031  0...1. . . . ......1
0000000000000014:   00490063 0043006f 006d0070 0061006e 0079004e  
.I.c.C.o.m.p.a.n.y.N
0000000000000028:   0061006d 00650031 0043006f 006e0074 00610063  .a.m.e.1.C.o.n.t.a.c
000000000000003C:   0074004e 0061006d 00650031 0043006f 006e0074  .t.N.a.m.e.1.C.o.n.t
0000000000000050:   00610063 00740054 00690074 006c0065 003100    .a.c.t.T.i.t.l.e.1.
Slot 0 Column 1 Offset 0x4 Length 10 Length (physical) 10
CustomerID = 1
Slot 0 Column 2 Offset 0x19 Length 24 Length (physical) 24
CompanyName = CompanyName1 
Slot 0 Column 3 Offset 0x31 Length 24 Length (physical) 24
ContactName = ContactName1          
Slot 0 Column 4 Offset 0x49 Length 26 Length (physical) 26
ContactTitle = ContactTitle1        
Slot 1 Offset 0xc3 Length 99
Record Type = PRIMARY_RECORD        Record Attributes =  NULL_BITMAP VARIABLE_COLUMNS
Record Size = 99
Memory Dump @0x0000005CF67780C3
0000000000000000:   30000e00 32002000 20002000 20000400 00030031  0...2. . . . ......1
0000000000000014:   00490063 0043006f 006d0070 0061006e 0079004e  .I.c.C.o.m.p.a.n.y.N0000000000000028:   0061006d 00650032 0043006f 006e0074 00610063  .a.m.e.2.C.o.n.t.a.c000000000000003C:   0074004e 0061006d 00650032 0043006f 006e0074  .t.N.a.m.e.2.C.o.n.t0000000000000050:   00610063 00740054 00690074 006c0065 003200    .a.c.t.T.i.t.l.e.2.Slot 1 Column 1 Offset 0x4 Length 10 Length (physical) 10
CustomerID = 2
Slot 1 Column 2 Offset 0x19 Length 24 Length (physical) 24
CompanyName = CompanyName2
Slot 1 Column 3 Offset 0x31 Length 24 Length (physical) 24
ContactName = ContactName2
Slot 1 Column 4 Offset 0x49 Length 26 Length (physical) 26
ContactTitle = ContactTitle2
Slot 2 Offset 0x126 Length 99
Record Type = PRIMARY_RECORD        Record Attributes =  NULL_BITMAP VARIABLE_COLUMNS
Record Size = 99                    
Memory Dump @0x0000005CF6778126
0000000000000000:   30000e00 33002000 20002000 20000400 00030031  0...3. . . . ......1
0000000000000014:   00490063 0043006f 006d0070 0061006e 0079004e  
I.c.C.o.m.p.a.n.y.N
0000000000000028:   0061006d 00650033 0043006f 006e0074 00610063  
a.m.e.3.C.o.n.t.a.c
000000000000003C:   0074004e 0061006d 00650033 0043006f 006e0074  .t.N.a.m.e.3.C.o.n.t
0000000000000050:   00610063 00740054 00690074 006c0065 003300    .a.c.t.T.i.t.l.e.3.
Slot 2 Column 1 Offset 0x4 Length 10 Length (physical) 10
CustomerID = 3                      
Slot 2 Column 2 Offset 0x19 Length 24 Length (physical) 24
CompanyName = CompanyName3          
Slot 2 Column 3 Offset 0x31 Length 24 Length (physical) 24
ContactName = ContactName3         
Slot 2 Column 4 Offset 0x49 Length 26 Length (physical) 26
ContactTitle = ContactTitle3        
Slot 3 Offset 0x189 Length 99
Record Type = PRIMARY_RECORD        Record Attributes =  NULL_BITMAP VARIABLE_COLUMNS
Record Size = 99                    
Memory Dump @0x0000005CF6778189
0000000000000000:   30000e00 34002000 20002000 20000400 00030031  0...4. . . . ......1
0000000000000014:   00490063 0043006f 006d0070 0061006e 0079004e  .I.c.C.o.m.p.a.n.y.N
0000000000000028:   0061006d 00650034 0043006f 006e0074 00610063  .a.m.e.4.C.o.n.t.a.c
000000000000003C:   0074004e 0061006d 00650034 0043006f 006e0074  .t.N.a.m.e.4.C.o.n.t
0000000000000050:   00610063 00740054 00690074 006c0065 003400    .a.c.t.T.i.t.l.e.4.
Slot 3 Column 1 Offset 0x4 Length 10 Length (physical) 10
CustomerID = 4                      
Slot 3 Column 2 Offset 0x19 Length 24 Length (physical) 24
CompanyName = CompanyName4
Slot 3 Column 3 Offset 0x31 Length 24 Length (physical) 24
ContactName = ContactName4          
Slot 3 Column 4 Offset 0x49 Length 26 Length (physical) 26
ContactTitle = ContactTitle4        
Slot 4 Offset 0x1ec Length 99
Record Type = PRIMARY_RECORD        Record Attributes =  NULL_BITMAP VARIABLE_COLUMNS
Record Size = 99                    
Memory Dump @0x0000005CF67781EC
0000000000000000:   30000e00 35002000 20002000 20000400 00030031  0...5. . . . ......1
0000000000000014:   00490063 0043006f 006d0070 0061006e 0079004e  .I.c.C.o.m.p.a.n.y.N
0000000000000028:   0061006d 00650035 0043006f 006e0074 00610063  .a.m.e.5.C.o.n.t.a.c
000000000000003C:   0074004e 0061006d 00650035 0043006f 006e0074  .t.N.a.m.e.5.C.o.n.t
0000000000000050:   00610063 00740054 00690074 006c0065 003500    .a.c.t.T.i.t.l.e.5.
Slot 4 Column 1 Offset 0x4 Length 10 Length (physical) 10
CustomerID = 5
Slot 4 Column 2 Offset 0x19 Length 24 Length (physical) 24
CompanyName = CompanyName5
Slot 4 Column 3 Offset 0x31 Length 24 Length (physical) 24
ContactName = ContactName5
Slot 4 Column 4 Offset 0x49 Length 26 Length (physical) 26
ContactTitle = ContactTitle5 
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
Completion time: 2020-03-12T02:01:07.1936969+03:30</description>
                <category>ابراهیم حمزه</category>
                <author>ابراهیم حمزه</author>
                <pubDate>Thu, 12 Mar 2020 02:11:01 +0330</pubDate>
            </item>
                    <item>
                <title>افزایش سرعت SQL SERVER قسمت ۲ (مفاهیم اولیه Page و DBCC)</title>
                <link>https://virgool.io/@pranc14/%D8%A7%D9%81%D8%B2%D8%A7%DB%8C%D8%B4-%D8%B3%D8%B1%D8%B9%D8%AA-sql-server-%D9%82%D8%B3%D9%85%D8%AA-%DB%B2-%D9%85%D9%81%D8%A7%D9%87%DB%8C%D9%85-%D8%A7%D9%88%D9%84%DB%8C%D9%87-page-%D9%88-dbcc-jik1mp5sjmow</link>
                <description>هر Database از دو فایل تشکیل شده که یکی فایل اصلی ماست و دیگری فایلی است که اطلاعات را به صورت موقت و یا لوگ شده نگه‌داری میکنید.(ما در اینجا حالت متداول در نظر گرفتیم و در آینده درباره‌ی ndf و... صحبت می‌کنیم)در LDF لوگ تمام تراکنش‌ها ذخیره می‌شود(تمام وقایع)(CRUD) و نحوه‌ی ذخیره اطلاعات هم به صورت ترتیبی است. یعنی سطر به سطر ذخیره می‌کنه و مانند MDF به صورت Random Access نیست. ممکن است برای هر عملیات ساده‌ای چندین سطر ثبت شود.مشاهده می‌کنیم که برای دو دستور Insert. ۶ سطر اطلاعات ثبت کرده است. یعنی هر تراکنش Insert ۳ سطر اطلاعات در لوگ ذخیره می‌کند. که یک سطر آن برای باز کردن تراکنش است و یک سطر برای ذخیره اطلاعات و سطر دیگر برای بستن تراکنش(Transaction).اما فایل اصلی که اطلاعات ما درون آن قرار دارد به شکل زیر ذخیره شده است.۱-Page: واحد اصلی ذخیره اطلاعات در SQL SERVER است.هر دیتابیس تمام اطلاعات خود را تبدیل به page میکنه و از کنار هم گذاشتن این pageها جداول واطلاعات ما تشکیل میشه. برای اطلاعات بیشتر.طرفیت هر صفحه۸۱۹۲ بایت است اما ظرفیت مورد استفاده برای ما ۸۰۹۶ بایت است. همان‌طور که در تصویر می‌بینید مابقی فضا برای page header و... دیگه است. برای اطلاعات بیشترحالا شاید شما از من بپرسید تا این مقدار ریز شدن در بحث نیاز است؟ من مجبورم بگم بله. شما وقتی به عنوان فردی که می‌خواهد سرعت عملیات را افزایش دهد، ظاهر می‌شود باید از تمام عملیات‌های که یک دیتابیس برای واکشی اطلاعات انجام می‌دهد باخبر باشید. باید بدونید هر پpage چه میزان اطلاعات نگهداری می‌کند. باید بدونید وقتی ما در آینده بحث می‌کنیم که اجرای این دستور ۳ بار درخواست I/O داشته منظور خواندن ۳ Extents است(چند خط پایین‌تر توضیح دادیم.). باید حدس بزنید وقتی بحث صفحه‌بندی است حتما محدودیتی وجود داره که باعث این اتفاق شده پس باید طول جداول از یک حدی زیاد نکنیم. باید ابزاری داشته باشیم و یا روشی را بدونیم تا بتونیم سنجش کنیم که اگر من طول جدول افزایش بدم خروجی بهتری می‌تونم دریافت کنم و یا از یک جدول کمکی استفاده کنم و اطلاعات را با آن JOIN کنم.خلاصه این‌هارو گفتم تا از خواندن ادامه مطالب پشیمان نشید و فکر نکنید اطلاعات ارائه شده فقط یک کپی از سایت مایکروسافت است.۲- Extent: به هر ۸ صفحه(page)ی متوالی یک Extent می‌گویند.حجم یک Extent هم برابر با ۶۴ کیلوبایت است. و واحد هر درخواست I/O هم برابر با یک Extent است. البته فراموش نکنید که بلوک‌های اطلاعاتی در SQL SERVER ۶۴ کیلوبایتی است و توصیه شده هر Alocation unit size درایوی که دیتابیس در آن است برابر ۶۴ کیلوبایت باشه.(توصیه شده است). برای اطلاعات بیشترخوبه اینو بدونید که دیتابیس به صورت Random Access اطلاعات ذخیره میکنه و ممکن Extent ها پشت سر هم قرار نگیرند.مانند تصویر زیر</description>
                <category>ابراهیم حمزه</category>
                <author>ابراهیم حمزه</author>
                <pubDate>Sun, 08 Mar 2020 01:19:01 +0330</pubDate>
            </item>
                    <item>
                <title>افزایش سرعت SQL SERVER قسمت ۱</title>
                <link>https://virgool.io/@pranc14/%D8%A7%D9%81%D8%B2%D8%A7%DB%8C%D8%B4-%D8%B3%D8%B1%D8%B9%D8%AA-sql-server-%D9%82%D8%B3%D9%85%D8%AA-%DB%B1-vtnye9ss61hh</link>
                <description>همه‌ی برنامه‌نویسان روزهایی را سپری کردن که نیازمند افزایش سرعت اجرای کوئری‌های خود بودن و شاید با افزایش منابع سرور تا حدی توانسته باشند این مشکل را رفع کرده باشند اما شاید به این باور نرسیده باشیم که همیشه راه‌حل مشکلات ارتقاع سخت‌افزاری نیست و رعایت نکات ریز می‌تواند سرعت اجرا را حد بسیار زیادی افزایش دهد. برای درک و یادگیری این نکات کافیست با تعاریف ابتدایی آن‌ها آشنا شویم تا در هنگام طراحی اولیه با رعایت آن‌ها مشکلات آینده را کمتر کنیم(البته بهترین روش عادت دادن خود با این اصول است).اصولی که با کمی سعی خطا هم می‌توان به آن رسید و نیازی نیست که شما مباحث اساسی SQL SERVER را یاد بگیری. اما گاهی اوقات یادگری مباحث اولیه برای درک ما از رفتار سیستم و تصمیمات سیستم الزامی است. برای مثال نیاز است یادبگیریم SQL SERVER چگونه مدریت  Page انجام میده تا بتوانیم در انتخاب بهتر Index تصمیم درست را انتخاب کنیم.سیر آموزشی که من سعی دارم بر اساس آن عمل کنم۱- مفاهیم اولیه Page و DBCC۲- کمی آموزش دیتابیس Northwind یا WideWorldImporters (هنوز تصمیمی نگرفته‌ام)۳- آشنایی با مفاهیم IO Time و Execution Plan۴- آشنایی با SCAN جدول و جستجوی جدول۵- آشنای با ساختار Indexها۶- آشنایی با ساختار Page یک Index۷- ‌Clustered Index ۸-NonClustered Index۹- Bookmark Lookup۱۰- Primary Key , Unique Key۱۱- Filter Index۱۲- Distribution Statistics۱۳- مدیریت Statistics ۱۴- آشنایی ساده با Column Storedامید است خداوند توفیق دهد تا موارد بالا را بتوانیم به درستی آموزش دهیم. در آخر متوجه خواهی شد با رعایت چند نکته و کمی تجربه می‌توان از ابتدا درخواست‌هایی با سرعت بالا اجرا کرد.نکته: آموزش SQL زمانی جذاب می‌شود که بتوان آن را به صورت تجربه بر روی دیتابیس به کار نشان داد.</description>
                <category>ابراهیم حمزه</category>
                <author>ابراهیم حمزه</author>
                <pubDate>Sat, 07 Mar 2020 01:13:27 +0330</pubDate>
            </item>
                    <item>
                <title>Excel در جاوااسکریپت</title>
                <link>https://virgool.io/@pranc14/excel-%D8%AF%D8%B1-%D8%AC%D8%A7%D9%88%D8%A7%D8%A7%D8%B3%DA%A9%D8%B1%DB%8C%D9%BE%D8%AA-zisyhf2dcvqq</link>
                <description>همیشه در برنامه های تحت وب مشاهده می کنید که مکانی برای import اطلاعات وجود داره و عموما هم فرمت دریافتی به صورت excel هست. این فرمت چون ساختار جدولی داره و عموم مردم هم با آن آشنا هستند، کمک میکنه تا بهتر اطلاعات دریافت کنیم.اما مشکل کجاست؟ مشکل این که کاربران عموما الگوی مارو رعایت نمی کنند و یا در ستون ها اطلاعات نامعتبر زیادی وارد می کنند. مشکل بعدی این است که برنامه نویس هم تا سطرهایی که دارای اطلاعات معتبری است, عملیات خودش انجام میده و در آخر پیغام میده که ۱۶ سطر ثبت شد.خلاصه اگر به کار این امکان بدیم که در همان بخش Front برنامه اعتبار سنجی انجام بده و تغییرات لازم هم بر روی سطرهاش داشته باشه.من برای رفع مشکل به دنبال کتابخانه جاوااسکریپتی گشتم تا فایل اکسل در جدولی به کاربر نمایش بدم به همراه خطاهایی که ممکن بود در ورود اطلاعات داشته باشه و بعد امکانی فراهم کردم تا بتونه اصلاحاتی انجام بده تا در صورت مشکل، آن‌ها رفع بشه.کتابخانه SheetJS تمام امکاناتی که من لازم داشتم را داشت و به راحتی فایل‌های اکسل به JSON تبدیل می‌کرد و برعکس آن.می‌تونید برای مشاهده مثال کامل از این لینک استفاده کنید.برای تبدیل فایل اکسل می‌تونید از نمونه کد زیر استفاده کنید let fileReader = new FileReader();
fileReader. = function (event) {
   const data = event.target.result;
   const workbook = XLSX.read(data, { type: &amp;quotbinary&amp;quot });
   const rowObject = 
   XLSX.utils.sheet_to_row_object_array(workbook.Sheets[workbook.SheetNames[0]]);
}
fileReader.readAsBinaryString(file);در اینجا ابتدای یک FileReader ایجاد می‌کنیم و اون در حالت readAsBinaryString  فراخوانی می‌کنیم. در این وضعیت تایع  آن فراخوانی می‌شود. و دست آخر اطلاعات به صورت JSON در متغیر rowObject ریخته می‌شود و می‌توانید از آن استفاده کنید. اگر عنوان ستون‌ها را به صورت انگلیسی وارد کنید، خروجی JSON مناسبی خواهید داشت.می‌تونید خروجی نهایی را در یک جدول به کاربر نمایش دهید(به همراه تغییرات مورد نیاز و خطاهای) و از کاربر بخواهید تا مشکلات را در همان جدول رفع کند و بعد از اتمام کار، اطلاعات را برای سرور ارسال کنید و نتیجه نهایی را به یک چک‌باس سبز به کار نمایش دهید تا اینگونه دیگر خط پشتیبانی شرکت هم مشغول نمی‌شود و دیگر نیازی نیست زمان زیادی را برای پشتیبانی صرف کنید. و یا برای دیتاهای تکراری ثبت شده برای کاربر دلیل بیاورید.اما برای تبدیل JSON به Excelconst ws = XLSX.utils.json_to_sheet(userImportConfirm);
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, &amp;quotکاربران&amp;quot);
XLSX.writeFile&#40;wb, &amp;quotsheetjs.xlsx&amp;quot&#41;;در اینجا userImportConfirm به صورت یک Object به کتابخانه مورد نظر ما ارسال می‌شود و XLSX.writeFile&#40;wb, &quot;sheetjs.xlsx&quot;&#41; باعث دانلود آن به صورت اتوماتیک می‌شود.این کتابخانه سرعت مناسبی دارد اما در اکسل‌های حجیم کار کمی سخت می‌شود. محدودیت مرورگر را هم در نظر بگیریدهمیشه به یاد داشته باشید کاربرانی که از برنامه استفاده می‌کنند هیچگونه دانشی ندارند و باید برای آن‌ها مسیر را گام به گام توضیح دهید و کمک کنید که از روندی منطقی پیروی کنند.ممنون از زمانی که گذاشتید.</description>
                <category>ابراهیم حمزه</category>
                <author>ابراهیم حمزه</author>
                <pubDate>Mon, 17 Feb 2020 23:36:18 +0330</pubDate>
            </item>
                    <item>
                <title>قسمت دوم PWA</title>
                <link>https://virgool.io/@pranc14/%D9%82%D8%B3%D9%85%D8%AA-%D8%AF%D9%88%D9%85-pwa-vr7cbf0lpq8r</link>
                <description>برای توسعه برنامه‌های PWA باید حتما از SSL یا همون https استفاده کنید تا به امکانات کامل بتونی به راحتی دسترسی پیدا کنیم. البته تنها PWA نیست که نیاز به SSL دارد، شما برای استفاده از امکان ضبط صدا در مرورگر هم مجبور به استفاده از آن هستید و یا استفاده از موقعیت جغرافیایی کاربر و ...به هرحال برای تست این گونه برنامه‌ها باید آن‌ها را از طریقی هاست کرد. که می‌توانید از Nodejs استفاده کنید برای اینکار(اینجوری به npm قنیع آن هم دسترسی دارید) یا از dotnet core.ما برای راحتی به شما برنامه Web Server پیشنهاد میکنیم که بر روی گوگل کروم نصب می‌شود و امکانات مناسبی هم دارد. که می‌تونید از اینجا دریافت کنید.مواردی که قرار در این قسمت بگیم در این سایت خود گوگل قرار دارد که میتوان گفت مرجع PWA می‌باشد.برای پیشنیاز هم لازم شما جاوااسکریپت و HTML بلد باشید.تصویر نهایی برنامه تولید شده هم مانند زیر استاین یک برنامه آب‌و‌هوا است که برای ایجاد اولیه آن نیاز داریم تا شما وارد سایت دارک‌اسکای شده و یک کلید برای دسترسی به اطلاعات مورد نیاز داشته باشید تا در درخواست‌های وب‌سرویسی خود از آن برای اعتبارسنجی استفاده کنید. این کلید ما نیاز داریم تا برنامه‌ای مانند تصویر بالا را ایجاد کنیم. اگر شما به درستی مراحل دریافت کلید اجرا کنید باید بتوانید از لینک تست زیر استفاده کنید. به جای DARKSKY_API_KEY از کلید خود استفاده کنید.https://api.darksky.net/forecast/DARKSKY_API_KEY/40.7720232,-73.9732319برای اینکه در زمان صرفه‌جویی کنیم می‌تونید پروژه اصلی این مخزن دانلود کنید و گام به گام با آموزش جلو برید. در کنار این پروژه حتما Nodejs هم نصب کنید تا بتوانید وابستگی‌های برنامه را دانلود کنید و هم بتونید برنامه را اجرا کنید.مراحل اجرا:۱- اول در خط فرمان(در همان پوشه برنامه) دستور npm install را اجرا کنید۲- فایل Server.js را برای جایگزاری کلید دارک‌اسکای ویرایش کنیدconst API_KEY = process.env.DARKSKY_API_KEY;۳- در خط فرمان دستور run server.js را وارد کنید تا برنامه در پورت 8000 اجرا شود۴- در مرورگر آدرس http://localhost:8000 را وارد کنید تا برنامه را مشاهده کنید.این برنامه تکمیل نیست و باید مانند ما کد‌های مورد نیاز را به آن اضافه کنید تا قابلیت‌های PWA آن اجرا شود.برای دریافت اطلاعات بیشتر از برنامه inspect element مرورگر کروم استفاده می‌کنیم و در در اولین گام از ابزار Audits آن بهره می‌بریم بتوانیم برنامه‌ی خود را سنجش کنیم و از کمبود‌ها و نقاط ضعف آن باخبر شویم.اگر آن را اجرا کنید با صفحه‌ی زیر روبرو می‌شوید که برای ما در این بخش بیشتر قسمت PWA آن مهم است اما خود نیز می‌توانید برای یادگیری بهتر و رفع مشکلات از قسمت‌های دیگر این بخش هم استفاده کنید.❗FAILED: Current page does not respond with a 200 when offline.❗FAILED: start_url does not respond with a 200 when offline.❗FAILED: Does not register a service worker that controls page and start_url.❗FAILED: Web app manifest does not meet the installability requirements.❗FAILED: Is not configured for a custom splash screen.❗FAILED: Does not set an address-bar theme color.این‌ها عموم خطاهایی هستند که برنامه ما دارد. ما کم کم این موارد را رفع میکنیم.(دلیل استفاده ما از این ابزار این است که شما در آینده راحت‌تر بتوانید مشکلات را بیابید و در پی رفع آن باشید.)خوب بریم سر پروژه‌ای که از گیت‌هاب دانلود کردیم. درابتدا باید بگیم که تمام برنامه‌های PWA دارای فایلی به نام manifest می‌باشند.مانند زیر{
  &amp;quotname&amp;quot: &amp;quotWeather&amp;quot,  
  &amp;quotshort_name&amp;quot: &amp;quotWeather&amp;quot,
  &amp;quoticons&amp;quot: [{
    &amp;quotsrc&amp;quot: &amp;quot/images/icons/icon-128x128.png&amp;quot,
      &amp;quotsizes&amp;quot: &amp;quot128x128&amp;quot,
      &amp;quottype&amp;quot: &amp;quotimage/png&amp;quot
    }, {
      &amp;quotsrc&amp;quot: &amp;quot/images/icons/icon-144x144.png&amp;quot,
      &amp;quotsizes&amp;quot: &amp;quot144x144&amp;quot,
      &amp;quottype&amp;quot: &amp;quotimage/png&amp;quot
    }, {
      &amp;quotsrc&amp;quot: &amp;quot/images/icons/icon-152x152.png&amp;quot,
      &amp;quotsizes&amp;quot: &amp;quot152x152&amp;quot,
      &amp;quottype&amp;quot: &amp;quotimage/png&amp;quot
    }, {
      &amp;quotsrc&amp;quot: &amp;quot/images/icons/icon-192x192.png&amp;quot,
      &amp;quotsizes&amp;quot: &amp;quot192x192&amp;quot,
      &amp;quottype&amp;quot: &amp;quotimage/png&amp;quot
    }, {
      &amp;quotsrc&amp;quot: &amp;quot/images/icons/icon-256x256.png&amp;quot,
      &amp;quotsizes&amp;quot: &amp;quot256x256&amp;quot,
      &amp;quottype&amp;quot: &amp;quotimage/png&amp;quot
    }, {
      &amp;quotsrc&amp;quot: &amp;quot/images/icons/icon-512x512.png&amp;quot,
      &amp;quotsizes&amp;quot: &amp;quot512x512&amp;quot,
      &amp;quottype&amp;quot: &amp;quotimage/png&amp;quot
    }],
  &amp;quotstart_url&amp;quot: &amp;quot/index.html&amp;quot,
  &amp;quotdisplay&amp;quot: &amp;quotstandalone&amp;quot,
  &amp;quotbackground_color&amp;quot: &amp;quot#3E4EB8&amp;quot,
  &amp;quottheme_color&amp;quot: &amp;quot#2F3BA2&amp;quot
}در مانیفست نام برنامه و نامی که در هنگام افزوده شدن به لیست برنامه‌ها به کاربر نمایش داده می‌شود را می‌توانید مشاهده کنید البته لیست آیکون‌ها هم در قابل تعریف می‌باشد. همچنین نباید فراموش کنید که آدرس شروع برنامه را هم می‌توانید در اینجا وارد کنید</description>
                <category>ابراهیم حمزه</category>
                <author>ابراهیم حمزه</author>
                <pubDate>Wed, 05 Feb 2020 23:32:09 +0330</pubDate>
            </item>
                    <item>
                <title>PWA قسمت اول</title>
                <link>https://virgool.io/@pranc14/pwa-e1-vwml7nqtz1c9</link>
                <description>درابتدا: PWA مخفف شده Progressive Web Apps به معنای وب اپلیکیشن‌های پیشرونده است که توسط گوگل در سال ۲۰۱۵ معرفی شد و در حال حاضر بیشتر مرورگر‌ها از آن پشتیبانی می‌کنند. این دستاورد باعث پیشرفت در تولید وب اپ‌ها شد و این حس را برای کاربر ایجاد می‌کند که در حال کار با برنامه Android یا IOS است. البته پشتیبانی مرورگر‌ها به نحوی است که این حس وب‌اپ بودن در مرورگر‌های جدید بیشتر ملموس است و در مرورگر‌های قدیمی و خیلی قدیمی، کمتر می‌شود.قبل از هر چیزی چند مزیت برای PWA بیان می‌کنیم تا بیشتر با آن آشنا شوید۱- با تبدیل برنامه به PWA به کاربرانی که با موبایل خود در کار مرور سایت هستند، حس بهتری را منتقل می‌کنیم و باعث افزایش سرعت می‌شویم و از همه مهمتر پیچیدگی‌های نصب را از میان برمی‌داریم و دیگر هیچ اپلیکیشن مارکتی(مانند App Store) نمی‌تواند مانع شما شود و یا هزینه‌ای برای لایسنس تولید برنامه از شما درخواست کند.۲- امکان افزودن برنامه به یک ایکون بر روی صفحه‌ی گوشی کاربر. به این نحو برنامه شما همیشه در دسترس کاربر است و می‌تواند Push Notificationها را دریافت کند و در جریان کمپین‌های شما قرارگیرد.(ایجاد ICON و Splash و رابط بسیار خوب)۳- در صورت قطع ارتباط اینترنت شما می‌توانید به صورت آفلاین به کاربر خدمات ارائه کنید و در زمان اتصال دوباره تمام موارد را با سرور هماهنگ کنید. البته می‌توانید تمام فایل‌های مورد نیاز برنامه را هم کش کنید تا در زمان مورد نیاز از آن‌ها استفاده کنید.شماره ۴- Responsive بودن برنامه: در برنامه‌های PWA این ویژگی کمک می‌کند تا UI و UX مناسبی داشته باشید و حس خوبی را برای کاربر ایجاد کنید۶- سرعت زیاد. چون برنامه سبک است سریع اجرا می‌شود و همچنین تغییرات هم سریع برای همه اعمال می‌شود و نیازی به تولید نسخه جدید و اطلاع رسانی آن نیست. البته هر چقدر بر روی وب اپ کار کنید می‌توانید سرعت آن را افزایش دهید به کمک روش‌های گوناگون.۶- نصب برنامه بر روی ویندوز و کروم OS. با تبدیل برنامه به PWA خود برنامه به کاربر اندروید پیشنهاد نصب می دهد و در ویندوز و مک و لینوکس هم می‌توانید همین‌ کار را انجام دهید .در تصویر زیر مزایای برنامه‌های وب و همچنین اپلیکیشن‌ نام برده شده است.و در آخر هم در تصویر برتری PWA را می‌توانید مشاهده کنید.خصوصیات یک وب اپلیکیشن پیش رونده چیستپیش رونده (قابل استفاده در هر دستگاه و سیستم‌عامل): یک وب اپلیکیشن پیش رونده فارغ از نوع مرورگر و نوع دستگاه، برای تمام کاربران قابل استفاده است.قابل جستجو: از آنجایی که وب اپلیکیشن‌های پیش رونده در واقع یک وب‌سایت محسوب می‌شوند، از طریق موتورهای جستجو قابل یافتن هستند. این خصوصیت، یک برتری قابل توجه آن‌ها بر اپلیکیشن‌های بومی است.قابل پیونددهی (لینک‌دهی): وب اپلیکیشن‌های پیش رونده برخلاف اپلیکیشن‌های بومی نیازی به طی کردن مراحل پیچیده‌ی دانلود و نصب ندارند و اشتراک‌گذاری آن‌ها از طریق یک نشانی وب (URL) به راحتی امکان‌پذیر است.انعطاف‌پذیر: رابط کاربری وب اپلیکیشن‌های پیش رونده خود را با هر نوع فرم فکتور اعم از موبایل و دسکتاپ و هر نوع اندازه‌ی نمایشگر تطبیق می‌دهد.ظاهر اپلیکیشن‌وار: یک اپلیکیشن پیش رونده شباهت بی‌بدیلی به اپلیکیشن‌های بومی دارد، از رابط کاربری مشابه آن‌ها استفاده می‌کند و مسیریابی در آن‌ها تفاوتی با اپلیکیشن‌های معمولی ندارد.بی‌نیاز از اتصال اینترنت: وب اپلیکیشن‌های پیش رونده در صورت ضعف اتصال اینترنت یا حتی به صورت آفلاین نیز قابل استفاده هستند.درگیر کردن کاربر: احتمال آنکه کاربران اپلیکیشن‌های موبایل مجددا از اپلیکیشن‌های خود استفاده کنند بیشتر از احتمال مراجعه‌ی مجدد به یک‌ وب‌سایت است. وب اپلیکیشن‌های پیش رونده با استفاده از ویژگی‌هایی نظیر اعلان‌های سمت سرور (Push Notification)، این ضعف را جبران کرده‌اند.قابل نصب: وب اپلیکیشن‌های پیش رونده را می‌توان همانند اپلیکیشن‌های بومی نصب و آیکون آ‌ن‌ها را به صفحه‌ی خانگی و حتی کشوی اپلیکیشن‌ها اضافه کرد؛ با این تفاوت که دسترسی به آن‌ها بی‌نیاز از دردسرهای جستجو در فروشگاه‌های اپلیکیشن است. این ویژگی استفاده از آن‌ها را به شدت آسان می‌کند.به‌روز بودن: در حالی که اپلیکیشن‌های بومی نیازمند به‌روزرسانی از طریق فروشگاه‌های نرم‌افزاری هستند، وب اپلیکیشن‌های پیش رونده به لطف فرآیند به‌روزرسانی سرویس ورکر، همیشه به آخرین نسخه، به‌روز هستند و هنگامی که محتوای جدید منتشر شود و کاربر به اینترنت متصل باشد، آن محتوا بلافاصله در دسترس کاربر قرار می‌گیرد.ایمن: از آنجایی که وب اپلیکیشن‌های پیش رونده در بستر HTTPS قرار دارند، از مخاطرات امنیتی در امان هستند.نکته: این موارد آخر از این لینک کپی کردم زومیتدر قسمت بعد یک پروژه رو با هم شروع می‌کنیم.</description>
                <category>ابراهیم حمزه</category>
                <author>ابراهیم حمزه</author>
                <pubDate>Fri, 15 Nov 2019 16:31:00 +0330</pubDate>
            </item>
            </channel>
</rss>