[[20240727140821]] 『VBA クロス集計』(Thomas) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) |

| 全文検索 | 過去ログ ]

 

『VBA クロス集計』(Thomas)

VBAでシート1の列・行とシート2の列・行に合う値をシートに2に抽出したく、以下のようなコードを書いたのですがうまくいかず、もしよろしければどなたかお教え頂けますとありがたいです。

<条件>
シート1の1行目とシート2の1行目が一致すること
シート1の4行目とシート2の4行目が一致すること
一致したシート1のセルの計算式をシート2へ抽出

<コード>

Sub Sample1()
Dim i As Long
Dim n As Long
Dim TargetRow As Long
Dim TargetCol As Long
Dim WS1 As Worksheet
Dim WS2 As Worksheet

Set WS1 = Worksheets(1)
Set WS2 = Worksheets(2)

For i = 3 To 50
If WS1.Cells(i, 1) = WS2.Cells(i, 1) Then
TargetRow = i
End If
Next i

For n = 2 To 50
If WS1.Cells(4, n) = WS2.Cells(4, n) Then
TargetCol = n
End If
Next n

WS2.Cells(TargetRow, TargetCol) = WS1.Cells(TargetRow, TargetCol).Formula

End Sub

< 使用 Excel:Excel2013、使用 OS:Windows8 >


 もっと規模が小さくて構いませんので、サンプルデータを示して、こんなデータから
 こういう結果を得たい、という説明をしてもらえませんか?
 コードはわかりますが、何を目的にしているかの出発点がよく理解できません。

(xyz) 2024/07/27(土) 16:16:26


列と行が混同されていてわかり難いけど、
ループ中に意図したセルの値を見つけたら、
Exit For
で、ループを抜けたらよいかと思いますが、
たぶん、同じ位置の値を比べたいのではなさそうな予感。。。

とりあえずたたき台。
変数名がわかり難いので、少し意図が分かりやすそうな変数名に変更しました^^;

Option Explicit

Sub Sample1()

    Dim ixCol As Long   '列番号
    Dim ixRow As Long   '行番号
    Dim wsOld As Worksheet  '転記元シート
    Dim wsNew As Worksheet  '転記先シート

    Set wsOld = Worksheets("Sheet1")
    Set wsNew = Worksheets("Sheet2")

    'Sheet1とSheet2の1列目の同じ位置で同じ値のセルを探す
    For ixRow = 3 To 50
        If wsOld.Cells(ixRow, 1).Value = wsNew.Cells(ixRow, 1).Value Then Exit For
    Next

    'Sheet1とSheet2の4行目の同じ位置で同じ値のセルを探す
    For n = 2 To 50
        If wsOld.Cells(4, ixCol).Value = wsNew.Cells(4, ixCol).Value Then Exit For
    Next

    '同じ位置のセルの数式を転記
    wsNew.Cells(ixRow, ixCol).Formula = wsOld.Cells(ixRow, ixCol).Formula
End Sub
(まっつわん) 2024/07/27(土) 16:40:22

皆様ご助言頂きまして有難うございます。
頂きましたコードで試したのですが、私のコードと同じく、何も転記されませでした。
やりたいと事の詳細としては、以下となります。
すみませんが、お教え頂けます様お願い致します。

<シート1>

   4行目| あ | い | う | え | お 
A列     
1       | A  | H  | O  |  V  | A3
2       | B  | I  | P  |  W  | A4
3       | C  | J  | Q  |  X  | A5
4       | D  | K  | R  |  Y  | A6
5       | E  | L  | S  |  Z  | A7
6       | F  | M  | T  |  A1 | A8
7       | G  | N  | U  |  A2 | A9

<シート2>

   4行目| え | い | お | あ | う 
A列     
1       | V  | H  | A3 |  A  | O
2       | W  | I  | A4 |  B  | P
3       | X  | J  | A5 |  C  | Q
4       | Y  | K  | A6 |  D  | R
5       | Z  | L  | A7 |  E  | S
6       | A1 | M  | A8 |  F  | T
7       | A2 | N  | A9 |  G  | U

(Thomas) 2024/07/27(土) 18:32:26


 すみません、わかりません。

     A列     B      C      D       E     
 1  
 2
 3
 4
 5
 6
 7
 8

 という普通の形式になりませんか?

 |   <条件>
 |  シート1の1行目とシート2の1行目が一致すること
 |  シート1の4行目とシート2の4行目が一致すること
 |  一致したシート1のセルの計算式をシート2へ抽出   
  というのは正しいですか?
  どちらも行の条件なんですか?
(xyz) 2024/07/27(土) 18:46:49

 処理する前のシート2はどんな状態なんですか?
 集計ということは、何か数値ではないんですか?
(xyz) 2024/07/27(土) 19:04:11

 >何も転記されませでした。

当然と言えば当然ですよね。

 >WS1.Cells(4, n) = WS2.Cells(4, n)

↑の比較式は例えば、
Sheet1のB4セルの値と、Sheet2のB4セルの値とを比較するように
あなたは書いています。
で、次でC4セルとC4セルを比較するようになります。
次はD4セルとD4セル。。。

ほとんどの場合がマッチしないですよね?
そこは理解できますでしょうか?

こういう場合は、書き込みたいセル範囲を順に見ていくとよいです。

サンプルを三つほど。。。お好みでわかりやすいやつを。。。

Sub test001()

    Dim i As Long, j As Long                     '書き込み側インデックス番号
    Dim ixR As Long, ixC As Long                 '読み取り側インデックス番号

    For i = 5 To 50
        For j = 2 To 50
            For ixR = 5 To 50
                For ixC = 2 To 50
                    If Worksheets(2).Cells(4, j).Value = Worksheets(1).Cells(4, ixC) Then Exit For
                Next
                If Worksheets(2).Cells(i, 1).Value = Worksheets(1).Cells(ixR, 1) Then Exit For
            Next
            Worksheets(2).Cells(i, j).Formula = Worksheets(1).Cells(ixR, ixC).Formula
        Next
    Next
End Sub

Sub test002()

    '注)3行目は空白行が前提条件のコード
    Dim rngToBody As Range                       '結果を記入したいセル範囲
    Dim rngFromBody As Range                     '元の表のデータ本体のセル範囲
    Dim c As Range                               '結果を記入する各セル
    Dim v As Variant                             '表側検索キーワード
    Dim h As Variant                             '表頭検索キーワード
    Dim ixRow As Long
    Dim ixCol As Long
    Dim e As Long

    With Worksheets("Sheet2").Range("A4").CurrentRegion
        Set rngToBody = Intersect(.Cells, .Offset(1, 1))
    End With
    Set rngFromBody = Worksheets(1).Range(rngToBody.Address)

    For Each c In rngToBody
        v = c.EntireRow.Cells(1, 1).Value
        h = c.EntireColumn.Cells(4, 1).Value
        On Error Resume Next
        ixRow = Application.Match(v, rngFromBody.Columns(0), 0)
        ixCol = Application.Match(h, rngFromBody.Rows(0), 0)
        e = Err.Number
        On Error GoTo 0
        If e = 0 Then c.Value = rngFromBody.Cells(ixRow, ixCol)
    Next
End Sub

Sub test003()

    Dim Rng As Range

    With Worksheets(1).Range("A4").CurrentRegion
        Set Rng = Intersect(.Cells, .Offset(, 1))
    End With
    Rng.AdvancedFilter Action:=xlFilterCopy, _
                       CopyToRange:=Worksheets(2).Range(Rng.Address).Rows(1)
End Sub

(まっつわん) 2024/07/27(土) 22:24:24


あ、ちょっとだけ説明を。。。

test001は行と列のインデックス番号をこねくり回して順にセルを見ています。
けど、ぱっと見どのセルがどれかわかりにくくないですか?
書いていても頭が混乱します^^;

test002は、セル範囲を指定して、
元の表の表頭と側頭を検索して、転記元のセルを決定しています。
ループはセルを集合体としてみて、その各要素をループしてます。
単語の意味が分からないとわかり難いかも知れません。

test003は、例を見させていただいて、列を入れ替えたいだけかなと
思われたので、それなら、エクセルのフィルターオプションの
機能が使えますので、その機能を呼び出して使ってます。

(まっつわん) 2024/07/27(土) 22:36:23


あ、、、
訂正

側頭× → 表側○
(まっつわん) 2024/07/27(土) 22:39:15


 前提に関してですが、行番号と列番号を正確に書かれることをお薦めします。
 これは列の入れ替えだけということなんでしょうか?

 これはワークシート上でINDEX関数とMATCH関数を使って簡単に書けると思います。

 一番気になったのは、Formulaをそのまま入力しているところですね。
 シート1のセルは値だけであれば問題ないと思いますが、
 他のセルを参照するような数式がもしあれば、結果は妙なものになることがあり得ます。
 列の順序を入れ替えたりすれば、循環参照式になることもあります。

 手元にマクロコードも作成してありましたが、既に回答があり重複も見られるので、
 質問者さんの負担になりかねないので、掲示は見合わせます。私は以上とします。

(xyz) 2024/07/28(日) 08:49:19


>やりたいと事の詳細としては、以下となります。
シート2を作成するのが面倒なので列を入れ替えての投稿ですか。
シート1、2の 4行目とは何を言っているのですか。
内容と辻褄が合いません。

(わからん) 2024/07/28(日) 10:44:38


返信遅くなり申し訳ございません。
またタイトルが"VBAクロス集計"としましたが、正しくは"クロス抽出や転記"でした。
また説明もうまくいかず混乱させてしまい、申し訳ございませんでした。
Index MatchやDictionaryではうまくいくのですが、各セルに計算式(=10÷60や20x10等)が入っており、その数式も抽出したくネットで見つけたコードを参照してやったのですが、うまくいかずご相談させて頂きました。
先程頂きましたコードにてうまくいきました。
自分なりにコードの中身を考えてやったつもりだったのですが、もう少し勉強してみます。
皆様ご協力頂きまして有難うございました。
(Thomas) 2024/07/30(火) 17:26:01

コメント返信:

[ 一覧(最新更新順) ]


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