データの過不足を確認するマクロを作成してみました。(毎年使うので、フィルタや関数ではなくマクロを作っておきたい)
10行×30列で動作確認したんですが、10000行×A~JQ列までの大量データでは時間がかかってしまい強制終了、一度も作業が完了していません。
ちなみに1行目にはスペースの列もあり、同列の作業を行わないようにするやりかたも教えていただければ…
Sub 過不足チェック()
'定義
Dim ws As Worksheet
Dim cell As Range
Dim lastRow As Integer
Dim lastCol As Integer
' シート名は適宜変更
Set ws = ThisWorkbook.Sheets("Sheet1")
' 塗りつぶしのクリア
ws.Cells.Interior.ColorIndex = xlNone
' 範囲指定(最終行、列まで)
lastRow = ws.Cells(Rows.Count, 1).End(xlUp).Row '1列目の最終行をカウント
lastCol = ws.Cells(2, Columns.Count).End(xlToLeft).Column '2行目の最終列をカウント
For Each cell In ws.Range(Cells(3, 3), Cells(lastRow, rng))
'未検査項目チェック(必須項目漏れに黄色を設定)
' A列(年齢)<30 かつ 1行目(年代別検査項目)=20 または
' A列(年齢)>=30 <40 かつ 1行目(年代別検査項目)<=30 または
' A列(年齢)>=40 <50 かつ 1行目(年代別検査項目)<=40 または
' A列(年齢)>=50 かつ 1行目(年代別検査項目)<=50 または
' B列(性別)女 かつ A列(年齢)偶数 かつ 1行目(年代別検査項目)=1(子宮がん) または
' B列(性別)女 かつ A列(年齢)>=40 & 偶数 かつ 1行目(年代別検査項目)=2(マンモ) のセルが
'空白以外なら…
If (ws.Cells(cell.Row, "A").Value < 30 And ws.Cells(1, cell.Column).Value = 20) Or _
(ws.Cells(cell.Row, "A").Value >= 30 And ws.Cells(cell.Row, "A").Value < 40 And ws.Cells(1, cell.Column).Value <= 30) Or _
(ws.Cells(cell.Row, "A").Value >= 40 And ws.Cells(cell.Row, "A").Value < 50 And ws.Cells(1, cell.Column).Value <= 40) Or _
(ws.Cells(cell.Row, "A").Value >= 50 And ws.Cells(1, cell.Column).Value <= 50) Or _
(ws.Cells(cell.Row, "B").Value = "女" And ws.Cells(cell.Row, "A").Value Mod 2 = 0 And ws.Cells(1, cell.Column).Value = "子宮がん") Or _
(ws.Cells(cell.Row, "B").Value = "女" And (ws.Cells(cell.Row, "A").Value >= 40 Or ws.Cells(cell.Row, "A").Value Mod 2 = 0) And ws.Cells(1, cell.Column).Value = "乳がん") Then
If cell.Value = "" Then
' 黄色を設定
cell.Interior.ColorIndex = 36
End If
End If
'追加項目チェック(必須項目以外+データありにピンクを設定)
' A列(年齢)<30 かつ 1行目(年代別検査項目)>=30 または
' A列(年齢)>=30 <40 かつ 1行目(年代別検査項目)>=40 または
' A列(年齢)>=40 <50 かつ 1行目(年代別検査項目)=50 または
' B列(性別)女 かつ A列(年齢)奇数 かつ 1行目(年代別検査項目)子宮がん または
' B列(性別)女 かつ A列(年齢)<40 or 奇数 かつ 1行目(年代別検査項目)乳がん のセルが
'空白以外なら…
If (ws.Cells(cell.Row, "A").Value < 30 And ws.Cells(1, cell.Column).Value >= 30 And ws.Cells(1, cell.Column).Value <= 50) Or _
(ws.Cells(cell.Row, "A").Value >= 30 And ws.Cells(cell.Row, "A").Value < 40 And ws.Cells(1, cell.Column).Value >= 40 And ws.Cells(1, cell.Column).Value <= 50) Or _
(ws.Cells(cell.Row, "A").Value >= 40 And ws.Cells(cell.Row, "A").Value < 50 And ws.Cells(1, cell.Column).Value = 50) Or _
(ws.Cells(cell.Row, "B").Value = "女" And ws.Cells(cell.Row, "A").Value Mod 2 = 1 And ws.Cells(1, cell.Column).Value = "子宮がん") Or _
(ws.Cells(cell.Row, "B").Value = "女" And (ws.Cells(cell.Row, "A").Value < 40 Or ws.Cells(cell.Row, "A").Value Mod 2 = 1) And ws.Cells(1, cell.Column).Value = "乳がん") Then
If cell.Value <> "" Then
' ピンクを設定
cell.Interior.ColorIndex = 22
End If
End If
Next cell
End Sub
No.7ベストアンサー
- 回答日時:
No6です。
乳がん検診の判定方法に誤りがありましたので、訂正します。(仕様の勘違いです)
変更前の仕様
セルが空白の場合
年齢が40以上でかつ偶数で女の場合、検査項目が乳がんなら、網掛けする。
セルが空白でない場合
年齢が40未満でかつ奇数で女の場合、検査項目が乳がんなら、網掛けする。
変更後の仕様
セルが空白の場合
年齢が偶数で女の場合、検査項目が乳がんなら、網掛けする。
又は、年齢が40以上で女の場合、検査項目が乳がんなら、網掛けする。
セルが空白でない場合
年齢が奇数で女の場合、検査項目が乳がんなら、網掛けする。
又は、年齢が40未満で女の場合、検査項目が乳がんなら、網掛けする。
上記の変更のため、以下のように変換値1,3,4の設定方法を変えています。
①1行目の年代別検査項目は、事前に以下の値に変換しておき、変換後の値を参照することにより高速化を行う。
空白→""
20 →1
30 →2
40 →3
50 →4
子宮がん→16
乳がん →32
上記以外はエラー終了する。変換後の値は変換値1へ格納しておく。
③セルが空白の場合のがん検診用の年齢及び性別は以下の形に変換する。
年齢が偶数かつ女の場合→16+32
年齢が40以上でかつ女の場合→32をorする。
上記以外 →0
変換後の値は変換値3へ格納しておく。
③セルが空白でない場合のがん検診用の年齢及び性別は以下の形に変換する。
年齢が奇数かつ女の場合→16+32
年齢が40未満でかつ女の場合→32をorする。
上記以外 →0
変換後の値は変換値4へ格納しておく。
④セルが空白の場合の判定方法
変換値1が16未満の場合
変換値2<変換値1であること
変換値1が16以上の場合
変換値3 and 変換値1の結果が0より大きいこと
上記条件が成立時、セルに黄の網掛けをする。
⑤セルが空白でない場合の判定方法
変換値1が16未満の場合
変換値2<変換値1であること
変換値1が16以上の場合
変換値4 and 変換値1の結果が0より大きいこと
上記条件が成立時、セルにピンクの網掛けをする。
修正後のソースのURLは下記参照
https://ideone.com/QbnFSF
No.6
- 回答日時:
No5です。
一部誤りがありました。③セルが空白でない場合のがん検診用の年齢及び性別は以下の形に変換する。
40以上で年齢が奇数かつ女の場合→10
40未満で年齢が偶数かつ女の場合→11
上記以外 →0
変換後の値は変換値4へ格納しておく。
の箇所ですが、
40未満で年齢が偶数かつ女の場合→11
は
40未満で年齢が奇数かつ女の場合→11
^^^
の誤りです。訂正します。(マクロは訂正不要です)
No.5
- 回答日時:
No4です。
補足ありがとうございました。
以下の使用でマクロを作成してみました。
1.1列目の最終行を最終行とする。(従来通り)
2.1行目の最終列を最終列とする。(新仕様)
3.セルのチェック範囲は、3行,3列~最終行、最終列とする。(従来通り)
4.高速化のための改造部分
①1行目の年代別検査項目は、事前に以下の値に変換しておき、変換後の値を参照することにより高速化を行う。
空白→""
20 →1
30 →2
40 →3
50 →4
子宮がん→10
乳がん →11
上記以外はエラー終了する。変換後の値は変換値1へ格納しておく。
②年齢は、事前に以下の形に変換する。
30未満 →1
30以上かつ40未満→2
40以上かつ50未満→3
50以上 →3
1~100以外の年齢はエラー終了する。変換後の値は変換値2へ格納しておく。
③セルが空白の場合のがん検診用の年齢及び性別は以下の形に変換する。
40未満で年齢が偶数かつ女の場合→10
40以上で年齢が偶数かつ女の場合→11
上記以外 →0
変換後の値は変換値3へ格納しておく。
③セルが空白でない場合のがん検診用の年齢及び性別は以下の形に変換する。
40以上で年齢が奇数かつ女の場合→10
40未満で年齢が偶数かつ女の場合→11
上記以外 →0
変換後の値は変換値4へ格納しておく。
④セルが空白の場合の判定方法
変換値1が10未満の場合
変換値2<変換値1であること
変換値1が10以上の場合
変換値3>=変換値1であること
上記条件が成立時、セルに黄の網掛けをする。
⑤セルが空白でない場合の判定方法
変換値1が10未満の場合
変換値2<変換値1であること
変換値1が10以上の場合
変換値4>=変換値1であること
上記条件が成立時、セルにピンクの網掛けをする。
5.網掛け時の転記
網掛けを行った行は、別シート(Sheet2)へ転記する。
6.処理時間について
1万行でJQ列までのデータで、約2分かかりました。
最初はまず、少ない行で、動作確認を行ってください。
ソースのURLは下記参照
https://ideone.com/skeYhn
No.4
- 回答日時:
補足要求です。
1.Rngについて
For Each cell In ws.Range(Cells(3, 3), Cells(lastrow, Rng))とありますが、
Rngは未定義です。
For Each cell In ws.Range(Cells(3, 3), Cells(lastrow, lastcol))
が正しいと思いますがいかがでしょうか。
2.最終列の判定は、2行目の最終列を求めていますが、通常は1行目の最終列を求めるかと思います。
2行目にした理由がなにかあるのでしょうか。参考までに教えていただけると嬉しいです。
3.1行目の3列~最終列は、年代別検査項目が定義されますが、その内訳は以下の内容であってますか。
①空白
②数字の場合 20 30 40 50 の何れか
③文字の場合 子宮がん 乳がん の何れか
特に、数字の場合、上記以外の数字が記入されることもありますか。
(例 10 19 21 29 31 51 60 等)
4.A列の年齢欄ですが、年齢が空白の行も存在しますか。(データのない行)
No.3
- 回答日時:
コードを読み切れていません、
for eachでセルをひとつずつ持ってきて、その上で、それを含む行の"A"列の値で・・・
次に、その右にあるセルをチェックする時、同じ処理をしているような気がします。つまり、同じ処理を何度も何度も繰り返しているような気がします。
兎に角、処理スピードを上げるのであれば、.currentregionで全エリアを選択して,variant変数にいれて、メモリ上の配列とし、以降このメモリ上の配列に対して判定処理をすべきと思います。
dim myData as variatnt
myData=Sheets("Sheet1").cells(1,1).CurrentRegion
lastRow = ubound(myData,1)
lastCol = ubound(myData,2)
for i=2 to lastRow
for j=1 to lastCol
if ...
end if
next
next
判定結果は別のメモリ上の配列(サイズはmyDataと同じ、myResultとか名前を付けて)に0とか1とかを入れるようにしておき、全ての処理が終わった段階で、現実のデータシートとmyResultを比較して
データシートの色塗りをすればよいかと思います。
尚、空白の行、空白の列があると、CurrentRegionで、正しくエリアをもってこれませんので、注意願います。
判定基準がテーブルで与えられているなら、choose関数でテーブルを構成するという手もあるかと思います。
参考にして頂ければ幸いです。
No.2
- 回答日時:
No1です。
連投すみません。判定方法に関して書き忘れましたので。
データの範囲や取りうる値の可能性が不明なので、ご提示に無い値などをどう扱うかがわかりませんけれど・・
例えば、
前半の年代と年代別検査項目の関係のチェックで言えば、
period = =MAX(MIN(INT(年齢/10),5),2)*10
を計算すると、20~50代はその年代が、10代以下は20、60代以上は50の値が返ります。
このような判断でも良いのなら、
年代別検査項目 <= period
のように1つの計算式で全部のデータを判定できるようになり、場合分けも不要になるので、計算量を大幅に減ずることができます。
上記はあくまでも例示ですが、判定内容を整理して、方法を工夫することでもコードを単純化でき、計算量を減らすことは可能そうに思われます。
(一般化した場合の概念がわかりやすいかどうかは、微妙ですけれど・・)
No.1
- 回答日時:
こんにちは
>10行×30列で動作確認したんですが、~
ご提示のコードで、動作確認できるとは思えません。
>For Each cell In ws.Range(Cells(3, 3), Cells(lastRow, rng))
の変数rngが未定義なので、範囲が定まらないはずです。
ついでながら・・
>lastCol = ws.Cells(2, Columns.Count).End(xlToLeft).Column
変数lastColはその後で使っていないようですが、検査項目用の値をカウントしているのなら、1行目の最終列を求めるべきなのでは?
(何をしたいのか不明なので、よくわかりませんが・・)
後のチェックで参照しているのは、1行目で2行目を参照しているものはなさそうですが・・??
判定内容がかなり煩雑ですが、二つのブロックで同じ判断(=年代分け)を繰り返しているので、先に「年代・性別」での分岐を行って、その上で各判断を行う方が効率的なように思われます。
また、年代判定を○○~◇◇のような方法で行っていますけれど・・
(毎回、全ての両端を判断している)
例えば、年齢の低い順なら
If age < 30 Then
' 20代用の判定(まとめて判定)
Else If age < 40 Then
' 30代用の判定(まとめて判定)
Else If age < 50 Then
' 40代用の判定(まとめて判定)
Else
' 50代用の判定(まとめて判定)
End If
のようなロジックにすることで、視認性があがると共に判定の回数も大幅に減ずることが可能になります。
なお、ご提示の処理手順だと、同じ行の各セルに対して、何度も年代分けの判定を行っていることになりますが、1行単位のデータだと思いますので、行単位で処理する方法に変えれば、年代の判定は1回/1行で済ませることができます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
-
初めて自分の家と他人の家が違う、と意識した時
子供の頃、友達の家に行くと「なんか自分の家と匂いが違うな?」って思いませんでしたか?
-
フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
あなたが普段思っている「これまだ誰も言ってなかったけど共感されるだろうな」というあるあるを教えてください
-
映画のエンドロール観る派?観ない派?
映画が終わった後、すぐに席を立って帰る方もちらほら見かけます。皆さんはエンドロールの最後まで観ていきますか?
-
海外旅行から帰ってきたら、まず何を食べる?
帰国して1番食べたくなるもの、食べたくなるだろうなと思うもの、皆さんはありますか?
-
天使と悪魔選手権
悪魔がこんなささやきをしていたら、天使のあなたはなんと言って止めますか?
-
データチェックを行うエクセルマクロをおしえてほしい
Excel(エクセル)
-
Excelを無料で使うには? パソコン購入して、マイクロソフトに登録して そのままExcelがデスク
Excel(エクセル)
-
Excelについて教えてください
Excel(エクセル)
-
-
4
VBAについての質問です
Excel(エクセル)
-
5
【マクロ】顧客番号にて一致させ、情報を表へ上書きする為には
Excel(エクセル)
-
6
職場の人から聞かれており、こんなことができるか教えて下さい。 vbaとかはできません。。 下記リスト
Excel(エクセル)
-
7
PDFの請求明細をエクセルにしたい
Excel(エクセル)
-
8
下記マクロでMsgBox 空白です。"の部分の メッセージボックスは現れるものの 空白です。の文字"
Excel(エクセル)
-
9
数字入力後他の文字等が表示される方法について
Excel(エクセル)
-
10
VBAコードのインデント表示
Visual Basic(VBA)
-
11
Excelの表示についての質問
Excel(エクセル)
-
12
Excel 対象のセルに入力が無いとセルに入力できないようにしたい
Excel(エクセル)
-
13
Excelの数式の効率化について
Excel(エクセル)
-
14
エクセルの神よ、ご回答を! エクセルのコメント欄について質問2点。
Excel(エクセル)
-
15
Excelで、10000,20000,30000と表示されているのですが、時々10000,20000
Excel(エクセル)
-
16
【関数】スペースがいくつ入った後の文字列を取り出したい
Excel(エクセル)
-
17
時間によってファイル名が変わるエクセルをほかのエクセルでデータを参照する方法
Excel(エクセル)
-
18
関数の説明
Excel(エクセル)
-
19
エクセルで上位バイトのセルと下位バイトのセルを1つのセルにして16進数を作る方法
Excel(エクセル)
-
20
エクセルのクイックアクセスツールバーには何を登録したら良いですか?罫線を引く「格子・枠なし・外枠」と
Excel(エクセル)
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
エクセルで離れた列を選択して...
-
「段」と「行」の違いがよくわ...
-
VLOOKUPの列番号の最大は?
-
LEFT関数とIF関数の組み合わせ...
-
エクセルのソートで、数字より...
-
列方向、行方向の定義
-
Excelの行数、列数を増やしたい...
-
エクセルの行を65536以上に増や...
-
リストからデータを紐付けしたい
-
VBAで結合セルを転記する法を教...
-
VBA 指定した列にある日時デー...
-
EXCEL VBA 文字列から電話番号...
-
エクセルでセル12個間隔で合...
-
【Excel VBA】セルで列番号を指...
-
Excel VBA マクロで複数列が共...
-
アクセス 取り込み時に、桁数(...
-
横軸を日付・時間とするグラフ化
-
Excel 区切り位置指定ウィザー...
-
エクセルマクロ、アウトライン...
-
Accessのレポートで繰り返し表...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
「段」と「行」の違いがよくわ...
-
エクセルで離れた列を選択して...
-
VLOOKUPの列番号の最大は?
-
LEFT関数とIF関数の組み合わせ...
-
Excelの行数、列数を増やしたい...
-
列方向、行方向の定義
-
VBA 指定した列にある日時デー...
-
エクセルマクロPrivate Subを複...
-
Excel文字列一括変換
-
エクセル マクロ 範囲指定で...
-
Alt+Shift+↑を一括で行うには、...
-
CSVファイルの「0落ち」にVBA
-
VBAで結合セルを転記する法を教...
-
エクセルで複数列の検索をマク...
-
リストからデータを紐付けしたい
-
横軸を日付・時間とするグラフ化
-
エクセルで最初の行や列を開け...
-
エクセルのソートで、数字より...
-
エクセルマクロの組み方
-
☆Excel VBAでAVERAGE関数を使う...
おすすめ情報
回答ありがとうございます。
1.Rng→lastcolの誤りです。(コピペ誤りです)
2.1行目の設定で問題ありません。
3.①~③のとおりです。
チェックしたい項目が50項目(列)以上あり、列を指定すると次年度以降、変更する場合マクロを変更するのも大変なので、20~50の別の区分を設けて列毎にチェックしてはどうかと考えた次第です。
4.年齢には空白はありません。
最終的には不足データ、余分データのある個人(網掛けがある行データ)を別シートに出力したいと思っています。参考までに網掛け以外にもいい方法があれば教えていただければ…
回答ありがとうございます。
・Rng→lastcolの誤りです。(コピペ誤りです)
・1行目の設定で問題ありません。
・回答いただいたif、elseifもチャレンジしましたが断念しまして…「20代用の判定」に該当するいいコードはありますか?
(補足)
・チェックしたい項目が50項目(列)以上あり、列を指定すると次年度以降、項目が変更した場合マクロのコードを変更するのも大変なので、別途、1行目に20~50と別の区分を追加して列毎にチェックしてはどうかと考えた次第です。(マクロは変更必要なし)
(例)A列が20代…1行目の値が20の列の値がスペースであれば網掛け(不足)、1行目の値が30~の列の値があれば網掛け(余分)を判定し、最終的にはそれぞれのリストを作成したいと考えています。