DATEDIF関数をなんとかユーザー定義関数に組み込んでみようと思い、VBAをはじめてみました。
標準モジュールでFunctionを使って書くところまでは何とかたどり着いたのですが、
DATEDIF自体の計算についてどうやって場合わけしていったらいいのか悩み始めてしまいました。
DATEDIF(開始日,終了日,単位)とした場合、
単位="D"もしくは"d"ならば、(開始日-終了日)/ 1 と、適当ではありながらも考えてみました。
そこからが問題で、月数、年数を数えるときに日付の違う月数をどうやって数えるのか、とか、うるう年の計算をどうしたらよいのかとか。。。
単にシリアル値を取り出して割るだけじゃだめですよね?

検索でユーザー定義関数についても、DATEDIF関数自体に関してもしてみたのですが、どうしても理解に苦しんでいます。

直接の答えでなくてもいいので、関連サイトや関連書籍でいいものがあったら教えてください。
本当は本は人に言われて買うものではないと思っているのですが、自分の踏み込んだことのない分野なのでちょっと手のつけようがなくて困っています。。。
どうかお願いします。

このQ&Aに関連する最新のQ&A

A 回答 (2件)

すみません、回答ではありません。


いくつか確認したいことがあります。
VBAを・・とありますが、これはACCESSのVBAですか?EXCELの?WORDの?
確かにEXCELにはDATEDIF関数があります。
知りたいのはこの関数のアルゴリズムですか?
そうではなくてACCESSでEXCELのDATEDIF関数と同等のことがしたいということですか?
というのであればDateDiff関数があります。
年、月、日だけでなく週、時間、分、秒の差もとれます。

見当違いのことを言ってるのであれば申し訳ないです。

この回答への補足

ごめんなさい。本当に初心者なもので、質問の仕方も心得ていませんでした。
EXCELのVBAで、ワークシート関数にユーザー定義関数としてDATEDIFを組み込んでみたいのです。
DATEDIF関数も普通に入力して使ってはいるので、使い方自体は理解してるのですが、自分で作るときにいったいどこから手をつければいいのか、場合わけに悩んでいます。
単位に入力された値によっては返す値を買えるということはIFで分けるわけですよね?
それをどこからやっていくかで今とまっているところのです。
これで質問の内容がおわかりいただけたでしょうか?

よかったら、またアドバイス下さい。

補足日時:2001/04/18 16:10
    • good
    • 0

補足ありがとうございます。


標準で用意されている関数をわざわざ自作して使用する
ということにまだちょっと納得いかないんですけど、
この先オリジナルの関数を作成したいための勉強で作成されている
と解釈しました。

とりあえず例です。

Function datedif2(dt1 As Date, dt2 As Date, tp As String)
'2つの日付の差を求める関数 datedif2(日付1,日付2,記号)
'記号の説明
' "d":日差を求めます
' "m":月差を求めます
' "y":年差を求めます

'変数の宣言
Dim tp_cv As String
Dim dt1_cv As Long
Dim dt2_cv As Long
'引数の変換
tp_cv = StrConv(tp, vbLowerCase) '記号を小文字に変換
dt1_cv = CLng(dt1) '日付1のシリアル値
dt2_cv = CLng(dt2) '日付2のシリアル値
'計算処理
Select Case tp_cv '記号によって処理分岐
Case "d" '日差の場合
datedif2 = tm2_cv - tm1_cv 'シリアル値の差をだして日数を計算
Case "m" '月差の場合
... '省略
Case "y" '年差の場合
... '省略
Case Else 'エラー処理
datedif2 = Null
End Select
End Function

*各関数などの詳細はHELPを参照してください。
 HELPは読みにくいかもしれませんが、関連を追ってじっくり読みこみ、
 使用例を参考にして理解していくと非常に強力な武器になります。

条件が多岐にわたる場合はIF文よりもSELECT CASEを使う方がすっきりします。
月差と年差に関しては単純に2000/12/31と2001/01/01の差が
1年または1月と計算してもよいのならばFormat関数などで
年と月を分離してそれぞれ計算すればいいかと思います。
上記の例で年差を出すなら2001-2000、
月差を出すなら(2001-2000)*12+1-12
という具合に計算できます。

トライアンドエラーの繰り返しになると思いますけど、
失敗に負けないで頑張ってくださいね!
    • good
    • 0
この回答へのお礼

ありがとうございます!
確かに、もともと存在する関数なので、わざわざ作る必要もないのですけれど、
勉強しようと思ったきっかけがDATEDIF関数だったので、そこから始めてみることにしました。
いきなり難しいのに手をつけすぎかもしれませんが、やっていく中で
抑えなきゃいけない基本的なことももちろん勉強していくつもりなので、
また、何かあったらよろしくお願いします。

まずはいろいろやってみないとですね!!

お礼日時:2001/04/19 21:41

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aと関連する良く見られている質問

QSchemeのプログラミング うるう年関連

Schemeのプログラミング うるう年関連
Schemeで、
「(1)閏年かどうかを判定する関数leap?(number -> boolean)を定義した後、(2)○年○月の日数は何日かを求める関数num-of-days(number number -> number)を定義せよ」
という内容の課題を出されたのですが、(例えば 2009年の7月→31日 2012年の2月→29日)
どうもエラーが出て実行できません。
自分は以下のように組みました。
;;(1)の関数
(define (leap? year)
(cond
[(= (remainder year 400) 0) #t]
[(and (= (remainder year 4) 0)(> (remainder year 100) 0)) #t]
[else #f]
)
)
;;(2)の関数
(define (num-of-days year month)
(cond
[(and (= month 2)(= (leap? year) #t)) 29]
[(and (= month 2)(= (leap? year) #f)) 28]
[(or (= month 1)(= month 3)(= month 5)
(= month 7)(= month 8)(= month 10)
(= month 12)) 31]
[else 30]
)
)

これを例えば
(num-of-days 2008 4) や (num-of-days 1995 12)
などとして実行すると、それぞれ30,31という正しい値を返してくれるのですが、
(num-of-days 2008 2) や (num-of-days 1995 2)
など、閏年・非閏年に関係無く、2月が絡むと
=: expects type <number> as 1st argument, given: false; other arguments were: true
というエラーを吐いてしまいます。
何度も見直しましたが、どこが間違っているのか見付けきれません…。どなたか間違いを指摘して頂けると幸いです。

Schemeのプログラミング うるう年関連
Schemeで、
「(1)閏年かどうかを判定する関数leap?(number -> boolean)を定義した後、(2)○年○月の日数は何日かを求める関数num-of-days(number number -> number)を定義せよ」
という内容の課題を出されたのですが、(例えば 2009年の7月→31日 2012年の2月→29日)
どうもエラーが出て実行できません。
自分は以下のように組みました。
;;(1)の関数
(define (leap? year)
(cond
[(= (remainder year 400) 0) #t]
[(and (= (remainder year 4) 0)(> (remainde...続きを読む

Aベストアンサー

ああ、ちなみに。

manaka3161 さんの作ったコードのロジックは「無駄がある」とは思いますが、基本的に「間違ってはいない」、とは思いますよ。
どこが悪いのか?と言うと、単純に、ここです。

(define (num-of-days year month)
(cond
[(and (= month 2)(= (leap? year) #t)) 29] ;; ここが間違ってる
[(and (= month 2)(= (leap? year) #f)) 28] ;; ここが間違ってる
[(or (= month 1)(= month 3)(= month 5)
(= month 7)(= month 8)(= month 10)
(= month 12)) 31]
[else 30]
)
)

「ロジックが合ってる」のに「エラーを返す」場合があるんです。何故なら、データ型に整合性がない、からです。
比較演算子=は「数値専用」で等価判定を下す。引数が数値である、ってのが前提なんですけど、引数にシンボル#tか#fが来てる、ってのがエラーの原因です。

> (= 1 2)
#f
> (= 1 1)
#t
> (= 'a 'b)
=: expects type <number> as 1st argument, given: a; other arguments were: b

=== context ===
/usr/lib/plt/collects/scheme/private/misc.ss:74:7

>

同じエラーですよね。見て分かる通り、=は数値しか引数に取れないんです。

つまり、シンボル同士を比較したい場合はeq?使った方が良いでしょう。すなわち、

(define (num-of-days year month)
(cond
[(and (= month 2)(eq? (leap? year) #t)) 29] ;二番目の判定式を eq? で行う
[(and (= month 2)(eq? (leap? year) #f)) 28] ;二番目の判定式を eq? で行う
[(or (= month 1)(= month 3)(= month 5)
(= month 7)(= month 8)(= month 10)
(= month 12)) 31]
[else 30]
)
)

これで動く筈です。

> (num-of-days 2009 7)
31
> (num-of-days 2012 2)
29
>

慣れない内は、数値/シンボルの比較を両方「考えずに行いたい」のなら、eqv?を使った方が良いかもしれません。eqv?はリストじゃなければ数値/シンボルの両方とも行えます。eq?はシンボル専用、ですね。=は数値専用。
大まかに言うと、繰り返しになりますが、次のようになってます。

eq? => シンボル比較の時に使う。高速。
eqv? => 数値、シンボル両方O.K。ある意味デフォルト。
equal? => リスト同士まで比較出来る。ただし、eq?に比べると遅い。
= => 数値専用。

ああ、ちなみに。

manaka3161 さんの作ったコードのロジックは「無駄がある」とは思いますが、基本的に「間違ってはいない」、とは思いますよ。
どこが悪いのか?と言うと、単純に、ここです。

(define (num-of-days year month)
(cond
[(and (= month 2)(= (leap? year) #t)) 29] ;; ここが間違ってる
[(and (= month 2)(= (leap? year) #f)) 28] ;; ここが間違ってる
[(or (= month 1)(= month 3)(= month 5)
(= month 7)(= month 8)(= month 10)
(= month 12)) 31]
[else 30]
)
)

「ロジックが合ってる」の...続きを読む

Q関数の宣言と定義

ずばり聞きます!
宣言と定義って何が違うんですか!?

Aベストアンサー

言語によって用語の厳密な定義は異なります。
C++であれば下記を参照してください。

参考URL:http://wiki.livedoor.jp/takagi_nobuhisa/d/%C4%EA%B5%C1

Qシェルスクリプトの中のawkユーザー定義関数

cシェルの中でawkのユーザー定義関数を使う方法について教えてください。

以下の内容の入力ファイルがあったとして、
3 3 306
2 2 258
1 1 105
3列目を数値の大小に応じて、別の数値に置き換えて以下のファイル
3 3 10
2 2 9
1 1 8
を出力したいのです。
cシェルスクリプト中でawkのユーザー定義関数を使って作成したいのですが、シェルスクリプト中に関数をどこでどう定義してよいか分かりません。

cシェルスクリプトの中身は
#/bin/csh -f
gawk'{print $1,$2,symbolsize($3)}' input_data > output_data
で、以下の関数を定義したいのです。
function symbolsize(ccc){
if (ccc >= 300)
return 10 #300以上なら10を返す
if (ccc >= 200 && ccc < 300)
return 9 #200以上300未満なら9を返す
else
return 8 #それ以外なら8を返す
}

プログラミング初心者なので、なにとぞよろしくお願いします。

cシェルの中でawkのユーザー定義関数を使う方法について教えてください。

以下の内容の入力ファイルがあったとして、
3 3 306
2 2 258
1 1 105
3列目を数値の大小に応じて、別の数値に置き換えて以下のファイル
3 3 10
2 2 9
1 1 8
を出力したいのです。
cシェルスクリプト中でawkのユーザー定義関数を使って作成したいのですが、シェルスクリプト中に関数をどこでどう定義してよいか分かりません。

cシェルスクリプトの中身は
#/bin/csh -f
gawk'{print $1,$2,symbolsize($3)}' input_data > ou...続きを読む

Aベストアンサー

#3の内容に関して補足です。
-f オプションの複数指定は、gawkでは問題なくできますがどのawkでもできるとは限りません。
(試せないけど Solarisのawkは怪しいと思う)

で、gawkを使ってよいという前提であれば

gawk -f functions.awk --source='print $1,$2,symbolsize($3)'

という記述ができます。

QMATLABでssを実行すると、未定義な関数としてエラーになる。

MATLABでssを実行すると、ssが未定義な関数として認識されて
エラーになっているようです。

どなたか、対処方法をご存じでしょうか?
宜しくお願いいたします。

■実行環境
OS:WindowsXP SP2
MATLAB:2007a

■実行したM-ファイル
%test
l=0.2404;
M=0.390;
J=0.0712;
c=0.695;
g=9.81;

A=[0 1; -M*l*g/J -c/J];
B=[0; 1/J];
C=[1 0];
D=0;

sys = ss(A,B,C,D);

■実行結果
??? 未定義の関数、またはメソッド 'ss' (タイプ'double' の入力引数)。

エラー ==> test at 13
sys = ss(A,B,C,D);

■調べた事項
>> ver
-------------------------------------------------------------------------------------
MATLAB Version 7.4.0.287 (R2007a)
MATLAB License Number: XXXXXX
Operating System: Microsoft Windows XP Version 5.1 (Build 2600: Service Pack 2) Java VM Version: Java 1.5.0_07 with Sun Microsystems Inc. Java HotSpot(TM) Client VM mixed mode
-------------------------------------------------------------------------------------
MATLAB Version 7.4 (R2007a)
Simulink Version 6.6.1 (R2007a+)
Communications Blockset Version 3.5 (R2007a)
Communications Toolbox Version 3.5 (R2007a)
Filter Design HDL Coder Version 2.0 (R2007a)
Filter Design Toolbox Version 4.1 (R2007a)
Fixed-Point Toolbox Version 2.0 (R2007a)
Link for ModelSim Version 2.2 (R2007a)
Signal Processing Blockset Version 6.5 (R2007a)
Signal Processing Toolbox Version 6.7 (R2007a)
Simulink Fixed Point Version 5.4.1 (R2007a+)

Trademarks
------------------
MATLAB, Simulink, Stateflow, Handle Graphics, Real-Time Workshop, and xPC TargetBox are registered trademarks and SimBiology, SimEvents, and SimHydraulics are trademarks of The MathWorks, Inc. Other product or brand names are trademarks or registered trademarks of their respective holders.
>> which ss -all
C:\Program Files\MATLAB\R2007a\toolbox\signal\signal\@dfilt\ss.m % dfilt method

>> matlabroot

ans =

C:\Program Files\MATLAB\R2007a

>> path

MATLABPATH

C:\Program Files\MATLAB\R2007a\toolbox\matlab\general
C:\Program Files\MATLAB\R2007a\toolbox\matlab\ops
(中略)
C:\Program Files\MATLAB\R2007a\toolbox\signal\signal
(後略)
>>

MATLABでssを実行すると、ssが未定義な関数として認識されて
エラーになっているようです。

どなたか、対処方法をご存じでしょうか?
宜しくお願いいたします。

■実行環境
OS:WindowsXP SP2
MATLAB:2007a

■実行したM-ファイル
%test
l=0.2404;
M=0.390;
J=0.0712;
c=0.695;
g=9.81;

A=[0 1; -M*l*g/J -c/J];
B=[0; 1/J];
C=[1 0];
D=0;

sys = ss(A,B,C,D);

■実行結果
??? 未定義の関数、またはメソッド 'ss' (タイプ'double' の入力引数)。

エラー ==> test at 13
sys = ss...続きを読む

Aベストアンサー

単純に該当するss関数がないだけでしょう。

> sys = ss(A,B,C,D);
この使い方をするss関数は、別のToolboxの関数じゃないですか?

■ Control System Toolbox
ftp://ftp.eng.auburn.edu/pub/bhidetm/t/jhelp/toolbox/control/ss.html

QRubyの関数定義

Rubyで関数を定義し、呼び出すとエラーになります。
sub1() #sub1の呼び出し
・・・
def sub1()
・・・
end
のようにすると、エラーになります。
def sub1()
・・・
end
sub1() #sub1の呼び出し
のようにするとエラーになりません。
関数の定義を呼び出し箇所のソースの後ろで定義してもエラーにならない方法はないのでしょうか。
ご存じのかた、いらしたら教えて下さい。

Aベストアンサー

こんばんは。
私の手に余りそうですが、できる範囲でお答えを。
細かいところで間違いはあるかもしれません。

>関数の定義を呼び出し箇所のソースの後ろで定義してもエラーにならない
>方法はないのでしょうか。
えっと、ありません。……じゃ愛想なさすぎですか。
現状の仕様では具体的にどのような不都合がございますでしょうか。
普通はクラスやメソッド定義は別ライブラリファイルにまとめておいて
最初にライブラリを require するのが(特に)Ruby の流儀だと思います。

Perl だったら以下のように手続きの定義を後に書いても動きますね。

sub1("camel");

sub sub1 {
my($arg) = @_;
print "Hello, ", $arg, ".\n";
}

しかし、まだ呼び出しの時点で定義されていないメソッドを使うのは
可読性を損なうことにはならないでしょうか。
メソッド定義を後回しにしたコードが動かないのは、
このことを危惧したまつもとさんの思想のような気がします。

「見かけ上」定義を後回しにする汚い裏技はこのようになるでしょうか。
あなたが本当にやりたいことからは外れるかもしれませんが。

#!/usr/local/bin/ruby

#class Object
def method_missing(name, *args)
defun = DATA.read
eval defun
send(name, args)
end
#end

greet "world!"

__END__
def greet(someone)
puts "Hello, " << someone
end

Ruby スクリプトの「__END__」以降の行は
DATA という File オブジェクトとしてアクセスできます。
未定義のメソッドが起動されたタイミングでフックされる
Object#method_missing を再定義しておいて、
DATA にあるメソッド定義を評価するというシナリオ。

以下余談です。
Ruby のすべてのオブジェクトが属する Object クラスにはもれなく、
Kernel モジュールによって method_missing メソッドが用意されています。
このメソッドは、レシーバオブジェクト(self)に対して呼び出された
メソッドが定義されていないときに起動されます。

「NoMethodError: undefined method ...」などという
デフォルトのエラーメッセージはRuby インタプリタ自身というより
この method_missing が出しているのです。
それが証拠に、このメソッドを再定義することによって
エラーメッセージを変えたり、または空の定義をすることで
エラーがなかったことにさせることもできます。

Ruby で関数のように見えるのは、
実はレシーバがトップレベルの Object であるプライベートメソッド
(「レシーバ.メソッド」の形で書けないメソッド)で、
このような関数風メソッドは Kernel モジュールで定義されています。
すなわち「func(args)」は「Kernel.func(args)」に等しく、
しかしてその実体は「Kernel.send(:func, args)」であります。

「Kernel.」を略せるのは、Object クラスが「include Kernel」しているからで、
「include Math」すると今まで「Math.cos Math::PI」としか書けなかったのが
「cos PI」と書けるのと同じです。

もっと突っ込んだ質疑をなさりたいなら、Ruby 一般についての
メーリングリスト ruby-list に登録されるといいでしょう。
まつもとさんからの回答メールも直に読めます。

購読されるには、ruby-list-ctl@ruby-lang.org まで
「subscribe (あなたのお名前)」という内容のメールを投げてください。
件名は空でも構いません。その後折り返し確認メールが来ます。
今は Windows で Internet Explorer とのインターフェイスに
ついての話題に花が咲いてますね。

参考URL:http://www.ruby-lang.org/ja/20020104.html,http://www15.web24.jp/~c01763n1/rubytips/

こんばんは。
私の手に余りそうですが、できる範囲でお答えを。
細かいところで間違いはあるかもしれません。

>関数の定義を呼び出し箇所のソースの後ろで定義してもエラーにならない
>方法はないのでしょうか。
えっと、ありません。……じゃ愛想なさすぎですか。
現状の仕様では具体的にどのような不都合がございますでしょうか。
普通はクラスやメソッド定義は別ライブラリファイルにまとめておいて
最初にライブラリを require するのが(特に)Ruby の流儀だと思います。

Perl だったら以下のように...続きを読む


人気Q&Aランキング

おすすめ情報