Excel VBA 質問スレ Part18at TECH
Excel VBA 質問スレ Part18 - 暇つぶし2ch942:デフォルトの名無しさん
11/05/14 22:07:24.26
>>938
関数は(あれば)引数を受け取って値を返すだけの機能
書式の変更等はできない仕様
Subのほうに書くしかない

943:896
11/05/14 23:03:54.96
>>942
functionから書式変更するsubを別途呼んでもダメだったので、
そういう仕様なのかと疑っていましたが、やっぱり仕様だったんですね。


諦めてボタン等から起動して、チェックと書式変更する処理を流すようにでもしてみます。
レスくれた方々、ありがとうございました。

944:デフォルトの名無しさん
11/05/14 23:44:07.49
>>943
もう見てないかな?
これはたしかユーザー定義型の制約で仕方ない事だったと思ったべさ。
>>922の人のが殆ど自分の考えと一緒だったけどちょっと違うのが、
変更された特定値をサーチするんじゃなくて、値の書き込み元の範囲を
最初に特定してしまって、その範囲外ならすぐに処理を抜けてしまえば
シート上の変更のたびに呼び出されても負担が少ないわさ。

たとえばシートのセル範囲にRng_TgtFromと言う名前を切って、これを
計算が反映される入力元の範囲とした場合、次の様にVBEのシートに書くべさ。

945:デフォルトの名無しさん
11/05/14 23:46:29.37
>>944の続き

Private Sub Worksheet_Change(ByVal Target As Range)
Dim oRngTgtFrom As Range
Dim oRngTgtTo As Range
Dim oRngMono As Range

Set oRngTgtFrom = Range("Rng_TgtFrom")

If oRngTgtFrom.Row > Target.Row + Target.Rows.Count - 1 Or _
oRngTgtFrom.Row + oRngTgtFrom.Rows.Count - 1 < Target.Row Or _
oRngTgtFrom.Column > Target.Column + Target.Columns.Count - 1 Or _
oRngTgtFrom.Column + oRngTgtFrom.Columns.Count - 1 < Target.Column Then
Exit Sub
End If

Set oRngTgtTo = Range(Cells(Target.Row + Target.Rows.Count - 1, _
Target.Column + Target.Columns.Count - 1), _
Cells(oRngTgtFrom.Row, _
oRngTgtFrom.Column))

946:デフォルトの名無しさん
11/05/14 23:47:57.42
>>945の続き

For Each oRngMono In oRngTgtTo
If oRngMono <> "" Then
oRngMono.Offset(0, 2).Value = "AAA"
oRngMono.Offset(0, 2).Interior.ColorIndex = 7
Else
oRngMono.Offset(0, 2).Value = ""
oRngMono.Offset(0, 2).Interior.ColorIndex = 0
End If
Next

End Sub


947:デフォルトの名無しさん
11/05/14 23:59:48.52
>>945の続き

まず入力したセルが指定範囲内かチェックしてるわさ。

次に入力したセルが範囲内だった場合、指定範囲と入力された範囲の
被った部分を処理対象にするわさ。

で、処理対象範囲の中のセルを一個づつガラガラまわして値と色を設定してるわさ。

値の"AAA"と結果出力位置は適当に後で直して欲しいわさ。

インデントが取れたからかなり見辛くなったから
コピッてはっつけてインデント補正してから見てほしいわさ。

948:デフォルトの名無しさん
11/05/15 00:24:17.64
ぐはぁ、>>944でユーザー定義型とか言っちゃってるよ。
ユーザー定義関数の間違いね。ユーザー定義型って言ったら構造体のことになっちゃうわさ。

949:デフォルトの名無しさん
11/05/15 04:36:24.95
ユーザ定義関数の引数にRangeをとって、その関数を使うときに
色を変えるセルを引数に指定すれば良いんじゃねえかと思うんだが


950:デフォルトの名無しさん
11/05/15 08:02:20.85
えっ?

951:デフォルトの名無しさん
11/05/15 10:36:16.75
>>949
やってみてから言えば?

952:896
11/05/15 11:54:30.92
>>947
改良案ありがとうございます。
たしかに範囲指定内でのみ処理が流れるようにすれば負荷を抑えられますね。

書いてもらったコードですが、名前付きセル内のセルの
値と書式を設定した場合は、設定時に再びworksheet_changeイベントが
発生しループするようだったので、私のほうでも方針は同じで、やり方を少し変えてみました。

Private Sub Worksheet_Change(ByVal Target As Range)

' "Rng_TgtFrom"セル内のみを処理対象とする
If Not Application.Intersect(Target, Range("Rng_TgtFrom")) Is Nothing Then

' "Rng_TgtFrom"セル内を書き換えたとき
' 再びWorksheet_Changeイベントが
' 発生しないようにイベント無効化
Application.EnableEvents = False

' 書式と値設定
Target.Interior.ColorIndex = 3
Target.Value = "aaa"

'イベント有効化
Application.EnableEvents = True

End If

End Sub

これなら私がやりたかったことにだいぶ近づきました。
ありがとうございます。


953:デフォルトの名無しさん
11/05/15 12:08:15.55
>>952
ちょっと待って、
今更だけどもうちょい考える余地がある事に気付いたべさ。

954:デフォルトの名無しさん
11/05/15 12:26:43.23
>>952
今更だけど条件付き書式を使ってやる方法も思いついたわさ。
複雑な条件で着色しなければいけないって話だったから、これもユーザー定義関数に
してしまって、出来るなら処理元を一緒にしてしまえば楽になるかな。こんな感じ。

Public Function hoge1(IN_str As String) As String
Dim bBool As Boolean
Call hoge3(IN_str, bBool)
hoge1 = IN_str
End Function

Public Function hoge2(IN_str As String) As Boolean
Dim bBool As Boolean
Call hoge3(IN_str, bBool)
hoge2 = bBool
End Function

Private Function hoge3(IN_str As String, IN_bool As Boolean)
IN_bool = False
If IN_str <> "" Then
IN_str = "aaa"
IN_bool = True
End If
End Function

シートのセルの数式からhoge1を呼び出す様にして、
同じセルの条件付き書式から数式でhoge2を呼び出す様に設定しとけば、
最初の1セルの設定は面倒だけど後はコピペで展開すれば
わざわざイベントの事を気にしないでも済むわさ。
まぁ、後は好みで使い分けるわさ。

955:896
11/05/15 13:06:05.15
>>954
おお、条件付き書式にユーザ定義関数指定すれば確かにいけますね。
もしかし>>898の方はそういう意味で言ってくれていたのかも・・・^^;

これのほうが考え方としてはシンプルかもしれませんね。

この方法も検討してみます。どうもです。

956:949
11/05/15 19:04:06.15
>>951
すまん。やってみたらできなかった
ユーザ定義関数でRangeさわると、どうもその段階で循環参照するっぽい
ということで代替案を考えた

まずクラスモジュール(updateclass)つくる
Public WithEvents App As Application
Public RangeToUpdate As Range
Public ColorToUpdate As Variant
Private Sub App_AfterCalculate()
    If Not RangeToUpdate Is Nothing Then
        RangeToUpdate.Interior.ColorIndex = ColorToUpdate
        Set RangeToUpdate = Nothing
    End If
End Sub
Private Sub Class_Initialize()
    Set App = Application
End Sub

やってることはApplicationのAfterCalculateで色を設定する
設定する範囲をRangeToUpdateで
設定する色をColorToUpdateで指定する

つづく

957:949
11/05/15 19:04:27.17

んで標準モジュール
Dim upd As New updateclass
Public Function hoge(color)
    Set upd.RangeToUpdate = Application.ThisCell
    upd.ColorToUpdate = color
    hoge = "aaa"
End Function

必要なのはupdateclassのインスタンス作ること

ユーザ関数呼んだセルはApplication.ThisCellでとれるみたいなので
引数にRangeとる必要はなさそう

hogeの引数に色指定できるようにしてるから
ワークシートで=hoge(7)とか指定する


958:デフォルトの名無しさん
11/05/15 20:18:50.35
というかそこまで苦労してプログラム作るのって
なんかVBAの本来の目的から外れてる気がしないでもない

本当に必要な要件なのか、その辺から見直しオススメw

959:デフォルトの名無しさん
11/05/15 20:31:17.58
>>957
>ユーザ関数呼んだセルはApplication.ThisCellでとれるみたいなので
>引数にRangeとる必要はなさそう

その方法だと再計算後のイベントで拾って来て1セルしか処理していないから
一度計算式を入れたセルを、違う色に着色して複数セル選択してコピペしても
一つのセルしか色が変わらないんじゃないか?

960:デフォルトの名無しさん
11/05/15 20:37:16.18
つか関数でやるとセルをクリアしたとき塗りつぶし残ったままじゃん
あと条件をチェックする前に塗りつぶしをクリアしないと

961:デフォルトの名無しさん
11/05/15 20:51:45.22
ま、>>958が正解だな


962:デフォルトの名無しさん
11/05/15 22:09:09.26
>>958
これが正論であるがゆえ、Word VBAは隆盛をみないんだよなw
Access VBAはともかく


最新レス表示
レスジャンプ
類似スレ一覧
スレッドの検索
話題のニュース
おまかせリスト
オプション
しおりを挟む
スレッドに書込
スレッドの一覧
暇つぶし2ch