質問: union(myrng, cells(1, j)) end if end if next j if not myrng is nothing then myrng.entirecolumn.delete end if end sub
回答: ・1行目に「交流電力量」が含まれない列を削除 ・1行目にデータが全く存在しない場合は問答無用で1列目を削除 という動作をします。 ◆sub sample1() プログラムの動作は基本的に、「sub ~()」の直後の行から(if文、for文などといった特殊な指示がない限り)必ず1行ずつ上から下に進行し、「end sub」に到達すると終了します。 ◆dim j as long, myrng as range この行は省略形になっています。本来の書き方だと dim j as long dim myrng as range のように2行になります。 これは宣言です。「j」という名前の long 型の変数と、「myrng」という名前の range 型の変数を宣言します。 「j」と「myrng」というのは、このプログラムの作者が勝手に作った言葉で、vba にもともと存在しない言葉です。だから、始めに「long 型の変数を新規作成して、これのことを今後は j と呼びます」という「宣言」をしているわけです。「myrng」も同様です。 dim <変数名> as <データ型など> この構文が基本です。 <データ型など>には、扱う値が整数であれば long、小数点以下のけたがある数であれば double、文字列であれば string と書きます。 long を指定して宣言された変数は、「整数を入れて保管する箱」のように機能します。range を指定して宣言された変数はちょっと特殊で、「特定のセル範囲を指し示す矢印」のように機能します。 ◆for j = 1 to cells(1, columns.count).end(xltoleft).column これは、いわゆる「for文」という構文です。「for ~」と書かれた行から「next」と書かれた行までの間の処理を複数回繰り返すということを意味します。 for <変数> = <最初の数> to <最後の数> となっています。<変数>に<最初の数>から<最後の数>までの数を1回ずつ入れ直しながら処理していきます。 for j = 1 to 10 <処理a> next こう書けば、<処理a>を10回実行します。 1回目は j = 1 (j に 1 が入っている)という状態で<処理a>を実行します。 2回目は j = 2 (j に 2 が入っている)という状態で<処理a>を実行します。 3回目は...... 以下同様 これを10回目までやって、ようやくnext の下の行に処理が進行します。 cells(1, columns.count).end(xltoleft).column は、1行目だけに注目して、1行目の「データが存在するセル」のうち最も右にあるセルが何列目であるかという数のことです。 cells(<行番号>, <列番号>) で特定のセルを指定します。columns.count の値は16384で、これはシートのすべての列の数であり、16384列目より右にセルは存在しません。なので cells(1, columns.count) は、1行16384列目(1行xfd列)のセルのことです。 .end(xltoleft) は、1行16384列目のセルを選択した状態で ctrl + ← キーを押したときに移動する先のセルを示します。excel は、シート内で ctrl + 方向キー を押すと、その方向に走査して値の有無が切り替わる地点に瞬間移動する機能があります。それのイメージです。 .column は、1行16384列目のセルを選択した状態で ctrl + ← キーを押したときに移動する先のセルの、「列番号」、つまり「そのセルが何列目か」を意味します。だから、シート内のデータが添付画像のようになっていたとしたら、 cells(1, columns.count).end(xltoleft).column は 4 です。さらに言えば、for j = 1 to 4 となり、この場合 j に入れる数を 1 から 4 まで切り替えながら処理を繰り返すことになります。 ◆'columns = 列 ◆'for j = i to cells ループ処理 「'」で始まる行は「コメント」といいます。 コメントはプログラムの実行時は完全に無視されるので、動作に何の影響も与えません。 コメントは、プログラムを書いたり読んだりする人が残していったメモ(覚え書き、備忘録)みたいなものとして機能します。今は実行したくないが削除もしたくないコードもコメントにされます。 ◆if not cells(1, j) like "*交流電力量*" then ここはこのプログラムの心臓部になります。 「if文」という構文です。 もし、<条件>が成立する(真実である)としたら、「if <条件> then」から「end if」の間の処理を実行します。 (ここでは「条件」と書きますが、厳密には「命題」です。) <条件>が成立しなかったら(嘘であったら)、「if <条件> then」から「end if」の間の処理を実行しません。このプログラムだと、「end if」の直後に「next」があるので for文の「繰り返し」によってまたif not cells(1, j) like "*交流電力量*" then に戻って来ます。 「if <条件> then」が基本形ですが、ここでは 「if not <条件> then」というアレンジ形になっています。not を付けると、<条件> が成立しなかったときに「end if」までの処理を実行する、というように基本形とは逆の動作をします。 cells(1, j) like "*交流電力量*" は、『1行j列目のセルに「交流電力量」という文字列が含まれている』という条件です。for文の効果でjの数が 1 ~ 最終列番号 まで切り替わりながら繰り返しこの条件を確認することになります。 添付画像の状況なら、j = 1 のとき、1行1(a)列目のセルは空白なので「交流電力量」を含みませんから、条件が成立せず、if文に「not」があるので「end if」までの処理を実行することになります。 j = 2 のときは、条件成立、「end if」までの処理を実行しません。 j = 3 のときは「電力量」がないので不成立、実行します。 j = 4 のときは、余計な文字が前後にくっついていても「交流電力量」を含むことに変わりないので条件成立、処理を実行しません。 ◆if myrng is nothing then またif文です。 if~then end if の中にさらに if~then else end if が入っています。 if~then <処理a> else <処理b> end if は、条件が成立すれば<処理a>のみを、成立しなければ<処理b>のみを実行するように動作します。 <変数など> is nothing という条件は、その<変数など>が「何も指し示していない」ことを意味します。 先述のとおり、「myrng」は「特定のセル範囲を指し示す矢印」のように機能します。 myrng is nothing は、「myrng という変数が何も指し示していない」という意味です。 range 型の変数は宣言時にもともとどこかのセルを指し示しているわけではありません。なので初めて if myrng is nothing then に来たときはまだ myrng をいじっていないので、myrng はまだ何も指し示していません。なので初回ではこの条件は必ず成立します。 ◆set myrng = cells(1, j) ◆set myrng = union(myrng, cells(1, j)) set <変数名> = <セル> この構文は、<変数名>という名前の変数にその<セル>を指し示させることができます。 set myrng = cells(1, j) の実行後は、myrng は1行j列目のセルを指し示すようになります。 よって、if myrng is nothing then の条件は1回成立すると2度と成立しません。 なので初回のみ set myrng = cells(1, j) を実行し、次からは set myrng = union(myrng, cells(1, j)) を実行します。 union(<セル>、<セル>) は、2つのセル範囲を合体させた範囲を指定できます。手作業で例えるなら、ctrl キーを押しながら複数のセルをクリックしていき、複数のセル範囲を「同時に」選択するようなものです。 set myrng = union(myrng, cells(1, j)) を実行するごとに、myrng は新たなセル「cells(1, j)」を、これまで指し示してきたセルと同時に指し示すようになります。 ◆if not myrng is nothing then 以降 myrng.entirecolumn で「myrng が指し示しているセル」が所属する列をすべて指定し、 .delete で指定した対象を削除します。何も削除対象を指定せずに.delete を実行するとエラーになります。 if not myrng is nothing then はエラーを防ぐために必要です。 myrng が何も指し示していないときは.delete を実行させてはいけませんから。