アプリ版:「スタンプのみでお礼する」機能のリリースについて

VBA勉強中のものですが、中々難しくて苦戦中です
下記はこの前に教えて頂いたコードですが、左上から右下に処理をしていますが、
これを、勉強の為に右下から左上に処理をしていくコードを考えてますが、何処を変えればいいのか色々試してますが、出来ません、皆さんはどの様に導き出しているのでしょうか?
教えていただけると幸いです。

https://gyazo.com/79969aefce4a4d2c02a2b85dadc12674

Option Explicit

Dim sh1 As Worksheet 'バラシシート
Dim sh2 As Worksheet '短冊シート
Public Sub 短冊シート設定3()
Dim maxrow1 As Long
Dim maxrow2 As Long
Dim max_box As Long
Dim i As Long
Dim wrow As Long
Dim boxNo As Long
Dim seqNo As Long
Dim box_row As Long
Dim box_col As Long
Dim pv As String
Dim y As Long
Set sh1 = Worksheets("バラシ")
Set sh2 = Worksheets("短冊")
maxrow1 = sh1.Cells(Rows.count, "S").End(xlUp).row 'S列の最大行取得
If maxrow1 < 2 Then Exit Sub
maxrow2 = sh2.Cells(Rows.count, "A").End(xlUp).row 'A列の最大行取得
If (maxrow2 + 1) Mod 7 <> 0 Then
MsgBox ("マス番号の行が不正")
Exit Sub
End If
max_box = ((maxrow2 + 1) \ 7) * 3
'短冊シートのマスをクリア
For i = 1 To max_box
Call clear_box(i)
Next
'バラシシートを処理
boxNo = 1
seqNo = 0
pv = ""
For wrow = 2 To maxrow1
If sh1.Cells(wrow, "S").Value = "" Then
If seqNo > 0 Then
boxNo = boxNo + 2
seqNo = 0
pv = ""
End If
Else
seqNo = seqNo + 1
If (seqNo Mod 4) <> 1 And pv <> sh1.Cells(wrow, "S").Value Then
y = (seqNo - 1) \ 4
seqNo = (y + 1) * 4 + 1
End If
If seqNo > 24 Then
boxNo = boxNo + 1
seqNo = 1
End If
'マス番号とマス内番号に対応する位置を取得
Call get_pos_in_box(boxNo, seqNo, box_row, box_col)
'該当位置へS列データを設定
sh2.Cells(box_row, box_col).Value = sh1.Cells(wrow, "S").Value
sh2.Cells(box_row, box_col).Interior.Color = sh1.Cells(wrow, "S").Interior.Color
pv = sh1.Cells(wrow, "S").Value
End If
Next
MsgBox ("完了")
End Sub

'指定マスクリア
Private Sub clear_box(ByVal box_no As Long)
Dim box_row As Long
Dim box_col As Long
Dim i As Long
For i = 1 To 24
Call get_pos_in_box(box_no, i, box_row, box_col)
sh2.Cells(box_row, box_col).ClearContents
sh2.Cells(box_row, box_col).Interior.Pattern = xlNone
Next
End Sub
'指定マス内の指定位置取得
Private Sub get_pos_in_box(ByVal box_no As Long, ByVal seq_no As Long, ByRef box_row As Long, ByRef box_col As Long)
Dim x1 As Long
Dim x2 As Long
Dim y1 As Long
Dim y2 As Long
y1 = (box_no - 1) \ 3       ←数字はどうやって導き出しているのでしょうか?
y2 = (seq_no - 1) \ 4        ←
box_row = y1 * 7 + 1 + y2     ←
x1 = (box_no - 1) Mod 3        ←
x2 = (seq_no - 1) Mod 4       ←
box_col = x1 * 5 + 2 + x2      ←
End Sub

A 回答 (6件)

右下から左上に処理をしていくコードです。


現行では枠番号、枠内番号とy1,y2,x1,x2の関係は以下のようになっています。

枠番号 1,2,3 => y1=0
枠番号 4,5,6 => y1=1
枠番号 7,8,9 => y1=2

枠内番号 1~4 => y2=0
枠内番号 5~8 => y2=1
枠内番号 9~12 => y2=2
枠内番号 13~16=> y2=3
枠内番号 17~20=> y2=4
枠内番号 21~24=> y2=5

枠番号 1,4,7 => x1=0
枠番号 2,5,8 => x1=1
枠番号 3,6,9 => x1=2

枠内番号 1,5,9,13,17,21 => x2=0
枠内番号 2,6,10,14,18,22 => x2=1
枠内番号 3,7,11,15,19,23 => x2=2
枠内番号 4,8,12,16,20,24 => x2=3
------------------------------------------------------
これを以下のように変えれば良いわけです。
枠番号の影響はないため、枠内番号のみ考慮します。
枠内番号 1~4 => y2=5
枠内番号 5~8 => y2=4
枠内番号 9~12 => y2=3
枠内番号 13~16=> y2=2
枠内番号 17~20=> y2=1
枠内番号 21~24=> y2=0

枠内番号 1,5,9,13,17,21 => x2=0
枠内番号 2,6,10,14,18,22 => x2=1
枠内番号 3,7,11,15,19,23 => x2=2
枠内番号 4,8,12,16,20,24 => x2=3

そうすると以下のようにすれば良いわけです。
y2 = 5-以前のy2の値
  = 5-((枠内番号-1)÷4の商)

x2 = 3-以前のx2の値
  = 3-((枠内番号-1)÷4の余り)

上記のように修正したマクロを下記にアップしました。
https://ideone.com/6Xbqqn
    • good
    • 0
この回答へのお礼

ありがとうございます。
手間も時間もかかったと思いますが、親切丁寧に解説していただきまして、ありがとうございます。非常に勉強になりました。
本を見たりネットを見たりで独学で勉強していますので、中々仕事で使うようなコードないので質問ばかりになります、分からない所で壁にぶつかりますが、頑張って勉強します。また、質問等あげることがあると思いますが、見かけたら宜しくお願い致します。

お礼日時:2022/05/04 16:00

インデントって、



sub abc()
  msgbox "うっ!"
  if 1 = 1 then
    msgbox "きゃっ!!"
  end if
end sub

乱れないのでは?
VBE画面からそのままコピペするから乱れるんじゃないかな?
    • good
    • 0
この回答へのお礼

ありがとうございます。

お礼日時:2022/05/04 16:00

まず、現行のx1,x2,y1,y2の変数の意味から説明します。


下記URLを参照ください。
https://gyazo.com/a6655139a3dfeda93defb0dfb711f076

枠番号は、1から始まり、左から右へ、上から下へ、順番に振る。(1~N)
枠内番号は、1から始まり、左から右へ、上から下へ、順番に振る。(1~24)

y1は、枠番号(box_no)が指定されたとき、枠の縦の順番です。(y1=0~n)
y2は、枠内番号(seq_no)が指定されたとき、枠内の縦の順番です。(y2=0~5)

x1は、枠番号(box_no)が指定されたとき、枠の横の順番です。(x1=0~2)
x2は、枠内番号(seq_no)が指定されたとき、枠内の横の順番です。(x2=0~3)

上記の変数は0始まりであることに注意してください。(その方が後で計算しやすいためです)

上記を導くための計算式です。
y1 = (枠番号- 1)÷3の商
y2 = (枠内番号-1)÷4の商

x1 = (枠番号-1)÷3の余り
x2 = (枠内番号-1)÷4の余り


上記の値が判れば、それらから、行番号、列番号は、以下の式で導けます。

行番号=y1×7+1+y2
列番号=x1×5+2+x2

現行のマクロに上記のコメントを付加したものです。
下記にアップしました。(コメント以外は変更ありません)
https://ideone.com/mqG07M

次の回答で、枠内番号を右から左へ、下から上へ変えた場合の処理を記述します。
    • good
    • 0
この回答へのお礼

ありがとうございます。

お礼日時:2022/05/04 16:00

前回回答者です。


>左上から右下に処理をしていますが、
>これを、勉強の為に右下から左上に処理をしていくコードを考えてます
ということですが、これは、マス内で右下から左上に処理をしていくということで良いでしょうか。(マスの処理の順番は変わらない)

マス内の番号は、6行×4列なので、1~24番まで割り振ります。
これを、マクロ内では、seq_noで定義しています。
マスの番号は、マクロ内では、box_no(1~)で定義しています。

上記の前提で、
マス内番号が1~24まで変化するとき、
マス内で右下から左上に処理をするということは、
新マス内番号が1の時、元のマス内番号=24の位置
新マス内番号が2の時、元のマス内番号=23の位置
・・
新マス内番号が24の時、元のマス内番号=1の位置
に対応することになります。
つまり、
元のマス内番号=25ー新マス内番号
なります。

従って、Private Sub get_pos_in_box
を呼び出すときに、新マス内番号を元のマス内番号に変換し、
呼び出せばよいことになります。

最小限の改造で済ませるために、
get_pos_in_boxをget_pos_in_box_org
に名称を変更し、
新たに、
Private Sub get_pos_in_boxを作成し、
その関数内で、
元のマス内番号を算出し、その後get_pos_in_box_org
を呼び出すようにします。

そのように修正したマクロが下記URLにアップしてあります。
https://ideone.com/4PQh18
(このサイトにアップするとインデントが乱れるのでideoneにアップしています。
ここのサイトの質問者の多くは、とにかくきちんと動作すればよいのでマクロの中身を勉強する気はないという方が多いので、インデントが乱れますが、通常はこのサイトにマクロをアップしています。)

あなたは、マクロについても勉強したいというスタンスでしたので、インデントもきちんとした形で提示しました。

上記の改造で実現はできますが、本当になさりたいことは、
Private Sub get_pos_in_boxをどのように改造すれば良いかを
知りたいということかと思いますので、
次の回答で、その方法を提示します。
    • good
    • 0
この回答へのお礼

ありがとうございます。

お礼日時:2022/05/04 16:00

正直人の作成したコードの解析は不可解な時もあります。


なのでこのコードをどうにかってなら、本来先の質問時にキチンと解説を付けてもらうようお願いしておくべきでは?と思います。

そのうち回答された方が見かければ解説が入ると思います。

>←数字はどうやって導き出しているのでしょうか?

これって逆なのでは?
質問者さんが望んだ結果を出すためには、そう計算するしかないだけだと感じますよ。
今の人は使わないのか不明ですけど、方眼紙に書いてみて移動させる際の計算式(座標などを書いてその変化を変数化させる)を求めるって中学位には良くやらされました。
それをコード化しているだけです。
プログラム覚えたての頃は良く方眼紙使ってました。(Basic時代)

詳細についてはコードではよくわかりませんが、画像?があるらしきリンク先は運営サイドで『不適切』と判断されているようですので見てません。
    • good
    • 0
この回答へのお礼

ありがとうございます。

お礼日時:2022/05/04 16:00

まずは、プログラムの構造を紐解いてください。


プログラムは、外側から内側へ読みます。

このプログラムの場合、以下のような構造になっています。
Subプロシージャ → Forループ → If文 → それぞれの処理

外側でざっくりどんな処理をしているか捉え、1つずつ内側の処理を読んでいきます。
字下げ(インデント)を正しく行うと、理解の助けになります。

構造を理解したら、プログラムの改造をしてみてください。
    • good
    • 3
この回答へのお礼

ありがとうございます。

お礼日時:2022/05/04 16:00

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!