プログラム作成時 Ctrl+C Ctrl+Vの前によく考えよう
[VBA系メニューへ]
[質問掲示板]
[バックナンバー目次]
こんにちは、三流プログラマーのKen3です。
三流君の書いてるメルマガ
http://www.ken3.org/guchi/ 作者の貧しい心の中が見れる愚痴系
で、
自分の貧しい技術に対する愚痴で書いたんだけど、
愚痴系で発行後、読み直すと、
VBA系の読者に見せたほうが、よさそうだったので、
こっちでも発行してます。
※愚痴系、VBA系読んでて、重複してしまった人はスミマセン。
三流君のお馬鹿な開発話を笑ってください
※反面教師でマネしないでね。
--- ここから はじまりです ---
どちらかと言えば、芸術的プログラムとは無縁の三流プログラマーです。
えっ、そんなのわかってるって?
そんな前フリは置いといて、
今回は、
Ctrl+C + Ctrl+V を使う前に一呼吸置こうよ
コピーして編集するプログラムは工夫できる率が高いよ
って話です。
まぁ、いつもの独り言だけど、聞いてください。
/*
* 1.今回のキッカケ
*/
VBA系のメルマガで、And演算子、Not演算子の解説を行ってました。
自己レスじゃないけど、フトお馬鹿なことに気がつく。
※いつになったら、手前味噌的な自慢系のメルマガに成長できるのだろう(笑)
オレ様のプログラムってキレイだろ、芸術品だよ、、と
いつか自信を持って、言って見たいよね。。。
おっと、挨拶はこれくらいにして、
/*
* 2.コピー -->貼り付け で作るプログラムの罠(笑)
*/
No.76 Access レポート Me.NextRecord = Falseで移動を止める
http://www.ken3.org/backno/backno_vba16.html#76
左端ならラベルを表示、レコード移動を止め次に実データを印刷する
そんなテストプログラムなのですが、
初めは下記のように、普通に作成してました。
Private Sub 詳細_Format(Cancel As Integer, FormatCount As Integer)
If (Me![cntA] Mod 3) = 1 Then '左端なら
If pFLG = False Then 'まだラベルエリアを印刷してなかったら
Me.NextRecord = False 'レコードの移動をまず止める
pFLG = True '印刷フラグを立てる
'ここにラベルのOn/Off処理を入れる
Me![lab01].Visible = True
Me![lab02].Visible = True
'実データをOff <−−−注目(笑)
Me![ID].Visible = False
Me![WrietTime].Visible = False
Me![F_TITLE].Visible = False
Me![F_MEMO].Visible = False
Else
'ここにラベルのOn/Off処理を入れる
Me![lab01].Visible = False
Me![lab02].Visible = False
'実データをOff <−−−注目(笑)
Me![ID].Visible = True
Me![WrietTime].Visible = True
Me![F_TITLE].Visible = True
Me![F_MEMO].Visible = True
End If
Else
pFLG = False 'その他の時
End If
End Sub |
よく見ると、同じような処理があって、
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'ここにラベルのOn/Off処理を入れる
Me![lab01].Visible = True
と
Else
'ここにラベルのOn/Off処理を入れる
Me![lab01].Visible = False
みたいな感じでOn/Offが逆なだけでした。
まぁ、処理が
左端ならラベルを表示、実データは非表示、
その他はラベル非表示、実データを表示だから、
True/Falseが違うだけで同じなんですよね。
そっか、それで、キーボードでCtrl+C,Ctrl+Vでコピーして、
True/Falseを逆に書いたんだ。
えっ、なんでCtrl+C,Ctrl+Vでコピーしたってわかったの?
だってさ、コメントが直ってないんだよ、アンタのコメントが?
えっ、どこどこ?
よく見ろよ、
If pFLG = False Then 'まだラベルエリアを印刷してなかったら
Me.NextRecord = False 'レコードの移動をまず止める
pFLG = True '印刷フラグを立てる
'ここにラベルのOn/Off処理を入れる
Me![lab01].Visible = True
Me![lab02].Visible = True
'実データをOff <−−−注目(笑)
Me![ID].Visible = False
Me![WrietTime].Visible = False
Me![F_TITLE].Visible = False
Me![F_MEMO].Visible = False
と
Else
'ここにラベルのOn/Off処理を入れる
Me![lab01].Visible = False
Me![lab02].Visible = False
'実データをOff <−−−注目(笑)
Me![ID].Visible = True
Me![WrietTime].Visible = True
Me![F_TITLE].Visible = True
Me![F_MEMO].Visible = True
End If
を良く見ると、
'実データをOff
^^^^^^^^^^^^^^^^^
ってコメントが一緒だよ。
Elseの部分のコメントは、実データをon、可視にする
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
が正しいんじゃないの?
コピーして作るのもいいけど、直してね、
コメントだから、まだ実害なかったけど、
もし、TrueとFalseを逆にするのを直し忘れてたら?
ゾッとするよね。
最近の開発スタイルって、エディターに直打ち、即実行確認、
なんて環境だから、
一呼吸置いて、考えないでコピー、貼り付けって多いと思う。
で、コピーした一部(部分的範囲)を変更する。
修正中にメールや携帯が鳴って、割り込みが入り作業中断、
そしたら、修正忘れがあったり、、なんて変なストーリーあったりしてね。
たまたま、今回は、
VBA系の
No.77 Not演算子で細工する、プログラムはパズルのように...
http://www.ken3.org/backno/backno_vba16.html#77
で、
Not演算子を使用して下記のようにまとめてみたけど、
何も考えないと、私のように同じ処理が氾濫してたりするよ(笑)
手前味噌、芸術的、ナルシスト的プログラムって言われてもたまには作ってみようよ。
Private Sub 詳細_Format(Cancel As Integer, FormatCount As Integer)
If (Me![cntA] Mod 3) = 1 Then '左端なら
'フラグを使用して可視/不可視をセットする
Me![lab01].Visible = Not pFLG 'ラベルはフラグの逆をセット
Me![lab02].Visible = Not pFLG
'実データ
Me![ID].Visible = pFLG '実データにはフラグそのままセット
Me![WrietTime].Visible = pFLG
Me![F_TITLE].Visible = pFLG
Me![F_MEMO].Visible = pFLG
If pFLG = False Then 'まだラベルエリアを印刷してなかったら
Me.NextRecord = False 'レコードの移動をまず止める
pFLG = True '印刷フラグを立てる
End If
Else
pFLG = False 'その他の時
End If
End Sub |
と、Not演算子を使用して、まとめました。
これなら、項目の1つだけTrue/Falseの修正忘れの単純ミスもないし、
項目が増えても、2ヶ所に処理を入れなくてOKです。
/*
* 3.プログラムには、ループや配列を使った処理が存在するんだよ(笑)
*/
画面に1回目、2回目、、4回目とMsgboxで表示してよと言われたら、
簡単なプログラムは、
Sub AAA()
Msgbox "1回目"
End Sub |
って書いてから、いつものCtrl+CでコピーCtrl+Vを3回押してと
Sub AAA()
Msgbox "1回目"
Msgbox "1回目"
Msgbox "1回目"
Msgbox "1回目"
End Sub |
としてから、
Sub AAA()
Msgbox "1回目"
Msgbox "2回目"
Msgbox "3回目"
Msgbox "4回目"
End Sub |
と直します(笑)
そんなことしないよFor文使うよ
~~~~~~~~~~~~~~~~~~
って、みなさん、心の中で言ったと思います
(私が勝手にアナタの心の中を予想しました)
ですよね、まぁ、コピー、一部変更プログラム極論でした。
では、チエちゃん好き、ミキちゃん好き、アキちゃん好き、マイちゃん好き
と名前を出すときは?
Sub AAA()
Msgbox "チエちゃん好き"
Msgbox "ミキちゃん好き"
Msgbox "アキちゃん好き"
Msgbox "マイちゃん好き"
End Sub |
じゃなくって、
Sub BBB()
Dim strNAME As Variant
Dim n As Integer
'配列を代入
strNAME = Array("チエ", "ミキ", "アキ", "マイ")
'データを表示
For n = 0 To 3
MsgBox strNAME(n) & "ちゃん好きです"
Next n
End Sub |
と、ループとArrayで配列を作成の知識のある人は作るかな。
/*
* 4.配列の要素数を返すUBound関数を使ったりする
*/
表示させたい、好きな子が増えたら?
コピー君は、
Sub AAA()
Msgbox "チエちゃん好き"
Msgbox "ミキちゃん好き"
Msgbox "アキちゃん好き"
Msgbox "マイちゃん好き"
Msgbox "アヤちゃん好き" '午後の紅茶のアヤちゃんは好きじゃないけど(笑)
End Sub |
とコピーで作成するのかな。
For君は、
Sub BBB()
Dim strNAME As Variant
Dim n As Integer
'配列を代入
strNAME = Array("チエ", "ミキ", "アキ", "マイ", "アヤ")
'データを表示
For n = 0 To 4 'カウンタも忘れずに増やす
MsgBox strNAME(n) & "ちゃん好きです"
Next n
End Sub |
とデータとカウンタを増やすのかな。
まぁ、忘れそうなのが、データ増やしてカウンタを増やすことを忘れるパターン。
それを防止する方法?があって、
昔からの古典的手法は
データの最後に"END"や"STOP","99"など、
ストップワードを入れて判断する方法もある。
Sub CCC()
Dim strNAME As Variant
Dim n As Integer
'配列を代入
strNAME = Array("チエ", "ミキ", "アキ", "マイ", "アヤ", "STOP")
'stopまでデータを表示
n = 0 'カウンタ初期化
While strNAME(n) <> "STOP" 'STOP以外の間ループする
MsgBox strNAME(n) & "ちゃん好きです"
n = n + 1 'カウントアップ次の子にする
Wend
End Sub |
これだと、ループの回数は指定しないで、"STOP"までループ可能。
まぁ、今風の書き方だと、配列の最大要素数を求めるUBoundって関数があって、
Sub DDD()
Dim strNAME As Variant
Dim n As Integer
'配列を代入
strNAME = Array("チエ", "ミキ", "アキ", "マイ", "アヤ")
'データを表示
For n = 0 To UBound(strNAME) '配列の最大要素までループ
MsgBox strNAME(n) & "ちゃん好きです"
Next n
End Sub |
ASPで作った例だけど、Split関数とUBound関数のサンプル
http://www.ken3.org/cgi-bin/test/test024-2.asp
こっちも参考にしてみてね。
/*
* 5.コントロールをループさせる For Each IN を使って
*/
この流れの解説だと、(話の流れだと)
読者の心の声をまたまた勝手に代弁すると、
^^^^^^^^^^^^^^
データをプログラム内に持たないで、ファイルなど外部に持つ方法だろ、、
と
普通は来るのですが、疲れたので、今日は辞めます(笑)
オイオイ、そりゃないでしょ。
えっと、このメルマガのタイトルに戻って、
タイトル?なんだっけ?
三流君、手前味噌的にプログラムを語る?だったっけ・・・
違うでしょ、
Ctrl+C + Ctrl+V を使う前に一呼吸置こうよ
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ってタイトルです。
下記のプログラムに戻ってと、
実は、ここでもCtrl+C Ctrl+Vでプログラム書いてるんですよね。
Me![ID].Visible = pFLG
をコピーして、
Me![F_TITLE].Visible = pFLG
Me![F_MEMO].Visible = pFLG
なんて、作ってるんですね。
※フィールド名が違うだけなので、コピーしてフィールド名を修正するかな普通。
Private Sub 詳細_Format(Cancel As Integer, FormatCount As Integer)
If (Me![cntA] Mod 3) = 1 Then '左端なら
'フラグを使用して可視/不可視をセットする
Me![lab01].Visible = Not pFLG 'ラベルはフラグの逆をセット
Me![lab02].Visible = Not pFLG
'実データ
Me![ID].Visible = pFLG '実データにはフラグそのままセット
Me![WrietTime].Visible = pFLG
Me![F_TITLE].Visible = pFLG
Me![F_MEMO].Visible = pFLG
If pFLG = False Then 'まだラベルエリアを印刷してなかったら
Me.NextRecord = False 'レコードの移動をまず止める
pFLG = True '印刷フラグを立てる
End If
Else
pFLG = False 'その他の時
End If
End Sub |
このプログラムでもいいんだけど、
実データの印刷フィールドが追加になったら、(F_TAKOフィールド)
Me![F_TAKO].Visible = pFLG
と、プログラムの追加が発生します。
※これも、上の一行Me![F_MEMO].Visible = pFLGをコピー後に名称変更かな
フィールドが追加になったから、ショウガナイヨネ、これは。
まぁ、そうなんですが、よく見ると、
Me![lab01]とMe![lab02]のラベル関係
と
実データのMe![F_XXXXX]の実データ関係
そんな2つのグループ分けができてます(IDとwriteなど例外あるけど(笑))
コントロールの名前付けで、
規則性があるなら、ループでまわせよってことで、
↑~~~~~~~~~~~~~~~~(コントロール名を規則正しく作ってね)
Controlsコレクションでまわしてみます。
Controls?コレクション?
コントロールにアクセスする方法は、
Me.Controls!新規データ
Me.Controls![新規データ]
Me.Controls("新規データ")
なんて、名前を指定する方法と、
インデックスでコントロールを参照することもできます。
Me(0) ' コレクションの最初の項目を参照します。
Me.Controls(0)
これを利用して、
Private Sub 詳細_Format(Cancel As Integer, FormatCount As Integer)
Dim n As Integer
If (Me![cntA] Mod 3) = 1 Then '左端なら
For n = 0 To Me.Controls.Count - 1 'コントロールの数ループする
If Left(Me.Controls(n).Name, 3) = "lab" Then '名前はラベル
Me.Controls(n).Visible = Not pFLG
Else
Me.Controls(n).Visible = pFLG
End If
Next n
If pFLG = False Then 'まだラベルエリアを印刷してなかったら
Me.NextRecord = False 'レコードの移動をまず止める
pFLG = True '印刷フラグを立てる
End If
Else
pFLG = False 'その他の時
End If
End Sub |
と書いて、
コントロールの名前付けの規則でTrue/False
を
切り替える方法も1つの手です。
Me.Controls(n).Visible
あっ、これが三流君のうわさのクセね。
ループのカウンタでまわしたがるってヤツね。
VBA系の
No.73 オブジェクトのループはFor Each In でループさせる
http://www.ken3.org/backno/backno_vba15.html#73
で、
偉そうなこと語ってて、これかよ。
~~~~~~~~~~~~~~~~~~~~
わかったよ、一般向けにFor Each版に修正するよ。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Private Sub 詳細_Format(Cancel As Integer, FormatCount As Integer)
Dim objITEM As Object 'コントロールのオブジェクトを入れる変数
If (Me![cntA] Mod 3) = 1 Then '左端なら
For Each objITEM In Me.Controls 'コントロールを取り出しループする
If Left(objITEM.Name, 3) = "lab" Then '名前はラベル
objITEM.Visible = Not pFLG
Else
objITEM.Visible = pFLG
End If
Next
If pFLG = False Then 'まだラベルエリアを印刷してなかったら
Me.NextRecord = False 'レコードの移動をまず止める
pFLG = True '印刷フラグを立てる
End If
Else
pFLG = False 'その他の時
End If
End Sub |
これなら、ラベルと実データの切り替えも、
コントロール名の規則にしたがって作成すれば、
変更の少ないプログラムで済みますね。
/*
* 6.終わりの挨拶(次回はアルのか?(爆))
*/
よくわからなかったけど、何が今日は言いたかったの?
えっと、
Ctrl+C , Ctrl+V でサクサク?コーディングするんだけど、
ちょっと待てよ、
コピー、貼り付け、一部変更、
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
なんてプログラムには、一工夫する余地があるのでは?
って話でした。
まぁ、キーボード打つのが早い、エディター使うのが早い
そんな若いプログラマーにトータル的に勝つには、
変更が来たとき、キーボード打量を減らす(もしくは打たなくていい)
そんなプログラム作りたいよね、
30代のキーボード打ち込み遅いおっさんプログラマーとしては(爆)
何か読者の心に残れば、うれしいです。
*私の独り言をうまく消化してくださいね。
手前味噌プログラム発表したいよねのKen3でした。
~~~~~~~(↑オイオイ)
質問・感想を送る
三流君のHP主な飛び先
VBA系のメルマガで書いた解説を項目ごとにまとめてます
[VBAでAccessを操作(一般)]
[VBAでAccessのレポートを操作]
[VBAでAccessのUserForm/サブフォームを操作]
[VBA Access から Excel 連携]
[VBA でExcel オブジェクト/プロパティ/メソッド/一般]
[VBA でExcel UserForm(ユーザーフォーム)を操作する]
[VBA ExcelからAccessを操作する]
[VBA Outlookの操作]
[VBA IEの操作]
[VBA テキストファイル(*.txt,*.html,*.csv)の操作]
[VBA標準関数関係とその他解説]
ASP系の解説を項目ごとにまとめてみました
[ASP Form等を使用したデータのやり取り]
[ASP その他処理サンプル]
[ASP テキストファイル処理]
[ASP VBScript関数関係の説明]
[ASP ADOでMdbファイルを使う]
[ASP ADOでExcelと接続してみた]
分類別
[アクセスランキング]
[サイトマップ]
[リンク先・相互リンク先など]
Ken3の日記(weblog) --
[広告・副収入系]
[プログラマー業務の愚痴]
[VBA系の話題]
[ASP系の話題]
[コンビニ系ネタ]
[その他]
その他、宣伝ページです
・[
アンケート/ポイント]などで月500円を必死に稼いでます(笑)
・[
SOHO/在宅プログラマー/派遣]の話題、Webエントリー後の反応など
・[
ネットで小金を稼げるか?]実験中だが成果は無し
※あとは、[パソコン関係の書籍]や[ゲームソフト]、
[パソコンパーツ]
をバナーから売ろうとするけど、
なかなかうまくはいかないよね(笑)