This page looks plain and unstyled because you're using a non-standard compliant browser. To see it in its best form, please visit upgrade to a browser that supports web standards. It's free and painless.

取之於網路用之於網路-只寫程式 會員登入 會員註冊

1.源由

在實務上,一支應用程式偶而會出現難以想像的錯誤情境,這情境在意料之外所以沒有預防,也不知為何會出現。
這時「偵錯模式」就派上用場了。以偵錯模式來追蹤問題的起源,找出問題根結後,答案也就不遠了。

「偵錯模式」設計目地在於偵察問題所在。其實這個模式本身是自我矛盾的。應用程式本身是無法自我偵錯的,那到底是如何偵錯的?方法就是加入“額外的程式碼”在關鍵的關卡紀錄(logging)執行了什麼程序、紀錄進出了什麼資料。再由這些紀錄去看問題的位置,去查出問題的原因。

2.目的, spec. statement.

試寫應用程式偵錯模式。
模擬一應用程式的組織,含蓋了主模組與副模組,與副模組的連結方式有靜態參考(static reference)與動態參考(dynamc reference)方式連結,如下圖:

Trace Lab modules

此例中:
主模組:conApp_TraceLab.exe
副模組一:ClassLibrary1.dll,以靜態參考方式連結。
副模組二:ClassLibrary2.dll,以動態參考方式連結。
在主模組設定成 Trace mode,在副模組會有效碼?答案是:有效。

3.解法, solution

偵錯模式是古老就有的議題,各個開發程式的供應商早有解了。在微軟的 .Net Framework 其解法就是「System.Diagnostics」,此命名空間專門處理系統診斷的工作。我們使用其中的「Trace」類別來實作偵錯模式。
「Trace」類別的用處其實很廣泛,但不在此文章討論範圍內,故不提了。

4.原碼

以下為本人練習原碼摘錄:
使用開發工具是 VS2010,此 Lab 的原始碼並不大,故把全部都放上。

先看一下方案總管:

trace sln

其中主模組的參考了 ClassLibrary1,但沒有ClassLibrary2。
ClassLibrary2 將以 Reflection技術 參考進來。

再看原始碼,

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace ClassLibrary1
{
public class Class1
{
public static void CallMe()
{
// go
Console.WriteLine("Hello world. in ClassLibrary1.");

Trace.WriteLine("I am in TRACE mode. in ClassLibrary1.");

Console.WriteLine("Good bye. in ClassLibrary1.");
}
}
}

上面是ClassLibrary1,下面是ClassLibrary2,兩邊的碼是一樣的。都是只say hello 就離開了,不過在中間加入「Trace」函式做紀錄。且都沒有設定成偵錯模式的碼,因為這部份是主模組的工作。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace ClassLibrary2
{
public class Class2
{
public static void CallMe()
{
// go
Console.WriteLine("Hello world. in ClassLibrary2.");
Trace.WriteLine("I am in TRACE mode. in ClassLibrary2.");
Console.WriteLine("Good bye. in ClassLibrary2.");
}
}
}

下面是主模組程式原始碼。其中 ClassLibrary1 是靜態參考可以直接叫用, ClassLibrary2 是動態參考需繞一下再 Invoke 才行。
其中關鍵之一,設成偵錯模組的程式碼只須一行:

Trace.Listeners.Add(new ConsoleTraceListener());

其原理什麼的實在懶得講…其實是量很多講不完…請自行補充。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Reflection;

namespace conApp_TraceLab
{
class Program
{
static void Main(string[] args)
{
#region ## parsing the arguments.
bool _TRACE = false;
foreach (var arg in args)
{
switch (arg)
{
case "/TRACE":
case "/t":
_TRACE = true;
break;
}
}
#endregion

// set up the running mode.
if(_TRACE)
Trace.Listeners.Add(new ConsoleTraceListener());

// go
Console.WriteLine("Hello world.");
Trace.WriteLine("I am in TRACE mode.");
Console.WriteLine("Good bye.");

// call static module function.
ClassLibrary1.Class1.CallMe();

// call dynamic module function.
Assembly lib2 = Assembly.LoadFrom("ClassLibrary2.dll");
Type class2 = lib2.GetType("ClassLibrary2.Class2", true);
class2.InvokeMember("CallMe", BindingFlags.InvokeMethod, null, null, null);
}
}
}

5.執行結果

附上執行結果。

trace lab

先以一般模式執行,無 Trace 輸出。
再以 /TRACE 模式執行,有 Trace 輸出。

(完)

此篇文章沒有引用,主要是同事的指教與自己的整理。

引言:

在報表製作上,偶而會有多欄報表的須求。
此多欄報表在Crystal Report上早有支援,還不錯用。
一直想在 reporting service上也做一支多欄報表看看。剛好同事在做就跟著學了一下。

回主題,多欄報表樣式大致如下:

代碼 名稱 代碼 名稱 代碼 名稱
第1筆 第5筆 第9筆
第2筆 第6筆 第10筆
第3筆 第7筆    
第4筆 第8筆    

此例中報表的欄位只有二個,“代碼”與“名稱”。以3“column(欄)”印在報表上。

目的:

製作 RDLC 多欄報表,使用VS2010。

 (閱讀全文)
1.源由

工作上須要,記下先。

在表單的編輯上,有時有批量編輯的須要,一格一格(cell)編輯會讓使用人想打人。
這時提供像是用Excel編輯介面,做表格內容的批量修改才能安撫使用者。

若要一次填入多個Cell,在Excel可以使用<Ctrl+Enter>把圈選的cell都填入相同值。

補充 on 2011-11-10 
今天發現這篇文章是做白工,因為DataGridView本身就技援批量填值的功能,與Excel的操作一樣使用<Ctrl+Enter>就行了。(=.=)

在這裡只使用<Enter>,填入相同的欄位下多個Cell,當然之前也要先選好目標Cells。

如下圖所示情境:(1)選好目標Cell。(2)填入新值。(3)按<Enter>。

 (閱讀全文)

引言:

一直想試一下拖拉的感覺。

解法:

還滿簡單的,關鍵指令有:

Control.AllowDrop : 設為true才能拖拉。

Control.DragEnter event : 判斷是否允許拖拉。

Control.DragDrop evnet : 處理拖拉。

Control.DoDragDrop() : 啟動拖拉。

Control.MouseDown evnet : 總之…拖拉操作由此事件開始。原理哦~懶得理了。

DragEventArgs.Data.GetData() : 取拖拉來的資料。

DragEventArgs.Data.GetDataPresent() : 用來判斷拖拉來的資料能不能吃得下肚,吃不下就吐了吧。

這幾個就能處理簡單的拖拉,謹於入門用,進階與實際應用等碰到再說吧。

練習結果:

 (閱讀全文)

引言:

總之就是要匯出EXCEL就對了。

解法:

不寫明細了,因為…總之認為微軟是故意不給的,所以有一大堆的解法而又無法收斂。

方法太概有:

ASP.NET匯出EXCEL(也就是在網頁下載EXCEL)

測試原碼:

用HTML-TABLE標籤匯出Excel。這招已驗證過,真的有效。致少在Excel2007可開啟該匯出檔並編輯。

此測試原碼為Winform程式。

private void btnExport_Click(object sender, EventArgs e)
{
//存檔名
System.Windows.Forms.SaveFileDialog fdlg = new SaveFileDialog();
fdlg.FileName = DateTime.Now.ToString("yyyyMMdd") + "匯出測試";
fdlg.Filter = "Excel檔(*.xls) |*.xls "; //存檔類型

if (fdlg.ShowDialog() == DialogResult.OK)
{
// open file
string filePath = fdlg.FileName;//路徑設定
System.IO.StreamWriter sw = new System.IO.StreamWriter(filePath, false, System.Text.Encoding.Unicode);

// 填入匯出明細
sw.WriteLine("<table border=1 cellspacing=0 cellpadding=0>");
//
sw.WriteLine("<tr><td>欄位一</td><td>欄位二</td><td>欄位三</td></tr>");
for (int i = 1; i < 10; i++)
{
sw.WriteLine("<tr><td>111</td><td>壹壹壹</td><td>111.111</td></tr>");
}
//
sw.WriteLine("</table>");

// 匯出EXCEL完成, close file.
sw.Close();
MessageBox.Show("匯出EXCEL完成。");
}
}

此篇文章引用自:使用 SQL 語法 LIKE 敘述句時的注意事項

使用 SQL 語法 LIKE 敘述句時的注意事項

你知道如何在使用 LIKE 的時候,去查詢 %, [, ], _ 這類的萬用字元嗎? 看看我寫的說明吧。

1. 比對規則

    萬用字元

    %      任何含有零或多個字元的字串。

    _      任何單一字元。

    [ ]    在指定範圍 ([a-f]) 或集合 ([abcdef]) 中的任何單一字元。

    [^]    不在指定範圍 ([^a-f]) 或集合 ([^abcdef]) 中的任何單一字元。

    e.g.

    SELECT * FROM table1 WHERE field LIKE '%[1234567890]%'

    代表任何有 0-9 的字元出現就算符合!

2. 若要 escape 特定字元可以用以下語法 ( 如:查詢字元中有百分比符號的字元)

    這是放在萬用字元前面的字元,用來指示應該將萬用字元解譯成正規字元而不是萬用字元。escape_character 是沒有預設值的字元運算式,只能得出一個字元。

    SELECT * FROM table1 WHERE field LIKE '%![1234567890!]%' ESCAPE '!'

    select * from table1 where field1 like '%My\\_Name%' escape '\\'

    這代表指定「逸出字元 (Escape Character)」為何,在 pattern 中出現在「逸出字元」後面的字元可以跳開「萬用字元」的功能!!

Reference:

    Using SQL Escape Sequences
http://msdn2.microsoft.com/en-us/library/ms378045.aspx

    使用 SQL 逸出序列
http://msdn2.microsoft.com/zh-tw/library/ms378045.aspx

    LIKE (Transact-SQL)
http://msdn2.microsoft.com/zh-tw/library/ms179859.aspx

1.源由

在ERP應用中,一份表單(一筆資料)中常有欄位是相依,如:

訂單項目之小計金額 = 單價 x 數量

原先使用DataGridVeiw 的 OnCellValidated 等的 event 來處理,卻發現偶有 lose event 的狀況。推測應該是高度分工化下的副作用,資料處理與資料呈現分工處理下的副作用。

2.目的, spec. statement.

解決 DataTable 之相依欄位計算填值的問題。

3.解法, solution

用老頭子的直覺找了一下,果然有了。就是這個光拉:

DataTable.OnColumnChanged 方法 
- 指向一筆資料(row)中的一個欄位(column) 的值的變更。

其它參考資料:

DataTable.OnRowChanged 方法
- 指向一整筆資料的狀態變更。

細節自己查吧。(其實是老了、懶了,也煩了)

4.原碼

以下為本人練習原碼摘錄:

法一,在應用面處理
public partial class Form1 : Form
{
 private void Form1_Load(object sender, EventArgs e)
 {
  // TODO: 這行程式碼會將資料載入 'tUMISDBDataSet.zz_numtpe' 資料表。您可以視需要進行移動或移除。
  this.zz_numtpeTableAdapter.Fill(this.tUMISDBDataSet.zz_numtpe);
  // 設定Evnet Handler
  tUMISDBDataSet.zz_numtpe.RowChanged += new DataRowChangeEventHandler(zz_numtpe_RowChanged);
  tUMISDBDataSet.zz_numtpe.ColumnChanged += new DataColumnChangeEventHandler(zz_numtpe_ColumnChanged);
 }
 void zz_numtpe_ColumnChanged(object sender, DataColumnChangeEventArgs e)
 {
  // 監看 OnColumnChanged 的運作方式。可把欄位的相依計算放在此處。
  textBox1.AppendText("\r\nON : ColumnChanged()...\r\n");
  textBox1.AppendText(string.Format("column : {0} \r\n", e.Column));
  textBox1.AppendText(string.Format("   row : {0} \r\n", e.Row));
  textBox1.AppendText(string.Format(" value : {0} \r\n", e.ProposedValue));
 }
 void zz_numtpe_RowChanged(object sender, DataRowChangeEventArgs e)
 {
  // 監看 OnRowChanged 的運作方式。
  textBox1.AppendText("\r\nON : RowChanged()...\r\n");
  textBox1.AppendText(string.Format("   row : {0} \r\n", e.Row));
  textBox1.AppendText(string.Format("action : {0} \r\n", e.Action));
 }
}
法二,在資料面處理,即在MetaDataSet裡就處理好
public partial class TUMISDBDataSet {
 partial class zz_numtpeDataTable
 {
  protected override void OnColumnChanged(System.Data.DataColumnChangeEventArgs e)
  {
   base.OnColumnChanged(e);
   // 先識別出相依的欄位
   if (e.Column.ColumnName == "mt_sta_num") 
   {
    // 再計算填值被相依的欄位,可能是:[小計]=[單價]x[數量]
    e.Row["tstamp"] = e.ProposedValue; 
   }
  }
 }
}

引言:

在LINQ TO SQL,看SQL的指令是 DataContext.GetCommand()。
那在 LINQ to Entities 下看SQL的指令是那一個?

目的:

在 LINQ to Entities 下看其產出的 SQL 指令。

解法:

Google果然神,膜拜幾次就找到了。

關鍵指令列下:

ObjectQuery.ToTraceString 方法

原碼:

下面是本人練習語法。

   1:          protected void Button1_Click(object sender, EventArgs e)
   2:          {
   3:              XXXDBEntities db = new XXXDBEntities();
   4:   
   5:              var qry = from c in db.table01
   6:                        select c;
   7:   
   8:              ObjectQuery qryObj = qry as ObjectQuery;
   9:   
  10:              string qryCmd = qryObj.ToTraceString(); // get Entity SQL
  11:   
  12:              Debug.WriteLine("qryCmd : " + qryCmd); // tracing 
  13:          }
 
 
 

此篇文章參考引用自:

Microsoft 技術支援  HOW TO:使用 Visual Basic .NET 擷取標示為已刪除的 DataRows 值

MSDN DataRow.Item 屬性

引言:

今天累,不寫了。引用一下重點就好。

重點:

因為在DataRow 的現行狀態中 (DataRowVersion.Current) 無法使用已刪除之列的值,必須使用DataRowVersion.Original 列舉才能取值。

例:
DataRow dr = … …
string columnValue = dr[“column_name”,DataRowState.Deleted] as string;

Key Code:

DataSet.HasChanges 方法
DataSet.GetChanges 方法
DataRow.RowState 屬性
DataRow.Item 屬性

此篇文章參考整理自:
Phate http://www.phate.tw/thread-9108-1-1.html
MSDN-HOW TO:讓使用者從 Windows Form DataGridView 控制項將多個儲存格複製至剪貼簿
http://msdn.microsoft.com/zh-tw/library/dec5efh1.aspx
MSDN-DataGridView.ClipboardCopyMode 屬性
http://msdn.microsoft.com/zh-tw/library/system.windows.forms.datagridview.clipboardcopymode.aspx

1.源由:

工作上須要,記下先。

在表單的編輯上,有時有批量編輯的須要,一格一格(cell)編輯會讓使用人想打人。
這時提供像是用Excel編輯介面,做表格內容的批量修改才能安撫使用者。

白話文就是,並不須要Excel批量編輯的功能全有,只要一項就可以安撫使用者了。
如下圖所示情境:(1)自一個Cell複製。(2)可多個Cell貼上。 這一招就夠用了。

圖一、用 Ctrl-C 複製一個Cell。

DataGridView copy-paste

圖二、用 Ctrl-V 貼上多個Cell。

DataGridView copy-paste

2.目的, spec. statement.

所以目的就是讓 DataGridView 元件上可以以複製一個Cell 再批量貼上Cell 的方式來編輯。

3.解法, solution

把keyword部份列下。
本人使用 VS2008 with .NET3.5 開發。

實作的機制上是利用剪貼簿(Clipboard)功能。

相關的event、handler的也列一下:

  • DataGridVeiw.KeyUp evnet
    在此接受 Ctrl-V 指令。
  • DataGridView.ClipboardCopyMode 
    使用預設值 EnableWithAutoHeaderText  或設成 EnableWithoutHeaderText  也行。
    設好此屬性設好就有 Ctrl-C 的能力了。
  • DataGridView.SelectedCells
    被選取的Cell。
  • DataGridViewCell.OwningColumn
    Cell 所屬的 Column,用來判斷是那一個 Field 以檢驗格式並貼上新值。
  • DataGridView.DataError event
    有些人會建議處理此event,將其 exception 全部 bypass,這是很爛的逃避問題的方式。此問題源由是Cell在接受貼上的值時只能吃能吃得下的格式,例如:數字型態的格式總不能吃文字型態的資料吧。
    比較好的解法是在讓Cell吃資料時,先檢驗格式型態為能接受的才吃,若不能吃就 ignore 不吃。

4.原碼

注:因DataGridView 預設有Ctrl-C 的複製能力,所以實作上只要補上Ctrl-V的部份就行了。

這是本人實戰的原碼節錄,如下:

   1:  private void dgvData_KeyUp(object sender, KeyEventArgs e)
   2:  {
   3:      //## <Ctrl> + V
   4:      if (e.Modifiers == Keys.Control && e.KeyCode == Keys.V)
   5:      {
   6:          try
   7:          {
   8:              // UI控制-mouse
   9:              this.Cursor = Cursors.WaitCursor;
  10:   
  11:              //# 自 Clipboard 取值
  12:              string copyText = Clipboard.GetText(TextDataFormat.Text);
  13:   
  14:              //# by each selected cells to proceed...
  15:              foreach (DataGridViewCell c in dgvData.SelectedCells)
  16:              {
  17:                  switch (c.OwningColumn.Name)
  18:                  {
  19:                      case "bdg_tpe": // 預算別
  20:                          string bdg_tpe;
  21:                          // 若不是合法的資料,離開。
  22:                          if (!this.DoParse_BdgTpe(copyText, out bdg_tpe)) return;
  23:                          // 貼上合法的資料
  24:                          c.Value = bdg_tpe;
  25:                          break;
  26:                      case "tckt_num": // 傳票號碼
  27:                          //......
  28:                          break;
  29:                  }
  30:              }
  31:          }
  32:          finally
  33:          {
  34:              // UI控制-mouse
  35:              this.Cursor = Cursors.Default;
  36:          }
  37:   
  38:      }
  39:      else if (e.KeyCode == Keys.Delete) // <Delete>
  40:      {
  41:          try
  42:          {
  43:              // UI控制-mouse
  44:              this.Cursor = Cursors.WaitCursor;
  45:   
  46:              //# by each selected cells to proceed...
  47:              foreach (DataGridViewCell c in dgvData.SelectedCells)
  48:              {
  49:                  switch (c.OwningColumn.Name)
  50:                  {
  51:                      case "bdg_tpe": // 預算別
  52:                      //......                    
  53:                          break;
  54:                  }
  55:              }
  56:          }
  57:          finally
  58:          {
  59:              // UI控制-mouse
  60:              this.Cursor = Cursors.Default;
  61:          }
  62:      }
  63:  }
1 2 3 4 5 6 7 8 9  下一篇»