X



Excel VBA 質問スレ Part52
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん垢版2018/01/27(土) 20:25:05.67ID:Xe+uGT7T
スレ立ての際は一行目に
!extend:checked:vvvvv:1000:512
と入れてスレ立てして下さい

ExcelのVBAに関する質問スレです
コード書き込みや作成依頼もOK

※関連スレ
VBAなんでも質問スレ Part2
http://mevius.2ch.net/test/read.cgi/tech/1432173164/
Access VBA 質問スレ Part1
http://mevius.2ch.net/test/read.cgi/tech/1328536426/

※前スレ
Excel VBA 質問スレ Part51
http://mevius.2ch.net/test/read.cgi/tech/1510107990/
0053デフォルトの名無しさん垢版2018/01/31(水) 14:08:57.02ID:4YhVePXS
>>52
スコープが広がるごとに許容範囲は狭まるだろ
クラス使うならモジュールレベルの変数は普通に使うつーか、使わんと大したもん作れない
0054デフォルトの名無しさん垢版2018/01/31(水) 15:23:18.93ID:1/FNqCDn
自分は他のソフトを制御するのにVBA使ってるけど、モジュールレベル変数やグローバル変数を使うとインスタンスが残って不具合出ることが多かったから使わないようにしてる。
解放させる手もあるけど、タイミングに気を使うし記述も面倒。そしてなにより不具合発生原因の特定がスコープが広すぎるときつい。
だったらプロシージャ内で終わるの前提で設計する方が楽という結論になった。

あと、公式でプロシージャレベル変数が保持されることに期待するマクロは推奨しないみたいなコメントなかったっけ。
0055デフォルトの名無しさん垢版2018/01/31(水) 17:43:55.07ID:QBWxlyAw
そうそう。
フォームもクラスも使ったプログラミングを始めるとグローバル変数を使わざる負えない場合がある。
下手にENDを使われると同時に開いてるアドインが使い物にならない可能性があるので注意したほうが良いかも
0056デフォルトの名無しさん垢版2018/01/31(水) 17:55:21.63ID:4YhVePXS
>>55
クラスにろフォームにしろそのモジュール内で完結させるのは前提だけどね
標準モジュールでもモジュールレベル変数が有効なことがないこともないがね
完全にパブリックなグローバル変数は可能な限り使わないのが基本だろう
0057デフォルトの名無しさん垢版2018/01/31(水) 19:46:12.53ID:/yXosPjR
今までグローバル変数を使わなければ
ならなかった局面に当たったことがない

どんな時に使わなければならなくなる?
いや、いつも外部とのやり取りは
パブリックなメソッドやプロパティで
やってるんだけど
0058デフォルトの名無しさん垢版2018/01/31(水) 19:50:56.33ID:wkRhZUuX
>>56
ID変わったけど55です。それについては異論はないかな。
ただ>>42のように勘違いする人が出てきそうなので、ENDを使わないのも基本だとして根拠を上げてみた。

例えばアドインでは常駐フォームとかWithEventsでイベントをフックするためのクラスを制御するのにグローバル変数を使わないといけない。
しかもENDを使った瞬間に開いてるフォーム全部消えるんだよね。
せめて同一プロジェクトのみのメモリ解放だと良いんだがExcel VBA全体のメモリが開放されてしまう。

ENDはおまじないはおまじないでも、バルスだと思って使って欲しい。
0059デフォルトの名無しさん垢版2018/01/31(水) 20:27:34.36
Endを使われても問題が生じない堅牢なアドインの作り方としては、設定値はレジストリに保持しておいてグローバル変数はあくまでキャッシュとして使うのがいいのかな?
(グローバル変数を使う前に必ず存在チェックして、NothingやEmptyなら都度レジストリから値を読み出してインスタンス再生成)
0060デフォルトの名無しさん垢版2018/01/31(水) 20:31:58.29
ちなみにグローバル変数と書いたけど、Endでモジュールレベルの変数もクリアされるという理解
0061デフォルトの名無しさん垢版2018/01/31(水) 20:42:31.70ID:8SvFgWa2
>>57
可愛い質問やなグローバル変数もプロパティも同じ事やで
お前はまずグローバル変数使わなきゃいいってもんやないて事を覚えた方がええな
0062デフォルトの名無しさん垢版2018/01/31(水) 20:43:12.79ID:wkRhZUuX
>>57
確かにモジュール変数にパブリックメソッドを経由してアクセスするようにすればグローバル変数は必要ないかな。
「使わざるを得ない」という表現は撤回するよ。

>>59
アドイン開発ではそれが基本かな。
ENDに相当する「停止」ボタンをデバッグ中に頻繁に押すから事前とそういう作り方になると思う。

あとレジストリも良いけど俺はXML派かな。
理由はPC間の移行がユーザーレベルでも出来るからだけど、今にして思えばインポートはダブルクリックで出来るレジストリのほうが簡単だな。エクスポートはちょっと厄介だけど。
0063デフォルトの名無しさん垢版2018/01/31(水) 20:43:32.54ID:QI8wXuam
>>59
そんなことしなくても
ちゃんとスコープ毎に解放する作りにしとけば
いいんじゃない?
処理が走り終わったときはこれこれ、
ブックが閉じるときはこれこれ、
といった感じで
0065デフォルトの名無しさん垢版2018/01/31(水) 21:19:51.64ID:pJssMamu
プリミティブな値を保持するコンテナが欲しいとき、ほとんどの場合はグローバル変数やモジュールレベル変数を使うまでもなくセルなどに書き込むだけで事足りる
セルへのアクセス時には組み込みのイベントがいくつも走るのでそこは要注意だし、巨大な動的配列を使用する場合は処理速度の問題が出てくるけど
0066デフォルトの名無しさん垢版2018/01/31(水) 21:22:46.33ID:aBe463em
サーバーの監視業務からいきなりVBAでデータ抽出したりする部署に飛ばされたんだけど、なんかいい勉強方法あります?
SQLサーバから引っ張ったりしてます。
0067デフォルトの名無しさん垢版2018/01/31(水) 21:32:20.06ID:4YhVePXS
endはホントに終わらせたいときにしかつかっちゃダメだろう
PCで言えば強制終了と同じようなもんだ
仕方なしに使うもんで、グローバル変数と同じように出来るだけ使わないようにするもの
少なくともおまじない感覚はダメだな
0068デフォルトの名無しさん垢版2018/01/31(水) 21:39:56.78ID:JpECFIQ2
エクセルはメモリを適切に解放しない事が多々あるので、Endが有効な場面もそれだけ増えるというのが困りもの
0069デフォルトの名無しさん垢版2018/01/31(水) 21:56:08.56ID:niw7tDFN
すみません質問です。初心者です
曜日を順番に表示したいのですが、出てくる曜日がデタラメなのです。
どこか悪いんでしょうが、さっぱりわかりません。
ベテラン様、教えてくだされ。

Dim 年 As Integer, 月 As Byte, 日 As Byte
年=2018
月=1
i = 1
For 日 = 1 To 31
Cells(i + 3, 3).Value = Format(年 / 月 / 日, "aaa")
i = i + 1
Next
0071デフォルトの名無しさん垢版2018/01/31(水) 22:13:47.19ID:niw7tDFN
>>70
日付型にしてみたけど、やはりダメみたいです。
0072デフォルトの名無しさん垢版2018/01/31(水) 22:14:33.51
>>69
> Format(年 / 月 / 日, "aaa")
なんで割り算してるの?
0073デフォルトの名無しさん垢版2018/01/31(水) 23:18:11.45ID:q0yM2zae
Cells(i + 3, 3).Value = Format(DateValue(年 & "/" & 月 & "/" & 日), "aaa")
0075デフォルトの名無しさん垢版2018/02/01(木) 06:16:45.45ID:6FACDdoC
>>72
>>73
うまくいきました。
助かりました、ありがとうございました。
0077デフォルトの名無しさん垢版2018/02/01(木) 19:37:02.10ID:cx2O6kE2
>>73
わざわざ日付を文字列にしなくてもいいよ
Cells(i + 3, 3).Value = Format(DateSerial(年, 月, 日), "aaa")

>>76
禿げ同
しょうがないので
> Cells(i + 3, 3).Value = Format(年 / 月 / 日, "aaa")
の行にブレーク掛けて止まったらイミディエートウィンドで
Debug.Print Format(年 / 月 / 日, "aaa")
Debug.Print 年 / 月 / 日
Debug.Print 年
...
ってやってる
0078デフォルトの名無しさん垢版2018/02/01(木) 19:45:37.17ID:mRcX8hpa
>>77
禿乙
0079デフォルトの名無しさん垢版2018/02/02(金) 10:09:17.92ID:VDaFhWcz
http://www.eurus.dti.ne.jp/~yoneyama/Excel/vba/bingo_game.html
すみません このページでダブルビンゴの判定を追加しようと思うのですがうまくいきません。。。
0082デフォルトの名無しさん垢版2018/02/02(金) 23:02:56.20
>>79
試してないけどこんな感じかね

・関数の先頭に「Dim cn5 As Integer」を追加
・「cn1 = 0: cn2 = 0」の直前行に「cn5 = (cn1 ¥ 5) + (cn2 ¥ 5)」を追加 (「/」ではなく「¥」)
・「cn3 = 0: cn4 = 0」の直前行に「cn5 = (cn3 ¥ 5) + (cn4 ¥ 5)」を追加
・「End With」の直前行に以下を追加
If cn5 = 5 Then
.Range(cf(k)).Value = "BINGO!!"
Beep
End If
0083デフォルトの名無しさん垢版2018/02/02(金) 23:03:49.77
>>82
間違えた

× If cn5 = 5 Then

○ If cn5 >= 2 Then
0084デフォルトの名無しさん垢版2018/02/08(木) 00:16:22.23ID:MSYeXSpW
クロスワードパズル、迷路探索アルゴリズムをExcelVBAで作ることができたので、
今度はテトリス作ってみようと思う。
が、飛躍しすぎ?
キー操作で回転させるとか、→押下で横に移動しつつ落下するとかは、難しそうだな。
タイマとかも張らないといけない?
0085デフォルトの名無しさん垢版2018/02/08(木) 07:26:16.72ID:XpMtH+Ey
>>84
5年くらい前に作った。
余裕とは言わないけどぷよぷよ作るよりは楽。
タイマーはAPIで見てる。
ブロックはセルに数字を入れて
条件付き書式で着色した。

今作ればクラスの理解があの頃とは全然違うので
多分また違う作りになると思う。
0086デフォルトの名無しさん垢版2018/02/08(木) 13:17:56.16ID:qQDxntOi
テトリスってWinAPIに慣れるために最初に作るようなヤツだから構造的にはそこまで難しくないだろうな
でもエクセルだと描画速度の問題があるから・・・
0087デフォルトの名無しさん垢版2018/02/08(木) 13:25:02.66ID:f2SIrsod
>>86
大丈夫。EXCELとは言えそこまで遅くはないよ。
むしろ遅くなったら作りに問題があると考えていいと思う。
0090デフォルトの名無しさん垢版2018/02/08(木) 19:48:57.07ID:aY4A4Yk1
>>89
それはそうなんですが変数を追加とかしたときに初期化漏れが出そうで・・・
その方法しかないんですかね?
0091デフォルトの名無しさん垢版2018/02/08(木) 19:51:00.94ID:fuTq97cg
>>88
宣言した直後は初期化されてる
マクロの動作がすべて終了したら自動的に初期化される

マクロの動作の途中ですべての変数を初期化したいなら、初期化するプログラムをいちいち書くしかないけど、
それはもともとの設計が悪い、方針がおかしい
0092デフォルトの名無しさん垢版2018/02/08(木) 19:52:33.01ID:x393c3Y0
構造体の初期値とかな
0093デフォルトの名無しさん垢版2018/02/08(木) 19:53:04.95ID:fuTq97cg
>>90
そもそも初期化漏れってなんだ?たとえば

Dim AAA As Integer

みたいに書いてあると、マクロが実行開始された時点ではAAAは必ず0になってるんだけど
ほかの言語と勘違いしてないか
0094デフォルトの名無しさん垢版2018/02/08(木) 20:07:30.59ID:nI+/jCYy
Integerとか使うなよw
0095デフォルトの名無しさん垢版2018/02/08(木) 20:12:43.47ID:aY4A4Yk1
設計が悪いのは確かです。私がVBAド初心者の頃から改良・機能追加を繰り返したコードでぐちゃぐちゃしてます。Public変数だらけなんです。
まとめて初期化する方法はなさそうですね、残念ですがレスありがとうございました。
0099デフォルトの名無しさん垢版2018/02/08(木) 21:48:43.16ID:Cj1tzdzh
変数の値なんて必要に応じてセットするもんだろ
なんだよ「全変数初期化」って
プログラミングの基礎からやりなおした方がいい
0101デフォルトの名無しさん垢版2018/02/08(木) 21:52:16.55ID:nI+/jCYy
>>88が必要だと思ったから聞いてんだろw
何を訳のわからん事言ってんだコイツはw
0102デフォルトの名無しさん垢版2018/02/08(木) 22:08:53.43ID:aY4A4Yk1
>>97
後からPublic変数を追加した場合、その"リセットするプログラム"も変更の必要ありますよね?
Public変数を一括で初期化できるならいいんですが
>>98
そうですよね。今更ですが実感しています。
>>99
そうです。変数の値を必要に応じてセットしたいんです。
必要な状態とは、変数宣言直後の値なんです。
できませんかね?
>>100
一括で初期化するサブルーチンってできますか?
0103デフォルトの名無しさん垢版2018/02/08(木) 22:30:18.23ID:gEZZVs8q
>>102
それを検討する間にソースを書き換えた方が早そう。
それもできない程、巨大なモノならVBAの範疇を超えてると思う。
0104デフォルトの名無しさん垢版2018/02/08(木) 22:47:07.92ID:XpMtH+Ey
>>102
ひとこと言わせてもらうと
そもそも「一括で全ての変数を初期化する」と言う
機能が必要になっている時点で多分構成的に
破綻していると思う。

変数を設定する前にどんなプログラムをどんな構成で組むのか、
そのためにはどんなライフサイクルの変数が必要で
スコープはどうするのか
次回から考えて作るようにした方がいい。

もっとも、今そんなことを言っても
多分取り返しのつかないようなコードになっているだろうから
とりあえず一つクラスを作っておいて
今パブリック変数として使っている変数を
そのクラスのプロパティとして移してやって、
生成する際にコンストラクタで初期化してやったら
どうだろうか。
条件によって初期値が変わるのならそのクラス内に
そのためのメソッドを作ってもいいと思う。

あまりいい作りとは言えないけど
そのクラスのインスタンスを
モジュール変数にセットしておいて
初期化したいときは新たに生成したものを
その変数に入れてやればとりあえずは
現状よりはもう少し手が入れやすくなると思う。
0105デフォルトの名無しさん垢版2018/02/08(木) 22:48:28.42
>>102
setvar, letvar, getvar, setarray, letarray, getarray みたいな共通関数を作りましょう。
型ごとに letstrvar, getintvar みたいなのも作っといたほうが便利かな。
まあ大きな関数5〜6個と小さな関数30個くらい実装すれば事足りるでしょう。
既存の g_FooBar, g_Baz みたいなPublic変数へのアクセスを全部 letstrvar("g_FooBar", local_str), local_int = getintvar("g_Baz") のような形式に書き換えましょう。
共通関数の中では、実際の値は巨大な配列に保持して、名前とインデックスを紐付けて管理しましょう。
こうすればグローバル変数の置換は機械的にできるし、変数の初期化も一発です。
健闘を祈ります。
0106デフォルトの名無しさん垢版2018/02/08(木) 23:00:19.46ID:aY4A4Yk1
>>103
>>104
レスありがとうございます。
このVBAコードは自分しか使わないし、自分以外がメンテすることはありえないので、
ろくにプログラミングの基本マナーなんてものを勉強しないまま、コード追加追加でわけわからなくなってしまったものです。
自分の書き込みから短時間で、お前のコードの設計が悪いんだとのレスを多く頂いて正直落ち込んでおります・・・
薄々気付いてはいましたが、他の方から指摘されると流石にこたえました。
少しずつ改善していこうと思います。
その上で、>>104をやっていこうと思います。
現時点で>>104の内容は理解できていませんが、なんかすごい貴重なアドバイスなような気がします。参考にさせていただきます。ありがとうございました。
0107デフォルトの名無しさん垢版2018/02/08(木) 23:48:09.40ID:XpMtH+Ey
>>106
構成に関しては単一責任原則に沿って作れば
上達が早くなると思うので
もし知らなければググってみた方がいいかも。

初期化というのは実はそこそこ奥の深い話で
ファクトリーパターンやファクトリーメソッドとか
ググると色々出てくるのだけれど
かなりObject指向寄りの話になってしまうので
ここではまぁ興味があればということで。

頑張ってくださいね。
0108デフォルトの名無しさん垢版2018/02/09(金) 06:47:45.10ID:Oqb9O2xf
>>102
> 後からPublic変数を追加した場合、その"リセットするプログラム"も変更の必要ありますよね?
変更すればいいじゃない
そもそも今あるPublic変数はともかく今後もPublic変数バンバン増やしちゃるって思ってるの?
0109デフォルトの名無しさん垢版2018/02/09(金) 08:10:43.77ID:pONSvQ5P
j自分しか使わないってんなら現状使っているのはそのまま置いといて、いい機会だと
思って新たに作るぐらいの気持ちで、「少しずつ改善」なんて小手先のことやらずに1度徹底的
に作り直したほうが良い。
0110デフォルトの名無しさん垢版2018/02/09(金) 12:00:04.92ID:liPrOEdm
グローバル変数、「さっき設定した値を後でまた参照する」的な意味でどうしても必要になることは理解できるけど、
あったとして一つか二つがいいところ。
データセット的なものを配列使わず保持するならたくさん必要になるけど、さすがにそれは配列かコレクション使え。
0111デフォルトの名無しさん垢版2018/02/09(金) 19:07:16.76ID:pFe+ikyv
毎回初期化が必要なグローバル変数があるならいっそ値をワークシートに保存して管理した方が安全だよな
0112デフォルトの名無しさん垢版2018/02/09(金) 19:29:49.16
誰か>>105を巨大配列じゃなくてワークシートに記録するやり方で実装してください。
0113デフォルトの名無しさん垢版2018/02/09(金) 19:45:27.04ID:mfiNCmZ5
>>105さん渾身のネタ、スベる
0114デフォルトの名無しさん垢版2018/02/10(土) 01:27:55.34ID:UqvxHzys
Worksheet_Calculateが頻繁に呼び出され、これが主な処理であるとき
Public変数だらけになったことはある
初心者だから他にもっといい方法があったのかもしれんが
0115デフォルトの名無しさん垢版2018/02/10(土) 04:42:12.40ID:sZXQwMqu
でもみんなPublicな変数使ってて怖くない?
標準、あるいはクラスモジュール単位で
作られたメンバ変数が勝手に外部から
書き換えられちゃうんだよ?
しかもブレークポイントにもかからないから
いろんなところから頻繁に書き換えられたら
変な値が入っても犯人探しが大変だし。

前にも書いたけどプロパティにしたり
関数にしたりしてアクセサつけといた方がいいと思うよ。
読み取り専用にも出来るしね。
0116デフォルトの名無しさん垢版2018/02/10(土) 05:43:42.77ID:FhCw4HrB
マクロの設計にもよるだろうけどグローバル変数使わずに大がかりなマクロ作ったことあるから、
絶対に避けられないというのは疑問だな。

だいたい初期化が必要な時点でグローバル変数にするのは不適当だし。
0117デフォルトの名無しさん垢版2018/02/10(土) 07:57:32.74ID:vxg4RvSK
初心者あるあるだな
修正や追加を繰り返すうちにコードがスパゲッティになって、変数がどこで書き換えられたか追跡できなくなったもんだから特定のタイミングで一気に初期化したい
すごい手間がかかってるから全面的な書き直しもやりたくない

保守性やモジュール化などの概念がわかってきたところで覚悟を決めて、設計からやり直した方が幸せになれるパターン
0118デフォルトの名無しさん垢版2018/02/10(土) 07:57:57.08ID:4c5k2dma
おまえらにはグローバル変数は決して悪いものではないという事を知って欲しい
0119デフォルトの名無しさん垢版2018/02/10(土) 12:25:34.71ID:silh4Kun
コントロールのイベントプロシージャはプライベートっていう制約があるから
シートと、ユーザーフォーム間のActiveXコントロールで変数の受け渡しをする場合は、パブリック変数を使用するしかいい方法がないと思う
0120デフォルトの名無しさん垢版2018/02/10(土) 12:29:55.88ID:XBpzoSQ/
ワークシートはグローバル変数みたいなもん
印刷さえしなければたいがい便利に使える
0121デフォルトの名無しさん垢版2018/02/10(土) 14:00:23.82ID:7mQmOVGk
シートから直接取ればいいのでは??
使い回すにしてもプライベート変数で事足りると思うけど。
パブリックにして読み書き自由にする必要はないんじゃないか?
0122デフォルトの名無しさん垢版2018/02/10(土) 17:52:03.19ID:pkIiHatw
rangeオブジェクトを分割して2つのrangeオブジェクトにしたいのですがこれだと値がおかしいので解決方法教えてください

Set obj = Range("a1:b100")
set obj1 = obj.range(obj.cells(1,1),obj.cells(100,1))
set obj2 = obj.range(obj.cells(1,2),obj.cells(100,2))
0124デフォルトの名無しさん垢版2018/02/10(土) 19:22:41.50ID:+Zdspcyw
>>122
objに設定してるセルが存在するシートの参照式が省略されてるけど、シートはActiveSheetでいいの?
あと、obj1とobj2には値を設定してるわけじゃないんだが、値がおかしいってどういうこと?
0125デフォルトの名無しさん垢版2018/02/10(土) 21:53:50.67ID:9qCKy78B
vbaに関する質問か分からないけど、
他者が作成したexcel vbaマクロの中身をのぞこうとしたら、パスワードがかかって開けなかった。
どうやったらパスワードを特定できる?
0129デフォルトの名無しさん垢版2018/02/10(土) 22:16:02.76ID:5tf0t1pe
>>123-124
Set obj = Application.InputBox("2列選択", Type:=8)
Set obj1 = obj.Range(obj.Cells(1, 1), obj.Cells(obj.Count / 2, 1))
Set obj2 = obj.Range(obj.Cells(1, 2), obj.Cells(obj.Count / 2, 2))

こんな風にした2列選択した後に1列毎のrangeオブジェクトに割り当てようとしています
試しにobj1.Selectとやって範囲を確認してみると関係のないセルが選択されてしまいました
0130デフォルトの名無しさん垢版2018/02/10(土) 23:02:35.50
>>129
Set obj = Application.InputBox("2列選択", Type:=8)
Set obj1 = obj.Worksheet.Range(obj.Cells(1, 1), obj.Cells(obj.Count / 2, 1))
Set obj2 = obj.Worksheet.Range(obj.Cells(1, 2), obj.Cells(obj.Count / 2, 2))
0131デフォルトの名無しさん垢版2018/02/10(土) 23:24:31.56
このほうが汎用的なのかな
Set obj = Application.InputBox("2列選択", Type:=8)
Set obj1 = Application.Range(obj.Cells(1, 1), obj.Cells(obj.Count / 2, 1))
Set obj2 = Application.Range(obj.Cells(1, 2), obj.Cells(obj.Count / 2, 2))
0132デフォルトの名無しさん垢版2018/02/10(土) 23:27:24.03
>>131はだめか
Application.Range プロパティ (Excel)
>オブジェクト修飾子を指定せずにこのプロパティを使用すると、 ActiveSheet.Range のショートカットとなります。

>>130でいいと思うけど、Range, Cellsの仕様がいまいち分からなかったから理論的になぜかは説明できない
0133デフォルトの名無しさん垢版2018/02/10(土) 23:39:33.30ID:o71hUKxM
set obj = nothing
は最後に入れるべきか、
ほったらかしでも問題無いのか
どうなんだろう?
0134デフォルトの名無しさん垢版2018/02/11(日) 00:18:26.88ID:q9UPBdZm
おまえらには必要
0135デフォルトの名無しさん垢版2018/02/11(日) 04:53:44.34ID:LDeaRbgm
同じADOでもデルファイのクローズはナッシングだけど、VB系の場合はクローズだよねだいたい
たしかクローズせずにナッシングするとクローズできなくなる
0136デフォルトの名無しさん垢版2018/02/11(日) 08:29:24.42ID:AIGXauyP
>>129
例えばC1:D:4を選択した場合

1.obj.Rangeの中で更にobj.Cellsを指定するということは、C列目を基準にC列目を指定をしていることになる。
だからRangeの中にCellsを書く時はobj.Cellsではなく、obj.Worksheet.Cellsが良い。

2.obj1がC1:C4、obj2にD1:D4をセットしたいってことだよな?
obj.Cells(obj.Count / 2, 1)
この書き方だと行数を半分にしているのだがこれは一体・・・
もしC1:F10を指定した場合にC1:D10、E1:F10に分けたいわけじゃないの?

3.可読性が死ぬからRange使うのをやめよう。
範囲指定をする時はResize、Offsetを使ったほうが直感的です。

当初の質問を参考に2の通りだと仮定して
Set obj1 = obj.Resize(, obj.Column / 2)
Set obj2 = obj.Resize(, obj.Column / 2).Offset(,obj.Column / 2)

Objには2列しか選択されない事が確定しているなら
Set obj1 = obj.Resize(, 1)
Set obj2 = obj.Resize(, 1).Offset(,1)
0137デフォルトの名無しさん垢版2018/02/11(日) 10:16:47.04
>>136
1についての文献あれば教えて

2に関しては、2列選択中だから総セル数を2で割れば行数が算出できるってことやろ
obj.Rows.Countのほうがいいとは思うけど
0138デフォルトの名無しさん垢版2018/02/11(日) 10:18:33.85
>>137
>1についての文献

あ、想像で書いてるどっかのブログとかじゃなくて
ちゃんとしたMicrosoftの公式文献ね
0139デフォルトの名無しさん垢版2018/02/11(日) 10:29:03.91ID:q9UPBdZm
文献()読んでもわからんからこんな掃き溜めで質問しとんのやろw
ややこしい奴やなあw
0140デフォルトの名無しさん垢版2018/02/11(日) 10:34:27.69
>>139
俺は回答者側や
0141デフォルトの名無しさん垢版2018/02/11(日) 10:37:10.14ID:q9UPBdZm
>>140
俺は回答者側や(キリッ

あのさあ〜お前羞恥心ないの?www
0142デフォルトの名無しさん垢版2018/02/11(日) 10:38:14.38ID:YMxCZLKM
ほったらかしで問題ない場合と
そうでない場合があるので
よくわからなければ明示的に
Nothing入れといた方がいい
0144デフォルトの名無しさん垢版2018/02/11(日) 10:58:29.29
>>143
どこにobj.Rangeの引数としてobj,Cellsが指定された場合の解釈のされ方が書いてあるの?
どこみてもActiveSheet.Rangeの引数として使ってる例ばっかりだし、内部的にどういう形式に変換されてるのか全然読み取れないんだわ
0145デフォルトの名無しさん垢版2018/02/11(日) 11:40:12.40ID:A61Ds/EI
>>144
> 偉そうにほざく前にMSDNぐらいググれ
って書いてあるのにバカすぎる
URLは単なるヒントな
まあ普通の理解力あればあれで充分だと思うが w
0146デフォルトの名無しさん垢版2018/02/11(日) 11:49:28.10
>>145
煽りはいいから笑
結局探したけど見つけられなかったんだろ?
気持ちは分かるわ
0148デフォルトの名無しさん垢版2018/02/11(日) 12:56:24.79ID:AIGXauyP
>>137
公式文献は知らないがそういうもんだと納得している。

想像()とか、こんなくらい知ってるわヴォケとか言われそうだが
set ws = Worksheets(1)があると仮定して。

これはどれもRange("B2")への参照を示すわけだが
ws.Cells(2,2)
ws.Cells(2,2).Cells(1,1)
ws.Cells(2,2).Range("A1")

CellsとかRangeは同一ワークシート内であれば、いくらでも参照先を変更できる。
例えばこれはどれもRange("C3")への参照。
B2を基準(1,1)として(2,2)を見ていることになるからだ。
ws.Cells(2,2).Cells(2,2)
ws.Cells(2,2).Range("B2")
ws.Range(ws.Cells(2,2).Range("B2"))

問題の件はobjに既にRangeが格納されているからわかりづらいが
Set obj = ws.Range("B2") の場合に
obj.Range(ws.Cells(2,2)) というのは
ws.Range("B2").Range(ws.Cells(2,2)) ってことだよね
単一セルの場合はws.Range("B2").Cells(2,2)と同一の結果になる。

範囲の場合も考え方は同じだがRange(a,b)でaとbに範囲を渡した場合
aとbを合わせた領域の最端の範囲を示すのは言わずもがな。

結局のところ何も難しい話ではなくて、Offsetの相対指定とResizeの範囲指定を同時にできるのがRangeだっていう話に戻る。

普段ws.Range("A1")と書いているものは、実はws.cells(1,1).Range("A1")の省略形だって考えて俺は納得した。
0150デフォルトの名無しさん垢版2018/02/11(日) 16:48:17.26
>>148
ありがとう。

結局、想像でしかないけど、
obj.Range(obj.Cells(x, x), obj.Cells(x, x))
を独自関数
SelectionRangeCells(obj, obj.Cells(x, x), obj.Cells(x, x))
に置き換えると、こんな感じのことをしているのかね。

Function SelectionRangeCells(ByRef rng As Range, ByRef cell1 As Range, ByRef cell2 As Range) As Range
Dim startRow As Long
Dim endRow As Long
Dim startColumn As Long
Dim endColumn As Long
startRow = WorksheetFunction.Min(cell1.Row, cell2.Row)
endRow = WorksheetFunction.Max(cell1.Row, cell2.Row)
startColumn = WorksheetFunction.Min(cell1.Column, cell2.Column)
endColumn = WorksheetFunction.Max(cell1.Column, cell2.Column)
Set SelectionRangeCells = rng.Resize(endRow - startRow + 1, endColumn - startColumn + 1).Offset(startRow - 1, startColumn - 1)
End Function

obj.Range("A1")という形式の場合は公式ドキュメントに明確に書かれてるね。
https://msdn.microsoft.com/ja-jp/vba/excel-vba/articles/range-range-property-excel

obj.Range(obj.Cells(x, x), obj.Cells(x, x))
の場合はobj.Cells(x, x)が実体セルを指していてobjとの相対位置も分かってるわけだから
Rangeプロパティ内で相対参照を算出する実装方法も考えられるしそのほうが使う側は分かりやすいはずだけど
そう実装していないという明確な記述がどこにもなかったから実際に動かしてみての想像しかできなかった。

(ちなみに>>149がなにやら勘違いしているようだがCells(x, x)【Cells._Default(x, x)】が何を返すかを知りたかったわけではない)
0151デフォルトの名無しさん垢版2018/02/11(日) 17:24:07.93ID:A61Ds/EI
>>150
> (ちなみに>>149がなにやら勘違いしているようだがCells(x, x)【Cells._Default(x, x)】が何を返すかを知りたかったわけではない)
その理解力で人を勘違い呼ばわりとか w
0152デフォルトの名無しさん垢版2018/02/11(日) 17:54:51.66ID:q9UPBdZm
>>151
俺からしたらおまえも>>150と似たりよったりだからw
まあ今回の件は僅差でお前の勝ちだけどw
■ このスレッドは過去ログ倉庫に格納されています

ニューススポーツなんでも実況