Excel VBA 質問スレ Part49©2ch.net
■ このスレッドは過去ログ倉庫に格納されています
!extend:checked:vvvvv:1000:512 !extend:checked:vvvvv:1000:512 スレ立ての際は一行目に !extend:checked:vvvvv:1000:512 と入れてスレ立てして下さい ExcelのVBAに関する質問スレです コード書き込みや作成依頼もOK ※前スレ Excel VBA 質問スレ Part48 http://mevius.2ch.net/test/read.cgi/tech/1494890685/ ※関連スレ VBAなんでも質問スレ Part2 http://mevius.2ch.net/test/read.cgi/tech/1432173164/ Access VBA 質問スレ Part1 http://mevius.2ch.net/test/read.cgi/tech/1328536426/ Excel総合相談所 126 https://mevius.2ch.net/test/read.cgi/bsoft/1496487719/ VIPQ2_EXTDAT: checked:vvvvv:1000:512:----: EXT was configured 地獄の社内SE https://anond.hatelabo.jp/20170626005657 > 社内SEはなんとなく楽そうなイメージがあったので、就職した。 > 言語はエクセルVBAとVB.NET 1.0。 > 中身を見るとどちらもかなりやばい。 > > VBA編 > ・ウォッチウインドウを知らないのか、変数はすべてセルに入れてる。変数名はすべてRANGE("A1").valueみたいな感じで全く意味が分からない。 > ・処理遷移がおかしい。 > セルに1を入れる。そのセルのchangeイベントで処理が動くとか。SHIFT+F2が無力化されてる。 > ・なるべくワークシート関数で処理してる > データベースからとってきたデータを丸ごとワークシートにコピーしてif,vlookup,match関数を駆使して帳票にしたり、CSVにしてる。 > データ100件制限があったり、1関数を直すときは100行コピーしないといけない。画面中に埋め尽くされたワークシート関数をみて途方に暮れる。 > ・format関数を知らない。 > 8桁の日付をとりたいときyear、month、day関数がワークシートにあり、 > その下の行で月の二けた判定、日の二けた判定のif関数で頭の0をつけ3行目でconcatenateしている > ・タイマー起動 > 毎朝100本ぐらいのマクロが動いてる。タイマー起動なので、毎日セットしないといけない。(タスクスケジューラーを知らない) > がんがんエラーが発生するので、マクロ設定をエラー処理対象外のエラーで中断にしないと動かない。 > ・遅い > textboxのchangeイベントでDBからのデータ取得処理を入れているので、データが多くなると1文字打つごとに数分待つ状態。exitイベントを知らないらしい > DBの更新処理でもテーブル全件とってきて、ループしながらキーが一致するのを探して更新。 > ・変数や関数のスコープの管理 > ない。基本グローバル。 > ・クラス > ない。 > ・ネスト > ない。 > そんなつっこみどころしかないEXCELマクロが200本以上ある。 > おじいさんが20年にわたって深夜残業や休日出勤を厭わず作ってきた、地獄の社内システムの担当になったらしい。 >>7 ちょっとそうぞうしただけですっげーーーーーーーーーーーーーーーゲンナリした うぇっっ 地獄とか書いてるけど、 全然地獄じゃないんだろうな。 強敵と戦う悟空みたいな感じで。 VBAが仕事っていいじゃねーか 業務の合間にマクロ作ってるけエクセルが得意な人扱いしかされない カラオケが上手いとか酒が強いとかと同じ扱いだよ俺もVBAだけやってたいな 何か公開するとか解説記事を続けて書くとかしないと残るものがないよな >>9 おれ、ああいうののメンテナンスする仕事したこと有るけど地獄だよ。 inputとoutputがわかってんなら作り直したほうが… どう考えてもイチから作り直すべきだが、それを現場がどう理解してるかだわ セルに値が入ってないと管理できない!とかありそう 質問失礼します。 ある一つのセルに、氏名コメント改行文字が5人分入っていて、選択するとformにテキストボックスが5人分用意されている所に、それぞれの氏名に合わせて入る様になっています。 やりたい事は、formのテキストボックスに作業者が入力したのの更新履歴を付けたいのです。 作業者は自分の氏名のテキストボックスに入力することになっています。 コマンドボタンをクリックしたタイミングで、どのテキストボックスが最後に変更されたのか取得できる方法が有りましたら教えてください。 >>17 AfterUpdateイベントやChangeイベントで最後に更新されたテキストボックスを記録して、ボタンを押したときにその内容を読み取る、みたいな感じになる。 ↓こんな感じ Private LastUpdated Private Sub TextBox1_AfterUpdate() LastUpdated = "TextBox1" End Sub Private Sub TextBox2_AfterUpdate() LastUpdated = "TextBox2" End Sub Private Sub CommandButton1_Click() Dim str If Not IsEmpty(LastUpdated) Then str = Me.Controls(LastUpdated).Text '処理 End Sub >>17 追伸 「vba フォーム イベント」でググると色々とできることの幅が広がると思う。 しばらく前に騒ぎになったランサムウェアってVBAマクロなのか マクロウイルスって今でもあるんだな >>19 ご回答ありがとうございます。 今回の件はAfterUpdateで対応出来ました。 今後の為にお聞きしたいのですが、例えばテキストボックスが100個とかあった場合、VBのコントロール配列の様に一つのプロシージャで100個のテキストボックスのAfterUpdateに対応することは出来ませんか? よろしくお願いします。 >>21 「vba フォーム イベント withevents」とかでググれば、クラスモジュールを使ってイベント付きコントロールを配列またはコレクション化する方法が出てくる。 フォームの履歴管理には、クラス変数にフォームへの参照と、配列のインデックスまたはコレクションのキーなんかを渡して処理すればたぶんOK。 >>22 ありがとうございます。 witheventsを使用してテキストボックスのチェンジイベントをひとまとめに出来ました。 afterupdateをまとめれるともっと良かったのですが、それは無理そうなのでこれで満足です。 本当にありがとうございます! 100という10進数をDo loop を使って2進数に変換させるにはどのようにすればよいのでしょうか? イメージとしては、100を2ずつ割っていってそこで出たそれぞれの余りの数をセルA1に表示させたいです。 よろしくお願い致します。 >>24 Do〜Loop縛りなの? worksheetfunction,dex2binを使えば楽ちんだけど。 セルA1を毎回上書きしてるとか まぁこの手の奴はぐぐれば腐るほどでてくるけどな セルA1を瞬時に上書きしていって、それで何をしたいんだか? 最終的な目標は何なのかワカンネ w 曖昧だけど設計まであるのにできてないのなら今どんなコードを書いてるのか提示して質問してほしいなぁ いっそのこと「この仕様を満たすコードをください!」と言ってくれてもいいけど はい、作ったよ 仕様満たしてるかどうかはあんたたちで みっちり見てね バグ見つけたら教えてね で仕様齟齬をあぶり出してもらわないと 仕様を具体的に言わないクライアント(身内だけど)とは付き合えない >>34 作ったモノ触らないと気がすまない連中なんだよ もちろん作る前に要求仕様は聞くけど 後からチマチマと何か言ってくる >>35 面倒でも文書化して読んでもらうのがいいよ 読んで始めて、自分が何を欲しているか気づく場合もあるし 後は、プロトタイプかな 全部できて「これ、全然違うし」とか言われるリスクあるなら、そういうことやってみたらいいと思う このスレの人間って質問者置いてけぼりであーだこーだ言うのが多いけど、一番ムカつくのは、 肝心の質問者が自分のやりたい事はこういうことだって言わないこと。 少しは自分の質問に責任くらい持ちやがれ こういった輩が多いから双方の軋轢が絶えないんだろな 先方はまったくの門外漢だ て前提で仕事を引き受けられない 相手も自分と同レベルだと信じて疑わない もしくは少し下ぐらい 初めて住宅を新築する顧客が、いきなり詳細設計図渡されて理解できるか? ソッチで仕様書と図面引いてください って言ってるのと同様だぞ? 引き受けるからにはその仕事を請け負う責任も勿論だが これから実施する作業の概要・概略を相手に理解してもらうテクニックだって 必要だろ それを持ち合わせないならサンプル品なり試作品なり作ってでも 相手と同じレベルで進捗を図るのが普通じゃ無いのか? こっちはざっくり動きや結果を見越せるけれど、相手にもそれを要求するのは 傲慢でしかないんだが いわんや、相手の業種・業態に依ってはコチラ側が思いもしないような入力・ 操作が要求されるケースだってままある 仕様も要件も書き出せますよ なんてぇ企業相手ならおまえら不要だろ 社内で事足りるわ も少し謙虚に成れんのか 会議だ仕様だ要件だなんてぇことに無駄な時間を 費やすぐらいなら、とっとと試作して「こうですか?」で何歩も進むだろ いやすまん なんでもない ここの人間は質問者から金貰ってるわけでもなんでもねーわ >>39 言いたいことはわかる だが発言のベースが「やったけどダメだった!答えを教えろ!ダメだったモノは見せない!」じゃあんまりだと思う 最近、趣味でVBAのプログラムを始めた初心者です 区切り記号を含むテキストデータを Split() を使って二次元配列に入れようと思っています。 テキストデータは、vbLf で改行、行内のデータは、vbTab で区切り です <例: String 型の TextData の内容> あああああ アアアアアアアアア いい イイイイイ ううううう ウウウ (以下、同様の形式で全500行ある) いろいろ宣言の仕方などを試した結果、次の方法でエラーなく実行できたのですが… Dim tmpDim As Variant Dim sqrDim(500) As Variant tmpDim = Split( TextData, vbLf ) For i = 0 to UBound( tmpDim ) - 1 For j = 0 to 1 sqrDim( i ) = Split( sqrDim( i ), vbTab ) Next j Next i これでは、途中の38行目を読み込んだところ(i=37,j=1)で、 実行時エラー '9': インデックスが有効範囲にありません とのエラーが出て止まってしまいます。 (一次方向(行)には500個確保できていると思うので、なぜインデックスエラーなのか不思議です) 2回目のSplitの受けも、別の一次元配列で行い、後で二次元配列に格納すればいいとは思いますが 上手く二次元配列でSplitのデータを受けるやり方はあるのでしょうか? お手数ですが教えてください >>43 splitしたのがうまく行ってないと思う ステップイン で実行しながら ウォッチ式 を見ると変数の中身が分かり安いよ そのテキストを上げてもらえればこっちでも確認する >>43 これ通るの? For j = 0 to 1 sqrDim( i ) = Split( sqrDim( i ), vbTab ) Next j で sqrDim( i ) を2回splitしてる。 1回めは文字列のsplitだからいいけど、2回めは配列のsplitになってエラーになりそうだけど。 For j のループは不要。 あとついでに For i = 0 to UBound( tmpDim ) - 1 だとTextDataの最終行のデータが配列に格納されないけど問題ないか? >>43 こうでしょ Dim tmpDim As Variant Dim sqrDim As Variant tmpDim = Split( TextData, vbLf ) ReDim sqrDim(LBound(tmpDim), UBound(tmpDim)) For i = LBound(tmpDim) to UBound( tmpDim ) sqrDim( i ) = Split( tmpDim( i ), vbTab ) Next i sqrDimは2次元配列じゃなくて配列の配列になるけど、むしろこっちの方があとで楽だと思う。 >>44-46 早々に回答ください、どうもありがとうございます。 いろいろ回答を頂いておきながら、大変申し訳ないのですが、 38行目のデータをよく見たところ、TAB区切りではなく、ここだけスペースが入っていました (他は、各行に2個の要素があったのですが、ここだけ要素が1個でした) そして、これを修正したら、エラーなく実行できました。 お手数をおかけし、申し訳ありませんでした。 おっしゃる通り、j のループは不要ですね。(いろいろ修正していて、j を使わなくなったようです) > だとTextDataの最終行のデータが配列に格納されないけど問題ないか? いえ、ちゃんと最終行まで格納出来てました (UBound()は要素数を表しているように思います) > ReDim sqrDim(LBound(tmpDim), UBound(tmpDim)) ReDim は使ったことがないので、また調べてみます 以上、ありがとうございました。 >>45 > これ通るの? > For j = 0 to 1 > sqrDim( i ) = Split( sqrDim( i ), vbTab ) > Next j これ、写し間違いでした。 2回目に Split するのは tmpDim でした ×: sqrDim( i ) = Split( sqrDim( i ), vbTab ) ○: sqrDim( i ) = Split( tmpDim( i ), vbTab ) 申し訳ありませんでした >>47 > (UBound()は要素数を表しているように思います) 一応言っておくと、これは間違い。 UBound(tmpDim) は配列tmpDimのインデックスの最大値を返す。 TextDataが500行(vbLfが499個)だとしたら、tmpDimのインデックスは(0 to 499)になるから、UBound(tmpDim) は499を返す。 このコードのsqrDim(500)が全部埋まってるのであれば、TextDataは501行あるはず。 まあ結果がOKならいいんだけどね。 失礼、>>49 に間違い。 sqrDim(500) だとsqrDimの要素数は501だから、全部埋まってるの場合のTextDataの行数は502行になるはず。 >>49-50 > 一応言っておくと、これは間違い。 > UBound(tmpDim) は配列tmpDimのインデックスの最大値を返す。 申し訳ないです。 おっしゃる通り、ググってみるとそのように書いてました。 なお、TextDataは実際には400行前後のため、偶然上手く動いているように見えてたのですね (実際は、400〜499までループが回っており、タチの悪いバグになるところでした、感謝です) 前にC言語を少しやっていたので、同じ扱いだと思っていましたが違ってたんですね わざわざありがとうございます。 >>51 そう [LBound, UBound) じゃなくて [LBound, UBound] で回さなきゃダメ ここの強者はExcelVBAエキスパートの資格持ってるの? 簡単そうだから取ろうかなと思ってる ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.5 2024/06/08 Walang Kapalit ★ | Donguri System Team 5ちゃんねる