顯示具有 程式設計觀念 標籤的文章。 顯示所有文章
顯示具有 程式設計觀念 標籤的文章。 顯示所有文章

2015年2月12日 星期四

[學習] 在C#實現VB函式【IsNumeric】

【CODE】
        static bool IsNumeric(object Expression)
        {
            // Variable to collect the Return value of the TryParse method.
            bool isNum;
            // Define variable to collect out parameter of the TryParse method. If the conversion fails, the out parameter is zero.
            double retNum;
            // The TryParse method converts a string in a specified style and culture-specific format to its double-precision floating point number equivalent.
            // The TryParse method does not generate an exception if the conversion fails. If the conversion passes, True is returned. If it does not, False is returned.
            isNum = Double.TryParse(Convert.ToString(Expression), System.Globalization.NumberStyles.Any, System.Globalization.NumberFormatInfo.InvariantInfo, out retNum);
            return isNum;
        }

【CODE】
        public static bool IsNum(String str)
        {
            for (int i = 0; i < str.Length; i++)
            {
                if (str[i] < '0' || str[i] > '9')
                    return false;
            }
            return true;
        }

參考:
判断一个字符串是否全是数字的多种方法及其性能比较(C#实现)
[C#]IsNumeric 判斷是否為數值
[C#]數值驗證 IsNumeric
C# Equivalent of VB's IsNumeric()
C# IsNumeric
C#的判斷是否為數字,難道只能用Try、Catch嗎?..沒有VB.NET的IsNumeric可用嗎

2013年5月21日 星期二

[學習] 四捨五入

[SQL]
select round(1.5446,2)
1.5400

select round(round(1.5446,3),2)
1.5500

select CAST(1.5446 AS decimal(9,2))
1.54

select CAST(1.546 AS decimal(9,2))
1.55

*資料型態decimal
  -生產數、工作分鐘 

統計數 =  Convert(Decimal(18,4) , 生產數 / 工作分鐘) * 60

[VB]
Module Module1
    Sub Main()
        Console.WriteLine((0.46).ToString("0"))
        'Console.WriteLine((1.45).ToString("0.0"))
        Console.WriteLine((0.5).ToString("0"))

        Console.WriteLine((0.46).ToString("f"))
        Console.WriteLine((0.5).ToString("f"))

        Console.WriteLine((4.625).ToString("0.00"))
        Console.WriteLine((4.645).ToString("0.00"))

        Console.WriteLine((4.625).ToString("f2"))
        Console.WriteLine((4.645).ToString("f2"))

        'Console.WriteLine((1.5).ToString("0"))
        Dim a As Double = 0.45
        Dim b As Decimal = 0.46
        'Dim c As Decimal = 4.625
        Console.WriteLine(Math.Round(a, 0, MidpointRounding.AwayFromZero))
        Console.WriteLine(Math.Round(b, 0, MidpointRounding.AwayFromZero))
        Console.WriteLine(Math.Round(4.625, 2, MidpointRounding.AwayFromZero))
        Console.WriteLine(Math.Round(CDec(4.645), 2, MidpointRounding.AwayFromZero))
        Console.Read()
    End Sub
End Module

-----------------

1. 整數以下四捨五入
     int(46410*0.05+0.5)=2321

2. 例 : 12.346 四捨五入至小數點以下一位
     int(12.346*10+0.5)/10=12.3

3. 例 : 12.346 四捨五入至小數點以下二位
     int(12.346*100+0.5)/100=12.35

參考:
浮點數計算結果更接近正解? 算錢用浮點,遲早被人扁

access中含四舍五入取值方法的查询sql语句
正確的四捨五入

[WIKI]數值簡化規則
C# Round (四捨五入) 使用 ToString()
利用VB.NET Format函数实现四舍五入功能
格式化输出-数字.ToString
c#中的常用ToString()方法总结
好用的string.Format或ToString()格式化字串的方法
[C#]簡單快速將各種數值字數轉成數字(string to int)
C#,double和decimal数据类型以截断的方式保留指定的小数位数

 '四捨五入
Public Function Round45(ByVal dblValue As Double) As Long
     Round45 = Fix(dblValue + 0.5 * Math.Sign(dblValue))
End Function

C#沒有四捨五入?只有五捨六入的涵數?
只要試試4.625與4.645兩個都對, 那才是真的對了

decimal 小數點位數 四捨五入
[C#]無條件進位,無條件捨去及四捨五入寫法

[ACCESS]單精準數運算Round取到小數位數問題
Round 函數

How To Implement Custom Rounding Procedures

2013年5月2日 星期四

[除錯] 並未將物件參考設定為物件的執行個體 DataGridViewComboBox [debug]

錯誤:
DataGridViewComboBox
並未將物件參考設定為物件的執行個體

程式:

            For Each dgvr As DataGridViewRow In DataGridView1.Rows
                'If dgvr.Index = DataGridView1.RowCount - 1 Then
                '    Exit For
                'End If
                'If dgvr.IsNewRow Then
                '    MsgBox("HAHA")
                '    Exit For
                'End If
                MsgBox(dgvr.Cells("供應商").Value.ToString.Trim)
            Next

解決:
因為 AllowUserToAddRows = True
所以 DGV 會自動 NewRow 出來

而 NewRow 在 for-loop 裡也會算作一份(index)
但實質上是 Nothing 的資料型態
當 loop 到 NewRow 時,便會發生如圖的錯誤

因此在 for-loop 時,要排除掉
可利用黃色方法或綠色方法

DataGridView 控制項 (Windows Form)

2013年4月25日 星期四

[除錯] System.ArgumentException:DataGridViewComboBoxCell 值無效 (1)


程式碼:

        Me.DataGridView1.AutoGenerateColumns = False
        Me.DataGridView1.DataSource = dt

        '加減項
        Dim installss() As Decimal = {-1, 1}
        Dim columnID As New DataGridViewComboBoxColumn()
        columnID.HeaderText = "加減項"
        columnID.Name = "加減項"
        columnID.DataPropertyName = "加減項"
        columnID.ValueType = GetType(System.Decimal)
        columnID.Items.AddRange(installss)  'columnID.Items.AddRange(+1, -1)
        'columnID.Items.AddRange(New Object() {-1, +1,})
        DataGridView1.Columns.AddRange(New System.Windows.Forms.DataGridViewColumn() {columnID})
 

原因:
出现这种问题有两种原因:
1.数据类型不匹配 
2.所赋数据项与绑定的数据源中数据不符 结贴!

此次debug為第一種原因:
資料庫的資料型態為 Decimal(13,6)
.NET的資料型態為 Decimal , Object 皆無法成功。

解決(一):
改用DataTable方式...
        Me.DataGridView1.AutoGenerateColumns = False
        Me.DataGridView1.DataSource = dt

        Dim dtttt As DataTable = New DataTable
        dtttt.Columns.Add("加減項", GetType(Decimal))
        dtttt.Columns.Add("中文", GetType(String))
        dtttt.Rows.Add(+1, "加")
        dtttt.Rows.Add(-1, "減")
        dtttt.TableName = "XXX"

        '加減項
        Dim installss() As Decimal = {-1, 1}
        Dim columnID As New DataGridViewComboBoxColumn()
        columnID.HeaderText = "加減項"
        columnID.Name = "加減項"
        columnID.DataPropertyName = "加減項"
        columnID.ValueType = GetType(System.Decimal)

        columnID.DataSource = dtttt
        columnID.DisplayMember = "中文"
        columnID.ValueMember = "加減項"

        DataGridView1.Columns.AddRange(New System.Windows.Forms.DataGridViewColumn() {columnID})

解決(二):
應該要依這個link的方式(類別),來繫結資料... """待測試"""
如何在程式內,直接給DataGridViewComboBoxColumn的下拉選單內容?
如何自訂DataGridView中DataGridViewComboBoxColumn物件
如何自訂DataGridView中DataGridViewComboBoxColumn物件

參考:
C# 類型的預設值 (C# 參考)  string就不會出錯,但數值有預設值,所以會出錯...

DataGridView 資料行下拉選單,資料繫結階段顯示 DataGridViewComboBoxCell 值無效
DataGridViewComboBoxCell.GetFormattedValue 方法
给DataGridViewComboBoxCell赋值的问题!
DataGridViewComboBoxColumn值无效
DataGridViewComboBoxColumn值无效
解决方法就是在窗体的构造函数里添加如下代码:
this.dataGridView1.DataError += delegate(object sender, DataGridViewDataErrorEventArgs e) { };

DataGridViewComboBoxColumn的使用 (高招)
Mapping CLR Parameter Data
DataGridView 使用问题
SQL Server 資料型別對應 (ADO.NET).
DataGridView.DataError 事件
DataGridViewDataErrorContexts 列舉型別

Non-String values in DataGridViewComboBoxColumn causing DataErrors in DataGridView
System.ArgumentException:DataGridViewComboBoxCell 值無效 (2)
DataGridViewComboBoxCell 值無效
DataGridView中comboBox数据绑定的问题
DataGridView 的DataGridViewComboBoxColumn 無效值問題

SqlServer中decimal(numeric )、float 和 real 数据类型的区别
What is a good mapping of .NET decimal to SQL Server decimal?

[除錯] System.ArgumentException:DataGridViewComboBoxCell 值無效 (2)

程式碼:
        Me.DataGridView1.AutoGenerateColumns = False
        Me.DataGridView1.DataSource = dt

        Dim installs(dt供應商.Rows.Count - 1) As String
        Dim x As Integer = 0
        For Each dr As DataRow In dt供應商.Rows
            installs(x) = dr(0).ToString
            x += 1
        Next

        '供應商
        Dim columnSex As New DataGridViewComboBoxColumn()
        columnSex.HeaderText = "供應商別"
        columnSex.Name = "供應商別"
        columnSex.DataPropertyName = "供應商別"
        columnSex.ValueType = GetType(String)  'dt供應商.Rows(0).Item(0).GetType()
        columnSex.Items.AddRange(installs)
        DataGridView1.Columns.AddRange(New System.Windows.Forms.DataGridViewColumn() {columnSex})

原因:
出现这种问题有两种原因:
1.数据类型不匹配 
2.所赋数据项与绑定的数据源中数据不符 结贴!

此次debug為第二種原因:
資料庫某一個Record的其供應商別的欄位的值為 X
而DataGridViewComboBoxColumn的Items的值為 Y,Z,S 不包含X


解決(一):
繫結資料庫dt時,必須確定資料庫的值可與DataGridViewComboBoxColumn的Items匹配。
只要把資料庫的值改掉就好。 也就是說必須確定資料庫的值不會是Items匹配以外的值。

解決(二):
直接在事件處理掉 ""DataGridView1_DataError""
就不會出現錯誤訊息,只要不影響作業!
但是若資料庫的數值型態與.NET數值型態不符時,雖然錯誤訊息已隱藏!
但當在選擇items時,會無法正常運作。
即使你選擇了某值,而此值因為違反規則,所以又會變成空白...

Private Sub DataGridView1_DataError(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewDataErrorEventArgs) Handles DataGridView1.DataError
        'e.ThrowException = False

        'If Me.DataGridView1.Columns(e.ColumnIndex).Name = "供應商別" Then
               'do something here
               '留空, 只要輸入符合欄位型態,(為繫結資料來源內的項目)可正常輸入!
        'End If

End Sub
可參考(DataGridViewComboBoxColumn的数据源有关问题)
DataGridViewDataErrorContexts 列舉型別

圖示:
原始資料(From DataBase)
紅色部份為不存在於繫結來源內的項目


沒有加入事件 DataGridView1_DataError (在AA03 就開始出現錯誤訊息...)

加入事件 DataGridView1_DataError

選擇來源為資料繫結內的項目-001

選擇來源為繫結資料內的項目-002

輸入自定義文字-001

輸入自定義文字-002 ∵不符合原始繫結資料內的項目,故還原為空白!


參考:
C# 類型的預設值 (C# 參考)  string就不會出錯,但數值有預設值,所以會出錯...

Datagridview ComboBoxColumn Nullable
DataGridViewComboBoxCell.GetFormattedValue 方法
给DataGridViewComboBoxCell赋值的问题!
DataGridViewComboBoxColumn值无效
DataGridViewComboBoxColumn值无效
解决方法就是在窗体的构造函数里添加如下代码:
this.dataGridView1.DataError += delegate(object sender, DataGridViewDataErrorEventArgs e) { };

DataGridViewComboBoxColumn的使用 (高招)
Mapping CLR Parameter Data
DataGridView 使用问题
DataGridView.DataError 事件
Non-String values in DataGridViewComboBoxColumn causing DataErrors in DataGridView
System.ArgumentException:DataGridViewComboBoxCell 值無效 (1)
DataGridViewComboBoxCell 值無效
DataGridView中comboBox数据绑定的问题
DataGridView 的DataGridViewComboBoxColumn 無效值問題

SqlServer中decimal(numeric )、float 和 real 数据类型的区别
What is a good mapping of .NET decimal to SQL Server decimal?


2013年4月15日 星期一

[除錯] Web Services (ASP.NET + IIS) 出現如msgbox的訊息框,需透過 WebForm 的 Response.Write 即可!

流程:
WinForm (client) --network-- (server) Web Service --- Class --- DB


錯誤訊息:(在 Class msgbox時所引發的錯誤。)
當應用程式不使用 UserInteractive 模式執行時,顯示強制回應對話方塊或表單不是有效的作業。指定 ServiceNotification 或 DefaultDesktopOnly 樣式以顯示來自服務應用程式的告知。


實作:(寫在class裡的一段程式)
Try

Catch e As Exception
          'MsgBox(e.ToString) <-- 錯誤訊息的原因
          HttpContext.Current.Response.Write(e.ToString)

Finally
          '
End Try


參考:
ASP.NET 使用 MsgBox 顯示提示訊息
在 ASP.NET 也能使用 MessageBox 彈出對話方塊的功能
讓 ASP.NET 也可以使用 MsgBox 方法
Class類別中的Response、Server、Request未宣告解決方法(使用HttpContext.Current屬性)
SQL Injection技巧大全 <-- 用來測試 Sql select 的強度!!

2013年3月26日 星期二

[學習] 事件(Event)的設計

可以讓重複出現的事情
讓已預定好的事件去執行

未事件前:

Public Class aaa
    Private _a As Integer = 0

    Public Property a() As Integer
        Get
            Return _a
        End Get
        Set(ByVal value As Integer)
            _a = value
        End Set
    End Property
End Class

Module Module1
    Dim  b As New aaa

    Sub Main()
        b.a = 1
        MsgBox(b.a)  '沒丟給事件處理時, 就必須Coding時寫N次 msgbox 
        b.a = 2
        MsgBox(b.a)
        Console.Read()
    End Sub
End Module


事件後:

Public Class aaa
    Event idxchg()  '宣告事件
    Private _a As Integer = 0

    Public Property a() As Integer
        Get
            Return _a
        End Get
        Set(ByVal value As Integer)
            _a = value
            RaiseEvent idxchg()  '觸發事件
        End Set
    End Property
End Class

Module Module1
    Dim WithEvents b As New aaa  '宣告帶有事件處理的物件

    Private Sub idxchg() Handles b.idxchg  '事件觸發時,要做的事情
        MsgBox(b.a)  '由事件來處理, 不須Coding時寫N次的msgbox
    End Sub

    Sub Main()
        b.a = 1
        b.a = 2
        Console.Read()
    End Sub
End Module

參考:
(200-06-28) VB.NET 委派(Delegate) 事件(Event)
DataGridView中如何在textbox列中限制输入。
事件教學課程
事件 (C# 程式設計手冊)
event (C# 參考)
事件 (Visual Basic)
AddHandler 陳述式
事件的深入分析(function pointer, delegate, event, EventHandler)

玩轉C#之【委派和事件】
C# 中的委托和事件(转载)
.NET 事件與委派詳論
C# Delegate and Event 委派和事件(一)

2013年3月24日 星期日

[技巧] 動態更改 ReportViewer.LocalReport.ReportPath


Me.ReportViewer1.Reset()
'組件路徑 (不必將 report檔 ".rdlc" 丟到實際資料夾底下...)
Me.ReportViewer1.LocalReport.ReportEmbeddedResource = "eHRsys.Report2.rdlc"  

Note:
eHRsys.Report2.rdlc
組件名稱.檔案名稱.檔案副檔名

參考:
[MSDN]LocalReport.ReportPath 屬性
如何動態更換ReportViewer的RDLC及DataSource
收藏 RDLC动态绑定问题
如何使用LocalReport - WebForm (3)
动态的rdlc报表
顯示整頁模式
The WinForms ReportViewer and Multiple Report Definition Files
Binding DataSet and Generic *.rdlc Reports to a ReportViewer at Runtime

2013年3月17日 星期日

[技巧] Using GetUpperBound(0) 取得儲存多筆Record的DataRow


Dim 病假() As DataRow = Me.MyCallForm.ds.Tables("attend").Select("type = '病假' and ym like '" & ComboBox1.Text & "%'")

For i As Integer = 0 To 病假.GetUpperBound(0)
    MsgBox(病假(i)("ym") + 病假(i)("type"))
Next

備註:
Dim 病假() As DataRow = Me.MyCallForm.ds.Tables("attend").Select("type = '病假' and ym like '" & ComboBox1.Text & "%' and substring(ym,6,2) <= " & Integer.Parse(ComboBox2.Text) & "")

ym欄位的資料型態為nchar
資料內容為六位數的 "月份日期" 組合
201003
201201
201202
201203
201302

可運用 substring() 來進行分割搜尋...
從條件來看 假設 ComboBox1.Text = 2012 , ComboBox2.Text = 02
則DataTable.Select()的filter結果為
201201
201202

參考:
DataTable.Select 方法 (String)
[C#] Datatable.Select 的運算式用法
C# [轉載] Datatable.Select 的運算式用法
DataTable.Select()中的表达式可使用的函数
dataTable 的處理
Convert DataRow Array to DataTable, DataTable Filter function DataTable.Select return DataTable
DataTable Select Function (datarow 轉為 datatable)

SQL函數 查詢SQL資料欄位相符的字串
MSSql 中Charindex ,Substring的使用
CHARINDEX (Transact-SQL)

2013年1月10日 星期四

[學習] DataGridView 資料繫結 與 資料清除

資料顯示方式:
DataGridView1.DataSource = ds.Tables(0)

資料清除方式:
DataGridView1.DataSource = Nothing
DataGridView1.Refresh()

========================================
資料顯示方式:
For i As Integer = 0 To ds.Tables("family").Rows.Count - 1
     DataGridView2.Rows.Add(
          ds.Tables("family").Rows(i)(0),
          ds.Tables("family").Rows(i)(1),
          ds.Tables("family").Rows(i)(2),
          ds.Tables("family").Rows(i)(3),
          ds.Tables("family").Rows(i)(4))
Next

資料清除方式:
DataGridView2.Rows.Clear()

Error Msg:
無法清除這個清單

參考:
DataGridView全部删除不成功

2012年12月26日 星期三

[學習] decimal 小數點位數 四捨五入

[SQL]
select round(1.5446,2)
1.5400

select round(round(1.5446,3),2)
1.5500

select CAST(1.5446 AS decimal(9,2))
1.54

select CAST(1.546 AS decimal(9,2))
1.55


*資料型態decimal
  -生產數、工作分鐘 

SELECT 生產數,工作分鐘,
生產數/工作分鐘*60,
Convert(Decimal(18,4),生產數/工作分鐘)*60,
floor(convert(decimal(18,4),生產數/工作分鐘)*60),
floor(生產數/工作分鐘*60),

Round(生產數/工作分鐘*60,1) AS 小數第1位,
Round(生產數/工作分鐘*60,4) AS 小數第4位,

(生產數/工作分鐘*60*10+0.5)/10,
FLOOR(生產數/工作分鐘*60*10+0.5)/10
FROM tblA



[ACCESS]

SELECT 生產數,工作分鐘,
 Round(生產數/工作分鐘*60,1),
 Int(CDBL(生產數/工作分鐘)*60*10+0.5)/10 ,
 Int((生產數/工作分鐘)*60*10+0.5)/10 
 FROM tblA

互相比對結果值(EXCEL)








[VB]
小數點表示法
^[0-9]+(.[0-9]{1,6})?$

通過
0
0.
0.0
0.123456
123456789.123456

-----------------

資料庫 insert 時,decimal型態自動進位(四捨五入)。
假設小位數到3,資料庫 decimal型態就必須設置小數點到3。
當然在程式設計時,也必須 decimal 型態 到小數點3。

-----------------

1. 整數以下四捨五入
     int(46410*0.05+0.5)=2321

2. 例 : 12.346 四捨五入至小數點以下一位
     int(12.346*10+0.5)/10=12.3

3. 例 : 12.346 四捨五入至小數點以下二位
     int(12.346*100+0.5)/100=12.35

參考:
浮點數計算結果更接近正解? 算錢用浮點,遲早被人扁

2012年12月25日 星期二

[SQL] bit欄位型態, 插入Insert 與 讀取Select的值為1與0, 而不是True與False...

insert/update:
資料必須為 1,0 而不是 True,False
Convert.ToInt16(CheckBox1.Checked)  轉換為 1,0

select:
資料會自動轉為 True,False

備註:
欄位 Uses , Char(255)
SELECT CASE Uses WHEN 'T' THEN true ELSE 'false'

參考:
bit和 bool的问题
SQL Server数据库中bit字段类型使用时的注意事项
boolean插入mysql中bit类型,读出来是false和true,但是用false查询用,是空的  <-- 要用 1,0 查詢
how-to-add-custom-checkbox-column-to-datagridview

Convert.ToBoolean

2012年12月23日 星期日

[學習] CheckedChanged 與 CheckedStateChanged 的區別

CheckedChanged 
 True / False

CheckedStateChanged  
 CheckState.Indeterminate(會打勾 並且會有灰色網格背景)
      / CheckState.Unchecked / CheckState.Checked

事件觸發:
從控制項改變值 或 從程式改變值
兩者事件都會觸發


'做驗證時,千萬別用 CheckedChanged 與 CheckedStateChanged 會進入無窮迴圈XD
Private Sub CheckBox2_Validating(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles CheckBox2.Validating

     '實現VBA Method [Me.Undo()功能] (解釋--還原到先前的值!!)

     If Me.CheckBox2.CheckState = CheckState.Checked Then
          Me.CheckBox2.CheckState = CheckState.Unchecked
     Else
          Me.CheckBox2.CheckState = CheckState.Checked
     End If
End Sub

NOTE:
如同 TextBox2.undo

參考:
CheckBox.CheckedChanged 事件
CheckBox.CheckStateChanged 事件
checkedBox 属性checkedChanged与checkedStateChanged 区别
VB2010之十二: CheckBox控件

2012年12月14日 星期五

[除錯] 字串或二進位資料會被截斷


資料庫insert時,Error Msg:
1.字串或二進位資料會被截斷
2.數值對 Int32 而言太大或太小


資料庫欄位型態:
int(4)


解決程式:
'不能用CInt 因為超過最大值 會無法判斷 (因為無法轉成INT)
If CDec(C.Text.Trim) > 2147483647 Then
MsgBox("資料欄位不准許大於[2147483647]!!")
End If


參考:
字串或二进位资料会被截断。
如何快速得知"字串或二進位資料會被截斷"是哪個欄位長度不足??
字串或二進位資料會被截斷

2012年11月26日 星期一

[技巧] 判斷是否已開啟視窗

法一 - A、
只能在 父MDI [MAIN_ligoHRsys] 下運作! 當嵌入其它組件時,無法在其下 父MDI 下運算!
        '若表單已存在 則讓他為主要顯示表單
        If l_Frm IsNot Nothing Then

            For i As Integer = 0 To MAIN_ligoHRsys.FindForm().MdiChildren.Length - 1
                If frmText.Equals(MAIN_ligoHRsys.FindForm().MdiChildren(i).Text) Then
                    MAIN_ligoHRsys.FindForm().MdiChildren(i).Tag = 4
                    MAIN_ligoHRsys.FindForm().MdiChildren(i).Activate()
                    DirectCast(MAIN_ligoHRsys.FindForm().MdiChildren(i), Object).MyDataRequery(Nothing)
                End If
            Next
        End If


法一 - B、
當嵌入在任何組件時 在其 父MDI 下運作,必使用 Me.Parent 方可執行!
        '若表單已存在 則讓他為主要顯示表單
        If l_Frm IsNot Nothing Then

            For i As Integer = 0 To Me.Parent.FindForm().MdiChildren.Length - 1
                If frmText.Equals(Me.Parent.FindForm.MdiChildren(i).Text) Then
                    Me.Parent.FindForm.MdiChildren(i).Activate()
                    Me.Parent.FindForm.MdiChildren(i).Tag = 1
                    DirectCast(Me.Parent.FindForm().MdiChildren(i), Object).MyDataRequery(Nothing)
                End If
            Next
        End If


法二、
If My.Application.OpenForms.Item("FormName") IsNot Nothing Then
     'do something here 已經打開
Else
     'do something here 還沒打開
End If


法三、[C#]
            if (Application.OpenForms.OfType<frm力高裝箱明細列印作業>().Count() == 1)
                Application.OpenForms.OfType<frm力高裝箱明細列印作業>().First().Activate();
            else
            {
                frm裝箱明細列印作業 frm = new frm裝箱明細列印作業();
                frm.MdiParent = this.MdiParent;
                frm.Show();
            }   


參考:
[MSDN]Form.ActiveMdiChild 屬性
[MSDN]My.Application.OpenForms 屬性
VB.NET判断一个窗口是否打开的代码
[C#.NET] 如何 使用 WinForm 關閉 視窗 事件
C# WinForm 只允许运行一个实例 ,如果有就激活到前段
WinFrom 判断窗体是否已存在

2012年11月20日 星期二

[學習] 多使用者 處理 同一筆資料 防止 race condition

系統架構
User1(程式)
                            <--------->       SV1(WebService)       <--------->       SV2(DataBase)
User2(程式)
       .
       .
       .
UserN(程式)


 (強碰問題~ 幾乎很少發生!!)
1.(程式-產生序號 Fetch From DB & +1) ex: sn+=1
當多個user同時處理同一筆record時~~
在不違反商業邏輯狀態下,直接覆蓋(update)前者的資料~~
每個record都會有記錄欄位,記錄修改者是誰~~

2.(程式-產生序號 Fetch From DB & +1) ex: sn+=1
在user1處理A-record時 不讓其它user同時處理A-record

user1(程式) 發出個訊息(參數) 給 SV1
其它user處理record時 並先與SV1判斷是否同record
若是 則告知其它user 目前不能用

-但會有網路斷線問題~~
-故需要一個機制~~
-那便是一個處理record的時間~~
-並在n分鐘內不讓其它使用者處理同一筆record~~

時間可存在 DataBase(同一筆record的欄位) 或 SV1

參考:
用 SELECT ... FOR UPDATE 避免 Race condition
数据库插入,多人操作,如何能做到绝对不重复插入?
select 後 insert
競爭危害

2012年11月18日 星期日

[除錯] 轉換 expression 到資料型別 smalldatetime 時發生算術溢位錯誤


---Error Message----
1.INSERT INTO SQL SERVER時引發錯誤,SQL資料類型 smalldatetime
將 varchar 資料類型轉換成 smalldatetime 資料類型時,產生超出範圍的值

2.
轉換 expression 到資料型別 smalldatetime 時發生算術溢位錯誤
轉換 nvarchar 到資料型別 smalldatetime 時發生算術溢位錯誤
,etc...




資料庫欄位型態為 datetime or smalldatetime
程式 insert 時,必須注意日期規則是否溢位

Ex:
一月份最大日期為31日
此時 insert 32 便會 error


解決辦法(1)--  
其實用 ISDate() 最準 
接受輸入格式 
(1)12-24 (自動加入今年)
(2)12-01-01 ,  2013-1-1,
(3)2011/1/1 ,  2012/01/12
(4)12/1-01 


在 insert 前判別規則
ex: 正規化表示法
If Not Regex.IsMatch(C.Text.Trim, "^((19|20)?[0-9]{2}[- /.](0?[1-9]|1[012])[- /.](0?[1-9]|[12][0-9]|3[01]))*$") Then
   'do something
End



解決辦法(2)--
將資料庫 欄位型態 改為 varchar / nvarchar


溢位是因為期中有NULL值或空白值 

解決辦法(3)--
WHERE下條件
where date <> "" and date is not null 或是 where isdate(date)

NOTE:
一、IsDate() 有效日期的範圍是介於西元 100 年 1 月 1 日與西元 9999 年 12 月 31 日之間;其有效範圍會因作業系統而有所差異。

二、
smalldatetime 有效時間範圍 1900/1/1~2079/6/6
datetime 有效時間範圍 1753/1/1~9999/12/31
所以如果不用到太遠的日期範圍,就會使用smalldatetime。
更關鍵的差別,smalldatetime只精準到分,而datetime可精準到3.33毫秒。





參考1
參考2
參考3




[學習] Directory.GetCurrentDirectory 和 Application.StartupPath 區別

Imports System.IO

—————————————————————————————
StartupPath 程式執行後,路徑位置不因外在因素而變。
GetCurrentDirectory 程式執行後,路徑位置會因外在因素而變。
—————————————————————————————

獲取文件路徑定義
Application.StartupPath——獲取啟動了應用程序的可執行文件的路徑,不包括可執行文件的名稱。
Environment.CurrentDirectory——獲取和設置當前目錄(即該進程從中啟動的目錄)的完全限定路徑。
Application.ExecutablePath——獲取啟動了應用程序的可執行文件的路徑,包括可執行文件的名稱。
Directory.GetCurrentDirectory()——獲取應用程序的當前工作目錄。
Directory.GetCurrentDirectory()——程序文件自身的路徑。


GetCurrentDirectory 會受 OpenFileDialog(SaveFileDialog) 的影響,而改變路徑位置。
假如有兩個程式 C:/A/a.exe 和 C:/B/b.exe
當在 a.exe 中啟動 b.exe,System.Diagnostics.Process.Start(@"C:/B/b.exe")
此時 b.exe 中的 Directory.GetCurrentDirectory() 返回值為 “C:/A”
Application.StartupPath 值為“C:/B”

如果直接在 C:/B/ 中啟動 b.exe,那麼兩個值就會一樣,都為“C:/B”
這就是 Directory.GetCurrentDirectory 和 Application.StartupPath 的區別

Application.StartupPath 是程序的啟動目錄,這個在程序運行以後,就不會改變了。
Directory.GetCurrentDirectory() 是"當前目錄",是可以在程序運行時候改變的 ,
用Directory.SetCurrentDirectory() 就可以改變。
Directory.GetCurrentDirectory() 初始值和 Application.StartupPath() 一樣。

參考:
[C#]使用 Path 類別取得檔案或目錄路徑資訊
File.Exists 方法
有关File.Exists(filename)的问题
c# 獲取相對路徑
取得目前執行程式的目錄

2012年11月9日 星期五

[學習] If Else 判斷式 細節注意~

AndAlso運算子


問題(Problem):
從資料庫撈資料時~
若某資料型態為日期(or 其它特殊型態)時~
用 Foor-loop or while-loop 取得資料列(並顯示在畫面上)~
用以下的 If判斷式 會出錯~

答案(Answer):
因為 If 判斷式~ 在判斷時會同時判斷 i是否符合條件 以及 arr(i + 1)是否符合條件~
故在此判斷式~ 便會出錯~
從字串 "XXXX" 至型別 'Date' 的轉換是無效的。

For i As Integer = 1 To 10
     If i = 3 And CDate(arr(i + 1)).ToShortDateString = "1900/1/1" Then
          C.Text = "尚無資料"
     End If
Next

需更改為
當判斷 i不符合時~ 就不會再判斷 arr(i + 1) 是否符合~
(1)
For i As Integer = 1 To 10
     If i = 3 Then
          If CDate(arr(i + 1)).ToShortDateString = "1900/1/1" Then
               C.Text = "尚無資料"
          End If
     End If
Next

或者
當更改判斷式 If AndAlso 判i不符合~ 就不會再判斷 arr(i + 1) 是否符合~
(2)

For i As Integer = 1 To 10

     If i = 3 And CDate(arr(i + 1)).ToShortDateString = "1900/1/1" Then
          C.Text = "尚無資料"
     End If

Next


或者
在判斷式之前 必須判斷 arr(i+1) 是否為日期型態
(3)
For i As Integer = 1 To 10

If IsDate(arr(i + 1)) = True Then
     '是日期型態
     If i = 3 And CDate(arr(i + 1)).ToShortDateString = "1900/1/1" Then
          C.Text = "尚無資料"
     End If
Else
     '不是日期型態
End If
Next


參考:

運算子 AndAlso 和 OrElse
VB.NET's Logical Operators AndAlso and OrElse