2011年2月18日金曜日

【VB.NET】ソートされたとしてもDataGridViewの行に対応するDataRowを取得する

DataGridViewのDataSourceに BindingSource や DataTable を関連付けした場合に
DataGridViewの4行目に当たるDataTableの行を取得したい、とかやりたい時ありますよね。

通常はそのまま同じ4行目が対応する行になるのですが、
ソートをしてしまうとDataGridViewはソートされますが、DataTableはソートされず、
行番号が食い違うようになってしまいます。
その場合、下記関数をご利用ください。

  1. #Region "DataGridViewのRowIndexからDataTableのDataRowを取得する"  
  2.         ''' <summary>  
  3.         ''' DataGridViewのRowIndexからDataTableのDataRowを取得する  
  4.         ''' </summary>  
  5.         ''' <param name="RowIdx">''' <returns></returns>  
  6.         ''' <remarks>ソート時など、DataGridViewのRowIndexが必ずしもDataTableのRowIndexとマッチしないため</remarks>  
  7.         Public Function GetDataRow_ByDataGridViewRowIdx(ByVal RowIdx As IntegerAs DataRow  
  8.             Try  
  9.                 If Me.Rows(RowIdx).DataBoundItem Is Nothing Then  
  10.                     Return Nothing  
  11.                 End If  
  12.             Catch ex As IndexOutOfRangeException  
  13.                 Return Nothing  
  14.             End Try  
  15.   
  16.             Dim Dr As DataRow  
  17.             Dim Drv As DataRowView = CType(Me.Rows(RowIdx).DataBoundItem, System.Data.DataRowView)  
  18.             Dr = CType(Drv.Row, System.Data.DataRow)  
  19.   
  20.             Return Dr  
  21.         End Function  
  22.  
  23.  
  24. #End Region  

対応するDataRowが取得できます。
これで行移動時に値の編集するなど、DataRowをいじっちゃってください。

2011年2月17日木曜日

【SQLServer】同一列名なのに桁数や列説明が食い違う他テーブルの列を抽出

同じ列名なのに他テーブルでは列説明が違ったり、
型が違ったり、桁数が違ったりする列ってちらほら出てきますよね。

発見するのが難しかったりするのでSQLを作成しました。

  1. SELECT DISTINCT  
  2.   COL1.TABLE_NAME  AS テーブル名  
  3. ,( select b.value from sys.tables a  
  4.    left join sys.extended_properties b on a.object_id = b.major_id and a.parent_object_id = b.minor_id   
  5.    where a.name =COL1.TABLE_NAME) AS テーブル説明  
  6. , COL1.COLUMN_NAME AS 列名  
  7. , COL1.DATA_TYPE AS 型  
  8. , COL1.CHARACTER_MAXIMUM_LENGTH AS 文字桁  
  9. , COL1.NUMERIC_PRECISION AS 整数桁  
  10. , COL1.NUMERIC_SCALE AS 小数桁  
  11. , COL1.IS_NULLABLE AS NULL許容  
  12. , COMMENT.COLUMN_COMMENT AS 列説明  
  13.   
  14. FROM INFORMATION_SCHEMA.COLUMNS COL1  
  15. -- コメントを取得  
  16. INNER JOIN(  
  17. select   
  18.      t.name as TABLE_NAME  
  19.     ,c.name as COLUMN_NAME  
  20.     ,ep.value as COLUMN_COMMENT  
  21. from  
  22.       sys.tables              t  
  23.      ,sys.columns             c  
  24.      ,sys.extended_properties ep  
  25. where  
  26.       t.object_id = c.object_id  
  27. and c.object_id = ep.major_id  
  28. and c.column_id = ep.minor_id) COMMENT  
  29. ON COMMENT.TABLE_NAME = COL1.TABLE_NAME  
  30. AND COMMENT.COLUMN_NAME = COL1.COLUMN_NAME  
  31.   
  32. -- 列の情報が食い違うもの  
  33. LEFT JOIN INFORMATION_SCHEMA.COLUMNS COL2  
  34. ON COL1.COLUMN_NAME = COL2.COLUMN_NAME   
  35. AND (COL1.DATA_TYPE <> COL2.DATA_TYPE   
  36.   OR COL1.CHARACTER_MAXIMUM_LENGTH <> COL2.CHARACTER_MAXIMUM_LENGTH   
  37.   OR COL1.NUMERIC_PRECISION <> COL2.NUMERIC_PRECISION   
  38.   OR COL1.NUMERIC_SCALE  <> COL2.NUMERIC_SCALE   
  39.   )  
  40. WHERE   
  41. (  
  42.        -- 列のコメントが食い違うもの  
  43.        (  
  44.               select  COUNT(distinct ep.value )--c.name AS COLUMN_NAME  
  45.   
  46.               from  
  47.                        sys.tables              t  
  48.                      ,sys.columns             c  
  49.                      ,sys.extended_properties ep  
  50.               where  
  51.                      t.object_id = c.object_id  
  52.               and c.object_id = ep.major_id  
  53.               and c.column_id = ep.minor_id  
  54.               and c.name = COL1.COLUMN_NAME   
  55.        group by c.name  
  56.        ) > 1  
  57.        -- 列の情報が食い違うもの のJOIN がヒットした  
  58. OR COL2.COLUMN_NAME IS NOT NULL  
  59. )  
  60.   
  61. -- 列名指定する場合はここに条件  
  62. --WHERE COL1.COLUMN_NAME = 'HIN_CD'  
  63.   
  64. ORDER BY COL1.COLUMN_NAME ASC  

実行すると修正の必要性がある列のみ抽出されます。

Oracleでも似たようなの作っておくと便利!

※ちなみにSQLはインデントなどちゃんと直してません。

2011年2月13日日曜日

【Windows】Skypeを2重起動させる方法

2つのアカウントを使用する場合など、
Skypeは標準に起動すると2重起動できません。

もし起動させたい場合は、

"C:\Program Files\Skype\Phone\Skype.exe" /secondary

のように /secondary というオプションをつけます。

ただし、これだけだと自動ログインがきかなくなるのです。

まぁ、アカウントが複数なのでもちろんそうなのですが。

そこで起動オプションを増やします。

"C:\Program Files\Skype\Phone\Skype.exe" /secondary /username:【username】 /password:【password】

/username , /password オプションで自動ログインが可能です。
これらを含めてショートカットを作成すると、複数アカウントにて自動起動が可能です。

ただしパスワードをショートカットに書いてしまうことになるので、
そこだけ気をつけてくださいね。

2011年2月12日土曜日

【VB.NET】Date型の定数の宣言

Date型の定数の宣言は以下の通りです。

  1. Public Const HogeDate As Date = #2/12/2011 12:00:00 PM#  

# で囲んだ日付で宣言します。
中はアメリカの日付表記ですね。

ちなみに

  1. Public Shared ReadOnly HogeDate As Date = #2/12/2011 12:00:00 PM#  
のような感じでも定数みたいなやつが作れるよな感じですけど、どうなんでしょうねぇ。。

まぁ、Constでいいと思います。

2011年2月11日金曜日

【Windows】ショートカット作成時「~へのショートカット」をつけなくする

※XPにて確認しています。

Windowsにてショートカット作成した場合、

「【ファイル名】へのショートカット」
という風に勝手に へのショートカット と名前がついてしまいます。

私はこの へのショートカットは消してしまうタチです。

初めからつけなくしたらいいのではないか、ということでレジストリを変更してしまいましょう。

-------------------------------------------------------------
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer]
"link"=hex:00,00,00,00
-------------------------------------------------------------

パッチは ここ に置いておきます。

実行するだけでショートカット作成時に へのショートカット という名前がつかなくなります。

2011年2月10日木曜日

【VB.NET】メソッドのステップ実行をスルーさせる

CellValueChangedの中にある自作の決まりきったメソッドなど、
ステップ実行する必要はもうないのにステップ実行の中に入ってしまう時ありますよね。

その時はメソッドの前に

<System.Diagnostics.DebuggerStepThrough()>

という属性をつけてください。

付け方としましては、
  1. <System.Diagnostics.DebuggerStepThrough()> _  
  2. Public Sub XXXX()  
  3.     ' 処理  
  4. End Sub  

となります。

ちなみに、VB2010では、属性の後の次の行につながるための _ がいらなくなりますね。

2011年2月9日水曜日

【VB.NET】Formの自動TabIndex設定

フォームのコントロールのタブインデックス設定は結構面倒です。
自分的には決まり切った規則があるにも関わらず、
同じ作業の繰り返しなのでかなり面倒です。

決まり切った規則とは以下の通りです。
-----------------------------------------------------
第1条件 Top値の少ないコントロール
第2条件 Left値の少ないコントロール
※子コントロールを持つコントロールは内部も設定する
-----------------------------------------------------
この並び順でTabIndexを自動で設定してあげれば解決するんでないの、ということです。

ということで、以下の関数とプロパティを作成しました。
継承元のFormに設置してみてください。

  1. #Region "自動タブインデックス設定"  
  2.   
  3.     Private _SetAutoTabIndex As Boolean  
  4.     <System.ComponentModel.Category("追加プロパティ")> _  
  5.     <System.ComponentModel.DefaultValue(GetType(Boolean), "False")> _  
  6.     <System.ComponentModel.Description("Trueにすると画面の全コントロールのタブインデックスを自動で設定します。")> _  
  7.     Public Property SetAutoTabIndex() As Boolean  
  8.         Get  
  9.             Return _SetAutoTabIndex  
  10.         End Get  
  11.         Set(ByVal value As Boolean)  
  12.             _SetAutoTabIndex = value  
  13.             If _SetAutoTabIndex Then  
  14.                 Dim UpdateCount As Integer  
  15.                 UpdateCount = SettingAutoTabIndex(Me)  
  16.                 MessageBox.Show(UpdateCount & "件のタブインデックスを自動設定しました。""自動設定", MessageBoxButtons.OK, MessageBoxIcon.Information)  
  17.                 _SetAutoTabIndex = False  
  18.             End If  
  19.         End Set  
  20.     End Property  
  21.   
  22.   
  23.     ''' <summary>  
  24.     ''' タブインデックスを自動で設定します。  
  25.     ''' </summary>  
  26.     ''' <param name="ControlsInObject">引数で渡されたコントロール(省略した場合はフォーム)</param>  
  27.     ''' <remarks></remarks>  
  28.     Public Function SettingAutoTabIndex(Optional ByVal ControlsInObject As Control = NothingAs Integer  
  29.         If ControlsInObject Is Nothing Then  
  30.             ControlsInObject = Me  
  31.         End If  
  32.         Dim UpdateCount As Integer = 0  
  33.         Dim sl As New System.Collections.SortedList()  
  34.   
  35.         ' ポジションが左上に近いコントロールから順にタブインデックスを設定する.優先順位は上、左の順  
  36.         For Each Ctrl As Control In ControlsInObject.Controls  
  37.             Try  
  38.                 Select Case True  
  39.                     ' 子コントロールを持てるコントロール(タブ、パネル、グループボックス...)  
  40.                     Case HasChildControls(Ctrl)  
  41.                         sl.Add(Ctrl.Top.ToString.PadLeft(10, "0") & Ctrl.Left.ToString.PadLeft(10, "0"), Ctrl)  
  42.                         UpdateCount += SettingAutoTabIndex(Ctrl)  
  43.   
  44.                     Case Else  
  45.                         sl.Add(Ctrl.Top.ToString.PadLeft(10, "0") & Ctrl.Left.ToString.PadLeft(10, "0"), Ctrl)  
  46.   
  47.                 End Select  
  48.             Catch ex As Exception  
  49.   
  50.             End Try  
  51.         Next Ctrl  
  52.         ' タブインデックスを設定する  
  53.         For Idx As Integer = 0 To sl.Count - 1  
  54.             If CType(sl.GetByIndex(Idx), Control).TabIndex <> Idx Then  
  55.                 CType(sl.GetByIndex(Idx), Control).TabIndex = Idx  
  56.                 UpdateCount += 1  
  57.             End If  
  58.         Next Idx  
  59.   
  60.         Return UpdateCount  
  61.     End Function  
  62. #End Region  
  63. #Region "子コントロールを持てるコントロールかどうかチェック"  
  64.     ''' <summary>  
  65.     ''' 子コントロールを持てるコントロールかどうかチェック  
  66.     ''' </summary>  
  67.     ''' <param name="Ctrl"></param>  
  68.     ''' <returns></returns>  
  69.     ''' <remarks>子コントロールを持てる場合、True。持てない場合、False</remarks>  
  70.     Public Function HasChildControls(ByVal Ctrl As Control) As Boolean  
  71.         Select Case True  
  72.             Case TypeOf Ctrl Is Panel, TypeOf Ctrl Is GroupBox, TypeOf Ctrl Is TabControl, TypeOf Ctrl Is UserControl  
  73.                 Return True  
  74.             Case Else  
  75.                 Return False  
  76.         End Select  
  77.     End Function  
  78. #End Region  

-----------------------------------------------------
・SettingAutoTabIndex
タブインデックスを設定します。引数としてGroupBoxなど渡せばその内部のみTabIndexを設定します。

・HasChildControls
子コントロールを持っているコントロールかどうかチェックします。

・SetAutoTabIndex
プロパティとして実装しました。Booleanで持っていることに特に意味はありませんが、
Trueにしてみるとタブインデックスを自動設定し、Falseに戻ります。
(本当はプロパティグリッドにボタンを置きたいです)
-----------------------------------------------------



FormのSetAutoTabIndex のプロパティをいじくるだけで自動でタブインデックスがデザイナ上で設定します。