Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


241 / 3841 ページ ←次へ | 前へ→

【77635】Re:【Excel】経理の表について
発言  β  - 15/11/13(金) 19:46 -

引用なし
パスワード
   ▼かお さん:

今後はルールを守っていただくとして。

レイアウト、不明なところもありますが、
A列が案件、B列が開始日、C列が終了日、D列から右に月(データとしては日付型。表示形式で m月になっている)
1行目がタイトル行、2行目からデータということにしています。
按分計算の結果でてきた計算誤差については最終月で調整しています。

Sub Test()
  Dim c As Range
  Dim dic As Object
  Dim v As Variant
  Dim n As Long
  Dim x As Long
  Dim d As Date
  Dim f As Long
  Dim t As Long
  Dim days As Long
  Dim tot As Long
  Dim amt As Long
  
  Set dic = CreateObject("Scripting.Dictionary")
  
  With Range("A1").CurrentRegion
    ReDim v(1 To .Rows.Count - 1, 1 To .Columns.Count - 4)
    For Each c In .Rows(1).Offset(, 4).Resize(, .Columns.Count - 4).Cells
      dic(Format(c.Value, "yyyymm")) = dic.Count + 1
    Next
    For Each c In .Columns(1).Offset(1).Resize(.Rows.Count - 1).Cells
     tot = 0
      days = DateDiff("d", c.Offset(, 1).Value, c.Offset(, 2).Value) + 1
      n = DateDiff("m", c.Offset(, 1).Value, c.Offset(, 2).Value) + 1
      d = c.Offset(, 1).Value
      For x = 1 To n
        If n = 1 Then
          f = Day(c.Offset(, 1).Value)
          t = Day(c.Offset(, 2).Value)
        Else
          If x = 1 Then
            f = Day(c.Offset(, 1).Value)
            t = Day(DateSerial(Year(c.Offset(, 1).Value), Month(c.Offset(, 1).Value) + 1, 0))
          ElseIf x = n Then
            f = 1
            t = Day(c.Offset(, 2).Value)
          Else
            f = 1
            t = Day(DateSerial(Year(d), Month(d) + 1, 0))
          End If
        End If
        
        amt = c.Offset(, 3).Value * (t - f + 1) / days
        If x = n Then amt = c.Offset(, 3).Value - tot
        tot = tot + amt
        If dic.exists(Format(d, "yyyymm")) Then
          v(c.Row - 1, dic(Format(d, "yyyymm"))) = amt
        End If
        
        d = DateAdd("m", 1, d)

      Next
    Next
  End With
  
  Range("E2").Resize(UBound(v, 1), UBound(v, 2)).Value = v
  
End Sub
・ツリー全体表示

【77634】Re:【Excel】経理の表について
発言  β  - 15/11/13(金) 18:17 -

引用なし
パスワード
   ▼かお さん:

質問箱ではマルチを容認しています。
していますが、「ルール」があります。

本サイトの基本方針をまとめました。こちら をご一読ください。

というところの こちら をクリックしてみてください。
・ツリー全体表示

【77633】【Excel】経理の表について
質問  かお  - 15/11/13(金) 17:30 -

引用なし
パスワード
   Excel初心者です。
・・・・・・・・・・・・・・・・・・・・・・・・・
 契約開始 契約終了 契約金額 10月 11月
A
B
C
・・・・・・・・・・・・・・・・・・・・・・・・・
上記のような表を作成しているのですが、
契約開始が、2015/10/30
契約終了が、2015/11/21
といったように、契約期間によっては月がまたがることがあります。

その場合に、契約金額を入力したら、
「2015/10/30〜2015/31」までの契約金額の「日割りの合計」
「2015/11/1〜2015/11/21」までの契約金額の「日割りの合計」
が、「10月」「11月」の欄に出てくるようにしたいのですが、可能でしょうか?

・・・・・・・・・・・・・・・・・・・・・・・・・
【例】契約期間:2015/10/30〜2015/11/2
   契約金額:10000円
   ↓
   10月:5000円 (2500円×2)
   11月:5000円 (2500円×2)
・・・・・・・・・・・・・・・・・・・・・・・・・

説明が分かりにくくてすみませんが、分かる方いましたらご回答お願いします。
・ツリー全体表示

【77632】Re:VBA初心者
発言  ウッシ  - 15/11/12(木) 14:37 -

引用なし
パスワード
   追記

どこまで求められているか分からないですけど、
不正な引数とか、行列範囲以外の数値とか判定するための
エラー処理は別途必要です。
・ツリー全体表示

【77631】Re:VBA初心者
回答  ウッシ  - 15/11/12(木) 14:32 -

引用なし
パスワード
   こんにちは

英文を最初に記載しておいた方が良かったですね。

βさんも書かれていますが、引数「row」の意味が分かりにくいですが、

「with data」という表現からすると、1000行目、1列という意味で指定する
ような意味合いではないでしょうか?

つまり判定範囲がセルA1〜A1000という。

一般的に最終行は下から探すので、シートの最大行数を使います。

課題としてはsubからfunctionを呼び出せとなっているので、

Sub test_sub()
'1列目の1000行目から調べて最初の値の行を表示する
  MsgBox test_function(1000, 1)
End Sub
Function test_function(r As Long, c As Long) As Variant
  Dim i As Long
  test_function = ""
  For i = r To 1 Step -1
    If Cells(i, c) <> "" Then
      test_function = i
      Exit For
    End If
  Next
End Function

と答えた方がいいでしょうね。

但し、rowを指定する意味は教授に確認した方がいいと思います。
・ツリー全体表示

【77630】Re:VBA初心者
発言  β  - 15/11/12(木) 14:13 -

引用なし
パスワード
   ▼井上 さん:

厳しいコメントになるかもしれませんが・・・・

>おそらく、そのような答えを教授が求めていると思います。
>本当に有難うございましたm−ーm

そうじゃないですね。
ウッシさんは、そもそも、そちらの要件提示があやふやだったので、
求めるのもは値かなと、そう解釈されてコードをアップしておられますが
課題は 「returns the row number of the last row with data 」ですから
値ではなく行番号を返さなくてはいけません。

ウッシさんにいただいたコードを、そのまま教授に提出すると、当然ながら
【赤点】ですね。(もちろん、ウッシさんのせいではなく、井上さんのせいです)

>英語でかかれてある問題を日本語に訳したら、VBAに詳しい人は理解してくれるだろう

まったくの思い違いです。
百歩譲って、【井上さんが正しく訳したら】回答側でも、想像できるところはあるでしょう。
でも、課題は、【与えられた列や行の情報から、その列の最終・・・・・】ということですよね。

説明するなら、まずそれを明記した上で、たとえば、1列目が与えられたとして、その時 A列が
こうこうこういった状態なら、そこの、何を返したいという例示。
こうすべきです。

だけど、井上さんは A列に こうこういったデータがある。そこに 列と行を与えて云々という
説明をしましたよね。説明の順序とポイントが間違っているわけです。

これも、VBAがどうこういう問題ではなく、意思疎通の課題、大人としての基本的な能力の
問題です。

さて、列はわかりましたが、まだ【行】の役割が見えません。
井上さんは見えていますか? 見えているなら、その役割を説明しなければいけません。
繰り返します。これはVBAの問題ではありません。物事の解釈・理解の問題です。

で、もし、井上さんも、この行の役割がわからない、ということなら、井上さんが
教授に質問しなければいけません。で、教授の見解を回答者に連絡しなければいけません。

もし、井上さんが、この行の役割に対して何の疑問も持っていないとすれば
それはそれで、問題ですねぇ。
・ツリー全体表示

【77629】Re:VBA初心者
お礼  井上  - 15/11/12(木) 12:52 -

引用なし
パスワード
   本当におっしゃる通りだと思います。
私のVBAに関する知識は本当に乏しいもので、英語でかかれてある問題を日本語に訳したら、
VBAに詳しい人は理解してくれるだろうという浅はかな考えで投稿してしまい、本当にご迷惑をおかけいたしました。今度は問題を理解してから質問出来るようにしたいと思います。

▼β さん:
>▼井上 さん:
>
>>実は、Functionがうまく使えるかどうかの海外の大学の課題なのです。なので、私も全く無意味だと思いますが、課題なのでこの通りにしなければいけないんですよね
>
>課題がどこか変だとして、でも、それが課題だから、それにそって答えなければいけないとして
>でも、その課題がどういうものかは、質問者さんは理解しているわけですよね?
>その理解している課題の内容を、回答がほしいということなら、回答者にきちんと伝えなければいけませんね。
>
>課題そのものが、何を言っているのかわからない、矛盾があると、そう思っているなら
>それを示しても、回答者は困りますよね。
>
>課題が何なのか、これをきちんと伝える、それが第一歩ではないですか?
>
>A列に値があるとします。
>で、Functionプロシジャに 「列」と「行」をあたえて「何か」をさせるのですよね?
>たとえば、「列」として 5(E列)、「行」として 20 が与えられたとします。
>このFunctionプロシジャは、与えられた 5 と 20 から A列の何をどうするのですか?
>
>それって、なんだかおかしいとは思いませんか?
>で、課題で出しているくらいだから、そんな、矛盾した課題ではないはずですね。
>ということは、その課題の伝え方が正しくないということになりませんか?
・ツリー全体表示

【77628】Re:VBA初心者
お礼  井上  - 15/11/12(木) 12:49 -

引用なし
パスワード
   分かりにくい私の説明の中、親切にご返答してくださり有難うございます。
課題は英文なんです。。


Write a function that receives a row number and a column number, finds the last row with data in that column, and returns the row number of the last row with data to the calling sub. Write a sub to test the function and display the number of the last row with data.

おそらく、そのような答えを教授が求めていると思います。

本当に有難うございましたm−ーm

▼ウッシ さん:
>こんにちは
>
>課題が英文なんでしょうか?
>
>想像で、
>
>Function test(r As Long, c As Long) As Variant
>'=test(1000,1)とすると
>'1列目の1000行まで調べて最後の値を表示する
>  Dim i As Long
>  test = ""
>  For i = 1 To r
>    If Cells(i, c) = "" Then
>      Exit For
>    End If
>    test = Cells(i, c)
>  Next
>End Function
>
>こんな事でしょうか?
・ツリー全体表示

【77627】Re:VBA初心者
回答  ウッシ  - 15/11/12(木) 11:26 -

引用なし
パスワード
   こんにちは

課題が英文なんでしょうか?

想像で、

Function test(r As Long, c As Long) As Variant
'=test(1000,1)とすると
'1列目の1000行まで調べて最後の値を表示する
  Dim i As Long
  test = ""
  For i = 1 To r
    If Cells(i, c) = "" Then
      Exit For
    End If
    test = Cells(i, c)
  Next
End Function

こんな事でしょうか?
・ツリー全体表示

【77626】Re:VBA初心者
発言  β  - 15/11/12(木) 10:30 -

引用なし
パスワード
   ▼井上 さん:

>実は、Functionがうまく使えるかどうかの海外の大学の課題なのです。なので、私も全く無意味だと思いますが、課題なのでこの通りにしなければいけないんですよね

課題がどこか変だとして、でも、それが課題だから、それにそって答えなければいけないとして
でも、その課題がどういうものかは、質問者さんは理解しているわけですよね?
その理解している課題の内容を、回答がほしいということなら、回答者にきちんと伝えなければいけませんね。

課題そのものが、何を言っているのかわからない、矛盾があると、そう思っているなら
それを示しても、回答者は困りますよね。

課題が何なのか、これをきちんと伝える、それが第一歩ではないですか?

A列に値があるとします。
で、Functionプロシジャに 「列」と「行」をあたえて「何か」をさせるのですよね?
たとえば、「列」として 5(E列)、「行」として 20 が与えられたとします。
このFunctionプロシジャは、与えられた 5 と 20 から A列の何をどうするのですか?

それって、なんだかおかしいとは思いませんか?
で、課題で出しているくらいだから、そんな、矛盾した課題ではないはずですね。
ということは、その課題の伝え方が正しくないということになりませんか?
・ツリー全体表示

【77625】Re:VBA初心者
発言  井上  - 15/11/12(木) 9:29 -

引用なし
パスワード
   ウッシさん

ご返答有難うございます。
実は、Functionがうまく使えるかどうかの海外の大学の課題なのです。なので、私も全く無意味だと思いますが、課題なのでこの通りにしなければいけないんですよね。。自分で試行錯誤したのですが、全くダメでした。。

行列には、
31
75
53
23
47
39
24
23
63
19

が入ります。そして、Functionキーを使い(For loopを使ってだと思うんのですが。。)レンジがA10に到達したときに答えである数字(19)をサブに呼び出してメッセージ表示したいのです。

私もこのクラスを取る前にVBAの知識が無く、説明がわかりにくく大変申し訳御座いません。


▼ウッシ さん:
>こんにちは
>
>>そして、行(row)数字と列(column)数字を受け取るFunction
>
>具体的に行列にはどんな数字が入るのですか?
>
>与えられた1つの行と1つの列に
>>最後の行に入力してある数字
>つまりA10の数字があるか見つけて、その数字をメインに渡す。
>
>って、無意味では?
>
>セルA10の数字そのものでは?
>
>多分意味が違うのでしょうけど、質問を他の人に分かりやすく
>書き直した方がいいと思います。
>
>
>▼井上 さん:
>>初めて投稿させてもらいます。質問なんですが、
>>A1からA10までランダムな数字を入力してあるとします。
>>そして、行(row)数字と列(column)数字を受け取るFunctionプロシージャーを作成します。その中に最後の行に入力してある数字を見つけます。そしてその数字をメインsubに呼び出し、Msgboxに表示させたいのですが、方法が分かりません。どなたかお助けお願い申し上げます。
>>説明が下手で申し訳御座いません。
・ツリー全体表示

【77624】Re:VBA初心者
質問  ウッシ  - 15/11/12(木) 9:10 -

引用なし
パスワード
   こんにちは

>そして、行(row)数字と列(column)数字を受け取るFunction

具体的に行列にはどんな数字が入るのですか?

与えられた1つの行と1つの列に
>最後の行に入力してある数字
つまりA10の数字があるか見つけて、その数字をメインに渡す。

って、無意味では?

セルA10の数字そのものでは?

多分意味が違うのでしょうけど、質問を他の人に分かりやすく
書き直した方がいいと思います。


▼井上 さん:
>初めて投稿させてもらいます。質問なんですが、
>A1からA10までランダムな数字を入力してあるとします。
>そして、行(row)数字と列(column)数字を受け取るFunctionプロシージャーを作成します。その中に最後の行に入力してある数字を見つけます。そしてその数字をメインsubに呼び出し、Msgboxに表示させたいのですが、方法が分かりません。どなたかお助けお願い申し上げます。
>説明が下手で申し訳御座いません。
・ツリー全体表示

【77623】VBA初心者
質問  井上  - 15/11/12(木) 7:34 -

引用なし
パスワード
   初めて投稿させてもらいます。質問なんですが、
A1からA10までランダムな数字を入力してあるとします。
そして、行(row)数字と列(column)数字を受け取るFunctionプロシージャーを作成します。その中に最後の行に入力してある数字を見つけます。そしてその数字をメインsubに呼び出し、Msgboxに表示させたいのですが、方法が分かりません。どなたかお助けお願い申し上げます。
説明が下手で申し訳御座いません。
・ツリー全体表示

【77622】Re:マクロ化の検討
回答  VBAビギナー  - 15/11/11(水) 8:40 -

引用なし
パスワード
   βさん
回答ありがとうございます。
VBAでの例も大変参考になりました。
プログラムに美しさすら感じます。
本当にありがとうございました。
・ツリー全体表示

【77621】Re:マクロ化の検討
お礼  VBAビギナー  - 15/11/11(水) 8:36 -

引用なし
パスワード
   独覚さん

早速の回答ありがとうございます。
VBAではなく関数だけで、複雑な処理ができることに驚きました。
関数にも興味が持てたので、これから精進してまいります。
・ツリー全体表示

【77620】Re:他のブックへのシートコピー
お礼  のんぼ E-MAIL  - 15/11/10(火) 20:24 -

引用なし
パスワード
   ▼マナ さん:
>▼のんぼ さん:
>
>1)複数シート、複数ブックを扱う場合は、どのブックの、どのシートを操作したいかわかるように、ブック、シート指定する
>2)Aのブック(マクロを書いてあるブック)は、ThisWorkbookで指定可能
>3)Bのブックは、開いた時に変数にセットしておくと、ブックの指定に使える
>4)新規シートを追加して、そこにすべてのデータをコピーするなら、最初からシートのコピーだけでよいです
>
>例えばこんな感じ
>
>Sub test2()
>  Dim vntfilename As Variant
>  Dim wb As Workbook
>  
>  vntfilename = Application.GetOpenFilename( _
>    filefilter:="エクセルファイル(*.xlsx),*.xlsx")
>  If vntfilename = False Then Exit Sub
>  
>  Set wb = Workbooks.Open(vntfilename)
>
>  ThisWorkbook.Worksheets("Sheet2").Copy after:=wb.Worksheets(1)
>  
>End Sub
大変わかりやすいご返答いただきまして、ありがとうございました。
構文をためしましたら、できました。マクロブックの表示の仕方など大変勉強になりました。本当にありがとうございました。
・ツリー全体表示

【77619】Re:マクロ化の検討
発言  β  - 15/11/10(火) 19:49 -

引用なし
パスワード
   ▼VBAビギナー さん:

独覚さんからの関数処理で充分かとは思いますがVBA処理としての一例です。
元シートが "Sheet1"、結果を "Sheet2" に表示します。

Sub Sample()
  Dim MAXQ As Object
  Dim OKNG As Object
  Dim CONT As Object
  
  Dim c As Range
  
  Set MAXQ = CreateObject("Scripting.Dictionary")
  Set OKNG = CreateObject("Scripting.Dictionary")
  Set CONT = CreateObject("Scripting.Dictionary")
  
  With Sheets("Sheet1")
    For Each c In .Range("A2", .Range("A" & Rows.Count).End(xlUp))
      If MAXQ.exists(c.Value) Then
        If c.Offset(, 1).Value > MAXQ(c.Value) Then MAXQ(c.Value) = c.Offset(, 1).Value
        If c.Offset(, 2).Value <> CONT(c.Value) Then OKNG(c.Value) = "Error"
      Else
        MAXQ(c.Value) = c.Offset(, 1).Value
        OKNG(c.Value) = "OK"
        CONT(c.Value) = c.Offset(, 2).Value
      End If
    Next
  End With
  
  With Sheets("Sheet2")
    .UsedRange.ClearContents
    .Range("A1:C1").Value = Array("製品", "最大重量", "チェック")
    .Range("A2").Resize(MAXQ.Count).Value = WorksheetFunction.Transpose(MAXQ.Keys)
    .Range("B2").Resize(MAXQ.Count).Value = WorksheetFunction.Transpose(MAXQ.Items)
    .Range("C2").Resize(MAXQ.Count).Value = WorksheetFunction.Transpose(OKNG.Items)
    .Select
  End With
  
End Sub
・ツリー全体表示

【77618】Re:マクロ化の検討
発言  独覚  - 15/11/10(火) 17:34 -

引用なし
パスワード
   C2セルの式で◯をokに×をerrorにしてください。
・ツリー全体表示

【77617】Re:マクロ化の検討
回答  独覚  - 15/11/10(火) 17:32 -

引用なし
パスワード
   ▼VBAビギナー さん:
全てワークシート関数で行う場合です。
また、バージョンは2007以降でレイアウトは以下とします。

Sheet1
    A    B   C
1  製品   重量  糖度
2 みかんA  10   10
  〜

Sheet2
    A    B   C
1  製品   重量  糖度
2 みかんA  12   ok
  〜


Sheet2のA2セルに
=IFERROR(INDEX(Sheet1!A$2:A$100,SMALL(IF(FREQUENCY(IFERROR(MATCH(Sheet1!
A$2:A$100,Sheet1!A$2:A$100,0),""),ROW($1:$100)),ROW($1:$100),""),ROW(A1))),"")

B2セルに
=IF(A2="","",MIN(IF(Sheet1!A$2:A$100=A2,Sheet1!B$2:B$100,"")))

C2セルに
=IF(A2="","",IF(COUNT(0/FREQUENCY(IF(Sheet1!A$2:A$100=A2,Sheet1!C$2:C$100,""),Sheet1!C$2:C$100))=1,"○","×"))
と入力し、三つとも式の確定時にShift+Ctrl+Enterで式を確定してください。
式の確定後、式が{}で囲まれます。

その後下へフィルコピーしてください。

なお、Sheet1のデータが最大100行目までに対応しています。
100行以上ある場合は各式の「$100」部分全てを同じ値で大きくしてください。

それとA2セルの「ROW($1:$100)」部分は必ず1から最大行数までとしてください。

なお、Sheet2のA列は式で行わずにSheet1のA列をSheet2に貼り付け、データ-重複の削除を行う方法もあります。
・ツリー全体表示

【77616】マクロ化の検討
質問  VBAビギナー  - 15/11/10(火) 15:58 -

引用なし
パスワード
   以前こちらで、ご質問させていただき迅速な回答に感激しました。
ありがとうございました。

さて、さっそくですが今回下記の用な表をVBAもしくはEXCEL関数等を使って
1〜2回の動作で作りたいのですが、何か良い案はありますでしょうか。


製品            製品重量    糖度
みかんA            10g        10
みかんA            11g        10
みかんA            12g        10
みかんB            15g        18
みかんB            17g        20
みかんB            16g        20
りんごA            20g        5
りんごA            22g        5
りんごA            21g        5
りんごA            25g        5
りんごB            27g        8
ぶどう            30g        25
ぶどう            33g        25
ぶどう            31g        24



みかんA            12g        ok
みかんB            17g        error
りんごA            25g        ok
りんごB            27g        ok
ぶどう            33g        error


商品の重量は最大値を、糖度は同じでなければエラーとなるようにしたい。
商品それぞれの検索範囲(データベース)が必要になると思うのでそれぞれの検索範囲が決定するような方法をみつけなければならないように思います。

今考えているのが、かなり回りくどいのですが、
1.品名が違う場合は、その手前で○をつける。
2.○のついたセルをコピーしSheet2に貼り付ける。←ここまで完成。
3.Sheet2に貼り付けた製品名を一つずつ検索し、Sheet3に貼り付ける。
(みかんAとみかんBとのセルの間隔を十分あけ、かぶらないよう貼り付ける。)
4.Sheet3に貼り付けられたそれぞれのデータベースから最大値等を検出、コピーしSheet5に貼り付ける。

下記に今回作ったVBAを記載します。この他の方法でも何か良い案がございましたら、
是非参考にさせていただきたく存じます。回答お待ちしております。
よろしくお願いします。
-----------------------------------------------------------------------
Sub ボタン2_Click()
  Dim myrow As Integer
  Dim i As Integer

  myrow = Cells(Rows.Count, 2).End(xlUp).Row
  
    For i = 1 To myrow
  
      If Not Cells(i, 2).Value = Cells(i + 1, 2).Value Then
      Cells(i, 1).Value = "○"
    
  
    End If
    
  Next i
  
End Sub

-----------------------------------------------------------------------
Sub ボタン3_Click()

Dim foundcell As Range, firstcell As Range
  Set foundcell = Cells.Find(what:="○")
  If foundcell Is Nothing Then
    MsgBox "見つかりません"
    Exit Sub
  Else
    Set firstcell = foundcell
    foundcell.Resize(1, 2).Copy Sheets("Sheet2").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)
  End If
  Do
    Set foundcell = Cells.FindNext(foundcell)
    If foundcell.Address = firstcell.Address Then
      Exit Do
    Else
      foundcell.Resize(1, 2).Copy Sheets("Sheet2").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)
    End If
  Loop
End Sub
・ツリー全体表示

241 / 3841 ページ ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free