- ベストアンサー
VBAで対象となる月の数を出す方法を教えて下さい。
2009.12.21~2010.1.20と入力された場合、結果2 2009.4.1~2009.4.30と入力された場合、結果1 のように対象となる(足かけ月数)月数を出す方法を知りたいのです。 下記コードのように変数A、BにVariant型で入力してもらい(Variant型でないと困る理由があるので) それをDate型に変換したり、またVariant型に戻したり(必要があり)しながら、myOpenFileNamesにMypath & MyFileを順次追加すべく進めたいのですが、Mcntを出せずにいます。 Month(B)-Month(A)では12月と1月で不具合が出るし‥ 期間が3か月以上の場合もあります。 なにかシンプルなのがありそうなので半日調べたのですが解りませんでした。皆様、お助け下さいませ。 ここまで省略 '●請求対象期間の入力 A = Application.InputBox("請求対象期間(開始日)を入力してください。", "開始日", "2009.12.21", Type:=2) If A = False Then MsgBox " Cancel ボタンが押されました" Exit Sub End If On Error GoTo OWARI3 A = CDate(Replace(A, ".", "/")) On Error GoTo 0 B = Application.InputBox("請求対象期間(締め日)を入力してください。", "締め日", Replace(Format(DateAdd("d", -1, DateAdd("m", 1, A)), "yyyy/mm/dd"), "/", "."), Type:=2) If B = False Then GoTo OWARI End If On Error GoTo OWARI3 B = CDate(Replace(B, ".", "/")) On Error GoTo 0 If A > B Then MsgBox A & "~" & B & " は請求日と締め日が逆転してます。", vbOKOnly + vbCritical, "最初からやり直して下さい。" GoTo OWARI End If D = B - A msgRec = MsgBox(A & "~" & B & "分でよろしいですか?", vbOKCancel + vbQuestion, "対象は" & D + 1 & "日分です") If msgRec = vbCancel Then MsgBox " Cancel ボタンが押されました" Exit Sub End If Mcnt = ●○○○● ←ここを出す方法を知りたいのです。******************************** ReDim BN(1 To Mcnt) For i = 1 To Mcnt BN(i) = Replace(Format(DateAdd("m", i - 1, A), "yyyy/mm"), "/", ".") Mypath = ThisWorkbook.Path & "\明細書一覧" & BN(i) & "月" MyFile = "\明細書一覧" & BN(i) & "月.xls" myOpenFileNames.Add (Mypath & MyFile) Next i 以下略
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
>BNを配列にしない方法とは‥知りたいです BN(Mcnt) を BN にするだけですが。 ただ、実際の流れが不明ですので詳しくは提示することはできません。 また、 >転記して集計するNEWBOOKを保存する際の部分(Save As ○○○)も >締め月単月のBNで済みそうですのでおっしゃるとおり とありますがこれなども意味が分かりません。 例えば、処理対象が2009/06/21~2009/10/20 とした場合 集計NEWBOOKを保存する時の、締め月単月、とはどの月をいうのでしょうか。 どういう集計方法をとられている不明ではありますが、 それを推測して、コードを書くとしたら ●BNは配列にしないし、 ●myOpenFileNamesも使用しないでしょう。 '------------------------------------- Set NewBook = Workbooks.Add Do Mcnt = Mcnt + 1 BN = Replace(Format(DateAdd("m", Mcnt - 1, A), "yyyy/mm"), "/", ".") Mypath = ThisWorkbook.Path & "\明細書一覧" & BN & "月" MyFile = MyPath & "\明細書一覧" & BN & "月.xls" Set DataBook = Workbooks.Open(myFile) =====ここで集計処理する=== Loop Until BN >= Replace(Format(B, "yyyy/mm"), "/", ".") NewBook.SaveAs ■■■ '-------------------------------------- 飽くまでも推測の域は出ませんので。 それから質問者に一言。 質問者は質問しながら自分でもちゃんと考えコードを書いているようですし、 回答があればそれを汲み取り自分自身で修正加筆をしておられるようなので、 回答する方としても回答のし甲斐があります。 が、残念なことに 質問者の提示する情報は、ケアレスミスが多いように思えます。 その結果、回答者を戸惑わせると同時にあらぬ方向へと向かわせることになります。 で、提示する情報は投稿する前に何回も確認して正確さを期すようにすることをお奨めします。 それは何よりも質問者のため、早期解決のため、になると考えます。
その他の回答 (3)
- end-u
- ベストアンサー率79% (496/625)
>しかし、Format$の 「$」の意味が解りません。 Format関数やReplace関数など、文字列を扱う関数には、$が付いた関数があります。 $付き関数は文字列型の値を返し、付いていないものはバリアント型の値を返します。 例えば、文字列型変数に受ける場合は、この$付き関数を使った方が速度的にも有利とされています。 ...が、今回のケースはあまり気にする事はないでしょう。 普段から、あまり意識して使い分けてるわけではないので適切ではなかったかもしれません。 参考にされるなら以下のサイトなど。 http://www.tsware.jp/labo/labo_32.htm http://hanatyan.sakura.ne.jp/vbhlp/sonota_no1.htm
お礼
end-uさん。いつもお世話になります。「$」を最初に見たとき、byteタイプ?だったかな。と思い調べましたが違い、Like演算子にはなかったよなぁとか思い調べてみたのですがこれもやはり違い。結局頼ってしまいました。文字列型だったのですね。バリアント型と文字列型でメモリ容量の問題で文字列型型が有利。しかし、変換効率は元の型と置き換わってしまうかににもよるので、元が文字列型で、変換先も文字列型に変換して問題がないのなら、$をつけて行った方が有利ということなのですね。勉強させてもらいました。しかし、自分では。探せずにお手数かけました。ありがとうございました。いま、請求関係で焦りながら手探り状態です。しばらくの間OKWAVEに頻繁に出没してしまいそうですので、また助けて下さい。本当に有難うございました。YOKOKAMA46
- myRange
- ベストアンサー率71% (339/472)
折角、開始日と終了日があるわけですから、 For~Next に拘らずに、Do~Loopを使う手もありかと。 '------------------------------------- Do Mcnt = Mcnt + 1 ReDim BN(1 To Mcnt) BN(Mcnt) = Replace(Format(DateAdd("m", Mcnt - 1, A), "yyyy/mm"), "/", ".") Mypath = ThisWorkbook.Path & "\明細書一覧" & BN(Mcnt) & "月" MyFile = "\明細書一覧" & BN(Mcnt) & "月.xls" myOpenFileNames.Add (Mypath & MyFile) Loop Until BN(Mcnt) >= Replace(Format(B, "yyyy/mm"), "/", ".") '--------------------------------------- それから余計なことかも知れませんが、 後で利用しないのであれば(この部分だけで使うのであれば) 変数BNをわざわざ配列変数にする必要はないと思いますが。
補足
myRangeさん。昨日の深夜、今日の早朝、そして今回の昼、いつもお世話になります。なんかお知り合いが増えてきてうれしい限りです。(とはいっても皆様に一方的に迷惑かけてるだけですが) ご提示のコードで置き換え検証しました。OKです。だいぶすっきりするものですね。月の数字を追加したりしないで、そのまま使っているのですね。私のは、一旦置き換えたりしてたものですので、ごちゃついていました。 BNは元々月の変数として使ってました。(しかし過去は単月の時) 今回から複数選択となって変わりにmyOpenFileNamesを使ったので、ファイルの開く、閉じるにもmyOpenFileNames(i)で済んでしまいます。まだ手を付けてませんが、転記して集計するNEWBOOKを保存する際の部分(Save As ○○○)も締め月単月のBNで済みそうですのでおっしゃるとおりBNは配列化の必要はなさそうです。開いたファイルは、変更点がないので(読み取り専用で開いてもいい)順次myOpenFileNames(i)で閉じるだけです。 でもBNを配列にしない方法とは‥知りたいです。教えてもらえませんか?お願いします。
- end-u
- ベストアンサー率79% (496/625)
こんにちは。 >2009.12.21~2010.1.20と入力された場合、結果2 >2009.4.1~2009.4.30と入力された場合、結果1 >のように対象となる(足かけ月数)月数を出す方法を... あまり深く考えてませんが Dim v As Date Dim w As Date Dim x v = #12/21/2009# w = #1/20/2010# v = CDate(Format$(v, "yyyy/mm/1")) w = CDate(Format$(w, "yyyy/mm/1")) x = DateDiff("m", v, w) + 1 MsgBox x こんな感じ?
補足
end-uさん。またまたありがとうございます。 DateDiff関数は知りませんでした。 またFormat関数を使い、全て1日に置き換えDateDiff関数により導き出すというのは大いに参考となりました。 実は、投稿後、今一度単純に考え直したら下記の方法 If Month(B) - Month(A) < 0 Then MM = Month(B) + 12 を思いつき進めることが出来ていました。 これにより MM = Month(B) If Month(B) - Month(A) < 0 Then MM = Month(B) + 12 End If Mcnt = MM - Month(A) + 1 ReDim BN(1 To Mcnt) For i = 1 To Mcnt BN(i) = Replace(Format(DateAdd("m", i - 1, A), "yyyy/mm"), "/", ".") Mypath = ThisWorkbook.Path & "\明細書一覧" & BN(i) & "月" MyFile = "\明細書一覧" & BN(i) & "月.xls" myOpenFileNames.Add (Mypath & MyFile) Next i としております。 しかし、Format$の 「$」の意味が解りません。この機会にもう少しだけお付き合いを頂いて教えてはもらえないでしょうか? お願い致します。
お礼
myRangeさん。すみませんでした。 締め月単月のBNというのは、単に締め月のことでした。 2009/06/21~2009/10/20の場合、変数Bの2009/10/20を2009.10のバリアント型に整形してそれを変数BNにして SaveAs ●●●の時使う予定だったので、BNを配列にしないほうが良いかなぁと思った一人言に近い書き込みでした。重ねてすみませんでした。 ご提示頂いたのコードの方がすっきりしそうです。 myOpenFileNamesは順次開き、最後に順次閉じる時用だったのですが、コレクションに順次追加しなくても、Do~Loopの中で順次Workbooks.Open(myFile)で開き、Set DataBookで登録し、転記済み時点でDataBook.Close Falseで順次閉じれるので、myOpenFileNamesのコレクションも不要。またBNもMcntの値で操作出来るので BN(Mcnt)は今思うと恥ずかしいです。しかし、本人は気付かないでいました。あせって作ってる結果の気がします。 myRangeさんから頂いたのは、単にコードということより、すっきりしたロジックでした。くどい文章を書き込みましたが、本人の確認の意味とシンプルなロジックを教わったことに関して、大変有り難く受け取らせて頂いたことを伝えたかったからです。有難うございました。これに懲りずにまたお付き合い下さい。YOKOKAMA46