星期五, 3月 25, 2016

[C#] OfType()、Cast()

之前在撰寫 WinForm 篩選控件時,很自然都會使用 OfType() 來做,一直都是把它當成 WHERE 來看待,閱讀 極意之道次世代 .NET Framework 3.5資料庫開發聖典 才發現到其內部運作模式
  • OfType() 和 Cast() 都是針對集合元素來進行轉型
  • OfType:利用 [as] 運算子進行轉型,轉型失敗就忽略該元素
  • Cast():利用 Convert.ChangeType() 進行轉型,轉型失敗拋出 InValidCast Exception

簡單範例

在 WinForm 內放置一個 Panel,並在 Panel 內放不同的控件,利用 OfType()、Cast() 來篩選 Panel 內 TextBox 控件

[C#] OfType()、Cast()-1

namespace LINQ_OfType_Cast
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnOfType_Click(object sender, EventArgs e)
        {
            string CtlNames = string.Empty;
            foreach (TextBox txt in panel1.Controls.OfType<TextBox>())
            {
                CtlNames += txt.Name + Environment.NewLine;
            }
            MessageBox.Show(CtlNames , "OfType() 結果" , MessageBoxButtons.OK , MessageBoxIcon.Information);
        }

        private void btnCast_Click(object sender, EventArgs e)
        {
           // 預期會丟出 InvlidCastException
           foreach (TextBox txt in panel1.Controls.Cast<TextBox>())
           {
 
           }
        }
    }
}
OfType() 結果

[C#] OfType()、Cast()-2

Cast() 結果

[C#] OfType()、Cast()-3

這樣更清楚使用 OfType()、Cast() 使用時機

星期四, 3月 24, 2016

[ADO.NET] 利用 SqlDataAdapter 產生預存程序

閱讀 極意之道次世代 .NET Framework 3.5資料庫開發聖典 發現,原來 SqlDataAdapter Wizard 可以根據 SelectCommand 產生對應的 INSERT、UPDATE 和 DELETE 預存程序,雖然說 Wizard 產生的 TSQL 語法慘不忍賭,但總比重頭開始,一個字一個字打來的好

SqlDataAdapter 選擇命令類型,選擇 [建立新的預存程序],之前都直接手打預存程序,然後選擇 [使用現有的預存程序],完全忽視第二個選項,Orz

[ADO.NET] 利用 SqlDataAdapter 產生預存程序-1

星期四, 3月 17, 2016

[RV] 列印本機報表而不進行預覽

實務上有列印報表要直接輸出至印表機,不需要預覽、也不需要出現列印視窗,找到這篇文章 逐步解說:列印本機報表而不進行預覽 來學習,基本上就是 LocalReport 搭配 PrintDocument 來進行列印

該練習需要參考下面三個 dll
  • System.Drawing
  • System.Windows.Forms
  • Microsoft.ReportViewer.Winforms
[RV] 列印本機報表而不進行預覽-2

該練習中使用的報表(Report.rdlc)請參考這篇 [RV] 使用 WinForms ReportViewer 控制項 內容,資料來源為 AdventureWorks2014 內的員工資料表,只抓出 10 筆來列印,避免實際練習要印出一堆紙
CREATE PROCEDURE [dbo].[GetEmployData]
AS
SELECT TOP 10
    E.BusinessEntityID ,
    P.LastName ,
    P.FirstName ,
    E.JobTitle ,
    E.Birthdate ,
    E.HireDate
FROM [HumanResources].[Employee] AS E
    JOIN Person.Person AS P ON E.BusinessEntityID = P.BusinessEntityID

星期三, 3月 16, 2016

[RV] 部屬 ReportViewer 控制項

把寫好的 WinForm 丟到 Client 端執行時,要開啟該 Form 時出現下面錯誤訊息

[RV] 部屬 ReportViewer 控制項-1
System.IO.FileNotFoundException:無法載入檔案或組件 'Microsoft.ReportViewer.WinForms, Version = 11.0.0.0' , Culture=neutral, PublicKeyToken = 89845dcd8080cc91' 或其相依性的其中之一。系統找不到指定的檔案
查到 部署報表和 ReportViewer 控制項 這篇文章提到,需要這 5 個 dll 檔案
  • Microsoft.ReportViewer.Common.dll
  • Microsoft.ReportViewer.ProcessingObjectModel.dll
  • Microsoft.ReportViewer.WebForms.dll
  • Microsoft.ReportViewer.WinForms.dll
  • Microsoft.ReportViewer.DataVisualization.dll
在專案中加入參考後,可以正常進入 Form,但沒想到 ReportViewer Render 時,又跑出下面錯誤訊息

[RV] 部屬 ReportViewer 控制項-2
System.IO.FileNotFoundException:無法載入檔案或組件 'Microsoft.SqlServer.Types, Version = 11.0.0.0' , Culture=neutral, PublicKeyToken = 89845dcd8080cc91' 或其相依性的其中之一。系統找不到指定的檔案
依樣畫葫蘆把 Microsoft.SqlServer.Types 也加入專案參考,ReportViewer 終於可以正常顯示,在 8 x 3 的標籤紙上列印出 3 張 QRCode,Orz

[RV] 部屬 ReportViewer 控制項-5


星期二, 3月 15, 2016

[C#] txt 資料放進 TextBox 內

論壇問題,要把下面的 txt 內容塞進 WinForm 畫面上 18 個 TextBox 內

[C#] txt 資料放進 TextBox 內-1

思考邏輯:讀每一行資料時,計算是屬於哪一個 TextBox 的資料,並透過 Controls.Find() 來尋找控件,並把值塞進去;TextBox 控件命名,要從 1 - 18 依序命名

星期三, 3月 09, 2016

[SQL] 分頁還原

紀錄當 DB 毀損時,利用分頁還原的步驟,利用 AdventureWorks2014 的 HumanResources.Employee Table 當成練習目標

事先準備
-- AdventureWorks2014 預設是簡單模式,分頁還原無法在該模式下進行,
-- 因此轉為完整模式
ALTER DATABASE AdventureWorks2014 SET Recovery FULL

-- 要進行分頁還原前,當然要有備份檔案存在
BACKUP DATABASE AdventureWorks2014 TO DISK = N'D:\PageRestoreDemo.bak' 
BACKUP LOG AdventureWorks2014 TO DISK = N'D:\PageRestoreDemo.bak' 

-- 對 DB 進行破壞,請參考 [SQL] 模擬資料庫毀損 該篇文章
-- 使用 DBCC WRITEPAGE 必須是單一使用者模式
ALTER DATABASE AdventureWorks2014 SET SINGLE_USER WITH ROLLBACK IMMEDIATE
-- 毀損 PK_Employee_BusinessEntityID 叢集索引,所在的 Page 733 => Data Page
DBCC WRITEPAGE('AdventureWorks2014', 1, 733, 60, 1, 0x00, 1)
-- 切回多人模式
ALTER DATABASE AdventureWorks2014 SET multi_user WITH ROLLBACK IMMEDIATE

星期一, 3月 07, 2016

[RV] 顯示外部圖片

實務上有該需求,了解一下要如何做到,下面為顯示外部圖片的簡單紀錄

建立報表

新增報表 ExternalPhoto.rdlc 並進行下列設定,報表資料 => 參數 => 滑鼠右鍵 => 加入參數
參數名稱:PhotoPath
設定完後的報表資料視窗
在報表內插入影像控件,影像屬性內的影像來源設定為外部
使用此影像運算式,一定要有 "file:///" 字樣在變數前面
= "file:///" & Parameters!PhotoPath.Value

ReportViewer 控件

拖曳 ReportViewer 控件到 Form 中,並選擇報表
設定變數來源

利用 Code 把報表中所需的 @PhotoPath 變數丟進報表內
using Microsoft.Reporting.WinForms;

namespace RSPhoto
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // 欲連結外部圖片必須設定該屬性
            reportViewer1.LocalReport.EnableExternalImages = true;
            // 設定 Report 內的 @PhoroPath 參數資料
            ReportParameter PhotoPath = new ReportParameter("PhotoPath", @"D:\Demo.jpg");
            reportViewer1.LocalReport.SetParameters(new ReportParameter[] { PhotoPath });
            // 更新 ReportViewer
            reportViewer1.RefreshReport();
        }
    }
}
顯示設定結果

星期五, 3月 04, 2016

[RV] 使用 WinForms ReportViewer 控制項

網路上找到這篇文章 Using ReportViewer control in Windows Forms (WinForms) Application using C# and VB.Net,覺得有幫助就拿來練習,資料抓 AdventureWorks2014 內的員工資料

建立 DataSet

新增資料集:Employee.xsd

[RV] 使用 WinForms ReportViewer 控制項-1

在 Employee.xsd 內新增 DataTable:dtEmploy,並建立 DataColumn

[RV] 使用 WinForms ReportViewer 控制項-2

HireDate 和 BirthDate 的 DataType 要改為 System.DateTime,預設為 System.String

[RV] 使用 WinForms ReportViewer 控制項-3

完成後就可以在資料來源視窗內看見該 DataSet

[RV] 使用 WinForms ReportViewer 控制項-4

星期三, 3月 02, 2016

[SQL] Linked Server 讀取 VFP 檔案

看見這篇 論壇討論,想說來試看看,畢竟 VFP 現在還是公司主力,雖然已經從純 VFP 改為 VFP + SQL Server,實務上也不會有這樣的需求和應用,加減學吧

測試環境:
  • Win10 64bit
  • SQL Server 2005 Express 32bit
  • VFP 9.0

星期二, 3月 01, 2016

[VFP] Automation 應用 - 儲存為 xls 格式

配合 HR 提出的需求,HR PC 上是 Office 2016 希望轉出來的 Excel 格式為 xls 格式,這樣才能匯入政府網站,原是想說把副檔名改為 xls 就行,沒想到打開 Excel 時,會出現下面的錯誤

SaveAs 語法
loExcel.ActiveWorkbook.SaveAs("D:\Excel.XLS")
打開 Excel 時出現的錯誤訊息

[VFP] Automation 應用 - 儲存為 xls 格式-1

利用 Excel 錄製 VBA 來觀察,看看轉為 xls 到底還需要甚麼參數,FileFormat:=xlExcel8 就是你啦
Sub 巨集1()
'
' 巨集1 巨集
'

'
    ChDir "C:\Users\jengting\Desktop"
    ActiveWorkbook.SaveAs Filename:="C:\Users\jengting\Desktop\活頁簿1.xls", _
        FileFormat:=xlExcel8, 
        Password:="", 
        WriteResPassword:="", _
        ReadOnlyRecommended:=False, 
        CreateBackup:=False
End Sub
把 VFP Automation 語法改為下述,xlExcel8 參數值為 56,就可以順利轉為 xls 格式啦
loExcel.ActiveWorkbook.SaveAs("D:\Excel.XLS" , 56)