Private Sub btn選択_Click()
Dim LNG顧客番号 As Long
'番号選択のチェック
If IsNull(Me![lst顧客番号]) Then '何も選択されていないか?チェック
MsgBox "顧客番号を選択してください"
Exit Sub '関数を抜ける
End If
'番号をローカル変数に保存する
LNG顧客番号 = Me![lst顧客番号]
Debug.Print LNG顧客番号 'テバックで表示
'フォームを閉じる
DoCmd.Close
'レコードを移動する
DoCmd.GoToControl "顧客番号" '顧客番号フィールドにコントロールを移動
DoCmd.FindRecord LNG顧客番号 '選択された番号のレコードに移動
'
End Sub
Private Sub btn選択_Click()
'番号選択のチェック
If IsNull(Me![lst顧客番号]) Then '何も選択されていないか?チェック
MsgBox "顧客番号を選択してください"
Exit Sub '関数を抜ける
End If
'番号を親フォームに保存する
Forms!顧客画面!顧客番号 = Me!lst顧客番号
'↑↑↑
'ここを印刷画面に変えて
Forms!顧客データ印刷!顧客番号 = Me!lst顧客番号
'フォームを閉じる
DoCmd.Close
End Sub
Private Sub btn開始番号検索_Click()
Dim stDocName As String
Dim stLinkCriteria As String
stDocName = "顧客番号検索画面"
DoCmd.OpenForm stDocName, , , stLinkCriteria, , , "顧客データ印刷/txtSTART"
End Sub
Private Sub btn終了番号検索_Click()
Dim stDocName As String
Dim stLinkCriteria As String
stDocName = "顧客番号検索画面"
DoCmd.OpenForm stDocName, , , stLinkCriteria, , , "顧客データ印刷/txtEND"
End Sub
Private Sub btnキャンセル_Click()
'フォームを閉じる
DoCmd.Close
End Sub
選択ボタンの時、Me.OpenArgsを参照して、データをセットする
Private Sub btn選択_Click()
'番号選択のチェック
If IsNull(Me![lst顧客番号]) Then '何も選択されていないか?チェック
MsgBox "顧客番号を選択してください"
Exit Sub '関数を抜ける
End If
'変換場所の判断
Dim n As Integer '/の位置判断
Dim strSETFORM As String 'フォーム名
Dim strSETCONTROL As String 'セットするコントロール名
n = InStr(Me.OpenArgs, "/")
If n <> 0 Then 'スラッシュの位置によって処理する
strSETFORM = Left(Me.OpenArgs, n - 1) '左から/の前まで
strSETCONTROL = Mid(Me.OpenArgs, n + 1) '/の次から最後まで
'顧客番号を指定フォームのコントロールにセット
Forms(strSETFORM).Controls(strSETCONTROL) = Me![lst顧客番号]
Else '下記、普通は通らないエラー処理
MsgBox "パラメータエラー、プログラム管理者にお伝えください"
End If
'フォームを閉じる
DoCmd.Close
End Sub
ポイントは、
~~~~~~~~~~~~
n = InStr(Me.OpenArgs, "/")
If n <> 0 Then 'スラッシュの位置によって処理する
strSETFORM = Left(Me.OpenArgs, n - 1) '左から/の前まで
strSETCONTROL = Mid(Me.OpenArgs, n + 1) '/の次から最後まで
で、/の位置を探し、
DoCmd.OpenForm stDocName, , , stLinkCriteria, , , "顧客データ印刷/txtSTART"
で送られてきた、
"顧客データ印刷/txtSTART"
のフォーム名とテキストボックスの名前を分解します。
'顧客番号を指定フォームのコントロールにセット
Forms(strSETFORM).Controls(strSETCONTROL) = Me![lst顧客番号]
で、
フォーム名とコントロール名を指定して、データをセットしています。
あまり見慣れない書き方かもしれませんが、
Forms(文字列).Controls(文字列)
で、代入/参照することが出来ます。
おまけで、
Private Sub lst顧客番号_DblClick(Cancel As Integer)
'リストボックスをダブルクリックしたら
Call btn選択_Click 'と、選択ボタンの処理を呼ぶ
End Sub
Private Sub 検索ボタン_Click()
Dim MyValue as String
'オリジナルのINPUTBOXもどき(ダイアログフォーム)から顧客番号が帰ってきて
MyValue = INPUT_顧客番号検索()
If MyValue = "" Then
'キャンセル処理を記述
Else
'ここに検索実行や値を使用したを記述します
'・
'・
End If
End Sub
Function INPUT_顧客番号検索() As Long
Dim stDocName As String
Dim stLinkCriteria As String
stDocName = "顧客番号検索画面"
'acDialog指定でフォームを開く
DoCmd.OpenForm stDocName, , , stLinkCriteria, , acDialog
INPUT_顧客番号検索 = 選択番号 '共通変数を代入しただけ
End Function
Private Sub btnキャンセル_Click()
'共通変数に選択データをセットする
選択番号 = 0 'ここではキャンセル時の0をセットする
'フォームを閉じる
DoCmd.Close
End Sub
Private Sub btn選択_Click()
'番号選択のチェック
If IsNull(Me![lst顧客番号]) Then '何も選択されていないか?チェック
MsgBox "顧客番号を選択してください"
Exit Sub '関数を抜ける
End If
'共通変数に選択データをセットする
選択番号 = Me![lst顧客番号] 'リストボックスの値をセットする
'フォームを閉じる
DoCmd.Close
End Sub
Private Sub btn開始番号検索_Click()
Dim lngNO As Long
lngNO = INPUT_顧客番号検索 '共通の検索ダイアログ
If lngNO <> 0 Then 'キャンセル0以外なら
Me!txtSTART = lngNO '検索された番号をセット
End If
End Sub
Private Sub btn終了番号検索_Click()
Dim lngNO As Long
lngNO = INPUT_顧客番号検索 '共通の検索ダイアログ
If lngNO <> 0 Then 'キャンセル0以外なら
Me!txtEND = lngNO '検索された番号をセット
End If
End Sub
Sub Macro1()
Sheets.Add
Sheets("Sheet4").Select
Sheets("Sheet4").Name = "名前の変更"
End Sub
でした。
.Nameプロパティを使用すれば出来そうですね。
Sub test1()
MsgBox ActiveSheet.Name
End Sub
なんてやると、現在選択されているシートの名前を表示可能です。
Sub test2()
MsgBox ThisWorkbook.Sheets(2).Name
End Sub
だと、左から2番目のシート名が表示されたと思います。
さらにバカっぽくヤルと、
Sub test3()
MsgBox ThisWorkbook.Sheets(2).Name
MsgBox ThisWorkbook.Sheets(3).Name
MsgBox ThisWorkbook.Sheets(4).Name
MsgBox ThisWorkbook.Sheets(5).Name
End Sub
Sub test4()
MsgBox "現在のシート数は、" & ThisWorkbook.Sheets.Count & "です"
End Sub
とやると、シートの個数が表示されると思います。
ループでまわして、
Sub test5()
Dim n As Integer 'カウンター変数
Dim strMSG As String 'メッセージ作成用のワーク
'一番目のシートから個数分処理を行う
For n = 1 To ThisWorkbook.Sheets.Count
strMSG = n & "番目のシート名は" & ThisWorkbook.Sheets(n).Name
MsgBox strMSG
Next n
End Sub
Sub test35()
Dim MyObject As Object 'オブジェクト型にしたけどシート型でも
Dim strMSG As String 'メッセージ作成用のワーク
'一番目のシートから個数分処理を行う
For Each MyObject In ThisWorkbook.Sheets 'ブックからシートを取り出す
strMSG = "今見ているシート名は" & MyObject.Name
MsgBox strMSG
Next
End Sub
となります。
こんな感じで処理すると、カウンターで回しているより、スマートです。
*まぁ、好みもありますが。。。
For Each MyObject In ThisWorkbook.Sheets
など、書式は、書いていくうちになれるので、
複数のオブジェクトをまわす時は、
ぜひ使ってみてください。
少しふっくらがイイのになぁ、、
(まだ言ってるよ、だれかコイツを黙らせて、、、)
オブジェクトのループはFor Each In でループさせる
http://www.ken3.org/backno/backno_vba15.html#73
も、ヒマな時、のぞきに来てね。
Function chkSHEET(strSNAME As String) As Boolean
・
・
End Function
>Function chkSHEET(strSNAME As String) As Boolean
^^^^^^^^^^^^^^^↑関数名です、重複しないわかりやすい名前にしましょう。
>Function chkSHEET(strSNAME As String) As Boolean
^^^^^^^^^^^^^^^^^^
ここでは、変数名strSNAME、変数の型は文字列で受け取ることにします。
最後の、
>Function chkSHEET(strSNAME As String) As Boolean
^^^^^^^^^^^^
As Booleanですが、聞きなれない、見なれない人も居るかもしれませんが、
ブール型 (Boolean)
真 (True) または偽 (False)を格納可能な変数の型です。
なんだか、堅苦しい話だなぁ、もっとサクッといかないかなぁ?
まぁまぁ、数作っているうちにわかるから。
*値の受け取り方や、型、関数の書式などは、
いろいろなプログラムを見てるうちにわかると思います。
シート名を表示するテストはできたから、
今度は、シート名の表示じゃなくって、
受け取ったシート名が存在するかのチェックをif文を使用して行います。
Function chkSHEET(strSNAME As String) As Boolean
Dim MyObject As Object
'ブック内のシート名の比較を行う
For Each MyObject In ThisWorkbook.Sheets
'.Nameプロパティのシート名と受け取ったstrSNAMEを比べる
If MyObject.Name = strSNAME Then
chkSHEET = True '名前が一致したのでTrueをセット
Exit Function 'もうすること無いので関数を抜ける
End If
Next
'一つも一致しなかったので、Falseをセット
chkSHEET = False
End Function
Sub testmain()
Dim strNAME As String 'INPUT BOX 値受け取り用
'InputBoxでシート名を入力する
strNAME = InputBox("シート名を入力してください")
'作ったユーザ関数をテストしよう
If chkSHEET(strNAME) = True Then
MsgBox strNAME & "シートはブック内に存在します"
Else
MsgBox strNAME & "シートはブック内に存在しません"
End If
End Sub
とやってみました。
三流君さぁ、なんか、しっくりこないんだよねぇ
えっ、どこが?テストで動いてるジャン、
'----
01: 'ブック内のシート名の比較を行う
02: For Each MyObject In ThisWorkbook.Sheets
03: '.Nameプロパティのシート名と受け取ったstrSNAMEを比べる
04: If MyObject.Name = strSNAME Then
05: chkSHEET = True '名前が一致したのでTrueをセット
06: Exit Function 'もうすること無いので関数を抜ける
07: End If
08: Next
09:
10: '一つも一致しなかったので、Falseをセット
11: chkSHEET = False
'----
では、言うけど、ここの処理なんだげとさぁ、
05: chkSHEET = True '名前が一致したのでTrueをセット
06: Exit Function 'もうすること無いので関数を抜ける
と
10: '一つも一致しなかったので、Falseをセット
11: chkSHEET = False
で、結果をセットして関数抜けてるんだけど、
もうすること無いのでいきなりExit Functionでその下実行しないで抜けてるけど、
流れがなんかなぁ、、、
流れを少しスッキリさせる
~~~~~~~~~~~~~~~~~~~~~~~~
では、少し頭を使って、、、
Function chkSHEET(strSNAME As String) As Boolean
Dim MyObject As Object
Dim MyRET As Boolean 'リターン値を保存
'ブック内のシート名の比較を行う
For Each MyObject In ThisWorkbook.Sheets
'.Nameプロパティのシート名と受け取ったstrSNAMEを比べる
If MyObject.Name = strSNAME Then
MyRET = True '名前が一致したのでTrueをセット
Exit For 'もう探す必要無いのでループを抜ける
Else
MyRET = False '見つからないのFalseをセット
End If
Next
'リターン値をセットして、関数を抜ける
chkSHEET = MyRET
End Function
これは、どうでしょうか?
Dim MyRET As Boolean
を定義して、下記の判断で戻り値をセット、
If MyObject.Name = strSNAME Then
MyRET = True '名前が一致したのでTrueをセット
Exit For 'もう探す必要無いのでループを抜ける
Else
MyRET = False '見つからないのFalseをセット
End If
見つかった時はExit For でループを抜けます。
三流君、なんかなぁ、、サクッといかないみたいね。
まぁ、書き方はいろいろ、女性の好みと一緒とかいつもいってるけど、
少しでもキレイでわかりやすいのにしたほうがいいよねぇ。
ギク、、パターンを読者に読まれているかも。。。
先にFalseで初期化しておくのも一つの手かなぁ?
~~~~~~~~~~~~~~~~~~~~~~
Function chkSHEET(strSNAME As String) As Boolean
Dim MyObject As Object
Dim MyRET As Boolean 'リターン値を保存
MyRET = False '先に見つからないFalseを初期化代入
'ブック内のシート名の比較を行う
For Each MyObject In ThisWorkbook.Sheets
'.Nameプロパティのシート名と受け取ったstrSNAMEを比べる
If MyObject.Name = strSNAME Then
MyRET = True '名前が一致したのでTrueをセット
Exit For 'もう探す必要無いのでループを抜ける
End If
Next
'リターン値をセットして、関数を抜ける
chkSHEET = MyRET
End Function
Function chkSHEET(strSNAME As String) As Boolean
Dim work As Variant
'エラーが発生したら、ラベルERR_NOSheetsへ飛ぶ
On Error GoTo ERR_NOSheets
'シートの値を取り出す。ここでエラーならシート無しと判断するため
work = Sheets(strSNAME).Cells(1, 1) 'ダミーで左上を参照
'エラーが発生しなかったら、リターン値をセットして、関数を抜ける
chkSHEET = True
Exit Function
'エラーの時、ここに飛んでくる
ERR_NOSheets:
chkSHEET = False 'シートの値が取れない=シートが無い
End Function
今回は、そんな単純な話じゃなくて、
クエリーのレコード単位で(1行単位で)、
処理を行いたいです。
う〜ん、何か無いかなぁ。。。
チョット無さそうなので、VBAで作ることにします。
AccessからExcelを作成するのは、少し前にもやりました。
これは、まず置いといて、
クエリーの中身をレコード単位で取り出す方法を調べてみたいと思います。
>> PS.Accessは97or2000どれでしょうか?
>
>ACCESS2000ですよろしくおねがいします。
ヤバ、Access2000かぁ・・・ADOでやるか。
※一昔前のDAOは少しやったことあるんだけど。
DAOとADO移行を調べてみると(これから始める人は過去の関係なんて聞かなくても)
※DAO から ADO への移植
http://www.microsoft.com/japan/msdn/data/techmat/ado/dao2ado.asp
上記の情報もみるといいかも。
ざっとみてみると、いろいろあるんだけど、
Recordset を開く場合
^^^^^^^^^^^^^^^^^^^^^
DAOだと、
Dim db as Database
Dim rs as DAO.Recordset
Set db = CurrentDB()
Set rs = db.OpenRecordset("Employees")
ADOだと、
Dim rs as New ADODB.Recordset
rs.Open "社員", CurrentProject.Connection, adOpenKeySet, adLockOptimistic
へぇ、そんな感じなんだぁ。
Private Sub btnTEST01_Click()
Dim rs As New ADODB.Recordset
rs.Open "Q_顧客情報", CurrentProject.Connection, _
adOpenKeyset, adLockOptimistic
MsgBox "テストでレコードカウント表示" & rs.RecordCount
End Sub
Private Sub btnTEST01_Click()
Dim rs As New ADODB.Recordset 'ADOのレコードセット
'レコードセットを開く(Q_顧客情報)
rs.Open "Q_顧客情報", CurrentProject.Connection, _
adOpenKeyset, adLockOptimistic
'ループ処理
While rs.EOF = False 'いつものEOFが偽の間
MsgBox "氏名は" & rs.Fields("氏名") '氏名をテストで表示する
rs.MoveNext '次のレコードに移動しないと、とんでもないことに(笑)
Wend
rs.Close '開いたら閉じろ、ドアを開けたら閉めるってしつけられたでしょ(笑)
Set rs = Nothing '変数も後始末しますか。使った器はキレイにしろって?
End Sub
Private Sub Form_Open(Cancel As Integer)
'フォームオープン時、カレンダーを当月の1日にする
Me!OLE_Calendar.Year = Year(Date) 'システム日付から
Me!OLE_Calendar.Month = Month(Date) 'システム日付から
Me!OLE_Calendar.Day = 1 '1日を固定代入
End Sub
としてみた。
あれ、、、変わらないよ、おかしいなぁ。。。
/*
* 4.フォームのイベント発生順に注意
*/
ヘルプを調べてみると、
Openイベントは、フォームが開くときに、最初のレコードが表示される前に発生
レポートの場合、レポートがプレビューされるか印刷される前に発生します。
Open イベントは、Load イベントよりも前に発生します。
Load イベントは、フォームが開くか、またはフォームのレコードが表示されたときに発生します。
最初にフォームを開くと、
次の順序でイベントが発生します。
Open --> Load --> Resize --> Activate --> Current
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
そんな順番なんだぁ、気にしてなかった。
コントロールへフォームのロード前に代入しているからか?
それで代入しても無視されているのか。
まぁ、Resize Activate Current のイベントで、
コントロールを初期化するとマズそうだから
(アクティブやサイズ変更と触っただけで、初期化すると処理的に怒られそう)
Loadに入れてテストしてみます。
Private Sub Form_Load()
'カレンダーを当月の1日にする
Me!OLE_Calendar.Year = Year(Date) 'システム日付から
Me!OLE_Calendar.Month = Month(Date) 'システム日付から
Me!OLE_Calendar.Day = 1 '1日を固定代入
End Sub