[[20120304204945]] 『関数をVBAに』(プレ) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『関数をVBAに』(プレ)

  関数を入れて休暇などをカウントしているのですが、VBAに入れるにはどうしたらいいのでしょうか? 教えて頂きたいのです。宜しくお願いします。

  現在、入っている関数

  ai7=COUNTIF(C7:AG7,"有休") aj7=COUNTIF(C7:AG7,"計画休") ak7=COUNTIF(C7:AG7,"午前休") al7=COUNTIF(C7:AG7,"午後休") am7=AI7+AK7*0.5+AJ7+AL7*0.5

  同じ関数が、7−18まで杯っています。

  宜しくお願いします。

 いろんな方法があるけど、もっともVBAらしくないコード(?)

 Sub Sample1()
    Dim z As Variant
    Dim i As Long

    For Each z In Array("有休", "計画休", "午前休", "午後休")
        Range("AI7:AI18").Offset(, i).Formula = "=COUNTIF(C7:AG7,""" & z & """)"
        i = i + 1
    Next

    Range("AM7:AM18").Formula = "=AI7+AK7*0.5+AJ7+AL7*0.5"

    With Range("AI7:AM18")
        .Value = .Value
    End With

 End Sub

 (ぶらっと

 で、VBAらしいといえばSample1よりVBAらしいかもしれないSample2。
でも、自分が書くならSample1かな?

 Sub Sample2()
    Dim col As Range
    Dim c As Range
    Dim v As Variant
    Dim i As Long
    Dim x As Long

    Application.ScreenUpdating = False

    v = Array("有休", "計画休", "午前休", "午後休")
    For Each col In Range("AI7:AL18").Columns
        For Each c In col.Cells
            i = c.Row
            c.Value = WorksheetFunction.CountIf(Range("C" & i).Resize(, Columns("AG").Column - Columns("C").Column + 1), v(x))
        Next
        x = x + 1
    Next

    For Each c In Range("AM7:AM18")
        With c.EntireRow
            c.Value = .Range("AI1").Value + .Range("AK1").Value * 0.5 + .Range("AJ1").Value + .Range("AL1").Value * 0.5
        End With
    Next

    Application.ScreenUpdating = True

 End Sub

 (ぶらっと)

わかりやすさ優先で(マナ)

 7とか18の部分に変数使えば、少しはVBAらしくなるかも。
 今のままじゃ修正も大変だし。

 Sub test()
    Range("AI7:AI18").Formula = "=COUNTIF(C7:AG7,""有休"")"
    Range("AJ7:AJ18").Formula = "=COUNTIF(C7:AG7,""計画休"")"
    Range("AK7:AK18").Formula = "=COUNTIF(C7:AG7,""午前休"")"
    Range("AL7:AL18").Formula = "=COUNTIF(C7:AG7,""午後休"")"
    Range("AM7:AM18").Formula = "=AI7+AK7*0.5+AJ7+AL7*0.5"
 End Sub

  ありがとうございます。

  Sheet1を入力用にしてSheet2から2012/4、Sheet3で2012/5・・・・Sheet13で2013/3にしています。
AMに集計した数字をだしてます。2012/4(Sheet2)のAM7で出した合計を、B7にこのように、=入力用!E5-'2011.4'!AM7して数字をだしています。

   最後の、2013/3(Sheet13)B7の数字を有休残数として、入力用(Sheet1)のF7に数字をだしています。
  どうでしょうか?難しいですか?

  (プレ)

 >どうでしょうか?難しいですか?

 VBAでできていることが関数ではできないこともあるけど、関数でできていることはVBAでも同じようにできる。

 ただし、スペックが明確じゃないとできない。
 最初の質問にあった計算をやらせたいのは入力用シート?それとも、2012.4〜2013.3シート?それとも、全て?
 B7にある式は、全てのシートにあるの?
 E5 というのも初登場で、そこに何が入っているのかわからないけど気にしなくてもいいの?

 >最後の、2013/3(Sheet13)B7の数字を有休残数として、入力用(Sheet1)のF7に数字をだしています。

 これも、よくわからないけど、単純に、入力用シートのF7に ='2013.3'!B7 といれておけばいいんじゃない?
 単に、これだけならVBAコードで処理する必要もない。
 VBAでやりやいなら、
 Sheets("入力用").Range("F7").Value = Sheets("2013.3").Range("B7").Value だけど。

 (ぶらっと)

Sub test()
    Range("AI7").Formula = "=COUNTIF(C7:AG7,""有休"")"
    Range("AJ7").Formula = "=COUNTIF(C7:AG7,""計画休"")"
    Range("AK7").Formula = "=COUNTIF(C7:AG7,""午前休"")"
    Range("AL7").Formula = "=COUNTIF(C7:AG7,""午後休"")"
    Range("AM7").Formula = "=AI7+AK7*0.5+AJ7+AL7*0.5"

Range("AI8").Formula = "=COUNTIF(C8:AG8,""有休"")"

    Range("AJ8").Formula = "=COUNTIF(C8:AG8,""計画休"")"
    Range("AK8").Formula = "=COUNTIF(C8:AG8,""午前休"")"
    Range("AL8").Formula = "=COUNTIF(C8:AG8,""午後休"")"
    Range("AM8").Formula = "=AI8+AK8*0.5+AJ8+AL8*0.5"

 End Sub

  こんな感じで7−18まで入っています。

Sub test()

    Range("AI7").Formula = "=COUNTIF(C7:AG7,""有休"")"
    Range("AJ7").Formula = "=COUNTIF(C7:AG7,""計画休"")"
    Range("AK7").Formula = "=COUNTIF(C7:AG7,""午前休"")"
    Range("AL7").Formula = "=COUNTIF(C7:AG7,""午後休"")"
    Range("AM7").Formula = "=AI7+AK7*0.5+AJ7+AL7*0.5"

 End Sub
これを VBAPRojectのSheet入れたのですが、数字が表示されませんでした。
なぜでしょうか?

(プレ)


 まず、お願いしたのは、何をしたいかを言葉で(関数とかVBAコードとかじゃなく)説明してもらえないかな? ということ。
 で、次に、アップされたコードだけど、私のコードはわかりにくかったとして、(マナ)さんのアドバイスが
 全く活かされてないのが残念。

 ところで、アップされたコードは、どこに記述したのかな?
 標準モジュールとかシートモジュールとか、いくつかあるんだけど。
 今回のテーマなら標準モジュール。ただし、複数シート対応は、もちろん必要だけど。
 なので、計算式を適用するシートは、どれとどれ? と質問している。

 >これを VBAPRojectのSheet入れたのですが、数字が表示されませんでした。
 >なぜでしょうか?

 コードは、書いただけでは動かない。このプロシジャを実行しなきゃいけないよ。
 ただ、アップされたものでは、期待する結果は得られないと思う。なんとなく。
 じゃぁ、どんなコードがいいんだ? ということになるけど、それを提案するために、いくつか
 質問しているので、それに回答もらえたらうれしいな。

 (ぶらっと)

  言葉足らずで申し訳ございませんでした。

  シートに関数を入れておきたくないのです。

  有休の管理Sheetを作成しています。

  A7〜A18に名前、B7〜B18有休残数 C7列〜AG7列まで有休などを選択できるように入力規則を入れています。
  C5〜AG5までは曜日が入っています。C6〜AG6までは日付が入っています。

  その後ろに、書かして頂いた関数を入力してカウントできるようにしたのです。ai7=COUNTIF(C7:AG7,"有休") aj7=COUNTIF(C7:AG7,"計画休") ak7=COUNTIF(C7:AG7,"午前休") al7=COUNTIF(C7:AG7,"午後休") am7=AI7+AK7*0.5+AJ7+AL7*0.5

  上記が、Sheet2から2012/4、Sheet3で2012/5・・・・Sheet13で2013/3に入っています。
  入力用は、最初の有休がいくつあるか入力しています。ここから引くように出来るのではないかと作成したのです。

  今後、VBAを勉強していくうえで、今はメンテしやすいほうがいいのかと思い、(マナ)さんのを参考にさせていただきました。決して(ぶらっと)さんのが良くないとかではありません。

  コードを入力したのは、標準モジュールです。

  ご面倒をお掛けして申し訳ございません。

  (プレ)


 >今はメンテしやすいほうがいいのかと思い、(マナ)さんのを参考にさせていただきました。

 私もそう思います。指摘したのは、(プレ)さんは、「こんな感じで7−18まで入っています。」
 一方、(マナ)さんのコードをよく見てほしいんだけど、
 Range("AI7:AI18").Formula = "=COUNTIF(C7:AG7,""有休"")"
 これは、AI7からAI18に、一挙に12個の式をいれることができる構文。

 シートに式を残したくないんだよね。
 そういう場合は、私のコードでやっているように、式をセットした後、
 当該セル領域.Value = 当該セル領域.Value と記述すれば、式が値に変更される。

 次に、ブックの中のすべてのシートに対応させる場合、たとえば以下のように。
 (マナさんの構文を借用)

 Sub Sample()
    Dim sh As Worksheet

    For Each sh In Worksheets   'ブックの中からシートを1枚ずつとりだす
        '必要なら、sh.Name にシート名が入っているので、それを判定して、このシートは処理しないとか、このシートを処理するといったことが可能。(If 文を使う)
        sh.Range("AI7:AI18").Formula = "=COUNTIF(C7:AG7,""有休"")"
        sh.Range("AJ7:AJ18").Formula = "=COUNTIF(C7:AG7,""計画休"")"
        sh.Range("AK7:AK18").Formula = "=COUNTIF(C7:AG7,""午前休"")"
        sh.Range("AL7:AL18").Formula = "=COUNTIF(C7:AG7,""午後休"")"
        sh.Range("AM7:AM18").Formula = "=AI7+AK7*0.5+AJ7+AL7*0.5"

        sh.Range("AI7:AM18").Value = sh.Range("AM7:AM18").Value '式の結果を値に変換

    Next

 End Sub

 (ぶらっと)

 こんにちは。横から失礼します。

 シートに式を残したくない理由は何ですか?
 ブックが重いからですか?
 数式を他人に見られたくないとか?
 それともなにか他の理由でしょうか。

 ご質問を拝見するに、目的は有給の残日数をリアルタイムで知ることと思われますが
 だとしたら、だれかが休暇を取るたびに計算し直す必要があります。
 そのたびに1年分のシートに(VBAで)数式を入れ 値に変換する……間違いではありませんが
 無駄な作業がおおいと思いませんか。

 ではどうすればいいか、と考えると
 シートに式を残したくない理由によって最適解は変わってきます。
 (ことによると、数式を残すのがいちばん合理的ということもあり得ます。)

 −佳−

コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.