[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『変則的な表の計算』(アユサン)
Sheet1の表は日々発生する、ライン別の不良原因と不良数をまとめたデータです。 Sheet1の処理日2013年3月分だけの、各ラインの原因別の不良数をSheet2に抽出し
Sheet3にはSheet2で抽出され値を%で表したいと思います。%の分母は2013年3月分だけの 良品数+不良合計です。例えばラインAの分母は27、ラインBは6、ラインCは26、ラインDは 3月分だけなので15になります。マクロでご教示お願いします。 Windows 8、Excel2010です。
Sheet1 A B C D E F G H I J 1処理日 ライン名 良品数 不良合計 原因1 不良数1 原因2 不良数2 原因3 不良数3 2 3/1 A 12 2 エンジン 1 シート 1 3 3/4 A 10 3 エンジン 2 ブレーキ 1 4 3/2 B 5 1 エンジン 1 5 3/20 C 12 2 塗装 1 ブレーキ 1 6 3/4 C 9 3 シート 1 アクセル 1 塗装 1 7 2/22 D 12 1 ブレーキ 1 8 3/5 D 11 4 エンジン 2 塗装 1 シート 1
Sheet2
A B C D E F
1 2013/3 エンジン シート ブレーキ 塗装 アクセル
2 A 3 1 1
3 B 1
4 C 1 1 2 1
5 D 2 1 1
Sheet3
A
1 2013/3 エンジン シート ブレーキ 塗装 アクセル
2 A 11.1% 3.7% 3.7%
3 B 16.7%
4 C 3.8% 3.8% 7.7% 3.8%
5 D 13.3% 6.7% 6.7%
少し強引な力技になったけど。
Sub Sample()
Dim dicH As Object
Dim dicV As Object
Dim dicT As Object
Dim c As Range
Dim reason As String
Dim line As String
Dim v() As Variant
Dim yymm As String
Dim i As Long
Dim j As Long
Dim w As Variant
Dim bDate As Date
bDate = DateSerial(2013, 3, 1)
yymm = Format(bDate, "yyyymm") '指定年月
Set dicH = CreateObject("Scripting.Dictionary")
Set dicV = CreateObject("Scripting.Dictionary")
Set dicT = CreateObject("Scripting.Dictionary")
With Sheets("Sheet1")
With .Range("A2", .Range("A" & .Rows.Count).End(xlUp))
For Each c In .Offset(, 1) 'B列
If Not dicV.exists(c.Value) Then dicV(c.Value) = dicV.Count + 1
Next
For Each c In Union(.Offset(, 4), .Offset(, 6), .Offset(, 8)) 'E,G,I列
If Len(c.Value) > 0 And Not dicH.exists(c.Value) Then dicH(c.Value) = dicH.Count + 1
Next
ReDim v(1 To dicV.Count, 1 To dicH.Count)
For Each c In .Cells 'A列
If Format(c.Value, "yyyymm") = yymm Then
line = c.Offset(, 1).Value
dicT(line) = dicT(line) + WorksheetFunction.Sum(c.Offset(, 2).Resize(, 2))
For j = 5 To 9 Step 2
reason = c.Offset(, j - 1).Value
If Len(reason) > 0 Then
v(dicV(line), dicH(reason)) = v(dicV(line), dicH(reason)) + c.Offset(, j).Value
End If
Next
End If
Next
End With
End With
With Sheets("Sheet2")
.Cells.ClearContents
.Range("A1").Value = bDate
.Range("A1").NumberFormatLocal = "yyyy""年""m""月"";@"
.Range("A2").Resize(dicV.Count).Value = WorksheetFunction.Transpose(dicV.keys)
.Range("B1").Resize(, dicH.Count).Value = dicH.keys
.Range("B2").Resize(UBound(v, 1), UBound(v, 2)).Value = v
w = .Range("A1").CurrentRegion.Value
End With
For i = 2 To UBound(w, 1)
For j = 2 To UBound(w, 2)
If Len(w(i, j)) > 0 Then w(i, j) = w(i, j) / dicT(w(i, 1))
Next
Next
With Sheets("Sheet3")
With .Range("A1").Resize(UBound(w, 1), UBound(w, 2))
.Value = w
.NumberFormatLocal = "0.0%"
End With
.Range("A1").NumberFormatLocal = "yyyy""年""m""月"";@"
End With
End Sub
(ぶらっと)
展開先の1行目タイトルの順番が、アップされたイメージとはちょっと違う順番だったので変更。 また、転記枠確定のためのループが2つになっていたのを集約。 ついでに、現在は原因3までだけど、原因4、原因5、といったものが追加されていっても対応。
Sub Sample2()
Dim dicH As Object
Dim dicV As Object
Dim dicT As Object
Dim c As Range
Dim reason As String
Dim line As String
Dim v() As Variant
Dim yymm As String
Dim i As Long
Dim j As Long
Dim w As Variant
Dim bDate As Date
Dim mCol As Long
bDate = DateSerial(2013, 3, 1)
yymm = Format(bDate, "yyyymm") '指定年月
Set dicH = CreateObject("Scripting.Dictionary")
Set dicV = CreateObject("Scripting.Dictionary")
Set dicT = CreateObject("Scripting.Dictionary")
With Sheets("Sheet1")
mCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
With .Range("A2", .Range("A" & .Rows.Count).End(xlUp))
For Each c In .Cells
If Not dicV.exists(c.Offset(, 1).Value) Then dicV(c.Offset(, 1).Value) = dicV.Count + 1 'B列
For j = 5 To mCol Step 2 'E列以降
reason = c.Offset(, j - 1).Value
If Len(reason) > 0 And Not dicH.exists(reason) Then dicH(reason) = dicH.Count + 1
Next
Next
ReDim v(1 To dicV.Count, 1 To dicH.Count)
For Each c In .Cells
If Format(c.Value, "yyyymm") = yymm Then
line = c.Offset(, 1).Value
dicT(line) = dicT(line) + WorksheetFunction.Sum(c.Offset(, 2).Resize(, 2))
For j = 5 To mCol Step 2
reason = c.Offset(, j - 1).Value
If Len(reason) > 0 Then
v(dicV(line), dicH(reason)) = v(dicV(line), dicH(reason)) + Val(c.Offset(, j).Value)
End If
Next
End If
Next
End With
End With
With Sheets("Sheet2")
.Cells.ClearContents
.Range("A1").Value = bDate
.Range("A1").NumberFormatLocal = "yyyy""年""m""月"";@"
.Range("A2").Resize(dicV.Count).Value = WorksheetFunction.Transpose(dicV.keys)
.Range("B1").Resize(, dicH.Count).Value = dicH.keys
.Range("B2").Resize(UBound(v, 1), UBound(v, 2)).Value = v
w = .Range("A1").CurrentRegion.Value
End With
For i = 2 To UBound(w, 1)
For j = 2 To UBound(w, 2)
If Len(w(i, j)) > 0 Then w(i, j) = w(i, j) / dicT(w(i, 1))
Next
Next
With Sheets("Sheet3")
.Cells.ClearContents
With .Range("A1").Resize(UBound(w, 1), UBound(w, 2))
.Value = w
.NumberFormatLocal = "0.0%"
End With
.Range("A1").NumberFormatLocal = "yyyy""年""m""月"";@"
End With
End Sub
(ぶらっと)
ぶらっとさん、ありがとうございました。 今から、仕事です。帰ってからゆっくり確認させていただきます。 まずはお礼まで。 (アユサン)
時間があったので、私も整理してみました。 検索対象月を、Sheet2 の [A1]から取得しています。 従って、ここに表示はともかく Monthの取得できる、日付データの入っているとの条件です。 なを、原因別項目数を、max 10 で設定していますが、それ以上の場合は、w の設定変更が必要になります。
Sub Test()
Dim i&, j&, m&, n&, r&, c&, v, w
Dim D As Object, Mon&, Sa$, Sb$
Set D = CreateObject("scripting.dictionary")
'準備
v = Sheets("Sheet1").Cells(1, 1).CurrentRegion.Value '元Data
With Sheets("Sheet2")
ReDim w(1 To UBound(v), 1 To 11) '展開用配列準備(原因別 Max 10項目)
w(1, 1) = .Cells(1, 1).Value
Mon = Month(w(1, 1)) '検索月
End With
'内部処理
m = 1: n = 1 '初期値
For i = 2 To UBound(v)
If Month(v(i, 1)) = Mon Then '3月
Sa = v(i, 2)
If Not D.exists(Sa) Then
m = m + 1
D(Sa) = m: w(m, 1) = Sa
End If
D("To" & Sa) = D("To" & Sa) + v(i, 3) + v(i, 4) '品数Count
For j = 5 To UBound(v, 2) Step 2
If Not IsEmpty(v(i, j)) Then
Sb = v(i, j)
If Not D.exists(Sb) Then
n = n + 1
D(Sb) = n: w(1, n) = Sb
End If
r = D(Sa): c = D(Sb)
w(r, c) = w(r, c) + v(i, j + 1) '原因別件数Count
End If
Next
End If
Next
'展開
With Sheets("Sheet2")
.Cells.ClearContents
.Cells(1, 1).Resize(m, n).Value = w
End With
For i = 2 To UBound(w)
For j = 2 To UBound(w, 2)
If Not IsEmpty(w(i, j)) Then
w(i, j) = w(i, j) / D("To" & w(i, 1)) '%処理
End If
Next
Next
With Sheets("Sheet3")
.Cells.ClearContents
.Cells(1, 1).Resize(m, n).Value = w
End With
Set D = Nothing
End Sub
(暇人)
ぶらっとさん、暇人さんありがとうございました。お返事遅れて申し訳ありません。 確認させていただき、どちらもうまくいきました。 ぶらっとさんに質問なんですが、月が変わる度、更新していきたいたいのですが、 その都度、Sample2の、bDate = DateSerial(2013, 3, 1)を替えるより、 Sheet4のA1に指定月日を入力するようにしたほうが良いのではないかとおもいます。 その方法をご指導おねがいします。
bDate = Sheets("Sheet4").Range("A1").Value
(ぶらっと)
ぶらっとさん、わかりました。ありがとうございました。 (アユサン)
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.