プログラミングと日々思ったことなど

ブログ名通りです。仕事でプログラミングをはじめました。

別クラスから、メソッドを操作する【VB.NET】

タイトル通りです。
どうすれば良いのか、思いつかなかったので先輩に教えてもらいました。

Private Sub frmTest_FormClosing(sender As System.Object, _
				e As System.Windows.Forms.FormClosingEventArgs) _
				Handles MyBase.FormClosing

	'呼び出したい画面
	Dim frm As frmTest = CType(Me.Owner,frmTest)

	'comboboxクリア
	frm.cmbテスト.DataSouce = Nothing
	'combobox設定
	frm.cmbテスト設定(frm.cmbテスト,"")
	'combobox選択名設定
	frm.cmbテスト.Text = Me.strTestNm

End Sub

frm.cmbテスト設定()が、メソッド名です。
呼び出したいメソッドは、スコープをPublicにします。
・・・これが思いつかなくて時間がかかりました。

DataGridのカラムを指定してデータを取得【VB.NET】

DataGridが苦手なので、少し復習します。


'カーソルを特定の1行まで移動させる
For Each dr As DataGridViewRow in grdテストグリッド.Rows
	
	'strIDには、システムIDのデータの1つが入っている
	If dr.Cells("テストID").Value = strID Then
		grdテストグリッド.Rows(dr.Index).Selected = True
	End If

Next
'カーソルの場所までデータグリッドをスクロール
grdテストグリッド.FirstDisplayedScrollingRowIndex =  _
			grdテストグリッド.SelectedCells(0).RowIndex

DataGridViewのColumnではなくRowを使って、データを取り出すというのが頭にしっくりきません。
忘れないように気をつけます。
似たようなコードをもう一つ。

For Each dtGrid_test As DataGridViewRow In grdテストグリッド.Rows
	'NullValueエラー回避
	If dtGrid_test.Cells("テストコード").Value = Nothing Then
		Exit For
	End If


	str_test = dtGrid_test.Cells("テストコード").Value.ToString().Trim()
	
	str_selectedvalには、インサートしようとしているデータが入っている。
	If str_test = str_selectedval
		blCheck = False
		Call MsgBox("重複しています",Me)
                Exit Sub
	End If

Next

日付について色々【VB.NET】

前回の記事から時間が経ってしまいました。
今回は、VB.NETでの日付変換についてです。

'和暦を日付変換することによって、正確な日付が入力されているのか確認する。
If Not DateTime.TryParse(cmb_年号.Text +
						 txt_年.Text + "年" +
						 txt_月.Text + "月" +
						 txt_日.Text + "日",chkDate) Then
	
	Call MsgBox("作成を入力してください",Me)
	cmb_年号.Focus()
	Return False

End If

chkDateの中には、多分こんなものの一部が入っています。
0730...chkDateは、何時何分何秒が入っているだけでした。このように和暦でも、TryParseはできるそうです。ただ、新しい和暦になるとエラーになってしまうかもしれないとのこと。(先輩談)

次は西暦から和暦の変換です。

Public Function chg_西和(ByVal str日付 As String,ByVal intフォーマット As Integer) As String

'基準日の年・月・日を取得
Dim BaseY As Integer
Dim BaseM As Integer
Dim BaseD As Integer

'ループに使う変数
Dim cnt As Integer
Dim 元号 As Integer = UBond(元号一覧) '元号一覧の中身も後で確認

'6桁なら(年月のみ)8桁にする
If str日付.Length = 6 Then
	str日付 = str日付 + "01"
ElseIf str日付 = "0" Then
	Return ""
End If

BaseY = Integer.Parse(Mid(str日付,1,4))
BaseM = Integer.Parse(Mid(str日付,5,2))
BaseD = Integer.Parse(Mid(str日付,7,2))

'戻り値初期化
 chg_西和 = ""

'元号の数だけループ
For cnt = 0 To 元号 Step 1

	With 元号一覧(Cnt)
	'取得した基準日と、DBにある元号開始日・終了日を比べる
	'開始日より基準日が大きい、かつ、基準日が終了日より小さい場合
	If(Integer.Parse(.getKaisi) <= Integer.Parse(str日付) And _
	   Integer.Parse(str日付) <= Integer.Parse(.getSyuryo)) Then

	   If intフォーマット = 0 Then
	   '平成xx年xx月xx日と返す
	   chg_西和 = .getGengoNm & _
	   			 String.Format("{0:D2}",BaseY - _
	   			 				(Integer.Parse(Mid(Trim(.getKaisi),1,4))-1)) &"年"& _
	   			 String.Format("{0:D2}",BaseM) &"月"& _
	   			 String.Format("{0:D2}",BaseD) &"日"&


	   Else If intフォーマット = 1 Then
	   '以下、戻す値の形が変更される処理が続く

	End If

Exit For

Else If (Integer.Parse(.getKaisi) > str日付 Or _
	   str日付 < Integer.Parse(str日付) >= Integer.Parse(.getSyuryo)) Then

	   MsgBox.Show("基準日が正しく設定されていません")
	   'For文を抜ける
	   Exit For
End If

End With
Next

End Function

SQLでの抽出方法 【IN】【ROW_NUMBER】【副問い合わせ】

①IN

SELECT * FROM test_table
WHERE aa IN (SELECT aa FROM (SELECT aa FROM test_table
			GROUP BY aa,bb,cc,dd HAVING COUNT(*) >= 2) AS X)

--6.28 これでもできた。
SELECT * FROM test_table
WHERE aa IN (SELECT aa FROM test_table
			GROUP BY aa,bb,cc,dd HAVING COUNT(*) >= 2)

IN句には複数の条件を記述することができます。
このsql文では、副問い合わせを行っている・・・のですが、副問い合わせの中で同じテーブルを使用するとエラーが出てしまうので、ASで別名をつけています。

書いていて思い出しました。
そのエラーが実際出るのかを試していません。
明日会社でやってみよう。


②ROW_NUMBER

SELECT aa,bb,cc,dd
      ,ROW_NUMBER() OVER(PARTITION BY aa,bb,cc,dd ORDER BY aa) AS 連番
FROM test_table

ROW_NUMBERは検索結果に順番をつけることができます。
ROW_NUMBER関数内にある、PARTITION BY でグループ化ができます。

③副問い合わせ

DELETE test_table FROM test_table AS C
INNER JOIN 
	(
	SELECT aa,bb,cc,dd
	,ROW_NUMBER() OVER(PARTITION BY aa,bb,cc,dd ORDER BY aa) AS 連番
		FROM test_table
	) AS A
	ON C.aa = A.aa
	AND C.bb = A.bb
	AND C.cc = A.cc
WHERE 連番 <> 1

副問い合わせは、SELECT文による問い合わせを入れ子にすることです。
③はINNER JOINの中で副問い合わせを行っています。
同じテーブルで、JOINさせているのはROW_NUMBER(連番)をつけるためなのですが、これはまだあやふやなので試す必要があります。

6.28
なんとなくわかってきたような・・・




上司が先輩におっしゃっていたことなのですが、自分も覚えておかなければならないと思ったので書き残しておきます。

自分の行ったこと(書いたプログラムとか)が、今後他のところでどんな影響を受けるのか考えなさい。

自分が作業した後のことまで考えるのは難しいです。
これから少しずつできるようになればいいな・・・。

SqlServerで、ストアドプロシージャを作成 その2

明日記事を書くと言っていたのに、遅れてしまいました。
反省。

前回の続きからです。

IF @header = 1
BEGIN
-- BCPコマンド出力設定をする
-- 半角スペースある/なしで正常に実行されないので注意する
SET @BCP_str = ''
SET @BCP_str = 'bcp "' + @SQL_heder_edit +'"'
SET @BCP_str = @BCP_str + ' queryout "' + @out_folder + ' Header.csv" '
SET @BCP_str = @BCP_str + '-c -t"," '
SET @BCP_str = @BCP_str + ' -S' + @S_name + ' '
SET @BCP_str = @BCP_str + '-d ' + ' test' + ' '
SET @BCP_str = @BCP_str + '-U ' + @U_id + ' '
SET @BCP_str = @BCP_str + '-P ' + @pass + ' ;'

-- CSVファイル実行
-- xp_cmdshell は、OS のコマンドを実行して出力をテキストの行として返す
EXECUTE @result = master.dbo.xp_cmdshell @BCP_str

IF @result = 1
BEGIN
	SET @R_Msg = 'ヘッダー作成失敗'
	RETURN @R_value
END

END

-- BCPの詳細ファイル出力
SET @BCP_str = ''
SET @BCP_str = 'bcp "' + @SQL +'"'
SET @BCP_str = @BCP_str + ' queryout "' + @out_folder + ' Detail.csv" '
SET @BCP_str = @BCP_str + '-c -t"," '
SET @BCP_str = @BCP_str + ' -S' + @S_name + ' '
SET @BCP_str = @BCP_str + '-d ' + ' test' + ' '
SET @BCP_str = @BCP_str + '-U ' + @U_id + ' '
SET @BCP_str = @BCP_str + '-P ' + @pass + ' ;'

EXECUTE @result = master.dbo.xp_cmdshell @BCP_str

IF @result = 1
BEGIN
	SET @R_Msg = '詳細ファイル作成失敗'
	RETURN @R_value
END

IF @header = 1
BEGIN
-- ヘッダーと詳細のファイル結合
SET @File_copy = ''
SET @File_copy = @File_copy + 'copy /B'
SET @File_copy = @File_copy + @out_folder + ' Header.csv'
SET @File_copy = @File_copy + ' +'
SET @File_copy = @File_copy + @out_folder + ' Detail.csv'
SET @File_copy = @File_copy + ' '
SET @File_copy = @File_copy + @out_folder + file_name
-- CSVファイル結合実行
EXECUTE @result = master.dbo.xp_cmdshell @File_copy
END

IF @header = 0
BEGIN
SET @File_copy = ''
SET @File_copy = @File_copy + 'copy /B'
SET @File_copy = @File_copy + @out_folder + ' Detail.csv'
SET @File_copy = @File_copy + ' '
SET @File_copy = @File_copy + @out_folder + file_name
EXECUTE @result = master.dbo.xp_cmdshell @File_copy
END

IF @header = 1
BEGIN
-- ヘッダー消去
SET @File_Del = ''
SET @File_Del + ' del /Q'
SET @File_Del + @out_folder + ' Header.csv'
EXECUTE master.dbo.xp_cmdshell @File_Del
END

-- 詳細ファイル消去
SET @File_Del = ''
SET @File_Del + ' del /Q'
SET @File_Del + @out_folder + ' Detail.csv'
EXECUTE master.dbo.xp_cmdshell @File_Del

END
-- 例外エラー
END TRY
BEGIN CATCH

RETURN @R_value	-- -1(失敗の値)が代入されている

END CATCH

SET @R_Msg = CAST(@Cnt AS VARCHAR) + '件を書き込みました。'
SET @R_value = 0 --成功の値(戻り値)
RETURN @R_value

END
GO

変数にどんどん代入していって、実行させるための文字列を作成するのが、難しかったです。


仕事を始めて数ヶ月、少しずつ慣れてきました。
まだ沢山学ばねばならないのですが、そろそろキーボードだけでパソコンを動かす方法(ショートカットキーだったかな)も覚えていこうかな。

SqlServerで、ストアドプロシージャを作成 その1

再びストアドを作成したので、2回に渡って復習します。
今回は、カーソル作成までです。

CREATE PROCEDURE SP_ABC (
		@file_name VARCHAR(50)
		,@table_name VARCHAR(50)
		,@out_folder VARCHAR(20) -- 出力先フォルダ(フルパス)
		,@S_name VARCHAR(30)
		,@U_id VARCHAR(20)
		,@pass VARCHAR(20)
		,@header CHAR(1)
		,@R_Msg VARCHAR(1000) OUTPUT	-- 返却メッセージ
)

AS

	DECLARE @hed_str NVARCHAR(3000)	
	-- ↑カーソルからfetchしてきた情報をカンマ区切りで格納
	DECLARE @hed_get VARCHAR(50)
	-- ↑列のヘッダーを格納
	DECLARE @SQL NVARCHAR(1000) -- SQL...は、SQL文を格納
	DECLARE @SQL_header NVARCHAR(1000)
	DECLARE @SQL_cursor NVARCHAR(1000)
	DECLARE @SQL_heder_edit NVARCHAR(1000)
	DECLARE @BCP_str VARCHAR(3000)
	DECLARE @File_copy VARCHAR(3000)
	DECLARE @File_Del VARCHAR(3000)
	DECLARE @R_value int --戻り値
	DECLARE @D_Msg VARCHAR(100)
	DECLARE @result int
	DECLARE @Cnt INTEGER

BEGIN

	SET @D_Msg = 'ストアドエラー発生'
	SET @R_value = -1

	BEGIN TRY

	-- テーブルデータ存在確認
	SET @SQL = N' SELECT * FROM ' + @table_name
	EXECUTE sp_executesql @SQL 	--SQL実行

	SET @Cnt = @@ROWCOUNT
	IF @Cnt = 0
	BEGIN
	SET @R_Msg = 'データなし' + @table_name
	RETURN @R_value
	END

	-- データ抽出SQL作成
	IF @header = 1
	BEGIN
	SET @SQL_header = N' SELECT d.name FROM Sys.tables AS t
					LEFT OUTER JOIN sys.columns AS c
					ON t.id = c.id
					WHRER t.name = ''' + @table_name + ''''
					+ N' ORDER BY c.column_nm '
	-- ↑ここがわかりづらい
   -- テーブルの名前を条件にして、カラムとテーブルを結合
	-- Sys.tablesというのはカタログビューと言う。
	-- カタログビューは、SqlServerデータベースエンジンによって使用される情報を返す。
	EXECUTE sp_executesql @SQL_header

	SET @SQL_cursor = N' DECLARE aa CURSOR FOR ' + @SQL_header
   -- ↑先ほど外部結合させるSQL文をカーソルの条件にしている。
	EXECUTE sp_executesql @SQL_cursor
	
	OPEN aa
	FETCH NEXT FROM aa INTO @hed_get
	
	IF @@FETCH_STATUS = 0
	BEGIN
	 SET @hed_str += @hed_get
	END

	WHILE @@FETCH_STATUS = 0
	BEGIN
	 FETCH NEXT FROM aa INTO @hed_get
	 SET @hed_str += ',' + @hed_get
	END

	CLOSE aa
	DECLARE aa

	SET @SQL_heder_edit = N'SELECT ' + '''' + @hed_str + ''''
	END
	

以上で、カンマ区切りのSELECT文を作成することができました。
これを、csvに出力させるためにbcpユーティリティを使っていきます。


続きはまた明日。

ストアドプロシージャからストアドプロシージャを呼び出す【SqlServer】

昨日は念願の(!)カーソルのあるストアドプロシージャの作成を行いました。
まだ未完成ですが、復習でコードを載せます。

USE testdb
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE testpro(
		@aaa VARCHAR(20)
		)
AS
	DECLARE @returnval int --戻り値
	DECLARE @SQL NVARCHAR(4000)
	DECLARE @lMsg(4000)

	--カーソルデータ格納変数
	DECLARE @kakunou VARCHAR(1000)

BEGIN
	BEGIN TRY
	SET @returnval = 1

	SET @lMsg = @aaa + 'のデータ移行を開始しました。'
	EXECUTE testbl '案内','',@aaa,0,@lMsg

	IF (@aaa IS NULL OR @aaa = '')
	BEGIN
		SET @lMsg = '引数が未設定'
		EXECUTE testbl 'エラー','',@aaa,1,@lMsg
		RETURN @returnval
	END

	--カーソル作成
	SET @SQL = 'DECLARE abc CUSOR FOR SELECT tosi From'
				+'(SELECT name From' + @aaa + ' .table) AS T'

	EXECUTE sp_executesql @SQL

	--カーソルオープン
	OPEN abc
	--abcから変数@kakunouに1件ずつデータを格納する
	FETCH NEXT FROM abc INTO @kakunou

	IF @@FETCH_STATUS <> 0
	BEGIN
		SET @lMsg ='テーブルが存在しません'
		EXECUTE testbl 'エラー','',@aaa,1,@lMsg
		RETURN @returnval
	END

	While @@FETCH_STATUS = 0
	BEGIN
		EXECUTE abcInsertpro @aaa,@kakunou
    #処理の後、FETCHで再び1行データを取得する
		FETCH NEXT From abc INTO @kakunou
	END

  CLOSE abc
       DEALLOCATE abc

        SET @lMsg = @aaa + 'のデータ移行を完了しました。'
	EXECUTE testbl '案内','',@aaa,0,@lMsg


	END TRY

	--例外エラー
	BEGIN CATCH
		SET @lMsg = '[ERROR_NUMBER]' + @SQL
		EXECUTE testbl 'エラー','',@aaa,1,@lMsg
		RETURN @returnval
	END CATCH
	SET returnval = 0
END

GO

@@FETCH_STATUSの設定がおかしいかな?
自分でもわかるように、土日で説明を書くつもりです。

...6月4日追加
データ以降が完了したことを判断する処理は、書かなくても良い(正常に処理されれば、下に流れていくため)


ここから雑記

金曜日に、映画「美しい星」という三島由紀夫原作のSF映画を見ました。
人間は人間自身を自然の一部だと思っていない...だったかな?
個人的にとても面白かったです。