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エキスパートの資格持ってるの?
簡単そうだから取ろうかなと思ってる コンピュータ関連も色んな資格あるけど、ああいう資格を基準にして採用している所ってどれだけあるんだろ。 基準にはしないかな
あーできるんですねって程度。どちらにしても実地試験は受けてもらう 俺、プログラムは作れるけど、試験は落ちそうだな。
DimとかRowとか、短い文字は打てるんだけど、
長いのは、普段コピペしてるから、打てない。
最近、やっとColumnsを間違えずに打てるようになったわ。
それまでは、Corums? ん? Colmns? え? Culomus? 違う?
Colums? わかんね。 もう諦めてコピペしよう、みたいな感じ。 プログラムの実技試験で暗記力が必要なのはそろそろどうかとは思う 10年選手だけど
フィボナッチとかハノイの塔とかソラで出できないぞ俺 それは数学の知識の問題だと思うので、別にできなくてもいいと思う。多分一生役に立たない
でも最小二乗法とか漸近線、偏差値など、統計学的な知識はあったほうが良いと思う >>53
昔、某掲示板で質問した人に話の内容から初心者として扱ったらその資格持ってるとのことでびっくりしたことがある。
どんな資格でもそうだけど、そういうもんなんでしょう。
そうしないと受かる奴いなくなっちゃう。 >>60
そんな問題が実際の案件に出てきた時に最適なコードが書ければ良いでしょ。
それにその程度の話ってググレば出てくるでしょ。
そんなのは何かあったよなと思うことが出来てググレればOK。
それよりも上手いやり方に気付かずにクソコード書く奴は多い。 >>66
支店名 状態 月 売上
A支店 3 200
B支店 3 10
C支店 3 500
A支店 4 300
B支店 閉店 4 0
C支店 4 600
4月の売上平均を求めよ(制限時間5分)
って感じ。
D1=(300+0+600)/3
にはたまげた。もちろん関数を使わない人はアウト
B支店を入れるかどうか疑問に思えば合格 >>68
あぁすまん、ここvbaスレか。Excelスレと思ってた。忘れてくれ エクセルのある部分をリストボックスにしたいのですが、rowsourceで設定すると、間に空白が多くなった時に使いにくいです。
そこで下記のように空白だったら、リストに加えないとしたら、リストに何も出てきません。
どこがおかしいでしょうか? RowPN(i)には既にエクセルの1セルの値が167個入ってます。
i = 1
i1 = 1
Do Until i > 168
On Error Resume Next
If RowPN(i) <> "" Then
UF6ComboBox1.AddItem RowPN(i), i1
i1 = i1 + 1
End If
i = i + 1
Loop VBAの試験って、やっぱ何らかの制限付きなんだろうか。
制限しないと、ソートにSQLとか、Worksheetfunctionとか、
Cells(1,1).Value="計算式"とか、正解だけど、試験の趣旨としてどうなの?
という答えが沢山出来てしまう。 >>70
・RowPNの中身が全て""またはEmptyになっていないか。
Dubug.Printまたはローカルウィンドウでの確認を推奨する。
・リストボックスと言っているが変数はUF6ComboBox1で合っているか。
・RowPNの要素が(0 To 166)ないし(1 To 167)だとDoループがi=168までカウントするのでインデックスエラーになる。
For文の方が無難そうに思えるのと、ここでOn Error Resume Nextはどうかと感じる。 >>70
セルから値をとってるならこれでいいと思われ
Dim i As Long
For i = 1 To 168
If Cells(i, 1) <> "" Then
ComboBox1.AddItem Cells(i, 1)
End If
Next >>72 3行目間違い。。
? Dubug.Print ○ Debug.Print >>71
ググればすぐわかる。
なんか1日対策勉強したら余裕そう。 >>72 >>73 ありがとうございます。 値は入ってるのは確認しました。FOR文も空白ですね・・・。
シート使っているので、そこに1エリア儲けて、空白除いて再整列させて、ROWSOURCEで設定してみます。 >>75
いきなりサンプル問題で躓いたwwwwwwww
セルの範囲指定で「"A1:B1"」以外に「"A1","B1"」も使えるとか知らんわwwwww >>76
その方法で納得ならいいですが
配列に入っているなら
On Error Resume Nextで
コントロールを参照できないのでエラーしているのを
すっ飛ばしているのではなかろうか。
つまり>>72が言っているようにUF6ComboBox1は存在しないのでは。
On Error〜をコメントアウトしてみてはどうか。
と思う。 >>78 オブジェクト名は間違うと動かなくなるので、いつもコピペしてるんですよ。
とりあえずシート使って逃げて、rowsourceでうまいこと動きました。 >>61
数学の知識というより再帰関数とかのプログラム技術の問題 こんばんわ、
シティーボーイズやってました、再帰しげるです こんばんわ、
膣に挿入したら動きません、きたろうです 以下のプログラムで「該当するセルが見つかりません」となってしまいます。
該当するセル範囲のセルはすべて空白です。
期待する動作は、「B4:B6の範囲の空白セルにコメントを入れる」です。
Sub commentAddToBlankCells()
____On Error GoTo ERROR_ALL
____Range("B4:B6").SpecialCells(xlCellTypeBlanks).AddComment "目視確認"
____Exit Sub
ERROR_ALL:
____MsgBox Err.Description
End Sub
※Excel2010です。 >>84
2007だけど、ActiveSheet.UsedRangeの範囲外のセルだとエラーになるっぽい。 ここの板で質問するレベルでExcelになすりつけるのは100000年ほど早い
まぁそう言いたくなるときもあるんだがw 例えば、
そのセルの値が0より大きければセルA1をコピーし、そのセルに書式を貼り付け、
そのセルの値が0より小さければセルA2のコピーし、そのセルに書式を貼り付ける。
この程度の処理を数百のセルに行うのに結構な時間がかかる。
短時間で完了させるにはどうしたらいいんでしょうか?
ある程度のセル範囲ごとにまとめて書式貼り付けすればいいんでしょうか? Sub nisinsu()
Dim Z As Single, S As Long, N As String, A As String
Z = 100
S = 1
Do Until Z <= 0
N = Z Mod 2
Cells(S, 1) = Z
Cells(S, 2) = N
Z = Z \ 2
S = S + 1
A = N + A
Loop
Cells(1, 3) = A
End Sub
上の方で2進数について質問したものです
このコードである程度無事に解決しましたが、一つ分らないことがあります
Loop を抜けた後の Cells(1, 3) = A の所は Loopの一つ上の A = N + A によって 1100100 と正しい数字が表示されます
しかしこの A = の中を A = A + N というように A と N を逆にすると 10011 と全く別の数字になってしまいます
この理由がどうしてなのかを教えてください >>91
まずはおめでとう!
質問についての回答は単純に逆転してるだけだよ
1100100となるところが0010011となってしまいそのまま表示させたら頭の0が消えたって感じ >>89
あー読み取れた
VBA使うまでもなく条件付書式使えば終わり >>89
多分これでOK
Application.ScreenUpdating = False
処理
Application.ScreenUpdating = True >>89です
>>90>>92>>94
わかりにくかったですか、すいません。かなり酔ってます。
一日200行ぐらい増えるブックがあります。列数は50ぐらいです。
一ヶ月で6000行ぐらいでしょうか。あらかじめ条件付き書式を設定していましたが、
なんかブックを開くときに重くて、きっと条件付き書式が原因だろうと思い、
条件付き書式ではなく、VBAで各セルの値に応じて書式を固定しようと思ったわけです
でも、そのVBAが時間がかかって困ってるわけです。
書式のコピペって時間かかるんですね。
もっと書式のコピペを早くできる方法はないのかなって思ったわけですわ。 >>96
書式コピペするんじゃなくて、直接指定したらまだ速くなると思うよ
クリップボードを介する処理はとても時間がかかる >>96
こんな単純な条件ひとつだけで重くなるわけがない
問題は別にあるよ >>96
条件付き書式が断片化してない?断片化ってのは勝手に作った言葉だけど・・・
例えば、A:Aに条件付き書式(=a1=1)を設定して、10行目を切り取って11行目に挿入したりすると
条件=A1=1
=$A$1:$A$10,$A$12:$A$1048576
条件=A11=1
=$A$11
のように分割される
一度条件付き書式の書式ルールの管理、「このワークシート」を見てみたほうがいいかも ■ このスレッドは過去ログ倉庫に格納されています