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

نمودار گانت استایل

در این مقاله آموزش می دهیم که چگونه یک نمودار گانت استایل در DataGridView بسازیم تا نتایج جدول زمانی پروژه را در آن نمایش دهیم. تمام منطق کار برای نمایش نتیجه در SQL Server Stored Procedure می باشد. برای نمایش نتیجه از Pivot query در Stored Procedure استفاده کرده ایم. جزییات مربوط به نوشتن Procedure را می توانیم در قسمت بعدی مشاهده کنیم.

نمودار گانت استایل

بخش کد:

جدولی با نام SCHED_Master در دیتابیس projectDB‘ ایجاد می کنیم. اسکریپت مربوط به ایجاد دیتابیس، جدول و کوئری insert نمونه در زیر آورده شده است که می توانید در SQL Server خود از آن استفاده کنید.

ایجاد دیتابیس و جدول:

USE MASTER GO Check for the Database Exists.If the database is exist then  
drop  
and create new DB IF EXISTS   
(  
    SELECT  
    [name]  
    FROM  
    sys.databases  
    WHERE  
    [name] = 'projectDB'  
)  
DROP  
DATABASE projectDB GO CREATE DATABASE projectDB GO USE projectDB GO CREATE TABLE [dbo].[SCHED_Master]  
(  
    [ID] [int] NOT NULL,  
    [ProjectName] [varchar](100) NULL,  
    [ProjectType] int NULL,  
    [ProjectTypeName] [varchar](100) NULL,  
    [SCHED_ST_DT] [datetime] NULL,  
    [SCHED_ED_DT] [datetime] NULL,  
    [ACT_ST_DT] [datetime] NULL,  
    [ACT_ED_DT] [datetime] NULL,  
    [status] int null PRIMARY KEY CLUSTERED ([ID] ASC) WITH (  
    PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,  
    IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,  
  ALLOW_PAGE_LOCKS = ON  
) ON [PRIMARY]  
) ON [PRIMARY]

کوئری Insert:

INSERT INTO [dbo].SCHED_Master   
(  
    [ID], [ProjectName], [ProjectType],  
    [ProjectTypeName], [SCHED_ST_DT],  
    [SCHED_ED_DT], [ACT_ST_DT], [ACT_ED_DT],  
    [status]  
)  
VALUES  
(  
    ۱۰۰۱, 'Project-1', 1, 'Urgent', '2015-06-01 00:00:00.000',  
    '۲۰۱۵-۰۹-۰۲ ۰۰:۰۰:۰۰.۰۰۰', '۲۰۱۵-۰۶-۲۲ ۰۰:۰۰:۰۰.۰۰۰',  
    '۲۰۱۵-۰۸-۲۶ ۰۰:۰۰:۰۰.۰۰۰', ۱  
)   
INSERT INTO [dbo].SCHED_Master   
(  
    [ID], [ProjectName], [ProjectType],  
    [ProjectTypeName], [SCHED_ST_DT],  
    [SCHED_ED_DT], [ACT_ST_DT], [ACT_ED_DT],  
    [status]  
)  
VALUES  
(  
    ۱۰۰۲, 'Project-1', 2, 'Important',  
    '۲۰۱۵-۰۶-۱۲ ۰۰:۰۰:۰۰.۰۰۰', '۲۰۱۵-۸-۰۲ ۰۰:۰۰:۰۰.۰۰۰',  
    '۲۰۱۵-۰۶-۱۹ ۰۰:۰۰:۰۰.۰۰۰', '۲۰۱۵-۸-۲۹ ۰۰:۰۰:۰۰.۰۰۰',  
    ۱  
)   
INSERT INTO [dbo].SCHED_Master   
(  
    [ID], [ProjectName], [ProjectType],  
    [ProjectTypeName], [SCHED_ST_DT],  
    [SCHED_ED_DT], [ACT_ST_DT], [ACT_ED_DT],  
    [status]  
)  
VALUES  
(  
    ۱۰۰۳, 'Project-1', 3, 'Normal', '2015-06-28 00:00:00.000',  
    '۲۰۱۵-۰۹-۰۳ ۰۰:۰۰:۰۰.۰۰۰', '۲۰۱۵-۰۷-۰۲ ۰۰:۰۰:۰۰.۰۰۰',  
    '۲۰۱۵-۰۸-۲۴ ۰۰:۰۰:۰۰.۰۰۰', ۱  
)   
INSERT INTO [dbo].SCHED_Master   
(  
    [ID], [ProjectName], [ProjectType],  
    [ProjectTypeName], [SCHED_ST_DT],  
    [SCHED_ED_DT], [ACT_ST_DT], [ACT_ED_DT],  
    [status]  
)  
VALUES  
(  
    ۱۰۰۴, 'Project-2', 1, 'Urgent', '2015-06-28 00:00:00.000',  
    '۲۰۱۵-۰۸-۰۲ ۰۰:۰۰:۰۰.۰۰۰', '۲۰۱۵-۰۷-۰۲ ۰۰:۰۰:۰۰.۰۰۰',  
    '۲۰۱۵-۰۸-۲۶ ۰۰:۰۰:۰۰.۰۰۰', ۱  
)   
INSERT INTO [dbo].SCHED_Master   
(  
    [ID], [ProjectName], [ProjectType],  
    [ProjectTypeName], [SCHED_ST_DT],  
    [SCHED_ED_DT], [ACT_ST_DT], [ACT_ED_DT],  
    [status]  
)  
VALUES  
(  
    ۱۰۰۵, 'Project-2', 2, 'Important',  
    '۲۰۱۵-۰۷-۰۹ ۰۰:۰۰:۰۰.۰۰۰', '۲۰۱۵-۱۲-۲۲ ۰۰:۰۰:۰۰.۰۰۰',  
    '۲۰۱۵-۰۶-۲۸ ۰۰:۰۰:۰۰.۰۰۰', '۲۰۱۵-۱۲-۱۴ ۰۰:۰۰:۰۰.۰۰۰',  
    ۱  
)   
INSERT INTO [dbo].SCHED_Master   
(  
    [ID], [ProjectName], [ProjectType],  
    [ProjectTypeName], [SCHED_ST_DT],  
    [SCHED_ED_DT], [ACT_ST_DT], [ACT_ED_DT],  
    [status]  
)  
VALUES  
(  
    ۱۰۰۶, 'Project-2', 3, 'Normal', '2015-06-01 00:00:00.000',  
    '۲۰۱۵-۰۸-۰۴ ۰۰:۰۰:۰۰.۰۰۰', '۲۰۱۵-۰۶-۲۲ ۰۰:۰۰:۰۰.۰۰۰',  
    '۲۰۱۵-۰۸-۲۴ ۰۰:۰۰:۰۰.۰۰۰', ۱  
)

کوئری select نیز به شکل زیر است:

select ID,ProjectName,ProjectType,ProjectTypeName,SCHED_ST_DT,SCHED_ED_DT,ACT_ST_DT,
ACT_ED_DT,status
 from SCHED_Master

بعد از ایجاد جدول، برای نمایش جدول زمانی پروژه با استفاده از Pivot query، باید یک Stored Procedure ایجاد کنیم.

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

گام اول:

Procedure را با پارامترهای آن ایجاد می کنیم و متغیرهای مورد نیاز را در آن تعریف می کنیم تا در Stored Procedure از آن استفاده کنیم.

توجه داشته باشید که در اینجا دو متغیر FromDate و ToDate را به صورت استاتیک تعریف کردیم. می توانید آن را به عنوان پارامتر از SP تغییر دهید تا نتایج داینامیک را به عنوان هر بازه تاریخی دریافت نمایید.

Alter PROCEDURE [dbo].[usp_ProjectSchedule_Select] @projectId VARCHAR(10) = '' AS BEGIN -- 1. Declared for setting the Schedule Start and End date  
--۱.Start /////////////  
Declare @FromDate VARCHAR(20) = '2015-06-08' --DATEADD(mm,-12,getdate())  
Declare @ToDate VARCHAR(20) = '2016-05-06' --DATEADD(mm, 1, getdate())  
-- used for the pivot table result  
DECLARE @MyColumns AS NVARCHAR(MAX),  
@SQLquery AS NVARCHAR(MAX)

گام دوم:

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

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

Start IF OBJECT_ID('tempdb..#TEMP_EveryWk_Sndays') IS NOT NULL  
DROP  
TABLE #TEMP_EveryWk_Sndays  
DECLARE @TOTALCount INT  
Select  
@TOTALCount = DATEDIFF(dd, @FromDate, @ToDate);  
WITH d AS   
(  
SELECT  
    top (@TOTALCount) AllDays = DATEADD(  
    DAY,  
ROW_NUMBER() OVER   
(  
    ORDER BY  
    object_id  
),  
REPLACE(@FromDate, '-', '')  
)  
FROM  
    sys.all_objects  
)  
SELECT  
    distinct DATEADD  
    (  
        DAY,  
        ۱ - DATEPART(WEEKDAY, AllDays),  
        CAST(AllDays AS DATE)  
) WkStartSundays,  
۱ as status into #TEMP_EveryWk_Sndays  
FROM  
d  
where  
AllDays <= @ToDate   
  AND AllDays >= @FromDate -- test the sample temptable with select query  
  -- select * from #TEMP_EveryWk_Sndays  
  --///////////// End of 2.  

گام سوم:

این جدول temp را با جدول واقعی جدول زمانی join می کنیم تا تاریخ ها را مقایسه کرده و نتایج را تولید کند. ابتدا نتایج جدول زمانی را چک می کنیم و با استفاده از اجتماع، نتایج را با Actual resultادغام می کنیم و نتایج نهایی را در یک جدول temp دیگر وارد می کنیم تا نتایج pivot خود را تولید کنیم.

نمودار گانت استایل

توجه داشته باشید که برای داده های واقعی در لیست pivot نتایج را به صورت زیر نمایش داده ایم:

“۱-” : برای تاریخ پایان هر دو نتیجهSchedule و Actual. در این برنامه مقدار حاصل را بررسی می کنیم، اگر “۱-” بود متن آن را با پس زمینه قرمز “پایان” نشان می دهیم که نشان دهنده پایان هر پروژه می باشد.

“۰” : اگر مقدار حاصل صفر باشد، یعنی این روزها در هیچ Schedule یا روزهای Actualنیست و باید خالی گذاشته شوند.

“۱”: اگر مقدار “۱” باشد، شروع Schedule و پایان روزها را نشان می دهد که از رنگ آبی برای نمایش روزهای Schedule استفاده کردیم.

“۲”: اگر مقدار “۲” باشد، شروع Actual و پایان روزها را نشان می دهد که از رنگ سبز برای نمایش روزهای Actual استفاده کردیم.

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

این جدول temp برای زمان بندی جزییات با استفاده از نتایج، ایجاد شده است، در اینجا از اجتماع استفاده کردیم.

کوئری اول نتایج Schedule Project را برمی گرداند و کوئری دوم نتایج Actual Project. هر دوی این کوئری ها در یک جدول موقتی Temp وارد می شوند.

 

--۳.Start /////////////  
IF OBJECT_ID('tempdb..#TEMP_results') IS NOT NULL  
DROP  
TABLE #TEMP_results  
SELECT  
ProjectName,  
viewtype,  
ProjectType,  
resultnew,  
YMWK INTO #TEMP_results  
FROM  
(  
SELECT  
A.ProjectName ProjectName -- Our Project Name  
,  
'۱-Scd' viewtype -- Our View type first we display Schedule Data and then Actual  
,  
A.ProjectType ProjectType -- Our Project type here you can use your own status as Urgent,normal and etc  
,  
Case when cast(  
DATEPART(  
wk,  
max(A.SCHED_ED_DT)  
) as varchar(2)  
) = cast(  
DATEPART(wk, WkStartSundays) as varchar(2)  
) then -1 else case when min(A.SCHED_ST_DT)<= F.WkStartSundays   
      AND max(A.SCHED_ED_DT) >= F.WkStartSundays then 1 else 0 end end resultnew -- perfectResult as i expect   
      ,   
      RIGHT(  
        YEAR(WkStartSundays),   
        ۲  
      )+ '-' + 'W' + convert(  
        varchar(2),   
        Case when len(  
          DATEPART(wk, WkStartSundays)  
        )= '۱' then '0' + cast(  
          DATEPART(wk, WkStartSundays) as varchar(2)  
        ) else cast(  
          DATEPART(wk, WkStartSundays) as varchar(2)  
        ) END  
      ) as 'YMWK' -- Here we display Year/month and Week of our Schedule which will be displayed as the Column   
    FROM   
      -- here you can youe your own table   
      SCHED_Master A (NOLOCK)   
      LEFT OUTER JOIN #TEMP_EveryWk_Sndays F (NOLOCK) ON A.status= F.status   
    WHERE   
      -- Here you can check your own where conditions   
      A.ProjectName like '%' + @projectId   
      AND A.status = 1   
      AND A.ProjectType in (1, 2, 3)   
      AND A.SCHED_ST_DT <= @ToDate   
      AND A.SCHED_ED_DT >= @FromDate   
    GROUP BY   
      A.ProjectName,   
      A.ProjectType,   
      A.SCHED_ED_DT,   
      F.WkStartSundays   
    UNION   
      -- This query is to result the Actual result  
    SELECT   
      A.ProjectName ProjectName -- Our Project Name   
      ,   
      '۲-Act' viewtype -- Our View type first we display Schedule Data and then Actual   
      ,   
      A.ProjectType ProjectType -- Our Project type here you can use your own status as Urgent,normal and etc   
      ,   
      Case when cast(  
        DATEPART(  
          wk,   
          max(A.ACT_ED_DT)  
        ) as varchar(2)  
      ) = cast(  
        DATEPART(wk, WkStartSundays) as varchar(2)  
      ) then -1 else case when min(A.ACT_ST_DT)<= F.WkStartSundays   
      AND max(A.ACT_ED_DT) >= F.WkStartSundays then 2 else 0 end end resultnew -- perfectResult as i expect   
      ,   
      RIGHT(  
        YEAR(WkStartSundays),   
        ۲  
      )+ '-' + 'W' + convert(  
        varchar(2),   
        Case when len(  
          DATEPART(wk, WkStartSundays)  
        )= '۱' then '0' + cast(  
          DATEPART(wk, WkStartSundays) as varchar(2)  
        ) else cast(  
          DATEPART(wk, WkStartSundays) as varchar(2)  
        ) END  
      ) as 'YMWK' -- Here we display Year/month and Week of our Schedule which will be displayed as the Column   
    FROM   
      -- here you can youe your own table   
      SCHED_Master A (NOLOCK)   
      LEFT OUTER JOIN #TEMP_EveryWk_Sndays F (NOLOCK) ON A.status= F.status   
    WHERE   
      -- Here you can check your own where conditions   
      A.ProjectName like '%' + @projectId   
      AND A.status = 1   
      AND A.ProjectType in (1, 2, 3)   
      AND A.ACT_ST_DT <= @ToDate   
      AND A.ACT_ED_DT >= @FromDate   
    GROUP BY   
      A.ProjectName,   
      A.ProjectType,   
      A.SCHED_ED_DT,   
     F.WkStartSundays  
  ) q --3.End /////////////

گام چهارم:

در این مرحله، نتایج نهایی را با استفاده از pivot query از نتایج نهایی حاصل از جدول temp نمایش می دهیم.

--۴.Start /////////////  
--here first we get all the YMWK which should be display in Columns we use this in our next pivot query  
select  
@MyColumns = STUFF(  
(  
SELECT  
    ',' + QUOTENAME(YMWK)  
FROM  
#TEMP_results  
GROUP BY  
YMWK  
ORDER BY  
YMWK FOR XML PATH(''),  
TYPE  
).value('.', 'NVARCHAR(MAX)'),  
۱,  
۱,  
''  
) --here we use the above all YMWK to disoplay its result as column and row display  
set  
    @SQLquery = N 'SELECT ProjectName,viewtype,ProjectType,' + @MyColumns + N ' from  
(  
SELECT  
    ProjectName,  
    viewtype,  
    ProjectType,  
    YMWK,  
    resultnew as resultnew  
    FROM #TEMP_results  
) x  
pivot  
(  
    sum(resultnew)  
    for YMWK in (' + @MyColumns + N ')  
) p order by ProjectName, ProjectType,viewtype' exec sp_executesql @SQLquery;

کد کامل شده Stored Procedure به شکل زیر می باشد:

CREATE PROCEDURE [dbo].[usp_ProjectSchedule_Select]                                                      
@projectId           VARCHAR(10)  = ''                                                                   
                                                           
AS                                                                        
BEGIN                                                         
       
 -- ۱. Declared for setting the Schedule Start and End date  
 --۱.Start /////////////  
  Declare   @FromDate          VARCHAR(20)  = '2015-06-08'--DATEADD(mm,-12,getdate())                                                             
  Declare   @ToDate            VARCHAR(20)  = '2016-05-06'--DATEADD(mm, 1, getdate())    
  -- used for the pivot table result  
  DECLARE @MyColumns AS NVARCHAR(MAX),  
    @SQLquery  AS NVARCHAR(MAX)       
  --// End of 1.  
    
  -- ۲.This Temp table is to created for  get all the days between the start date and end date to display as the Column Header                                                        
 --۲.Start /////////////                                                                  
 IF OBJECT_ID('tempdb..#TEMP_EveryWk_Sndays') IS NOT NULL                                                                            
    DROP TABLE #TEMP_EveryWk_Sndays                                                                         
                                                                            
 DECLARE @TOTALCount INT                                            
    Select  @TOTALCount= DATEDIFF(dd,@FromDate,@ToDate);             
   WITH d AS                                                                         
            (                                                                        
              SELECT top (@TOTALCount) AllDays = DATEADD(DAY, ROW_NUMBER()                                                                         
                OVER (ORDER BY object_id), REPLACE(@FromDate,'-',''))                                                                        
              FROM sys.all_objects                                               
            )                                                                        
                                                                              
         SELECT  distinct DATEADD(DAY, 1 - DATEPART(WEEKDAY, AllDays), CAST(AllDays AS DATE))WkStartSundays  ,1 as status                                                                
                                                                             
 into #TEMP_EveryWk_Sndays                                                                      
    FROM d                               
   where                            
        AllDays  <= @ToDate                                        
   AND AllDays  >= @FromDate          
     
   -- test the sample temptable with select query  
  -- select * from #TEMP_EveryWk_Sndays  
   --///////////// End of 2.  
     
   -- ۳. This temp table is created toScedule details with result here i have used the Union ,  
   --the 1st query return the Schedule Project result and the 2nd query returns the Actual Project result both this query will be inserted to a Temp Table  
 --۳.Start /////////////  
 IF OBJECT_ID('tempdb..#TEMP_results') IS NOT NULL                                                                            
    DROP TABLE #TEMP_results     
   
       SELECT ProjectName,viewtype,ProjectType,resultnew,YMWK  
       INTO #TEMP_results  
       FROM(  
                SELECT                                                                  
                         A.ProjectName ProjectName   -- Our Project Name                                         
                        ,'۱-Scd' viewtype            -- Our View type first we display Schedule Data and then Actual                                                   
                        , A. ProjectType ProjectType -- Our Project type here you can use your own status as Urgent,normal and etc   
                        ,  Case when   cast(DATEPART( wk, max(A.SCHED_ED_DT)) as varchar(2)) =  cast(DATEPART( wk, WkStartSundays) as varchar(2))  then -1 else  
                            case when min(A.SCHED_ST_DT)<= F.WkStartSundays AND max(A.SCHED_ED_DT) >= F.WkStartSundays                                                          
                          then 1 else 0  end end resultnew  -- perfectResult as i expect     
                        ,  RIGHT(YEAR(WkStartSundays), 2)+'-'+'W'+convert(varchar(2),Case when len(DATEPART( wk, WkStartSundays))='1' then '0'+                                  
                          cast(DATEPART( wk, WkStartSundays) as varchar(2)) else cast(DATEPART( wk, WkStartSundays) as varchar(2)) END                               
                          ) as 'YMWK'  -- Here we display Year/month and Week of our Schedule which will be displayed as the Column                   
  
              FROM   -- here you can youe your own table                                                            
                         SCHED_Master A (NOLOCK)         
                                 LEFT OUTER JOIN   
                         #TEMP_EveryWk_Sndays F (NOLOCK)  ON A.status= F.status                                                              
                                                        
                WHERE  -- Here you can check your own where conditions       
                        A.ProjectName like '%' + @projectId                                                        
                    AND A.status=1                                                                            
                    AND A.ProjectType in (1,2,3)   
                    AND A.SCHED_ST_DT  <= @ToDate                                            
                    AND A.SCHED_ED_DT  >= @FromDate    
                GROUP BY                                                               
                       A.ProjectName                                                           
                     , A. ProjectType    
                     ,A.SCHED_ED_DT                     
                    ,F.WkStartSundays  
  
    UNION  -- This query is to result the Actual result  
            SELECT                                                                  
                         A.ProjectName ProjectName   -- Our Project Name                                         
                        ,'۲-Act' viewtype            -- Our View type first we display Schedule Data and then Actual                                                   
                        , A. ProjectType ProjectType -- Our Project type here you can use your own status as Urgent,normal and etc   
                        ,  Case when   cast(DATEPART( wk, max(A.ACT_ED_DT)) as varchar(2)) =  cast(DATEPART( wk, WkStartSundays) as varchar(2))  then -1 else  
                            case when min(A.ACT_ST_DT)<= F.WkStartSundays AND max(A.ACT_ED_DT) >= F.WkStartSundays                                                          
                           then 2 else 0  end end resultnew  -- perfectResult as i expect   
                          
                        , RIGHT(YEAR(WkStartSundays), 2)+'-'+'W'+convert(varchar(2),Case when len(DATEPART( wk, WkStartSundays))='1' then '0'+                                  
                              cast(DATEPART( wk, WkStartSundays) as varchar(2)) else cast(DATEPART( wk, WkStartSundays) as varchar(2)) END                               
                              ) as 'YMWK'  -- Here we display Year/month and Week of our Schedule which will be displayed as the Column                   
  
              FROM   -- here you can youe your own table                                                            
                         SCHED_Master A (NOLOCK)         
                                 LEFT OUTER JOIN   
                         #TEMP_EveryWk_Sndays F (NOLOCK)  ON A.status= F.status                                                              
                                                        
                WHERE  -- Here you can check your own where conditions        
                        A.ProjectName like '%' + @projectId                                                       
                    AND A.status=1                                                                            
                    AND A.ProjectType in (1,2,3)   
                    AND A.ACT_ST_DT  <= @ToDate                                            
                    AND A.ACT_ED_DT  >= @FromDate    
                GROUP BY                                                               
                       A.ProjectName                                                           
                     , A. ProjectType    
                     ,A.SCHED_ED_DT                     
                    ,F.WkStartSundays  
  
     )  q                   
  
 --۳.End /////////////  
  
 --۴.Start /////////////  
   
 --here first we get all the YMWK which should be display in Columns we use this in our next pivot query  
select @MyColumns = STUFF((SELECT ',' + QUOTENAME(YMWK)   
                    FROM #TEMP_results  
                    GROUP BY YMWK  
                    ORDER BY YMWK  
            FOR XML PATH(''), TYPE  
            ).value('.', 'NVARCHAR(MAX)')   
        ,۱,۱,'')  
 --here we use the above all YMWK  to disoplay its result as column and row display  
set @SQLquery = N'SELECT ProjectName as Project,viewtype as ViewType,ProjectType as PrpjectType,' + @MyColumns + N' from   
             (  
                 SELECT   
       ProjectName,   
       viewtype,  
       ProjectType,  
       YMWK,  
        resultnew as resultnew   
    FROM #TEMP_results  
            ) x  
            pivot   
            (  
                 sum(resultnew)  
                for YMWK in (' + @MyColumns + N')  
            ) p  order by ProjectName, ProjectType,viewtype'  
  
exec sp_executesql @SQLquery;  
                                     
END 

اگر Procedure خود را اجرا کنیم، خروجی نهایی آن به شکل زیر خواهد بود. همانطور که مشاهده می کنید، نتایج هفتگی را با استفاده از pivot query نمایش دادیم.

نمودار گانت استایل

ایجاد یک برنامه Windows Form در ویژوال استودیو:

همانطور که در شکل زیر نمایش داده شده است، یک پروژه از نوع Windows Form Application ایجاد می کنیم، نام مناسب و محل ذخیره سازی آن را انتخاب می کنیم.

نمودار گانت استایل

فرم خود را طراحی می کنیم. در این فرم از یک Textbox برای جستجوی جزییات بر اساس نام پروژه ها و یک button برای اتصال (bind) نتایج استفاده کرده ایم.

توجه داشته باشید که از DataGridView helper class برای ایجاد DataGridView در زمان اجرا به جای ایجاد در زمان طراحی استفاده کرده ایم.

Form Load:

در Form Load، DataGridView را مقداردهی اولیه کرده و با استفاده از helper class به کنترل پنل اضافه می کنیم. بعد از مقداردهی آن، داده ها را به Grid متصل می کنیم.

private void shanuDatagridViewPaint_Load(object sender, EventArgs e)   
{  
    MasterGrid_Initialize();  
    bindData();  
}  

مقداردهی Grid:

با استفاده از helper class، GridView را در زمان اجرا ایجاد خواهیم کرد. تمام پارامترها مانند رنگ پس زمینه Grid، عرض و ارتفاع آن و تمام ویژگی ها را برای ایجاد در زمان اجرا را به صورت زیر ارسال می کنیم:

public void MasterGrid_Initialize()  
{  
    //First generate the grid Layout Design  
    Helper.ShanuDGVHelper.Layouts(Master_shanuDGV, Color.White, Color.WhiteSmoke, Color.WhiteSmoke, false, Color.WhiteSmoke, true, Color.FromArgb(112, 128, 144), false, false, false, Color.White, 40, 20, "small");  
    //Set Height,width and add panel to your selected control  
    Helper.ShanuDGVHelper.Generategrid(Master_shanuDGV, pnlGrid, 1000, 600, 10, 10);  
    Master_shanuDGV.CellFormatting += new DataGridViewCellFormattingEventHandler(MasterDGVs_CellFormatting);  
}

همانطور که مشاهده می کنید، بعد از مقداردهی DataGridView از رویداد CellFormatting استفاده کرده ایم.

رویداد CellFormatting :

در این رویداد، نتیجه هر سلول را چک خواهیم کرد و با توجه به مقدار حاصل رنگ پس زمینه آن را انتخاب خواهیم کرد تا نمودار گانت خود را درون DataGridView نمایش دهیم. همچنین آنها را از لحاظ نوع پروژه هم چک خواهیم کرد و به آنها دو نوعactual و schedule با رنگ های متمایز می دهیم تا نتیجه را به صورت گرافیکی تری مشاهده کنیم.

void MasterDGVs_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) 
{  
    try {  
        ProjectType = ds.Tables[0].Rows[e.RowIndex]["PrpjectType"].ToString();  
        if (e.ColumnIndex > 2)   
        {  
            Color color1 = Color.FromArgb(116, 176, 30); //Green  
            Color color2 = Color.FromArgb(0, 76, 153); //Blue  
            if (e.Value.ToString() == "0")   
            {  
                e.Value = "";  
            }  
            if (ProjectType == "1")   
            {  
                color1 = Color.FromArgb(116, 176, 30); //Green  
                color2 = Color.FromArgb(0, 76, 153); //Blue  
            } else if (ProjectType == "2")   
            {  
                color1 = Color.FromArgb(218, 165, 32); //golden rod  
                color2 = Color.FromArgb(255, 215, 0); //GOLD   
            } else if (ProjectType == "3")   
            {  
                color1 = Color.FromArgb(147, 112, 219); //medium purple  
                color2 = Color.FromArgb(255, 105, 180); //hot pink  
            }  
            switch (e.Value.ToString())   
            {  
                case "-1":  
                    e.CellStyle.BackColor = Color.FromArgb(255, 69, 0); // Orange  
                    e.CellStyle.SelectionBackColor = Color.FromArgb(255, 69, 0); // Orange  
                    e.CellStyle.ForeColor = Color.White;  
                    e.CellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;  
                    e.Value = "END";  
                    break;  
                case "2":  
                    e.CellStyle.BackColor = color1;  
                    e.CellStyle.SelectionBackColor = color1;  
                    e.Value = "";  
                    break;  
                case "1":  
                    e.CellStyle.BackColor = color2;  
                    e.CellStyle.SelectionBackColor = color2;  
                    e.Value = "";  
                    break;  
            }  
        }  
    } catch (Exception ex) {}  
}

کلیک دکمه جستجو:

در رویداد کلیک دکمه و رویدادForm Load، متد bindData() را برای اتصال داده ها به DataGridView فراخوانی می کنیم.

نمودار گانت استایل

private void btnSearch_Click(object sender, EventArgs e)  
{  
   bindData();  
}

متد bindData():

در این متد، نامstored procedure و پارامترها را به کلاس Business Logic ارسال می کنیم. از کلاس Business logic نام stored procedure و پارامترها به کلاس DAL ارسال می شود که این کلاس به دیتابیس متصل می شود، نتایج را دریافت می کند و آن را به صورت یک DataSet برمی گرداند. DataSet نتیجه نهایی از BL در فرم دریافت شده و نتایج را به DatagridView متصل می کند.

private void bindData()   
{  
    try {  
        // Bind data to DGV.  
        SortedDictionary < string, string > sd = new SortedDictionary < string, string > () {};  
        sd.Add("@projectId", txtProjectID.Text.Trim());  
        ds = new ShanuProjectScheduleBizClass().SelectList(sd);  
        Master_shanuDGV.DataSource = null;  
        if (ds.Tables[0].Rows.Count > 0)   
        {  
            Master_shanuDGV.DataSource = ds.Tables[0];  
        }  
    } catch (Exception ex) {}  
}  

نکته: شما حتی می توانید این برنامه را طوری گسترش دهید که با استفاده از رویداد DatagridviewCell painting خروجی به صورت بسیار گرافیکی تر از این نمایش دهد. می توانید فرمت دلخواه خود را با استفاده از این رویداد رسم نمایید.

نکته ای درباره Connection string:

می توانید “DBConnection.txt” را در فولدر bin پیدا کنید، آن را مطابق تنظیمات SQL Server خود تغییر دهید.

تغییر Connection String در کد:

نمودار گانت استایل

“BizBase.cs” را درون فولدر Helper/Biz می توانید پیدا کنید. Connection String را به رشته اتصال SQL Server محلی خود تغییر دهید.

داریوش فرخی

داریوش فرخی هستم از سال 92 شروع به یادگیری برنامه نویسی و از سال 93 در بخش برنامه نویسی و تولید محتوای سایت mspsoft.com مشغول هستم. فعالیتم نیز بیشتر در زمینه های برنامه نویسی با سی شارپ و asp.net بوده است. اوقات فراغتم را هم غالبا با تماشای فیلم یا بازی های کامپیوتری پر میکنم .

نوشته‌های مرتبط

دیدگاه‌ها

*
*

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