星期日, 5月 31, 2015

[SSRS] 串聯參數

根據 第 4 課:加入串聯參數 (SSRS) 這篇的練習

主報表設定

dsMain DataSet 語法 - 報表主語法
USE [AdventureWorks2014]
GO

SELECT 
    PC.Name AS Category,
    PSC.Name AS Subcategory,
    P.Name AS Product,
    SOH.[OrderDate],
    SOH.SalesOrderNumber,
    SD.OrderQty, 
    SD.LineTotal
FROM [Sales].[SalesPerson] AS SP 
    JOIN [Sales].[SalesOrderHeader] AS SOH ON SP.[BusinessEntityID] = SOH.[SalesPersonID]
    JOIN Sales.SalesOrderDetail AS SD ON SD.SalesOrderID = SOH.SalesOrderID
    JOIN Production.Product AS P ON SD.ProductID = P.ProductID
    JOIN Production.ProductSubcategory AS PSC ON P.ProductSubcategoryID = PSC.ProductSubcategoryID
    JOIN Production.ProductCategory AS PC ON PC.ProductCategoryID = PSC.ProductCategoryID
WHERE PC.ProductCategoryID = @CategoryID
    AND PSC.ProductSubcategoryID = @SubcategoryID
    AND P.ProductID = @ProductID
根據主語法產生的精靈報表

[SSRS] 串連參數-2

星期五, 5月 29, 2015

[C#] 動態載入控制項

在 PlaceHolder 內產生 10 個 Button 並設計 Click 事件必須顯示該 Button Text 資料
public partial class _Default : System.Web.UI.Page
{
    // 動態載入控件,建議在 Page_Init 內進行,這篇紀錄唯一的重點
    protected void Page_Init(object sender, EventArgs e)
    {
        for (int i = 1 ; i <= 10; i++)
        {
            Button btn = new Button();
            string btnDescript = string.Format("btn{0}", i.ToString("00"));

            btn.ID = btnDescript;
            btn.Text = btnDescript;
            btn.Click += btn_Click;
            PHButton.Controls.Add(btn);
        }
    }

    void btn_Click(object sender, EventArgs e)
    {
        Button btn = sender as Button;
        if (btn == null) return;
        Response.Write(btn.Text);
    }
}

[C#] 動態載入控制項

星期日, 5月 24, 2015

[C#] PictureBox - 亂數產生圓

論壇問題,討論 Random class 使用,拿來練習

Random 產生相同值的 MSDN 說明
預設的種子值是從系統時鐘衍生而來,而且解析度有限。 因此,若在極短時間內連續呼叫預設建構函式,建立不同的 Random 物件,這些物件就會有完全相同的預設種子值,也就會產生完全相同的幾組亂數。 只要使用單一 Random 物件來產生所有的亂數,就可以避免這個問題。 您也可以解決它,方法是修改系統時鐘傳回的種子值,然後明確地提供這個新的種子值給 Random(Int32) 建構函式。
採用下列寫法來避免 Random 產生相同值
Random r = new Random(Guid.NewGuid().GetHashCode());

畫面配置,利用 Timer 每隔一秒自動畫圓

C# Code
namespace DrawRandom
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // Timer 預設每一秒觸發一次
            tmrDraw.Enabled = false;
            tmrDraw.Interval = 1000;
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            // 覆蓋一張顏色畫布在 PictureBox 上
            Graphics g = PBRandom.CreateGraphics();
            g.Clear(this.BackColor);
        }

        public void DrawPie()
        {
            int
              PieWidth = 100,
              PieHeight = 100,
              PBWidth = PBRandom.Width,
              PBHeight = PBRandom.Height;

            Random RX = new Random(Guid.NewGuid().GetHashCode());
            Random RY = new Random(Guid.NewGuid().GetHashCode());
            Random RR = new Random(Guid.NewGuid().GetHashCode());
            Random RG = new Random(Guid.NewGuid().GetHashCode());
            Random RB = new Random(Guid.NewGuid().GetHashCode());

            // 限制亂數範圍
            // 1. 圓的寬和高必須在畫布內
            // 2. RGB 數字必須在 0 - 255 之間
            int
              X = RX.Next(0, PBWidth - PieWidth),
              Y = RY.Next(0, PBHeight - PieHeight),
              R = RR.Next(0, 255),
              G = RG.Next(0, 255),
              B = RB.Next(0, 255);

            // 在 PictureBox 上產生畫布
            Graphics g = PBRandom.CreateGraphics();

            // 設定 Brush 顏色
            Color RandomColor = new Color();
            RandomColor = Color.FromArgb(R, G, B);
            SolidBrush brush = new SolidBrush(RandomColor);

            // 畫實心圓
            g.FillPie(brush, X, Y, PieWidth, PieHeight, 0, 360);
        }

        #region Timer 相關
        private void txtTimerStart_Click(object sender, EventArgs e)
        {
            tmrDraw.Start();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            tmrDraw.Stop();
        }

        private void tmrDraw_Tick(object sender, EventArgs e)
        {
            DrawPie();
        } 
        #endregion
    }
}

星期五, 5月 22, 2015

[C#] GridView 練習

論壇問題 - GridView 練習題,討論內還有大神的 Youtube 教學

問題說明

[C#] GridView 練習-1

[C#] GridView 練習-2

大神 YouTube 教學

星期三, 5月 20, 2015

工業電腦主機板著火

廠長回報工業用 PC 傳出濃濃的塑膠味且有看見煙飄出,一聽見描述直覺是 Power 燒掉,趕快過去把電腦搬回來檢測。

電源檢查器 OK,拆開外殼也沒有看見燒掉的部分,拿新 Power 對 PC 進行測試,一通電就看見主機板燒起來, 真的是一小團火焰在那燒,Orz

下圖紅框框就是起火點

主機板失火

處理事件簿:
  • 20150430:
    • 淘寶網上找到比較接近該主機板型號,一片 3,2000 元,暈
    • 工業電腦台灣代理商目前沒現貨,詢問德國總公司
  • 20150504:
    • 代理商回電告知德國公司,該主機板為設備廠商專有型號,只能直接跟廠商直接購買
    • 決定老方法處理,Ghost 到一般 PC 內來使用
  • 20150505:
    • 找台比較接近的主機,利用 Ghost 弄出一顆硬碟,確保原本硬碟不會在測試過程中破壞掉,Ghost 硬碟放上一般 PC 測試,可正常開機,解決硬體問題
    • 開啟工業軟體時,發現功能不完全,懷疑是 COM Port 通訊有問題
  • 20150510:
    • 工業軟體部分一直沒有搞定,原本以為是 COM Port 出問題,因此買了 IDE 的 COM Port 來外接和 COM Tester ,利用 Tester 來判斷是不是正常通訊,後來發現 COM Port 不是問題所在
  • 20150511:
    • 經過交叉測試,確定西門子通訊卡是正常,但卻沒有正常作動,卡上燈號理論上一開機就應該要亮燈,但卻沒有
    • 老大從軟體設定方面著手,有找相關設定,讓卡上燈號順利亮起來,且工業軟體上消失的功能,也都出現
  • 20150512:
    • 上線測試,沒問題,搞定
  • 20150513:
    • 維修商技術人員來電告知,剛好有其他廠商也遇上工業電腦主機板燒掉問題,想要系統移轉至一般 PC,德國原廠可以支援該移轉動作,想詢問我們要不要一起弄,沒想到我們已經搞定
    • 一張西門子通訊卡要 30,000 元,一開始懷疑它掛掉時,很擔心買不到
    • COM Tester 測試 COM Port 時,有發現到似乎不需要它,Tester 燈號完全沒有閃爍,詢問才知道,那是觸控螢幕用

星期一, 5月 18, 2015

[SQL] ISNULL() 回傳值

使用者回報說,報表列印功能,規格欄位資訊沒有顯示完全,從下圖就可以看見第四項資訊全部都被截斷

[SQL] ISNULL() 回傳值-2

從 TSQL 語法發現到規格資訊(Mt_Nam_Dim)是透過 ISNULL() 來判斷產生,原資料庫的資料是完整的,ISNULL() 回傳值就是問題所在
SELECT
    BD.BillNO,
    ID.MtCode,
    ISNULL(M.Mt_num, D.Mt_Num) AS Mt_Num,
    ISNULL(M.Mt_Nam_Dim,D.Spec) AS Mt_Nam_Dim,
    ID.RushQty,
    ID.RushPrice,
    ID.SubTotal
FROM PurchBillDetail AS BD
    JOIN PurchPayDetail AS PD ON BD.PNO = PD.PNO AND BD.RowNO = PD.RowNO
    JOIN PurchIn AS I ON PD.PINO = I.PINO
    JOIN PurchInDetail AS ID ON I.PINO = ID.PINO
    JOIN PurchDetail AS D ON ID.PurNO = D.PurNO AND ID.MtCode = D.MtCode
    LEFT JOIN MtData AS M ON ID.MtCode = M.MtCode
WHERE BD.BillNO = 'P1040518028'
MSDN ISNULL() 相關資訊
  • 語法:ISNULL ( check_expression , replacement_value )
  • 傳回類型:傳回與 check_expression 相同的類型。 如果提供了常值 NULL 做為 check_expression,就會傳回 replacement_value 的資料類型。 如果提供了常值 NULL 做為 check_expression 但是沒有提供任何 replacement_value,就會傳回 int。
  • 備註:如果 check_expression 值不是 NULL,便傳回這個值;否則,如果類型不同,便在 replacement_value 隱含地轉換成 check_expression 的類型之後,再傳回它。 如果 replacement_value 比 check_expression 長,replacement_value 可能會被截斷。
從備註中發現到線索,查欄位資料型態長度,發現分別
  • Mt_Nam_Dim:char(100)
  • Spec:varchar(500)
資料長度從 500 變成 100,規格說明也就被截斷,好細的小細節,Orz

修正 TSQL,在 ISNULL() 內強制把第一參數轉型為 varchar(500) 來避免這個問題
SELECT
    BD.BillNO,
    ID.MtCode,
    ISNULL(M.Mt_num, D.Mt_Num) AS Mt_Num,
    ISNULL
    (
        CAST(M.Mt_Nam_Dim AS varchar(500)),  -- char(100)
        D.Spec                               -- varchar(500)
    ) AS Mt_Nam_Dim,
    ID.RushQty,
    ID.RushPrice,
    ID.SubTotal
FROM PurchBillDetail AS BD
    JOIN PurchPayDetail AS PD ON BD.PNO = PD.PNO AND BD.RowNO = PD.RowNO
    JOIN PurchIn AS I ON PD.PINO = I.PINO
    JOIN PurchInDetail AS ID ON I.PINO = ID.PINO
    JOIN PurchDetail AS D ON ID.PurNO = D.PurNO AND ID.MtCode = D.MtCode
    LEFT JOIN MtData AS M ON ID.MtCode = M.MtCode
WHERE BD.BillNO = 'P1040518028'
下圖為正確顯示

[SQL] ISNULL() 回傳值-1

星期五, 5月 15, 2015

[SQL] sp_executesql 參數限制

在 Store Procedure 中,利用 sp_executesql 執行動態 TSQL 語法時,出現下面的錯誤訊息
程序必須有類型 'ntext/nchar/nvarchar' 的參數 '@statement'。
閱讀 MSDN 上發現,原來 sp_executesql 的第一、二個參數都必須是 Unicode
  • @stmt:Transact-SQL 陳述式或批次的 Unicode 字串。@stmt 必須是 Unicode 常數或 Unicode 變數。
  • @params:包含 @stmt 的所有內嵌參數定義的字串。 此字串必須是 Unicode 常數或 Unicode 變數。
USE [AdventureWorks2014]
GO

CREATE PROCEDURE [dbo].[uspQtyStat] 
(
    @StartDate date, 
    @EndDate date, 
    @ProdNO char(5) = '', 
    @Status nchar(4) = ''
)
AS
BEGIN

    SET NOCOUNT ON;

    DECLARE @TSQL varchar(max) -- 問題所在,不是 Unicode
 
    SET @TSQL = 
        'SELECT 
             ProdName , 
             ProdNO , 
             Status , 
             Area ,
             COUNT(*) AS Qty
         FROM GVPractice
         WHERE CreateDate BETWEEN @StartDate AND @EndDate'
 
    IF @ProdNO <> ''
        SET @TSQL += 
            '
            AND ProdNO = @ProdNO'

    IF @Status <> ''
        SET @TSQL +=
            '
            AND Status = @Status'
 
    SET @TSQL += 
        '
        GROUP BY ProdName , ProdNO , Status , Area'

    EXEC dbo.sp_executesql 
        @TSQL,
        N'@StartDate date, @EndDate date, @ProdNO char(5), @Status nchar(4)',
        @StartDate ,
        @EndDate ,
        @ProdNO ,
        @Status

END
GO

把 @TSQL 宣告為 nvarchar(max) 就可以執行

星期六, 5月 09, 2015

[C#] IComparer<T>

閱讀 泛型介面 文章時,發現 IComparer<T> 範例,把之前這篇學習紀錄 [C#] IComparable 和 IComparer,改成利用泛型來練習

[C#] IComparer - 1