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

前の記事

回答者さんのを見て、order by について調べると、
列の番号で指定したり、order by に計算式を設定したりも出来るらしい。

まず、列の番号で指定する方法。

mysql> select A,sum(C)/sum(B)*100 from hoge group by A order by 2 desc;
+--------+-------------------+
| A      | sum(C)/sum(B)*100 |
+--------+-------------------+
| 木村   |   154.54545454545 |
| 伊藤   |   109.67741935484 |
| 山田   |                40 |
+--------+-------------------+
3 rows in set (0.00 sec)

これで列に名前を付けなくても、並べ替えられた。

次に、order by に計算式を設定する場合。

mysql> select A,concat(round(sum(C)/sum(B)*100,1),"%") as RIEKIRITU from hoge group by A o
rder by sum(C)/sum(B) desc;
+--------+-----------+
| A      | RIEKIRITU |
+--------+-----------+
| 木村   | 154.5%    |
| 伊藤   | 109.7%    |
| 山田   | 40.0%     |
+--------+-----------+
3 rows in set (0.00 sec)

ただ、これ件数が多くなると2回計算される形になるから遅くなったりするのかな?

http://q.hatena.ne.jp/1199118290
とりあえず、下のような表で。

mysql> select * from hoge;
+--------+-----+-----+
| A      | B   | C   |
+--------+-----+-----+
| 木村   | 100 | 200 |
| 山田   | 100 |   0 |
| 伊藤   | 200 | 540 |
| 木村   | 120 | 140 |
| 山田   | 500 | 240 |
| 伊藤   | 420 | 140 |
+--------+-----+-----+
6 rows in set (0.00 sec)

まず、グループ化するには、group by

mysql> select A from hoge group by A;
+--------+
| A      |
+--------+
| 伊藤   |
| 山田   |
| 木村   |
+--------+
3 rows in set (0.00 sec)

グループ毎に合計するには、sum

mysql> select A,sum(B),sum(C) from hoge group by A;
+--------+--------+--------+
| A      | sum(B) | sum(C) |
+--------+--------+--------+
| 伊藤   |    620 |    680 |
| 山田   |    600 |    240 |
| 木村   |    220 |    340 |
+--------+--------+--------+
3 rows in set (0.00 sec)

利益率を求める

mysql> select A,sum(C)/sum(B)*100 from hoge group by A;
+--------+-------------------+
| A      | sum(C)/sum(B)*100 |
+--------+-------------------+
| 伊藤   |   109.67741935484 |
| 山田   |                40 |
| 木村   |   154.54545454545 |
+--------+-------------------+
3 rows in set (0.00 sec)

利益率の項目に項目名をつける。asを使う

mysql> select A,sum(C)/sum(B)*100 as RIEKIRITU from hoge group by A;
+--------+-----------------+
| A      | RIEKIRITU       |
+--------+-----------------+
| 伊藤   | 109.67741935484 |
| 山田   |              40 |
| 木村   | 154.54545454545 |
+--------+-----------------+
3 rows in set (0.00 sec)

利益率の項目が大きい順に並べ替える。order by

mysql> select A,sum(C)/sum(B)*100 as RIEKIRITU from hoge group by A order by RIEKIRITU desc;
+--------+-----------------+
| A      | RIEKIRITU       |
+--------+-----------------+
| 木村   | 154.54545454545 |
| 伊藤   | 109.67741935484 |
| 山田   |              40 |
+--------+-----------------+
3 rows in set (0.00 sec)

利益率を小数第一位で四捨五入する。round

mysql> select A,round(sum(C)/sum(B)*100,1) as RIEKIRITU from hoge group by A order by RIEKIRITU desc;
+--------+-----------+
| A      | RIEKIRITU |
+--------+-----------+
| 木村   |     154.5 |
| 伊藤   |     109.7 |
| 山田   |      40.0 |
+--------+-----------+
3 rows in set (0.00 sec)

とりあえずこれで質問者さんが必要としてるデータはでたと思う。

不明点が何個か。

order by RIEKIRITUで、利益率の項目でas で名前を付けたのを使ったけど、これは名前を付けないとorder by で指定できないのだろうか?

あと、質問者さんの求める形は、利益率に%をくっつけて表示してるんだけど、concatを使って、

mysql> select A,concat(round(sum(C)/sum(B)*100,1),"%") as RIEKIRITU from hoge group by A order by RIEKIRITU desc;
+--------+-----------+
| A      | RIEKIRITU |
+--------+-----------+
| 山田   | 40.0%     |
| 木村   | 154.5%    |
| 伊藤   | 109.7%    |
+--------+-----------+
3 rows in set (0.00 sec)

とすると、並び順がおかしくなる。。
多分に、RIEKIRITUを文字列とみなして、それの降順で表示しちゃってるからだと思うんだけど、これを数値の降順として表示することはできるのかな?

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