Excel VBA質問箱 IV

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

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


2009 / 13645 ツリー ←次へ | 前へ→

【70097】該当するセルにオートシェイプで丸印を付けたい どぢょりん 11/10/15(土) 0:11 質問[未読]
【70098】Re:該当するセルにオートシェイプで丸印を... kanabun 11/10/15(土) 8:46 発言[未読]
【70104】Re:該当するセルにオートシェイプで丸印を... kanabun 11/10/15(土) 16:46 発言[未読]
【70105】Re:該当するセルにオートシェイプで丸印を... kanabun 11/10/15(土) 17:02 発言[未読]
【70109】Re:該当するセルにオートシェイプで丸印を... kanabun 11/10/15(土) 20:13 発言[未読]
【70110】Re:該当するセルにオートシェイプで丸印を... どぢょりん 11/10/15(土) 22:39 お礼[未読]
【70111】Re:該当するセルにオートシェイプで丸印を... kanabun 11/10/15(土) 22:51 発言[未読]
【70114】Re:該当するセルにオートシェイプで丸印を... どぢょりん 11/10/16(日) 7:32 質問[未読]
【70115】Re:該当するセルにオートシェイプで丸印を... kanabun 11/10/16(日) 7:40 発言[未読]
【70185】Re:該当するセルにオートシェイプで丸印を... どぢょりん 11/10/18(火) 22:20 お礼[未読]
【70474】Re:該当するセルにオートシェイプで丸印を... どぢょりん 11/11/19(土) 8:22 質問[未読]
【70476】Re:該当するセルにオートシェイプで丸印を... kanabun 11/11/19(土) 13:29 発言[未読]
【70483】Re:該当するセルにオートシェイプで丸印を... どぢょりん 11/11/19(土) 23:08 発言[未読]
【70484】Re:該当するセルにオートシェイプで丸印を... どぢょりん 11/11/19(土) 23:46 発言[未読]
【70485】Re:該当するセルにオートシェイプで丸印を... kanabun 11/11/20(日) 1:53 発言[未読]
【70486】Re:該当するセルにオートシェイプで丸印を... kanabun 11/11/20(日) 2:17 発言[未読]
【70487】Re:該当するセルにオートシェイプで丸印を... どぢょりん 11/11/20(日) 8:08 発言[未読]
【70488】Re:該当するセルにオートシェイプで丸印を... kanabun 11/11/20(日) 9:36 発言[未読]
【70491】Re:該当するセルにオートシェイプで丸印を... kanabun 11/11/20(日) 16:22 発言[未読]
【70506】Re:該当するセルにオートシェイプで丸印を... どぢょりん 11/11/22(火) 6:15 お礼[未読]
【70508】Re:該当するセルにオートシェイプで丸印を... kanabun 11/11/22(火) 11:20 発言[未読]
【70514】Re:該当するセルにオートシェイプで丸印を... どぢょりん 11/11/23(水) 8:27 お礼[未読]
【70521】Re:該当するセルにオートシェイプで丸印を... kanabun 11/11/23(水) 17:23 発言[未読]
【70524】Re:該当するセルにオートシェイプで丸印を... どぢょりん 11/11/24(木) 22:14 お礼[未読]

【70097】該当するセルにオートシェイプで丸印を付...
質問  どぢょりん  - 11/10/15(土) 0:11 -

引用なし
パスワード
   困っています。ご教授をお願いします。


Sheet1には元データが入っています。
  A列(コード) B列(品名) C列(価格) D(個数) E(仕入先)
____________________________________
1  11111-111    商品A    10,000     5     A社
____________________________________
2  22222-222    商品B    20,000     3     B社
____________________________________
3  33333-333    商品C    30,000     2     C社
____________________________________
4  44444-444    商品D    40,000     8     D社
____________________________________
  (以下 約200行)


このうち、該当する行だけを選択してsheet2に貼り付けるマクロを作りました。
sheet3が定められた様式になっていて、sheet2と結ばれています。


sheet3
   A列      B列  C列  D列  E列  F列
____________________________
1 11111-111 商品A 10,000  5   A社   B社
2                        C社   その他
____________________________
3 22222-222 商品B 20,000  3   A社   B社 
4                        C社   その他
____________________________
5 33333-333 商品C 30,000  2   A社   B社   
6                        C社   その他
____________________________
7 44444-444 商品D 40,000  8   A社   B社
8                        C社   その他
____________________________
       以下約10品目程度記入

       A2〜D2、A4〜D4、A6〜D6は
       それぞれ上の行と結合されています。

A1セルには=sheet2!A1
B1セルには=sheet2!B1
等の式が入れてあり、マクロでsheet1からsheet2に転記すれば
sheet3に表記されるようになっています。
マクロ実行時に、E・F列の該当するセルにオートシェープで丸を付けたいのですが、
うまくいかずに困っています。

商品Aの場合は、E1に、商品BはF3に、商品CはE6に、また、商品DのようにA社・B社・C社以外から仕入れた商品には、その他に丸を付けたいのです。
今のマクロは以下のとおりです。

Sub ボタン1_Click()
Sheets("sheet2").Select
  Cells.Select
  Selection.ClearContents
  
Sheets("sheet1").Select
On Error Resume Next
Range("A1:A65536").SpecialCells(xlCellTypeConstants).EntireRow.Select
  Selection.Copy
  Sheets("sheet2").Select
  Range("A1").Select
  ActiveSheet.Paste 

Sheets("sheet3").Select

End Sub


説明が分かりにくいかもしれませんが、
どうかよろしくお願いします。

【70098】Re:該当するセルにオートシェイプで丸印...
発言  kanabun  - 11/10/15(土) 8:46 -

引用なし
パスワード
   ▼どぢょりん さん:
おはようございます。
前にこの質問が出た時も思いましたが、
「セルにオートシェープで丸を付け」る処理そのものはマクロ記録で
基本が得られます。

>Sheet1には元データが入っています。
>  A列(コード) B列(品名) C列(価格) D(個数) E(仕入先)
>____________________________________
>1  11111-111    商品A    10,000     5     A社
>____________________________________
>2  22222-222    商品B    20,000     3     B社
>____________________________________
>3  33333-333    商品C    30,000     2     C社
>____________________________________
>4  44444-444    商品D    40,000     8     D社
>____________________________________
>  (以下 約200行)
>
>
>このうち、該当する行だけを選択してsheet2に貼り付けるマクロを作りました。
>sheet3が定められた様式になっていて、sheet2と結ばれています。
これはフィルタで抽出しているわけですか?
つまり、
「商品A」 といったら 「A社」が返ってくるような、LOOKUPテーブルを
メモリ上につくっておけば、

>sheet3
>   A列      B列  C列  D列  E列  F列
>____________________________
>1 11111-111 商品A 10,000  5   A社   B社
>2                        C社   その他
>____________________________
>3 22222-222 商品B 20,000  3   A社   B社 
>4                        C社   その他
>____________________________
>5 33333-333 商品C 30,000  2   A社   B社   
>6                        C社   その他
>____________________________
>7 44444-444 商品D 40,000  8   A社   B社
>8                        C社   その他
>____________________________

>E・F列の該当するセルにオートシェープで丸を付けたい
という目的のために「商品 - 仕入れ先」対応表をLOOKUPすることができる
のではないかと思います。
LOOKUPテーブルといったのは、具体的には Dictionaryオブジェクトのこと
です。
Sheet2に出現している「商品と対応する仕入れ先名」をDicに格納していけば
LOOKUPテーブルは簡単につくれます。
 Dim dic As Object
 Set dic =CreateObject("Scripting.Dictionary")
 dic("商品A") = "A社"
  〜
 イメージとしては こういう感じです。

これができあがったら、
Sheet3 の「商品」の列をうえから順にみていって、
 If dic.Exists("商品A") Then
  'dic("商品A") で"A社" が返るから、
   E,F列の その行.Range(E1:F2)に書いてある仕入れ先名のなかで
    "A社"のセルに 丸を描く

といったLoop処理をしていけばいいと思います。

【70104】Re:該当するセルにオートシェイプで丸印...
発言  kanabun  - 11/10/15(土) 16:46 -

引用なし
パスワード
   ▼どぢょりん さん:
Sheet2 のシートレイアウトが分からないので、
とりあえず、 Sheet1を使って「商品〜仕入れ先」対応表を
つくり、Sheet3に対して仕入れ先の書いてあるセルに四角形を
描画するまでの一連の処理をコードにしてみました。
(使う商品は Sheet2にあるものだけなら、Sheet2を使ったほうが
効率よいのですが、まあ、200行程度ならそうちがわないでしょう。)

'------------------------ 標準モジュール
Option Explicit

Sub test1()
 Dim dic As Object
 Dim dic2 As Object
 Dim c As Range
 Dim i As Long
 
 Set dic = CreateObject("Scripting.Dictionary")
 Set dic2 = CreateObject("Scripting.Dictionary")
 
 With Worksheets(1)
   For Each c In .Range("B1", .Cells(.Rows.Count, 2).End(xlUp))
     dic(c.Value) = c.Offset(, 3).Value
   Next
 End With
 
 With Worksheets(3)
   For Each c In .Range("E1").Resize(2, 2)
     If Len(c.Value) > 0 Then
       i = i + 1
       dic2(c.Value) = i
     End If
   Next
   .Rectangles.Delete
   For Each c In .Range("B1", .Cells(.Rows.Count, 2).End(xlUp))
     If Len(c.Value) > 0 Then
       If dic.Exists(c.Value) Then
         ss = dic(c.Value) '仕入れ先名
         If dic2.Exists(ss) Then
           i = dic2(ss)
         Else
           i = dic2.Count
         End If
         drawCircle c.Offset(, 3).Resize(2, 2).Item(i)
       End If
     End If
   Next
 End With
 
 Set dic = Nothing
 Set dic2 = Nothing

End Sub


【解説】
初めにこのプログラム(test1プロシージャ)内で使用する
変数を宣言します。
 Dim dic As Object
 Dim dic2 As Object
 Dim c As Range
 Dim i As Long


つぎに、宣言した2つのオブジェクト dic, dic2 を実体化します。
(2つのDictionaryオブジェクトを使えるようにします)
>  Set dic = CreateObject("Scripting.Dictionary")
>  Set dic2 = CreateObject("Scripting.Dictionary")


シート1のほうをみて、
「商品」と1対1に対応する「仕入れ先」をDictionaryに
順に格納していきます。
ワークシート1の[B1]セルから順に下方に、
>  With Worksheets(1)
>    For Each c In .Range("B1", .Cells(.Rows.Count, 2).End(xlUp))
>      dic(c.Value) = c.Offset(, 3).Value
>    Next
>  End With

>     dic(c.Value) = c.Offset(, 3).Value
の部分は ご提示の最初のデータでいえば、
     dic("商品A") = "A社"
という処理をしていることになります。
B列を最後まで処理すると、dic 内には
 key   Item 
---------------
 商品A A社
 商品B B社
 商品C C社
 商品D D社

というLOOKUPテーブルができていることになります。
これで、LOOKUPテーブルのほうはできましたので、
つぎに シート3 に行って、B列の「商品」に対応する「仕入れ先」
をE,F列の2行の範囲から検索し、該当するセルの上にマルを描く
処理に入ります。
まず、E列  F列 の仕入れ先名はどの2行も同じアイテムなので
先頭の「仕入れ先候補」範囲 [E1:F2] すなわち [E1].Resize(2, 2)
の範囲より、仕入れ先候補名とそのセル位置を 先ほどと同様
dic2にセットすることにします。
>  With Worksheets(3)
>    For Each c In .Range("E1").Resize(2, 2)
>      If Len(c.Value) > 0 Then
>        i = i + 1
>        dic2(c.Value) = i
>      End If
>    Next

>sheet3
>   A列  B列   C列  D列  E列 F列
>____________________________
>1 11111-111 商品A 10,000  5   A社 B社
>2                   C社 その他

> With Worksheets(3)
>   For Each c In .Range("E1").Resize(2, 2)
と書いているので、For Each c のLoopは
[E1]→[F1]→[E2]→[F2]
とLoopします。このとき、この4つのセルには下図の右側のような
位置番号が振られます。
[E1] [F1]       [1] [2]
[E2] [F2]       [3] [4]

dic2には 「仕入れ先」に対応するセル位置番号をセットしています。
この結果、dic2というもう一つのLOOKUP TABLEは
(今回の例では)以下のようになります。
key Item
-----------
A社  1
B社  2
C社  3
その他 4


>   .Rectangles.Delete
これは、シート内のすべての四角形を削除しているところです。
(注) 今回は「角丸目四角形」を使いましたが、楕円で囲む場合は
   .Obals.Delete
  としてください。

さて、以上で準備ができましたので、ここから
B列の商品をみて dic(「商品-仕入先」対応表)より対応する仕入れ先を
取得し、
dic2(「仕入れ先-セル位置番号」対応表)に取得してあるセル位置に
図形を描いていく処理をします。
   [B1]から最終データまで順に下方に調べていきます。
>   For Each c In .Range("B1", .Cells(.Rows.Count, 2).End(xlUp))
     ただし、B列セルに値の入っている行だけ処理をします。
>     If Len(c.Value) > 0 Then

     商品名がdicのkeyにあるか?以下で問い合わせます。
     対応表は dicというメモリ内にあり、あるかないかは
     dicのkey(商品名)を順に調べなくても↓で分かります。
>       If dic.Exists(c.Value) Then

     たとえばB列が「商品A」ならその「仕入先名」はA社、
       変数ss にこの「A社」を代入します。
>         ss = dic(c.Value) '仕入れ先名

      「A社」はE,F列のどの位置に書かれているか?
      それは dic2に書いてありますので、その値を変数iに
      代入します。ただし、「商品D」の仕入れ先「D社」は
      dic2の対応表に書いてありませんので、そのときは(Else)
      変数iに dic2.Countを代入します。今回は dic2.Countは
      4です(4番目のセルという意味)
>          If dic2.Exists(ss) Then
>            i = dic2(ss)
>          Else
>            i = dic2.Count
>          End If

       こうして、いま注目している行のE,F列のどのセル位置に
       図を描けばいいか?が分かりましたので、このセルを指定
       して、図を描くサブ・プロシージャをCallします。
>         drawCircle c.Offset(, 3).Resize(2, 2).Item(i)
>       End If
>     End If
>   Next
> End With


さいごに、使用オブジェクトの利用が終わったことをオブジェクトに
通知してやります(この通知はプロシージャがEndするとき暗黙のうちに
されますから、ま、絶対必要ということはないですが)
> Set dic = Nothing
> Set dic2 = Nothing


>Private Sub drawCircle(c As Range)
のほうは、こちらが「丸い角の四角形」を描く操作のマクロ記録を
編集して作ったものです。そちらの描きたい図形にあわせて、適宜
変更してください。

【70105】Re:該当するセルにオートシェイプで丸印...
発言  kanabun  - 11/10/15(土) 17:02 -

引用なし
パスワード
   すみません。タイプミスです
>>   .Rectangles.Delete
>これは、シート内のすべての四角形を削除しているところです。
>(注) 今回は「角丸目四角形」を使いましたが、楕円で囲む場合は
>   .Obals.Delete
    ↓
   .Ovals.Delete
>  としてください。

【70109】Re:該当するセルにオートシェイプで丸印...
発言  kanabun  - 11/10/15(土) 20:13 -

引用なし
パスワード
   >▼どぢょりん さん:

>>Private Sub drawCircle(c As Range)
>のほうは、こちらが「丸い角の四角形」を描く操作のマクロ記録を
>編集して作ったものです。

といいながら、紹介してなかったですね
↓こんなんでした

Private Sub drawCircle(c As Range)
  With c.Worksheet.Shapes.AddShape( _
    msoShapeRoundedRectangle, c.Left, c.Top, c.Width, c.Height)
    .Fill.Visible = msoFalse
    .Line.Weight = 1#
    .Line.ForeColor.SchemeColor = 10
    .Line.BackColor.RGB = RGB(255, 255, 255)
  End With
End Sub

※先ほどの Sub test1() と同じモジュールに置いて、
お試しください。作成される図形は
msoShapeRoundedRectangle
となってますが、ここをお望みの図形タイプに変更してください。

【70110】Re:該当するセルにオートシェイプで丸印...
お礼  どぢょりん  - 11/10/15(土) 22:39 -

引用なし
パスワード
   kanabunさん、ありがとうございます。
まだ実行できていませんが、書いていただいたようにやってみます。


質問時のsheet1の表示に間違いがありましたので、訂正します。

Sheet1には元データが入っています。
  A列(空欄) B列(コード) C列(品名) D(価格) E(個数) F(仕入先)
____________________________________
1      11111-111    商品A    10,000     5     A社
____________________________________
2      22222-222    商品B    20,000     3     B社
____________________________________
3      33333-333    商品C    30,000     2     C社
____________________________________
4      44444-444    商品D    40,000     8     D社
____________________________________
  (以下 約200行)

空欄のA列に数字を入力して、マクロを実行しています。

【70111】Re:該当するセルにオートシェイプで丸印...
発言  kanabun  - 11/10/15(土) 22:51 -

引用なし
パスワード
   ▼どぢょりん さん:
>kanabunさん、ありがとうございます。
>まだ実行できていませんが、書いていただいたようにやってみます。
>
>
>質問時のsheet1の表示に間違いがありましたので、訂正します。

こんばんは〜
まずは、テスト用の新規Bookに、最初ご提示いただいた形式の
シート1 とシート3 を作り(Sheet2は何も入力しなくてよい)
それでお試しください。

【70114】Re:該当するセルにオートシェイプで丸印...
質問  どぢょりん  - 11/10/16(日) 7:32 -

引用なし
パスワード
   丁寧な回答をしていただき、ありがとうございました。

早速実行してみましたが、
ss = dic(c.Value) '仕入れ先名
のところで、

「コンパイルエラー
変数が定義されていません」

と表示されてしまいます。
理由がお分かりでしたら、ご教授願います。

【70115】Re:該当するセルにオートシェイプで丸印...
発言  kanabun  - 11/10/16(日) 7:40 -

引用なし
パスワード
   ▼どぢょりん さん:

>早速実行してみましたが、
>ss = dic(c.Value) '仕入れ先名
>のところで、
>
>「コンパイルエラー
>変数が定義されていません」
>
>と表示されてしまいます。
>理由がお分かりでしたら、

あ、ごめんなさい。
ss という変数が最初に宣言されてませんでした m(_ _)m

>Sub test1()
> Dim dic As Object
> Dim dic2 As Object
> Dim c As Range
> Dim i As Long
 Dim ss As String

としてください。

【70185】Re:該当するセルにオートシェイプで丸印...
お礼  どぢょりん  - 11/10/18(火) 22:20 -

引用なし
パスワード
   希望通り動きました。
ありがとうございました。

【70474】Re:該当するセルにオートシェイプで丸印...
質問  どぢょりん  - 11/11/19(土) 8:22 -

引用なし
パスワード
   先日はありがとうございました。
順調だったのですが、疑問点が2つ出てきました。

1.業者がA・C社となっているものがあったのです。
これを入力すると、当然その他のセルに○がついてしまいます。
これをできれば、AとCの両方に○を付けたいのです。
どのようにすればいいか、アドバイスをお願いできませんか?


2.シート3(様式)は10行までしかありません。
11行目以降になることも考えられたため、下記のようなマクロに変更しました。
IF〜Else Do Untilを使って、10品目までをまず印刷し、
11品目からはシート2に再度張りなおしてシート3に表しています。
ところが2枚目以降になると、オートシェイプの位置がずれてしまいます。
何が悪いのでしょうか。
分かりましたら教えてください。


 Dim dic As Object
 Dim dic2 As Object
 Dim c As Range
 Dim i As Long
 Dim ss As String
 
 Set dic = CreateObject("Scripting.Dictionary")
 Set dic2 = CreateObject("Scripting.Dictionary")


With Sheets("Sheet2")
   For Each c In .Range("C1", .Cells(.Rows.Count, 3).End(xlUp))
     dic(c.Value) = c.Offset(, 3).Value
   Next
End With
 

 With Sheets("Sheet3")
   For Each c In .Range("F1").Resize(2, 2)
     If Len(c.Value) > 0 Then
       i = i + 1
       dic2(c.Value) = i
     End If
   Next
   .Ovals.Delete
   For Each c In .Range("C1", .Cells(.Rows.Count, 3).End(xlUp))
     If Len(c.Value) > 0 Then
       If dic.Exists(c.Value) Then
         ss = dic(c.Value)
         If dic2.Exists(ss) Then
           i = dic2(ss)
         Else
           i = dic2.Count
         End If
         drawCircle c.Offset(, 3).Resize(2, 2).Item(i)
       End If
     End If
   Next
 End With

 Set dic = Nothing
 Set dic2 = Nothing


 Sheets("Sheet3").PrintOut


If Sheets("Sheet2").Range("C11") = "" Then  
  Sheets("Sheet3").Select
   
 
Else
Do Until Sheets("Sheet2").Range("C11").Value = ""
  
  
  Sheets("Sheet2").Rows("11:65536").Copy
  Sheets("Sheet2").Rows("1:1").PasteSpecial


 Set dic = CreateObject("Scripting.Dictionary")
 Set dic2 = CreateObject("Scripting.Dictionary")


With Sheets("Sheet2")
   For Each c In .Range("C1", .Cells(.Rows.Count, 3).End(xlUp))
     dic(c.Value) = c.Offset(, 3).Value
   Next
End With
 

 With Sheets("Sheet3")
   For Each c In .Range("F1").Resize(2, 2)
     If Len(c.Value) > 0 Then
       i = i + 1
       dic2(c.Value) = i
     End If
   Next
   .Ovals.Delete
   For Each c In .Range("C1", .Cells(.Rows.Count, 3).End(xlUp))
     If Len(c.Value) > 0 Then
       If dic.Exists(c.Value) Then
         ss = dic(c.Value)
         If dic2.Exists(ss) Then
           i = dic2(ss)
         Else
           i = dic2.Count
         End If
         drawCircle c.Offset(, 3).Resize(2, 2).Item(i)
       End If
     End If
   Next
 End With

 Set dic = Nothing
 Set dic2 = Nothing

 Sheets("Sheet3").PrintOut
 
 Loop
 Sheets("Sheet3").Select
 
End If
End Sub


大変分かりにくいかもしれません。
よろしくお願いします。

【70476】Re:該当するセルにオートシェイプで丸印...
発言  kanabun  - 11/11/19(土) 13:29 -

引用なし
パスワード
   ▼どぢょりん さん:こんにちは〜

出かけてましたので、発見がおそくなりすみません。
またすぐ出かけるのですが、

>1.業者がA・C社となっているものがあったのです。

>これをできれば、AとCの両方に○を付けたいのです。

こちらのほうですが、
「A社・C社」のようになっていれば、区切り記号「・」でデータを
分割し、ループするとかの方法はあると思いますが、
「A・C社」となってると、とても難しいですね

2.のほうはまだ考えてません。

使用するシートは Sheet2 とSheet3 だけですか?
ちなみに Sheet1から Sheet2 へは フィルタで必要なデータだけを
抽出してるわけですか?

【70483】Re:該当するセルにオートシェイプで丸印...
発言  どぢょりん  - 11/11/19(土) 23:08 -

引用なし
パスワード
   よろしくお願いします。


>こちらのほうですが、
>「A社・C社」のようになっていれば、区切り記号「・」でデータを
>分割し、ループするとかの方法はあると思いますが、
>「A・C社」となってると、とても難しいですね

正確には「A・C」となっています。


>使用するシートは Sheet2 とSheet3 だけですか?
>ちなみに Sheet1から Sheet2 へは フィルタで必要なデータだけを
>抽出してるわけですか?

Sheet1はデータのシートです。
その中から、Sheet3に転記したい行だけをSheet2に貼り付けています。
以下のようなマクロでSheet1からSheet2に転記しています。
Sheet1のA列に数字を入れて、以下のマクロを実行しています。

Sheets("Sheet1").Select
On Error Resume Next
Range("A1:A65536").SpecialCells(xlCellTypeConstants).EntireRow.Copy Sheets("Sheet2").Range("A1")

【70484】Re:該当するセルにオートシェイプで丸印...
発言  どぢょりん  - 11/11/19(土) 23:46 -

引用なし
パスワード
   最初の質問時と比べ、Sheet1・Sheet3ともに、若干変更されました。


Sheet1には元データが入っています。
  A列(数字入力) B列(コード) C列(品名) D(価格) E(個数) F(仕入先)
____________________________________
1           11111-111    商品A    10,000     5     A
____________________________________
2           22222-222    商品B    20,000     3     B
____________________________________
3           33333-333    商品C    30,000     2     C
____________________________________
4           44444-444    商品D    40,000     8     D
____________________________________
5           55555-555    商品E    50,000     3     A・C
____________________________________
  (以下 約200行)

Sheet2はSheet1でA列に数字を入力した行だけ転記しています。
  A列(数字)   B列(コード) C列(品名) D(価格) E(個数) F(仕入先)
____________________________________
1           11111-111    商品A    10,000     5     A
____________________________________
2           22222-222    商品B    20,000     3     B
____________________________________
3           33333-333    商品C    30,000     2     C
____________________________________
4           44444-444    商品D    40,000     8     D
____________________________________
5           55555-555    商品E    50,000     3     A・C
____________________________________


sheet3が定められた様式になっていて、sheet2と結ばれています。
セルB1=Sheet2!B1
のように式が入れてあります。

sheet3
   A列      B列  C列  D列  E列  F列  G列
____________________________
1  1    11111-111 商品A 10,000  5   A   B
2                               C  他
____________________________
3  2    22222-222 商品B 20,000  3   A   B 
4                               C  他
____________________________
5  3    33333-333 商品C 30,000  2   A   B   
6                               C  他
____________________________
7  4    44444-444 商品D 40,000  8   A   B
8                               C  他
____________________________
9  5    55555-555 商品E 50,000  3   A   B
10                               C  他
____________________________

以下用紙1枚で10品目記入(20行目まで)できるようになっています。
A2〜D2、A4〜D4、A6〜D6はそれぞれ上の行と結合されています。

このSheet3が1枚に10品までしか記入されないため、1度に11品目以上を
処理する場合は、Loopで複数回印刷するしかないのかなと考えたのです。

面倒なことばかりお聞きしてます。
よろしくお願いします。

【70485】Re:該当するセルにオートシェイプで丸印...
発言  kanabun  - 11/11/20(日) 1:53 -

引用なし
パスワード
   ▼どぢょりん さん:

>最初の質問時と比べ、Sheet1・Sheet3ともに、若干変更されました。
まだ見てなくてすみません。

1.の「仕入先が複数」問題はちょっと置いておいて、
2.の Sheet2に10行以上のデータが抽出された時の、Sheet3の印刷方法です
 が、今おやりになっているように、Sheet2 に10行を超えるデータがあった
 ときは、1〜10行を 印刷した後、11行目以降を1行目にコピーしていく
 方式が分かりやすいと、ぼくも思います。
 ただ、書かれているコードはもうすこし簡単になりそうなので、2.の
 問題を先に片づけておこうと、
ワークシート用の 変数WS2 と WS3を用意して、
以下のようにまとめてみました。

Sub 仕入先に○_印刷2()
 Dim dic As Object
 Dim dic2 As Object
 Dim c As Range
 Dim i As Long
 Dim ss As String
 Dim WS2 As Worksheet: Set WS2 = Worksheets(2)
 Dim WS3 As Worksheet: Set WS3 = Worksheets(3)
 
 Set dic = CreateObject("Scripting.Dictionary")
 Set dic2 = CreateObject("Scripting.Dictionary")

' シート2の[C1]セルから順に下方に、C列の「商品名」と
' F列の「仕入れ先」対応関係を辞書dicに格納していきます
 With WS2
   For Each c In .Range("C1", .Cells(.Rows.Count, 3).End(xlUp))
     dic(c.Value) = c.Offset(, 3).Value
   Next
 End With
'  最後まで処理すると、dic 内には
'  key  Item
' ---------------
' 商品A A社
' 商品B B社
' 商品C C社
' 商品D D社
'    のようなLOOKUPテーブルが作成されます。


 With WS3
   .Select
   For Each c In .Range("F1").Resize(2, 2)
     If Len(c.Value) > 0 Then
       i = i + 1
       dic2(c.Value) = i
     End If
   Next
'   dic2には 「仕入れ先」に対応するセル位置番号をセットしています。
'   この結果、dic2というもう一つのLOOKUP TABLEは
'   (今回の例では)以下のようになります。

'    key Item   key Item
'    ----------------------------
'    A社  1    B社  2
'    C社  3    その他 4
   
   
'  dic2(「仕入れ先-セル位置番号」対応表)に取得してあるセル位置に
'  図形を描いていく処理をします。
   Dim y As Long
   Do While Len(WS2.Range("B1").Text) > 0
     .DrawingObjects.Delete
     For y = 1 To 20 Step 2
       Set c = .Cells(y, 3)
       If Len(c.Value) = 0 Then Exit For
       
       If dic.Exists(c.Value) Then
         ss = dic(c.Value)
         If dic2.Exists(ss) Then
           i = dic2(ss)  '辞書2 にある仕入れ先位置
         Else
           i = dic2.Count '「その他」の位置
         End If
         drawCircle c.Offset(, 3).Resize(2, 2).Item(i)
       End If
     Next
     '仕入先の楕円囲みが終わったら、印刷
     .PrintPreview  '←デバッグのため プレビュー
     '.PrintOut   ←◆本来の印刷は こちら
     
     '印刷が終わったら WS2のデータを上方向シフト
     With WS2.Range("B1")
       .CurrentRegion.Offset(10).Copy .Cells
     End With
   Loop
 End With

 Set dic = Nothing
 Set dic2 = Nothing
End Sub

仕入先が複数ある問題はいったん置いておいて、
2.の問題に対して、↑のコードに書いたやりかたで、試してみて
くださいませんか?
どんな不具合が出るか、はたまた、思ったように印刷されるか?

 

【70486】Re:該当するセルにオートシェイプで丸印...
発言  kanabun  - 11/11/20(日) 2:17 -

引用なし
パスワード
   ▼どぢょりん さん:
>最初の質問時と比べ、Sheet1・Sheet3ともに、若干変更されました。

Sheet2 ですが、A列にも番号が入っているのですか?
もしそうなら、先ほどの試案のコード、以下のように変更してみてください。

>   Do While Len(WS2.Range("B1").Text) > 0
   Do While Len(WS2.Range("A1").Text) > 0
     .DrawingObjects.Delete

     (途中、省略)

     '印刷が終わったら WS2のデータを上方向シフト
     'With WS2.Range("B1")
     With WS2.Range("A1")
       .CurrentRegion.Offset(10).Copy .Cells
     End With
   Loop


さて、
>Sheet2
ですが、
>____________________________________
>5           55555-555    商品E    50,000     3     A・C
>____________________________________
>

「商品E」 の仕入れ先は 必ず「A・C」となるのですか?
それならば、(Sheet3に)複数○で囲む方法はあると思います。
そうでなく、「商品E」の仕入れ先がある行では「E」であったり、
別の行では「A・C」になったりすると、今のやり方は捨てないと
いけません。

【70487】Re:該当するセルにオートシェイプで丸印...
発言  どぢょりん  - 11/11/20(日) 8:08 -

引用なし
パスワード
   ▼kanabun さん:
早速ありがとうございます。
やってみて報告します。


>Sheet2 ですが、A列にも番号が入っているのですか?

Sheet2のA列は必ず数字が入っています。


>
>さて、
>>Sheet2
>ですが、
>>____________________________________
>>5           55555-555    商品E    50,000     3     A・C
>>____________________________________
>>
>
>「商品E」 の仕入れ先は 必ず「A・C」となるのですか?
>それならば、(Sheet3に)複数○で囲む方法はあると思います。
>そうでなく、「商品E」の仕入れ先がある行では「E」であったり、
>別の行では「A・C」になったりすると、今のやり方は捨てないと
>いけません。


残念ながら商品Eは、ある行では「C」、ある行では「A・C」になっています。
品名で使い分けるのは難しそうです。
それ以外のコードも価格も同一になる場合があります。
ただし、Sheet3には出てこないので必要ないかと思って書きませんでしたが、Sheet1のG列に枝番号が入っています。
同じ商品Eでも
            仕入先 枝番
55555-555 商品E  A・C 001
55555-555 商品E   C  002

のような感じです。
Sheet2にも転記されています。

【70488】Re:該当するセルにオートシェイプで丸印...
発言  kanabun  - 11/11/20(日) 9:36 -

引用なし
パスワード
   ▼どぢょりん さん:

>残念ながら商品Eは、ある行では「C」、ある行では「A・C」になっています。
>品名で使い分けるのは難しそうです。
>それ以外のコードも価格も同一になる場合があります。

>同じ商品Eでも
>            仕入先 枝番
>55555-555 商品E  A・C 001
>55555-555 商品E   C  002
>
>のような感じです。
>Sheet2にも転記されています。

「商品名」と「仕入先」に1:1対応がないということになると、
「商品名」から「仕入先」を辞書引きするLookup は原理的に不可能、という
ことになります。

前提が崩れたのですから、これまでの考え方は捨てて別の方法にする
必要がありそうです。

Sheet3 のデータは Sheet2とリンクしています。
Sheet3 の各行の「仕入先」は(現在は 記入されていないけれど)
 Sheet2を見れば分かります。
 たとえば、
Sheet3の 1行目の仕入れ先は Sheet2の 1行目のデータです。
Sheet3の 3行目の仕入れ先は Sheet2の 2行目のデータです。
Sheet3の 5行目の仕入れ先は Sheet2の 3行目のデータです。
以下同様。

【70491】Re:該当するセルにオートシェイプで丸印...
発言  kanabun  - 11/11/20(日) 16:22 -

引用なし
パスワード
   ▼どぢょりん さん:
>Sheet3 のデータは Sheet2とリンクしています。
>Sheet3 の各行の「仕入先」は(現在は 記入されていないけれど)
> Sheet2を見れば分かります。
> たとえば、
>Sheet3の 1行目の仕入れ先は Sheet2の 1行目のデータです。
>Sheet3の 3行目の仕入れ先は Sheet2の 2行目のデータです。
>Sheet3の 5行目の仕入れ先は Sheet2の 3行目のデータです。
>以下同様。

このことを利用すると、たとえばですが、以下とか?

Sub 仕入先に○_印刷3()
 Dim c As Range, cLast As Range, r As Range
 Dim i As Long
 Dim y As Long
 Dim ss As String, s1 As String
 Dim WS2 As Worksheet: Set WS2 = Worksheets(2)
 Dim WS3 As Worksheet: Set WS3 = Worksheets(3)
 
 With WS3
   .Select
   Do Until IsEmpty(WS2.Range("B1").Value)
     .DrawingObjects.Delete
     For y = 1 To 20 Step 2
       If Len(.Cells(y, "C").Text) = 0 Then Exit For
       
       ss = WS2.Cells((y + 1) \ 2, "F").Value 'Sheet2仕入先文字列
       Set r = .Cells(y, "F").Resize(2, 2)
       For Each c In r
         s1 = c.Value
         If InStr(ss, s1) Then
           drawCircle c
           ss = Replace(ss, s1, "")
           If Len(ss) = 0 Then Exit For
         End If
       Next
       If Len(ss) > 0 Then
        If Len(Replace(ss, "・", "", Compare:=vbTextCompare)) > 0 Then
          drawCircle r.Item(r.Count)
        End If
       End If
     Next
     '仕入先の円囲みが終わったら、印刷
     .PrintPreview  'デバッグのため プレビュー
     '.PrintOut   ’本来は こちら
     
     '印刷が終わったら WS2のデータを上方向シフト
     With WS2.Range("A1")
       .CurrentRegion.Offset(10).Copy .Cells
     End With
   Loop
 End With
End Sub

【70506】Re:該当するセルにオートシェイプで丸印...
お礼  どぢょりん  - 11/11/22(火) 6:15 -

引用なし
パスワード
   ▼kanabun さん:
いつもありがとうございます。
実行してみましたが、エラーがでてしまします。

   .CurrentRegion.Offset(10).Copy .Cells

この部分で、「オブジェクトが必要です」と出ています。
よろしければ、対応を教えてください。


また、できれば書いていただいたマクロの説明をしていただけませんか。
初心者で、まだまだわからないことだらけで、何が書いてあるのか理解できない部分もあります。
お願いすることばかりで恐縮です。

よろしくおねがいします。

【70508】Re:該当するセルにオートシェイプで丸印...
発言  kanabun  - 11/11/22(火) 11:20 -

引用なし
パスワード
   ▼どぢょりん さん:

>実行してみましたが、エラーがでてしまします。
>
>   .CurrentRegion.Offset(10).Copy .Cells
>
>この部分で、「オブジェクトが必要です」と出ています。
>よろしければ、対応を教えてください。

>  '印刷が終わったら WS2のデータを上方向シフト
>  With WS2.Range("A1")
>    .CurrentRegion.Offset(10).Copy .Cells
>  End With
の部分は
WS2 のデータが(たとえばですが)
当初、以下のようだったとき、
[Sheet2]
   A   B    C    D   E   F
1  1 11111-11  商品A  10,000  5  A社
2  2 22222-22  商品B  20,000  3  B社
3  3 33333-33  商品C  30,000  2  C社
4  4 2323-444  商品C 190,000 11  C社・D社
5  5 44444-44  商品D  50,000  8  C社・D社
6  6 2323-555  商品D 210,000 12  D社
7  7 5555-666  商品E  70,000  6  E社
8  8 3434-900  商品F  90,000  7  F社
9  9 2345-987  商品G 110,000  8  G社
10 10 1233-987  商品X 130,000  9  A社
11 11 2323-777  商品Y 150,000 10  B社
12 12 3434-999  商品Z 170,000 11  C社

Sheet3には このSheet2の「1行目〜10行目を参照する式」がセットして
ありますので、プログラムを実行してSheet3の該当する仕入れ先リストの
範囲の該当する仕入れ先に○を描画して印刷する
という処理をしたあとの「Sheet2のつぎの範囲を1行目にもってくる」
処理の部分です。
>  With WS2.Range("A1")
>    .CurrentRegion.Offset(10).Copy .Cells
>  End With
この部分は上の実例範囲に即して書くと
WS2.Range("A1").CurrentRegion が → [A1:F12]の範囲のこと【12行あります】
よって、この範囲を下方へ10行Offsetした [A1:F12].Offset(10) とは
   → [A11:F22]の範囲のことです。ここも【12行あります】
この範囲を WS2.Range("A1").Cells つまり[A1]セルにコピーしています。

首尾よくいけば、上の例ですと Sheet2は

[Sheet2]
   A   B    C    D   E   F
1  11 2323-777  商品Y 150,000 10  B社
2  12 3434-999  商品Z 170,000 11  C社
3
4
5
6
7
8
9
10
11
12
:
:
------------------------
となるはずです。
元の11行目から【12行分】1行目にコピーしたのですから、
コピーした時点で、元の11〜12行目のデータは空白で上書きされ、無くなります。

それが、そうならなくて「オブジェクトが必要です」のエラーになる
というのですが、こちらではそういうエラーにはならないので、原因が
掴めません。

確認
第1回目の印刷までは 実行できるんですよね?

【70514】Re:該当するセルにオートシェイプで丸印...
お礼  どぢょりん  - 11/11/23(水) 8:27 -

引用なし
パスワード
   ありがとうございます。

再度やってみましたら、今回は普通に処理ができました。
ご迷惑をおかけしました。

もしよろしければ、お時間のあるときでいいので、下記の部分の解説をお願いできませんか?
お恥ずかしい限りですが、"C"や"F"が何を指しているのか、ぜんぜん分かりませんでした。

Do Until IsEmpty(WS2.Range("B1").Value)
     .DrawingObjects.Delete
     For y = 1 To 20 Step 2
       If Len(.Cells(y, "C").Text) = 0 Then Exit For
       
       ss = WS2.Cells((y + 1) \ 2, "F").Value 'Sheet2仕入先文字列
       Set r = .Cells(y, "F").Resize(2, 2)
       For Each c In r
         s1 = c.Value
         If InStr(ss, s1) Then
           drawCircle c
           ss = Replace(ss, s1, "")
           If Len(ss) = 0 Then Exit For
         End If
       Next
       If Len(ss) > 0 Then
        If Len(Replace(ss, "・", "", Compare:=vbTextCompare)) > 0 Then
          drawCircle r.Item(r.Count)
        End If
       End If

【70521】Re:該当するセルにオートシェイプで丸印...
発言  kanabun  - 11/11/23(水) 17:23 -

引用なし
パスワード
   ▼どぢょりん さん:

>再度やってみましたら、今回は普通に処理ができました。
>ご迷惑をおかけしました。

あれ?
できちゃったんですか?
とすると、原因は何だったんでしょうねェ


>もしよろしければ、お時間のあるときでいいので、下記の部分の解説をお願いできませんか?
>お恥ずかしい限りですが、"C"や"F"が何を指しているのか、ぜんぜん分かりませんでした。
>

■Cells(行Index, 列Index)
のことですけど、ほんとうはこれ Cells.Item(行, 列) のことなんです。
「Cells」というのはすべてのセルの集合のことで、
「.Item(行, 列)」というのが、その集合の中の単一要素を指定するしかたで、
セルの集合だから、行位置と列位置の2次元座標でセル位置を指定しています。
このとき
  Cells.Item(1,3)
とすると [C1]セルのことですが、この 列番号3 の代わりに 列名"C" を使って、
  Cells.Item(1, "C")
とも表せますよ、ってことです。集合のなかの要素を指定するための Itemプロ
パティは 省略することができるので、
  Cells.Item(1,3) は Cells(1,3) と表すことが多いです(マクロ記録でも)
同様に
  Cells.Item(1, "C") は Cells(1, "C") と表すことが多いです。

〔参考〕
Worksheets(1) を Worksheets("Sheet1") と名前を使って表してもいいです。
これも同じことで、「Worksheets」というワークシートのコレクション(集合)
のなかの「第1番目の」シートと指定するときは番号を使い Worksheets(1)
とするけれど、「Sheet1」という名前の特定のシートというときは そのシート
の名前を使って Worksheets("Sheet1") と表すことができるのも、同じ理由
からです。
Worksheets(1) は ほんとは Worksheets.Item(1) という意味なんです。
Worksheets("Sheet1") は ほんとは Worksheets.Item("Sheet1") なんです。


>Do Until IsEmpty(WS2.Range("B1").Value)
>     .DrawingObjects.Delete

      Sheet3を 1行おきに調べていきます(2行づつ結合されているので)
>     For y = 1 To 20 Step 2
        もしy行目の C列に文字が書き込まれてなければ、処理終了です
>       If Len(.Cells(y, "C").Text) = 0 Then Exit For
>       
        Sheet2の"F"列にある「仕入先」文字列を取得します
        Sheet2の何行目を見ればいいかは、
         (y + 1) \ 2 すなわち、Sheet3の現在行+1した値を2で
         割った答えが Sheet2の行番号 という関係より計算します。
>       ss = WS2.Cells((y + 1) \ 2, "F").Value 'Sheet2仕入先文字列
        ss には、たとえば「C社・D社」というSheet2の文字列が代入されます。

        Sheet3の仕入れ先リスト範囲を変数r にセットします。
        y行目の"F"列から始まる2×2 の範囲です。
>       Set r = .Cells(y, "F").Resize(2, 2)
        この4つのセルを順に調べます
>       For Each c In r
>         s1 = c.Value
          s1 最初は「A社」次が「B社」その次のセルが「C社」です
          ↓ssのなかに s1があるか調べます。
>         If InStr(ss, s1) Then
          ↑ ss「C社・D社」のなかに s1「C社」は含まれていますので
            ↓このセルを○で囲みます
>           drawCircle c
            そして元のss文字列「C社・D社」から見つかった「C社」
            部分を抜き取ります → ss「・D社」 にします。
>           ss = Replace(ss, s1, "")
>           If Len(ss) = 0 Then Exit For
>         End If
>       Next
        4つの「仕入先候補」セルの巡回が終わって、ssにまだ文字列が
        残っていれば「その他」のセルに○を描きます。
>       If Len(ss) > 0 Then
         ただし「・」はすべて見つかっても残っていますので、
         ここで「・」も除いて、まだ見つからなかった仕入れ先が
         あったか、調べなくてはなりません。それを以下でやってます。
          Compare:=vbTextCompare) というオプションは 全角半角を
         問わずすべての「・」を削除という意味です。
>        If Len(Replace(ss, "・", "", Compare:=vbTextCompare)) > 0 Then
>          drawCircle r.Item(r.Count)
>        End If
>       End If

【70524】Re:該当するセルにオートシェイプで丸印...
お礼  どぢょりん  - 11/11/24(木) 22:14 -

引用なし
パスワード
   どうもありがとうございました。

参考になりました。

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