http://q.hatena.ne.jp/1206174892

「ワークシート関数だけでやる」ということで、「VBAのお勉強」じゃないですが(^^;)

質問者さんの「ワークエリア」という言葉の意味がちょっとわからなかったのですが、

ワークエリア excel」で検索するとこちらのサイトが出てきました。

「一時的に用いられる記憶領域」という事ですね。
んじゃ、Sheet3を一時的に使ってみます。

さて。Sheet1からAの値を探して、Sheet2に値を出力すると言うことで。
ワークシート関数で何かを探すといったら、よく使うのはVLOOKUP関数ですね(^^)

VLOOKUP関数の書式は、「VLOOKUP関数」で検索すると、

こちらが見つかりました。

=vlookup(検索対象文字列,検索対象セル,抽出列,検索方法)

こんな感じですね。

んでも、これを普通に使ったんじゃ、複数の候補があった場合、最初の1つ目しか見つからないんじゃないかな?

VLOOKUPって、あんまり使ったことないので、ためしにやってみます。

Sheet1が

97-1.jpg

こんな状態だとします。

Sheet2のB1のセルで、VLOOKUPワークシート関数を使いたいのですが、

VLOOKUPで探すことが出来るのは、2つめのパラメータの「検索対象セル」の

左端の列だけなんですよね。。。ということは、このSheet1の形式ではB列の

値で検索したいので、使えません。

ということで、Sheet3に一時的に検索用にデータを入れてみます。

Sheet3のセルB1に

=Sheet1!B2

セルB2に

=Sheet1!A2

として、値をコピーし、その計算式を、8行目までドラッグします。

97-02.jpg

ん(^^)。これで、VLOOKUPを使えるような列の順番になりました。

とりあえず、A2~B8の範囲でA列で「A」の値を探してB列の値を返してみます。

Sheet2のB1のセルに、

=VLOOKUP(“A”,Sheet3!A2:B8,2,FALSE)

と入れてみます。

97-03.jpg

ん、とりあえずおっけい(^^)

1つめのパラメータが探したい値(”A”)、

2つめのパラメータが値を探すセルの範囲(Sheet3のA2からB8)

3つめのパラメータが見つかった行の値を返す列の番号(上で指定した範囲の中で、2列目の値を返す)

4つめのパラメータが、完全に一致するものを探す(FALSE)

という指定になっています。

ただ、、、B3の列で2つめのAの値をどうやって探すのか?

VLOOKUPワークシート関数には、「2つめに一致する行を探す」なんて機能はなさげですし。。。

探すセルの範囲を変える事はできますが、1つ前で見つかった次の行から探す?というのを、

どうやって指定すればいいか。。。

「1つめのA」、「2つめのA」、「3つめのA」という情報があれば、なんとかなるかな?

97-04.jpg

今あるのは、この情報ですから、ここでなんとか、

5行目のAが1つめのA、

6行目のAが2つめのA、

8行目のAが3つめのA

という事を導き出せば、VLOOKUPでなんとかなりそうです。

んじゃ、どうやって、5行目のAが1つめのAかを探すか、ですが。

頭の中で考えた場合、B列をB2から下に見ていって、

最初に見つかったAが1つめのA、

次に見つかったAが2つめのA、

その次に見つかったAが3つめのA

ということになります。

Aが見つかったら、値を一つ増やしてカウントしていく、、、これならなんとか計算式でできそう(^^)

分かりやすくするために、とりあえず、Sheet1でやってみます。

Sheet1のC2に

=IF(B2=”A”,1,0)

と入れて、B8までコピーします。

97-05.jpg

B列が「A」だったら1、そうでなければ0、という感じです(^^)

んで、D2に

=C2

D3には、

=C3+D2

と計算式を入れて、D3の計算式をD8までコピーすると、

97-06.jpg

こんな感じ(^^)。欲しい情報が得られました。

「Aが見つかったら1つ増やす」という列をD列に設けることで、

その行が上から何個目のAなのか、が分かるようになります。

後は、VLOOKUPワークシート関数を使って、

1つ目のA、

2つ目のA、

3つ目のA

って感じで探していけばいいですね(^^)

Sheet3でやってみます。とりあえず、今のSheet1のC列、D列と、さっき作ったSheet3の計算式は消しちゃいます。

Sheet3では、Aかどうかを判断する列とカウントする列を1つにまとめちゃいます。

Sheet3のA2に

=IF(Sheet1!B2=”A”,1,0)

A3に、

=IF(Sheet1!B3=”A”,Sheet3!A2+1,Sheet3!A2)

と入れて、A3をA8までコピーします。

B2に

=Sheet1!A2

として、B2をB8までコピーします。

97-07.jpg

ん、いいんでないかい?(^^)

A2の計算式は、

Sheet1のA2が「A」だったら1、そうでなければ0

という意味です。

A3の計算式は、

Sheet1のA3が「A」だったら、Sheet3のA2に1を足す、そうでなければ、Sheet3のA2の値そのまま。

という意味です。

A3の計算式をA8までコピーすることで、

Sheet1がAだったら1つ上のセルの値に1を足し、そうでなければ、1つ上のセルの値そのまま。

ということになります。

後は、Sheet2で、VLOOKUPワークシート関数を使うだけです。

Sheet2のB1のセルに、

=VLOOKUP(1,Sheet3!$A$2:$B$8,2,FALSE)

Sheet2のB2のセルに、

=VLOOKUP(2,Sheet3!$A$2:$B$8,2,FALSE)

Sheet2のB3のセルに、

=VLOOKUP(3,Sheet3!$A$2:$B$8,2,FALSE)

と入れると、、、

97-08.jpg

ん、よいようです(^^)

ただ、、、この計算式のままだと、1つめのパラメータ、

これは計算式をコピーしても1のままで変わらないので、いちいち手で直していかないといけないです。

めんどくさいですね(^^;)

ということで、Sheet3のB2からずっと右側に

97-09.jpg

こんな感じで、1からドラッグして値を入れておけば、Sheet2のB1の式を

=VLOOKUP(Sheet3!B1,Sheet3!$A$2:$B$8,2,FALSE)

とすることで、この式をC1以降にコピーしていけばよいですね(^^)

んでは、試しに、Sheet1のカバの値を「A」にしてみます。

97-10.jpg

すると、Sheet2は、、、
97-11.jpg

ん、いい感じ(^^)

ただ、D1までしか計算式を設定していないので、4つ目の値(ハシビロコウ)は出てないですね。

同じようにE1以降も計算式を設定すれば出るようになります。

E1~P1にも式をコピーしておきます。

97-12.jpg

(^^;) E1はきちんと出ましたけど、それ以降は・・・?

たぶんに、VLOOKUPワークシート関数で、5以降の値が見つからなかったということでしょう。

あまり美しくないので、#N/Aは出ないようにしたいですね。

VLOOKUP #N/A」で検索すると、こちらのページが見つかりました。ISERROR関数を使うようですね。

B1の計算式を以下のように直します。

 

=IF(ISERROR(VLOOKUP(Sheet3!B1,Sheet3!$A$2:$B$8,2,FALSE)),"",VLOOKUP(Sheet3!B1,Sheet3!$A$2:$B$8,2,FALSE))

 

んで、この式をC1からP1までコピーすると、

97-13.jpg

ん、いいんでないかい?(^^)

いちおう、これで完成ということで。

Sheet1で行数が増えた場合、参照するセルの範囲が変わりますので、計算式が全部変わってくることになりますが、

たぶん、検索対象の範囲を指定する際に、セル範囲の名前を指定することが出来たと思いますので(やったことないですが(^^;))

それを使えばいちいち計算式全部を直す必要はなくなると思います。

とりあえず、こちらにアップしておきます。vbastudy_0010.xls

http://q.hatena.ne.jp/1205765249

質問者さんのシート、これはシフト管理をするものなのかな?

左側のシートは、

「ある日のある人がどの当番に入っているか」

がわかる表で、これを、

「ある日のある当番が誰なのか」

を一覧にしたものが右側のシート、
と思われます。

質問者さんの左側のシート、1行目の数字が何を意味してるのかは
わかりませんが、日付としてみます。
2行目は曜日のようですが、これは右側のシートに出てきていませんので、
ここでは無視します。

とりあえず、5日までダミーで作ってたのがこちら。

easycapture0.jpg

これを右側の形に直すVBAを作ってみます。

まず、日付と思われる数字をいれちゃいます。
このシートでは5日までですが、何日まで入っているかわからないので、
1行目がどの列までデータが入っているかを調べてみます。

いつもは、縦(下)方向にデータが最後に入っている行を探していましたが、
今度は横(右)方向に調べてみます。

いつもの下方向は、
ActiveSheet.Range(“A1″).End(xlDown).Select
lastgyou = ActiveCell.Row
こんな感じ。

XlDownってなってるところが、下方向に探すところかな?
これを変えれば、右方向に探してくれると思うので、なんて変えればいいかを
調べてみます。
xlDown 右方向 で検索すると、
http://www.eurus.dti.ne.jp/~yoneyama/Excel/vba/vba_cell.html#xlup
のページが見つかりました。

xlToRightでいいみたいですね。

いつもはA1から下に調べていますが、今回は、B1から右に調べます。

Sub test()
    Dim lastretu As Integer
    Dim i As Integer

    Sheets("Sheet1").Select
    ActiveSheet.Range("B1").End(xlToRight).Select
    lastretu = ActiveCell.Column

    For i = 2 To lastretu
        Debug.Print (ActiveSheet.Cells(1, i).Value)
    Next

End Sub

lastretuという変数に、最終列が何列目かを入れるようにしました。

いつもの、
lastgyou = ActiveCell.Row

lastretu = ActiveCell.Column

となっています。アクティブのセルの列番号を取ってきています。

実行してみると、

easycapture1.jpg

ん、いい感じ(^^)

とりあえず、この値を結果のシートに入れちゃいます。

入れる場所なんですけど、列はAでいいんですが、行は何行目になるかを
計算しないといけないですね。

For ループで、iは2からlastretuまで変化します。

i=2の時(B2の時、つまり日付が1の時)、この「1」という日付の値をコピーする先は
Sheet2の2行目になります。

i=3の時(B3の時、つまり日付が2の時)、この「2」という日付の値をコピーする先は
Sheet2の5行目になります。

なんで5行目になるかですが、質問者さんが「各当番は最高3人まで」と書いていますので、
1日である当番の値は最大3行分です。というわけで、3行分開けた5行目が2列目の最初になります。

同じように
i=4の時、Sheet2の8行目、
i=5の時、Sheet2の11行目、



i=xの時、Sheet2の(x-2)*3+2 行目ですね(^^;)
Sheet2が結果のシートだとして、縦に入れていきます。

Sub test()
    Dim lastretu As Integer
    Dim i As Integer
    Dim copydata As String

    '1行目の最終列を求めます
    Sheets("Sheet1").Select
    ActiveSheet.Range("B1").End(xlToRight).Select
    lastretu = ActiveCell.Column

    '日付をコピーします
    For i = 2 To lastretu
    'コピーするデータをcopydataという変数に入れます。
        Sheets("Sheet1").Select
        copydata = ActiveSheet.Cells(1, i).Value
    'Sheet2にデータをコピーします。
        Sheets("Sheet2").Select
        ActiveSheet.Cells((i - 2) * 3 + 2, 1).Value = copydata
    Next

End Sub

コメントを入れてみました。copydataという変数を設けて、Sheet1から1つずつ抜き出して、Sheet2の該当するセルにコピーしていきます。

実行してみると、

easycapture2.jpg

ん、できてます(^^)

で、次。
Sheet1をAさんからIさんまで順番にSheet2にコピーしていきたいと思います。

まず、AさんからIさんまでを抜き出してみます。
これはいつもどおりですね。

Sub test()
    Dim lastretu As Integer
    Dim lastgyou As Integer
    Dim i As Integer
    Dim copydata As String

    '1行目の最終列を求めます
    Sheets("Sheet1").Select
    ActiveSheet.Range("B1").End(xlToRight).Select
    lastretu = ActiveCell.Column
    '最後の人を求めます
    ActiveSheet.Range("A3").End(xlDown).Select
    lastgyou = ActiveCell.Row

    '日付をコピーします
    For i = 2 To lastretu
    'コピーするデータをcopydataという変数に入れます。
    Sheets("Sheet1").Select
        copydata = ActiveSheet.Cells(1, i).Value
    'Sheet2にデータをコピーします。
    Sheets("Sheet2").Select
        ActiveSheet.Cells((i - 2) * 3 + 2, 1).Value = copydata
    Next

    '最初の人から最後の人まで表示します。
    Sheets("Sheet1").Select
    For i = 3 To lastgyou
        Debug.Print (ActiveSheet.Cells(i, 1).Value)
    Next

End Sub

実行してみます。

easycapture3.jpg

ん、全員出ました(^^)

では、それぞれの人の当番を抜き出してみます。
これは先ほど見つけたlastretuの値を使って、抜き出せますね。

Sub test()
    Dim lastretu As Integer
    Dim lastgyou As Integer
    Dim i As Integer
    Dim j As Integer
    Dim copydata As String

    '1行目の最終列を求めます
    Sheets("Sheet1").Select
    ActiveSheet.Range("B1").End(xlToRight).Select
    lastretu = ActiveCell.Column

    ActiveSheet.Range("A3").End(xlDown).Select
    lastgyou = ActiveCell.Row

    '日付をコピーします
    For i = 2 To lastretu
    'コピーするデータをcopydataという変数に入れます。
    Sheets("Sheet1").Select
        copydata = ActiveSheet.Cells(1, i).Value
    'Sheet2にデータをコピーします。
    Sheets("Sheet2").Select
        ActiveSheet.Cells((i - 2) * 3 + 2, 1).Value = copydata
    Next

    '最初の人から最後の人まで表示します。
    Sheets("Sheet1").Select
    For i = 3 To lastgyou
        Debug.Print (ActiveSheet.Cells(i, 1).Value)
        '各個人の当番を抜き出します。
        For j=2 to lastretu
                Debug.Print (ActiveSheet.Cells(i, j).Value)
        Next
    Next
End Sub

jの変数でループしています。
実行すると、

easycapture4.jpg

ん、Hさん、Iさんしか見えませんが、抜き出せていますね(^^)

これで、

いつ(jの値でわかります)、
誰が(iの値でわかります)、
何の当番か(Cells(i, j)のセルの値でわかります)

を、全てのセルに対して抜き出すことが出来ましたので、
上の値を使って、今度はSheet2にその情報を書き出していきます。

とはいえ、Sheet2のどこに何を書き出すのかは、単純な計算式などでは求まりません。
この部分のアルゴリズムがこのプログラムの肝になりそうです。

試しに、Aさんの情報を手動で、Sheet2に書き出す手順を考えていきます。

easycapture5.jpg
まず、Aさんの1日、これは「早番」です。

Sheet2は最初、

easycapture6.jpg

こんな状態です。
1行目には、当番を書きます。今回は「早番」を抜き出してきたので、
B1のセルに「早番」と入れます。

easycapture7.jpg

で、1日の「早番」はAさんである、という情報は、B2のセルに表現します。

easycapture8.jpg

とりあえず、これで1つ目の処理は終わりですね。

次、今度はAさんの2日について。今度は「遅番」です。
Sheet2の1行目に今度は「遅番」という情報を追加します。
C1のセルになりますね。

easycapture9.jpg

で、2日の「遅番」はAさんである、これは、C5のセルに表現します。

easycapture10.jpg

こんな感じ(^^)

次、Aさんの3日について。今度は「早番」です。
早番は、さっき1日の時に、B列に作っちゃいましたので、1行目は
何もしません。
で、3日の「早番」はAさんである、これは、C8のセルに表現します。

easycapture11.jpg

次、Aさんの4日について。今度は「普通」です。
これは今までには出てきていない当番なので、1行目に増やさないといけないですね。
3つ目の当番ですので、D1のセルになります。

easycapture12.jpg

で、4日の「普通」はAさんである、これは、D11のセルに表現します。

easycapture13.jpg

次、Aさんの5日について。「遅番」ですので、これはもうCの列に作ってあります。
5日の「遅番」はAさんである、これは、C14のセルに表現します。

easycapture14.jpg

これでAさんの情報は表示が終了しました。

同じようにBさん、Cさん・・・最後のIさんまでやっていきます。
さて、まず1行目の当番について。
これは抜き出したデータの当番が新しいものだったら(すでに出ている当番でなければ)、
どんどん右へ追加していく形でよいと思います。

どこに情報を出すのかを決める際、列は

・すでに出ている当番の場合は、その列に。
・今までに出ていない当番の場合は、最後の列に追加して、その列に。

で決めることが出来ます。

行は、どこになるでしょうか?
今、Aさんの情報を抜き出してきた時は、Aさんははじめの人ですから、
1日は2行目、
2日は5行目、
3日は8行目、
4日は11行目、
5日は14行目
と、すんなり書き出せましたけど、、、。

試しにBさんもやってみます。

Bさんの1日の当番は「遅番」です。列は、すでにC列にありますから追加する必要はありません。
で、1日の「遅番」はBさんである、これはC2のセルに表現します。

easycapture15.jpg

次、Bさんの2日の当番も「遅番」です。C列に書き出しますが、
2日はAさんも「遅番」です。
ということは、C5のセルはすでにAさんが入っていますから、その下に書き出さなければ
なりません。C6に入ることになります。

easycapture16.jpg

こんな感じですね。

ということで、抜き出した情報をどこに出すかですが、
・まず、当番の値で列を決める(今の例だと、C列)。
・その列で、何日目かにより、基準となる行を求める(今の例だと、5行目)。
・その列と行のセルに値が入っていなければ、そこに書き出す。入っていたら、その下を見る。
 その下も入っていたら、さらにその下を見る、以下繰り返し。

って感じですね(^^;)

プログラムにしてみます。

Sub test()
    Dim lastretu As Integer
    Dim lastgyou As Integer
    Dim i As Integer
    Dim j As Integer
    Dim k As Integer
    Dim copydata As String

    Dim nukidashihito As String
    Dim nukidashitouban As String

    Dim kakidashiretu As Integer
    Dim kakidashigyou As Integer

    'Sheet2をすべて空にしておきます。
    Worksheets("Sheet2").Cells.Clear

    '1行目の最終列を求めます
    Sheets("Sheet1").Select
    ActiveSheet.Range("B1").End(xlToRight).Select
    lastretu = ActiveCell.Column

    '一番最後の人を求めます
    ActiveSheet.Range("A3").End(xlDown).Select
    lastgyou = ActiveCell.Row

    '日付をコピーします
    For i = 2 To lastretu

    'コピーするデータをcopydataという変数に入れます。
        Sheets("Sheet1").Select
        copydata = ActiveSheet.Cells(1, i).Value

    'Sheet2にデータをコピーします。
        Sheets("Sheet2").Select
        ActiveSheet.Cells((i - 2) * 3 + 2, 1).Value = copydata
    Next

    '最初の人から最後の人まで抜き出します。
    For i = 3 To lastgyou

        '今から処理する人の名前をnukidashihitoに入れます
        Sheets("Sheet1").Select
        nukidashihito = ActiveSheet.Cells(i, 1).Value

    '各個人の当番を抜き出します。
    'jは2列目から最後の列までを表しています。
    For j = 2 To lastretu

            'その人のその日付の当番を nukidashitoubanに入れます。
            Sheets("Sheet1").Select
            nukidashitouban = ActiveSheet.Cells(i, j).Value

            'nukidashitoubanの値から、どこの列に書き出すかを求めます。
            'Sheet2をB1から右に見ていき、すでにあれば、その列に
            'なければ、そのnukidashitoubanの値を追加して、その列にします。
            Sheets("Sheet2").Select

            '書き出す列をB列(右から2つめの列)から探します。
            kakidashiretu = 2

            Do
                'もし、すでにその列に同じ当番があったら、ループを抜ける
                If ActiveSheet.Cells(1, kakidashiretu).Value = nukidashitouban Then Exit Do

                'もし、何も書かれていないセルだった場合、新しい当番なので、
                'そのセルにnukidashitoubanの値を入れ、ループを抜ける
                If ActiveSheet.Cells(1, kakidashiretu).Value = "" Then
                    ActiveSheet.Cells(1, kakidashiretu).Value = nukidashitouban
                    Exit Do
                End If

                '1つ右のセルを調べる
                kakidashiretu = kakidashiretu + 1

            Loop


            '何日目の情報を抜き出しているか( j の値・・・2~lastretuまで変化します)によって、書き出すセルの基準の行を決めます。
            kakidashigyou = (j - 2) * 3 + 2

            '書き出す基準となったセルを含めて、下に3つ分のセルの中から、開いている
            'セルに値を代入します。どこも開いていなければ、何もしません

            For k = kakidashigyou To kakidashigyou + 2

                If ActiveSheet.Cells(k, kakidashiretu).Value = "" Then
                    ActiveSheet.Cells(k, kakidashiretu).Value = nukidashihito

                    Exit For
                End If

            Next

    Next

    Next

End Sub

一気に長くなっちゃいました(^^;)
まず、全ての処理を行う前に、Sheet2を空にしておきます。
赤い部分で、書き出す列を決めています。kakidashiretu を2から調べていき、
赤い部分を抜けた段階で、書き出す列の値がkakidashiretu に入っていることになります。

青い部分で、書き出す行を決めています。
Sheet1の列( j )の値を使って、まず基準となる行をkakidashigyouに入れます。
その後で、まず、kakidashigyou行目を見て、そこに値が入っていなければ、そこに当番の人を
書き込みます。For のループで、下2つ分で見つかるまで繰り返しています。

実行してみると、
easycapture17.jpg
いいんでないかい(^^)

これで一応完成かな?

Sheet1に入っている値によっては、問題が出る場合もあります。
例えば、「当番は3人まで」という条件以外のデータが入っていたりすると、4人目以降の人の情報は出ません。

また、例えば当番のない人(休みとか?)の場合、当番の値を空にするかもしれませんが、
その場合も正しく値が代入されません。

人数が増えても、当番の種類が増えても、このままのプログラムで問題ないですが、
「一日最大3人まで」の条件が変わる場合は、何箇所か手を入れる必要があります。
セルを求める式の掛け算の3の値と、最後のFor の K のTo のところの+2を変えれば、
大丈夫だと思います。

とりあえず、ここにおいておきます→vbastudy_0009.xls

Fizz Buzz問題」って、
・ループ
・条件判断
っていう、プログラムを作る際の基本的な考え方を使って作るものなんで。
自分なりにいろんな言語で書いてみたりして、練習してたんですが。

「3の倍数」「5の倍数」・・・最近お笑い番組で出てる、
世界のナベアツ」のネタって、確かそんなネタだったような(^^;)

と思って、世界のナベアツ fizz buzzで検索してみると、

(^^;) やはり同じことを考えている人がいるもんですね。

というわけで、彼の持ちネタの1つ「3の倍数と3がつく数字のときアホになり、8の倍数のとき
気持ちよくなる」を、VBAとExcelのワークシート関数で作ってみました。

まず、VBAバージョン。

Sub test()
Dim i As Integer
For i = 1 To 40
    Debug.Print i;

    If i Mod 3 = 0 Or InStr(Str(i), "3") <> 0 Then

        Debug.Print "~~~";

    End If

    If i Mod 8 = 0 Then

        Debug.Print "ぅぅういえぇえあ";

    End If

    Debug.Print

Next

End Sub

イミディエイトウィンドウに表示するだけのものです。
語尾につける文字列は、こちらのサイトを参考にさせていただきました。

実行してみます。

69-1

ん、ネタそのまま(^^;)

つぎはワークシート関数で。
A1~A40に1から40の値を入れておき、B1に以下の計算式を入れます。

 
 

=A1 & IF(MOD(A1,3)=0,"~~~",IF(ISERROR(FIND("3",A1)),"","~~~")) & IF(MOD(A1,8)=0,"ぅぅういえぇえあ","")
 
 

で、A1の計算式をA2~A40までコピーすると、

69-3.jpg

ん、こちらもOK(^^;)

「3のつく数字」を探す際のFINDワークシート関数の扱いがちょっと分かりにくかったです。
探して見つからなかった場合、#VALUE!というエラーになってしまうので、
ISERROR関数を使ってFIND関数の値を調べ、

エラーだったら(つまり3がつかなかったら)何も表示しない、
そうでなければアホになる。

という感じですね。

あと、VBAのMODとワークシートのMODの記述の仕方が違うんですね(^^;)

VBA・・・5 mod 3→2
ワークシート関数・・MOD(5,3)→2

これもこんがらがっちゃいました(^^;)

こちらにおいておきます→vbastudy_0008.xls

Yahoo!地図情報Flash版のルート再生機能を使用する際に必要となるルート情報をxmlファイルで生成する際に、全部の軌跡を緯度・経度で取得するのが面倒なので、経由地点を地図で指定していくと、自動的にその途中の緯度・経度を計算して作成し、xmlを作成するプログラムを作ってみました。

こちらからどうぞ(このページの動作のみ、Win2000,IEで確認)

この記事は、複数の列を比べて重複行を探す、というものです。

「単独の列で重複している行を探す」というサンプルは、
VBAのお勉強 VBAでExcelの重複した行を探して表示
をご覧下さい。
「重複している行を1行だけ残して削除する」というサンプルは、
VBAのお勉強 Excelで1行残して重複行を削除
をご覧下さい。

http://q.hatena.ne.jp/1205154937

「列単位でコンペアさせ、コンペア結果、重複データがある場合」という条件がはっきりしないので、

勝手に「Sheet1のA列のある行のデータがSheet2のA列のどこかにあった場合、重複データとする」としてみました。

イメージとしては、

  • Sheet1のA列の1行目の値を取り、その値がSheet2のA列にあるかどうかを調べる。
  • あったらその値をSheet3に書き出す、なければそのまま。
  • これをSheet1の最後の行まで繰り返す。

という感じでしょうか。

例えばこんな感じのワークシートがあったとします。

02.jpg04.jpg

まずSheet1のA列の1行目の値「a」に注目します。

この値がSheet2のA列の1~7行目にあれば、Sheet3に書き出します。

この場合、「a」はありませんので何もしません。

次、Sheet1の2行目の「b」。これもないので何もしません。

次、Sheet1の3行目の「c」。これはSheet2のA列の1行目にありますので、 Sheet3に書き出します。

書き出す位置は、これが見つかった値の1個めですからA1にします。

次、Sheet1の4行目の「1」。これもないので何もしません。

次、Sheet1の5行目の「2」。これもないので何もしません。

次、Sheet1の6行目の「3」。これはSheet2のA列の4行目にありますので、 Sheet3に書き出します。

書き出す位置は、これが見つかった値の2個めですからA2にします。

これでSheet1の全部の行を見ました。

これでおっけい(^^)

ではこれをプログラムにしてみます。

Excelから「ツール」→「マクロ」→「Visual Basic Editor」でプロジェクトの中の「Sheet1」をダブルクリック、するとコードを記述するウィンドウが表示されます。

まず、Sheet1のA列を一行ずつ見ていく必要があるので、とりあえず、イミディエイトウィンドウに Sheet1のA列を1行ずつ表示するプログラムを作ってみます。

この記事でやったことと全く同じですね(^^;)

Sub test()

    Dim lastgyou As Integer
    Dim i        As Integer
    
    ActiveSheet.Range("A1").End(xlDown).Select
    lastgyou = ActiveCell.Row
    
    For i = 1 To lastgyou
        
        Debug.Print (ActiveSheet.Cells(i, 1).Value)
    
    Next

End Sub

で、実行してみます。

  06.jpg

ん、いいんでないかい(^^)

次、こうやって取り出した値を1つずつ、Sheet2にあるかどうかを探す事になりますので、 Sheet2も同じように、A列の何行目までデータが入っているかを調べてみます。

。。。はて。上のプログラムだと、ActiveSheetってなってますので、今現在選択しているシートの事しかわからないですね。

というか、これじゃ、このプログラムを実行したときに選択されているシートの値を表示しちゃうかな?

試しに、Sheet2を選択した状態でこのプログラムを動かしてみると、

  08.jpg

(^^;)Sheet2の値が表示されちゃいました。

これじゃ駄目ですね。 どうしたもんか。。。

どのシートが選択されている状態でもSheet1の値を見るようにしないとまずいですね。

プログラムでシートを選択する方法を調べてみます。

Yahoo!で「vba excel シートの選択」で検索すると、こちらのページが見つかりました。

Sheets(“Sheet1″).Select で良いみたいですね。 これをプログラムの先頭に入れてみます。

Sub test()
    
    Dim lastgyou As Integer
    Dim i        As Integer
    
    Sheets("Sheet1").Select
    ActiveSheet.Range("A1").End(xlDown).Select
    lastgyou = ActiveCell.Row
    
    For i = 1 To lastgyou
        
        Debug.Print (ActiveSheet.Cells(i, 1).Value)
    
    Next

End Sub

Sheet2を選択した状態で、

  10.jpg

プログラムを実行してみます。

12.jpg

ん、Sheet1に切り替わってますね。いいかんじ(^^)

Sheet2について調べたければ Sheets(“Sheet2″).select に切り替えればいいですね。

それでは、Sheet1とSheet2、それぞれ何行目までデータが入っているかを調べてみます。

Sub test()
    
    Dim sheet1lastgyou As Integer
    Dim sheet2lastgyou As Integer
    
    Sheets("Sheet1").Select
    ActiveSheet.Range("A1").End(xlDown).Select
    sheet1lastgyou = ActiveCell.Row
    
    Sheets("Sheet2").Select
    ActiveSheet.Range("A1").End(xlDown).Select
    sheet2lastgyou = ActiveCell.Row
    
    Debug.Print ("sheet1は" + Str(sheet1lastgyou) + "行目まで")
    Debug.Print ("sheet2は" + Str(sheet2lastgyou) + "行目まで")

End Sub

Sheet1の最終行の行番号がsheet1lastgyouに入り、Sheet2がsheet2lastgyouです。

14.jpg

ん、よいようです(^^)

それではとりあえず、Sheet1のデータがSheet2にあるかどうかを調べるプログラムを作ってみます。

Sub test()

    Dim i              As Integer
    Dim j              As Integer
    Dim check          As String
    Dim sheet1lastgyou As Integer
    Dim sheet2lastgyou As Integer
    
    'Sheet1の最終行を求める
    Sheets("Sheet1").Select
    ActiveSheet.Range("A1").End(xlDown).Select
    sheet1lastgyou = ActiveCell.Row
    
    'Sheet2の最終行を求める
    Sheets("Sheet2").Select
    ActiveSheet.Range("A1").End(xlDown).Select
    sheet2lastgyou = ActiveCell.Row
    
    'Sheet1を1行目から最終行まで
    For i = 1 To sheet1lastgyou
        
        'Sheet1を選択します
        Sheets("Sheet1").Select
        
        'Sheet1のi行目の値を取り出します
        check = ActiveSheet.Cells(i, 1).Value
        
        'Sheet2を選択します
        Sheets("Sheet2").Select
        
        'Sheet2を1行目から最終行まで
        For j = 1 To sheet2lastgyou
            
            'Sheet2のj行目の値とcheckの値が同じだったら
            If ActiveSheet.Cells(j, 1).Value = check Then
                
                'とりあえずイミディエイトウィンドウに表示します
                Debug.Print (check)
            
            End If
        
        Next
    Next
End Sub

プログラムにコメントを入れてみました。やってることは、さっき言葉で書いたことそのままです。

動かしてみます。

14_2.jpg

ん、重複している値(「c」と「3」)が表示されました(^^)

あとは、この見つけた値をSheet3に書き出していけばいいですね。

1つ目を見つけたら、Sheet3のA1にその値を入れる、

2つ目を見つけたら、Sheet3のA2にその値を入れる、

以下繰り返しって感じで。

今何個目なのかを入れておく変数を作り、見つけたら、セルに値を入れ、変数を1つ増やす、これで行きます。

Sub test()
    Dim i              As Integer
    Dim j              As Integer
    Dim check          As String
    Dim sheet1lastgyou As Integer
    Dim sheet2lastgyou As Integer
    Dim sheet3gyou     As Integer
    
    'Sheet1の最終行を求める
    Sheets("Sheet1").Select
    ActiveSheet.Range("A1").End(xlDown).Select
    sheet1lastgyou = ActiveCell.Row
    
    'Sheet2の最終行を求める
    Sheets("Sheet2").Select
    ActiveSheet.Range("A1").End(xlDown).Select
    sheet2lastgyou = ActiveCell.Row
    
    'Sheet3の行数を0にしておく
    sheet3gyou = 0
    
    'Sheet1を1行目から最終行まで
    For i = 1 To sheet1lastgyou
        
        'Sheet1を選択します
        Sheets("Sheet1").Select
        
        'Sheet1のi行目の値を取り出します
        check = ActiveSheet.Cells(i, 1).Value
        
        'Sheet2を1行目から最終行まで
        For j = 1 To sheet2lastgyou
            
            'Sheet2を選択します
            Sheets("Sheet2").Select
            
            'Sheet2のj行目の値とcheckの値が同じだったら
            If ActiveSheet.Cells(j, 1).Value = check Then
                
                'Sheet3に代入するセルの行数を1つ増やします。
                sheet3gyou = sheet3gyou + 1
                
                'Sheet3を選択します
                Sheets("Sheet3").Select
                
                'セルに見つけた値を代入します
                ActiveSheet.Cells(sheet3gyou, 1).Value = check
            End If
        Next
    Next
End Sub

sheet3gyouという変数を設け、最初は0、見つけたら1つ増やして、 Sheet3に切り替え、見つけた値をセルに代入する、という感じです。

プログラムを動かしてみると。。。

151.jpg

ん、いいんでないかい?(^^)

これで完成、、、と思ったんですけど。

今入ってるデータだったら問題ないんですけど、 Sheet1内、Sheet2内で重複しているデータがあった場合、例えばこんな感じ。

16.jpg

この状態で実行すると、

17.jpg

こんな感じ。「a」はいいとして、「b」「c」が2つ出てます。

「b」はSheet1に2つありますから、それぞれがSheet2の1つと一致します。

なので、2つ出ます。「c」はSheet1の1つがSheet2の2つと一致しますので、やはりこれも2つ出ます。

重複しているものは出ているので、これでいいっちゃいいんですけど、ここは、

18.jpg

こう出たほうがスマートですかね?(^^;)

さて、どうやろうかな。

Sheet2の中で重複している場合(この場合「c」)は、Sheet2を上から見ていくとき、 1つ目が見つかった段階で、もうその値を探すのを止めてしまえばよさそうです。

見つかった場合、forのループを抜け出してしまう感じですね。

Sub test()
    Dim i              As Integer
    Dim j              As Integer
    Dim check          As String
    Dim sheet1lastgyou As Integer
    Dim sheet2lastgyou As Integer
    Dim sheet3gyou     As Integer
    
    'Sheet1の最終行を求める
    Sheets("Sheet1").Select
    ActiveSheet.Range("A1").End(xlDown).Select
    sheet1lastgyou = ActiveCell.Row
    
    'Sheet2の最終行を求める
    Sheets("Sheet2").Select
    ActiveSheet.Range("A1").End(xlDown).Select
    sheet2lastgyou = ActiveCell.Row
    
    'Sheet3の行数を0にしておく
    sheet3gyou = 0
    
    'Sheet1を1行目から最終行まで
    For i = 1 To sheet1lastgyou
        
        'Sheet1を選択します
        Sheets("Sheet1").Select
        
        'Sheet1のi行目の値を取り出します
        check = ActiveSheet.Cells(i, 1).Value
        
        'Sheet2を1行目から最終行まで
        For j = 1 To sheet2lastgyou
            'Sheet2を選択します
            
            Sheets("Sheet2").Select
            'Sheet2のj行目の値とcheckの値が同じだったら
            
            If ActiveSheet.Cells(j, 1).Value = check Then
                
                'Sheet3に代入するセルの行数を1つ増やします。
                sheet3gyou = sheet3gyou + 1
                
                'Sheet3を選択します
                Sheets("Sheet3").Select
                
                'セルに見つけた値を代入します
                ActiveSheet.Cells(sheet3gyou, 1).Value = check
                
                '1つ目が見つかったので、ループから抜けます
                Exit For
            End If
        Next
    Next
End Sub

見つかった後、セルに代入した後でExit forでループを抜け出します。実行してみると、

19.jpg

ん、「c」は1つだけになりました(^^)。

後は、Sheet1内で重複していた場合ですね。

Sheet1を1行ずつ見ていって、これからチェックしようとする値(checkという変数に代入しています)が、それまで見てきた行の中にあるかどうかをチェックし、もしもあった場合、その行を飛ばす、というのでどうでしょうか。

これなら、Sheet1の3行目の「b」を見ているときは、すでに2行目に「b」がありますから、飛ばすことになります。

というわけで、プログラムにしてみます。

Sub test()
    Dim i              As Integer
    Dim j              As Integer
    Dim k              As Integer
    Dim atta           As Integer
    Dim check          As String
    Dim sheet1lastgyou As Integer
    Dim sheet2lastgyou As Integer
    Dim sheet3gyou     As Integer
    
    'Sheet1の最終行を求める
    Sheets("Sheet1").Select
    ActiveSheet.Range("A1").End(xlDown).Select
    sheet1lastgyou = ActiveCell.Row
    
    'Sheet2の最終行を求める
    Sheets("Sheet2").Select
    ActiveSheet.Range("A1").End(xlDown).Select
    sheet2lastgyou = ActiveCell.Row
    
    'Sheet3の行数を0にしておく
    sheet3gyou = 0
    
    'Sheet1を1行目から最終行まで
    For i = 1 To sheet1lastgyou
        
        'Sheet1を選択します
        Sheets("Sheet1").Select
        
        'Sheet1のi行目の値を取り出します
        check = ActiveSheet.Cells(i, 1).Value
        
        'attaという変数を0にします。
        atta = 0
        
        'もし、Sheet1の2行目以降を見ている場合
        If i >= 2 Then
            
            '今見ている行の前の行までに今回の値があるかどうかを探します
            
            For k = 1 To i - 1
                
                If ActiveSheet.Cells(k, 1).Value = check Then
                    atta = 1
                    Exit For
                End If
            
            
            Next
        End If
        
        'もし、atta=0ならば、Sheet2を探します。
        If atta = 0 Then
            
            'Sheet2を1行目から最終行まで
            For j = 1 To sheet2lastgyou
                
                'Sheet2を選択します
                Sheets("Sheet2").Select
                
                'Sheet2のj行目の値とcheckの値が同じだったら
                If ActiveSheet.Cells(j, 1).Value = check Then
                    
                    'Sheet3に代入するセルの行数を1つ増やします。
                    sheet3gyou = sheet3gyou + 1
                    
                    'Sheet3を選択します
                    Sheets("Sheet3").Select
                    
                    'セルに見つけた値を代入します
                    ActiveSheet.Cells(sheet3gyou, 1).Value = check
                    
                    '1つ目が見つかったので、ループから抜けます
                    Exit For
                
                End If
            
            Next
        End If
    Next
End Sub

新たに、attaとkという変数を作りました。

もし、Sheet1の2行目以降を探す場合、それ以前の行の値を For k=1 to i-1 ということで、1行目から、今探している行(i)の1つ前までループし、その行のセルの値が、checkの値と同じかどうかを調べ、同じだったら、attaという変数に1を入れます。

もし見つからなかったら、attaの変数は0のままですので、 attaが0だったら、今度はSheet2を調べる、という事になります。

プログラムを実行すると、、、

20.jpg

ん、いいんでないかい(^^)

いちおう、これで完成、でいいかな・・・?

こちらにアップしておきます→vbastudy_0006.xls

前の記事の仕組みを使って、ちょっとお遊びで作りました(^^;)Yahoo!のトップページのトピックスから見出しを取ってきて、適当につぎはぎにして表示するプログラムです。
まったく乱数で表示してるので、出てくる見出しはでたらめです。

取ったテキストを抜き出してなんやらかんやら加工をかけてます。
もっとスマートな方法があるとは思うんですが、、、今の自分では
この辺で限界(^^;)

JavaScriptで正規表現とか、配列の操作、タイマー、乱数とかほとんどはじめて使ってみました。今後こういったプログラムを書くときのために残しておきます。

やはりこれもローカルでないと動きません。

<?xml version="1.0">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">

<script language="javascript">
<!--
varhttpObj;

function httpRequest(target_url)
{
try
{

httpObj = false;

if(window.XMLHttpRequest) {
    // Firefox, Opera など
    httpObj = new XMLHttpRequest();

} else if(window.ActiveXObject) {
    // IE
    try {
        httpObj = new ActiveXObject('Msxml2.XMLHTTP');
    } catch (e) {
        httpObj = new ActiveXObject('Microsoft.XMLHTTP');
    }
}

}
catch(e)
{
alert('エラーです');
return;
}

//データを取得する
httpObj.open("GET", target_url, true);
httpObj.onreadystatechange = DataRead;
httpObj.send("");

return;
}

function DataRead()
{
        if (httpObj.readyState == 4 && httpObj.status == 200)
{

//取得したレスポンスをgetTextに入れる
var getText=httpObj.responseText;

//getText1にgetTextの「<ul class="emphasis">」から始まるテキストを入れる
var getText1=getText.substring(getText.indexOf('<ul class="emphasis">'));

//getText2にgetText1の「</ul>」の前までのテキストを入れる
var getText2=getText1.substring(0,getText1.indexOf('</ul>'));

//getText3の配列に、<a>~</a>を入れる
var getText3=getText2.match(/<a.+?>.+?</a>/g);

//すべてのgetText3の配列のタグを取り除く
for (var i=0;i<getText3.length;i++){
var xx=getText3[i].match(/<a.+?>(.+?)</a>/);
getText3[i]=RegExp.$1;
}

//すべてのgetText3の「、」を半角スペースに置き換え
for (var i=0;i<getText3.length;i++){
getText3[i]=getText3[i].replace('、',' ').replace('「',' ').replace('」',' ');
}
//すべてのgetText3の連続する半角スペースを1つにする
for (var i=0;i<getText3.length;i++){
while (getText3[i].indexOf('  ')!=-1){
getText3[i]=getText3[i].replace('  ',' ');
}
}

//すべてのgetText3の両端の半角スペースを削除する
for (var i=0;i<getText3.length;i++){
getText3[i]=getText3[i].replace(/^[  ]*/gim, "").replace(/[  ]*$/gim,"");
}

//半角スペースがあるものだけがつぎはぎの対象なので、それの要素番号をtaishouYousoにpushする
var taishouYouso=new Array();
for (var i=0;i<getText3.length;i++){
if (getText3[i].indexOf(' ')!=-1){
taishouYouso.push(i);
}
}

//もし要素が1つ以下の場合、作れないのでごめんなさい
if (taishouYouso.length<=1){
alert('今の見出しでは作れませんでした。。。ごめんなさい');
} else {

//異なる2つの要素を取得する
ret="                            ";
for (var youso1=0;youso1<taishouYouso.length;youso1++){
do {
var youso2=Math.floor( Math.random() * taishouYouso.length );
} while (youso1==youso2)

//1つめの要素の前半部分と、2つめの要素の後半部分をくっつけて見出しを作る

var nukidashi1=getText3[taishouYouso[youso1]].substr(0,getText3[taishouYouso[youso1]].indexOf(' '));
var nukidashi2=getText3[taishouYouso[youso2]].substr(getText3[taishouYouso[youso2]].indexOf(' '));
ret=ret+nukidashi1+nukidashi2+'                     ';
}
setTimeout("scroll()",200);
}

       }
}
function getTsugihagi(){
httpRequest('http://www.yahoo.co.jp/');
}
function scroll(){
    ret=ret.substring(1,ret.length)+ret.substring(0,1);
    document.fm.txt.value=ret;
    setTimeout("scroll()",200);
}

//-->
</script>
</head>

<body onload="getTsugihagi()">
<form name="fm">
<input type="text" name="txt" size="30">
</form>
</body>
</html>

問い合わせ先をこのサーバー上のCGI(Yahoo!からトップのソースを取ってくるだけ)にして、動作するものを置いておきます。こちらからどぞ。

http://q.hatena.ne.jp/1204789749

この質問で「スクレイピング」ってはじめて知りました。
同様のことは他のツールを使ってやってましたけど、
JavaScriptだけでこんなことができるなんて、すごい(^^)

回答者さんのリンク先のプログラムを参考に、任意の
銘柄コードを入力すると、Yahoo!からデータを取ってくる
プログラムを作ってみました。

<?xml version="1.0">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>

<script language="javascript" type="text/javascript">
<!--
varhttpObj;
function httpRequest(target_url)
{
try
{
      if(window.XMLHttpRequest)
{
httpObj = new XMLHttpRequest();
}
else if(window.ActiveXObject)
{
httpObj = new ActiveXObject("Microsoft.XMLHTTP");
}
else
{
alert('エラーです');
return;
}
}
catch(e)
{
alert('エラーです');
return;
}

//データを取得する
httpObj.open("GET", target_url, true);
httpObj.onreadystatechange = DataRead;
httpObj.send("");

return;
}

function DataRead()
{
        if (httpObj.readyState == 4 && httpObj.status == 200)
{

//取得したレスポンスをgetTextに入れる
var getText=httpObj.responseText;

//kanrenにgetTextの「関連情報」から始まるテキストを入れる
var kanren=getText.substring(getText.indexOf('関連情報',0));

//trtagにkanrenの「<tr」から始まるテキストを入れる
var trtag=kanren.substring(kanren.indexOf('<tr',0));

//trtagの5つ目の「<td」の位置を調べて
var found=-1;
for (var i=1;i<=5;i++){
found=trtag.indexOf('<td',found+1);
}

//trtagの5つ目の「<td」以降の文字列で「<b」で始まるところの3文字あとの文字列をstartkabukaに入れる
var startkabuka=trtag.substring(trtag.indexOf('<b',found)+3);

//startkabukaの「</b」で始まる前までの文字をkabukaに入れる
var kabuka=startkabuka.substring(0,startkabuka.indexOf('</b',0));

//kabukaをフォームに入れる
document.form1.getkabuka.value=kabuka;
       }
}
//-->
</script>
</head>

<body>
<form name="form1">
銘柄コード<input type="text" name="code" style="ime-mode:disabled">の
<input type="button" value="株価GET" onclick="httpRequest('http://quote.yahoo.co.jp/q?s='+document.form1.code.value+'&d=v1&k=c3&h=on&z=m')"><br>
株価<input type="text" name="getkabuka">円
</form>
</body>
</html>

取得した文字列から必要なところを抜き出すのは、きっと
もっと良い方法があるんでしょうけど、とりあえずベタな
文字列関数で。

こちらにおいておきます→
http://www.simple-sys.com/archive/jsstudy_4.html

と思ってサーバーに置いて実行しようとしたら、エラーが出ちゃいました(^^;)
多分、Same-Originポリシー
によるものかな?

ローカルにHTMLファイルを落とせば使えました。
あとブラウザーによって使えなかったりするのかな?
IE6なら動きました。
こちらによれば、
new ActiveXObject(“Microsoft.XMLHTTP”) はIEでしか使えないっぽいですね。

http://q.hatena.ne.jp/1204273508

とにかく簡単に。

<html>
<head>
<script>
function keisan(){

if (document.fm.tate.value=='50'){
//縦が「50」の場合
if (document.fm.yoko.value=='10'){
kekka=500;
} else
if (document.fm.yoko.value=='20'){
kekka=1000;
} else
if (document.fm.yoko.value=='30'){
kekka=1500;
}
}

if (document.fm.tate.value=='100'){
//縦が「100」の場合
if (document.fm.yoko.value=='10'){
kekka=1000;
} else
if (document.fm.yoko.value=='20'){
kekka=2000;
} else
if (document.fm.yoko.value=='30'){
kekka=3000;
}
}

if (document.fm.tate.value=='200'){
//縦が「200」の場合
if (document.fm.yoko.value=='10'){
kekka=2000;
} else
if (document.fm.yoko.value=='20'){
kekka=4000;
} else
if (document.fm.yoko.value=='30'){
kekka=6000;
}
}

//値段に kekka を入れる
document.fm.nedan.value=kekka;

}
</script>
</head>
<body onLoad="keisan()">
<form name="fm">
縦
<select name="tate" onChange="keisan()">
<option value="50">50
<option value="100">100
<option value="200">200
</select>×
横
<select name="yoko" onChange="keisan()">
<option value="10">10
<option value="20">20
<option value="30">30
</select><br>
値段は<input type="text" name="nedan">円
</form>
</body>
</html>

上のソースを
http://www.simple-sys.com/archive/jsstudy_3.html
に置いておきました。

http://q.hatena.ne.jp/1202199353
Checkの部分が大分長くなっちゃったけど。
(Q1が1もしくは2もしくは3の場合)でかつ、
(Q2が選択されてない または Q3が選択されてない)場合アラート

って感じで。

<html>
<head>
<SCRIPT Language="JavaScript">
<!--
function Check()
{
if ((document.test.Q01[0].checked==true || document.test.Q01[1].checked==true || document.test.Q01[2].checked==true) && (document.test.Q02[0].checked==false  && document.test.Q02[1].checked==false  && document.test.Q02[2].checked==false  && document.test.Q02[3].checked==false || document.test.Q03[0].checked==false  && document.test.Q03[1].checked==false  && document.test.Q03[2].checked==false  && document.test.Q03[3].checked==false && document.test.Q03[4].checked==false)) { alert("問1で「1~3」と回答した人は、問2と問3にもお答えください"); return false; }
}
// -->
</SCRIPT>
</head>
<body>
<form name="test" onsubmit="return Check();">
問1<br>
<input type="radio" name="Q01" value="1">1<br>
<input type="radio" name="Q01" value="2">2<br>
<input type="radio" name="Q01" value="3">3<br>
<input type="radio" name="Q01" value="4">4<br>
<br><br>
問1で「1~3」を選んだ方は、問2、問3もお答えください<br><br>
問2<br>
<input type="radio" name="Q02" value="1">1<br>
<input type="radio" name="Q02" value="2">2<br>
<input type="radio" name="Q02" value="3">3<br>
<input type="radio" name="Q02" value="4">4<br>
<br>
問3<br>
<input type="radio" name="Q03" value="1">1<br>
<input type="radio" name="Q03" value="2">2<br>
<input type="radio" name="Q03" value="3">3<br>
<input type="radio" name="Q03" value="4">4<br>
<input type="radio" name="Q03" value="5">5<br>
<br>
<input type="submit" value="submit">
</form>
</body>
</html>

上記のソースを設置したのが、こちら→http://www.simple-sys.com/archive/jsstudy_2.html

http://q.hatena.ne.jp/1202193955
ラジオボタンがチェックされてるかどうかをチェックするのに、
radioの名前の後ろに [ ] で数字を指定してできるんですね。
勉強になりました。

<html>
<head>
<SCRIPT Language="JavaScript">
<!--
function Check()
{
if (document.test.Q01[3].checked==true && document.test.Q02[0].checked==false  && document.test.Q02[1].checked==false  && document.test.Q02[2].checked==false  && document.test.Q02[3].checked==false) { alert("問1で「持っていない」と回答した人は、問2にもお答えください"); return false; }
}
// -->
</SCRIPT>
</head>
<body>
<form name="test" onsubmit="return Check();">
問1<br>
<input type="radio" name="Q01" value="1">1<br>
<input type="radio" name="Q01" value="2">2<br>
<input type="radio" name="Q01" value="3">3<br>
<input type="radio" name="Q01" value="4">持ってない<br>
<br><br>
問2<br>
<input type="radio" name="Q02" value="1">1<br>
<input type="radio" name="Q02" value="2">2<br>
<input type="radio" name="Q02" value="3">3<br>
<input type="radio" name="Q02" value="4">4<br>
<br>
<input type="submit" value="submit">
</form>
</body>
</html>

上記のソースを設置したのが、こちら→http://www.simple-sys.com/archive/jsstudy_1.html

© 2011 simple blog いろいろ勉強中 Suffusion theme by Sayontan Sinha