意の中のカワズ(35歳の壁 別館)

35歳の壁の別館ブログです。コード中心になるようにしたいので、技術雑記はできるだけ本館に書きます。

VBA:「シェイプの存在確認」

シェイプに何かする前。
つまり、シェイプを指定する場合には当然、
シェイプが存在している必要があるわけで
それを関数にするとなると色んなやり方がうまれます。


都度書くのが面倒なので、以下に残します。



' 指定したシェイプが存在すればTrueを返します。
' ただしこれは全検索タイプなので遅い
Public Function srchShape(srchName As String) As Boolean

Dim objShp As Shape

For Each objShp In ActiveSheet.Shapes
If StrComp(objShp.Name, srchName) = 0 Then
srchShape = True
Exit For
End If
Next

End Function

個人的には、こういう処理の仕方は嫌いなのですが、
速度のためには仕方ないってことで、速くしたいときはこっち。


' 指定したシェイプが存在すればTrueを返します。
' エラーで回避するのは好きじゃないが・・。
Public Function srchShape2(strSrchName As String) As Boolean

Dim objShp As Shape

On Error GoTo NO_OBJECT
If IsObject(ActiveSheet.Shapes(strSrchName)) Then
srchShape2 = True
End If

Exit Function

NO_OBJECT:
srchShape2 = False
Err.Clear
End Function


実は、どちらの処理も好きじゃありませんが、
今急いでるんでこれで。

VBA:「シェイプの位置(Rangeアドレス)の取得」

どうせ使うことになるので、書いておきます。


Public Function getShapeRange(strShapeName As String) As String
getShapeRange = _
ActiveSheet.Shapes(strShapeName).TopLeftCell.Address(False, False)
End Function

まぁ、オフセットでなくRangeで返したり、行番号だけ知りたいなどあるけど
自分はRangeのアドレスさえわかればそこからまた変換するCommonがあるので
それでよいかと。

VBA:「OnAction で呼び出す関数に引数を渡す方法」

んだよ。
できるんじゃん!

すみません。
探してみるものです。

シェイプにマクロを登録することができるわけですが、
そのマクロに引数が渡せないのかと思っておりました。

シェイプにマクロを登録すると、そいつをクリックしても
Selection にはならないので、どうやってそのシェイプから
来たかを判定する方法に苦慮しておりました・・。orz

以下、簡単な例。

まずは、呼び出されるマクロ。


Sub testName(testName As String)
MsgBox testName
End Sub


続いて、シェイプを作成しつつマクロ登録。


sub makeShape()
ActiveSheet.Shapes.AddLine(1278.75, 174#, 1357.5, 174#).Select
Selection.OnAction = "'testName""1234""'"
end sub

参考URLはこちら。
http://www.moug.net/tech/exvba/0080029.htm

関数名は、むき出しで引数をダブルクウォートで括る。
つまり、

testName"1234"

ですね。
これをシングルクウォートで括る。

'testName""1234""'

当然、ダブルクウォートは "" にしてエスケープさせる。
最後にそれらをダブルクウォートで括る。

"'testName""1234""'"

はい。
コレがわかってりゃ、無駄なコードかかずに済んだのに・・。

あ・・・あれ・・・なんか記憶のどこかでこの作業した気が・・。

ヤバイ・・・忘れすぎだろ・・。w


追記:
で、結局


sub makeShape()
ActiveSheet.Shapes.AddLine(1278.75, 174#, 1357.5, 174#).Select
Selection.OnAction = "'testName(1234)'"
end sub

でもできるし、シェイプ右クリックでマクロ登録時に

'testName("1234")'

で充分なことが判明。
やっぱり、これやったことあるわ・・。

で、第二引数の指定がうまくいかない問題が残ってるけど、ちょっと
今は進むことにします。

覚えている方いたら教えてください。

VBA:「Selection対象がシェイプの場合の注意点」

例えば、Line のシェイプを選択した状態。
つまり、Selection の中身はLineオブジェクト(Object/Line) の場合、
あたかもSelection のプロパティに Lineオブジェクトのプロパティも
表示されるような気になってはいけない。

当たり前だが、内部変数がLineなだけで参照はObject なのだと思う。

なので、例えばラインシェイプの線の種類にアクセスしたければ、

 Selection.ShapeRange.Line.DashStyle

としないとエラーとなる。
Selection.DashStyle ではない。

まぁ。当たり前のことだけどついついやってしまうし、忘れていることが多い。
ので、メモしておきます。

VBA:「イメージコンボボックスの初期選択行指定」

どこにも記載がないので載せておきます。

Me.imageCombobox1.SelectedItem でも、.text でも
初期行の選択ができなかったので以下の処理で実現。
なんか、これ.NET時代にやった気が・・・。w


Me.imageCombobox1.ComboItems(intIndex).Selected = True

参考までに珍しくイメージコンボについて結構書いてあるページを見つけました。

http://www6.plala.or.jp/MilkHouse/practical/contents313/contents31301d.html

スゴイやわらかい感じで、わかりやすいです。
というか、SelImageパラメータ の説明を書いてるのはここだけのような気がします。



一応、これらのイメージコンボを使用して作成した結果がこれ。

一番上の画像と色設定の画像は、シェイプをクリップボードに送りつけて
そこからPicureに設定しています。
まぁ、他のもがんばればそういう画像で動的にできるわけですが、面倒だし。
そこまでがんばる必要もないと思うんだよね。

VBA:「シェイプの書式変更」

シェイプの書式変更をコモンダイアログから設定する方法。
以下は、指定したシェイプ名の書式を変更します。
※ Line シェイプじゃないと動作しないようにしています。


' 選択したオブジェクトの色をダイアログから設定させます。
Public Sub colorSetFromDialogSelectItem( _
Optional strTargetName As String = "")

Dim intRet As Integer

If strTargetName <> "" Then
ActiveSheet.Shapes(strTargetName).Select
End If
If StrComp(TypeName(Selection), "Line") = 0 Then
intRet = Application.Dialogs(xlDialogPatterns).Show
End If

End Sub

実は、自分で作ったオリジナルの設定画面で色だけを設定するために
作ったのですが、これだと他の書式も同時に設定されてしまいます。


色だけを取得するためのカラーピッカーを作成(取得)する場合には、
やはり以下のほうがよいと思う。(また余計なものを作ってしまった・・。)
セルに対して行うためのダイアログを表示して、色情報だけ返してもらうものです。
IRO_FOR_DIALOG_DUMMY は、ダミーセル(そのセルに対してのカラーリストを
表示する)のRange名がConstで定義されています。

これを応用すれば選択したアイテムがLineのときのRGBだけを返すものが
できるはず。(面倒なのでもうつくらない!)



' 色をダイアログから設定させます。
' ただし、事前に設定場所(Range文字列)を選択した場所に対してになります。
' ソレをいいことにダミーポイントを使う方法にしました。
' (戻り画面で設定を押すまで有効にしたくないため。)
' 設定後の値を戻り値として返します。
Public Function colorSetFromDialog(strColorName As String) As Variant

Dim intRet As Integer

Range(IRO_FOR_DIALOG_DUMMY).Select
intRet = Application.Dialogs(xlDialogPatterns).Show
' 組み込みダイアログは、[OK] でtrue、キャンセルでfalse を返す。
If intRet Then
colorSetFromDialog = Range(IRO_FOR_DIALOG_DUMMY).Interior.Color
Else
colorSetFromDialog = Range(strColorName).Interior.Color
End If
Range(IRO_FOR_DIALOG_DUMMY).Interior.ColorIndex = xlNone

End Function


あぁ・・・くだらないことに時間掛けてて本題が進んでない!
バカ・・。



追記:2011.0928 22:01

一応の補足として、当然ながらDialogs関数で
ダイアログ定数を指定して表示することができるなら、
最初からLineオートシェイプ用の書式設定ダイアログを指定すればよい。
と、思うのだが(今回イチイチ頭がまわらんかった。)、なんか
前も探してだめだった気がしている。

▼ 今回探しているダイアログ


一応、ダイアログ定数の一覧は、こちら。
ありがたいよね。

http://www.excel7.com/personal/vba_shiryou1.htm

で、今一度試してみたが、関連してそうなのは全部ダメだった。

そんななか、Googleで検索することを思いつく。(ぉい!w
いやぁ・・・最近作ることばかり考えててだめだね・・。
いえ、今風邪ひいてるんで頭回ってないのが大きいのですが。

やぁ、真実を見つけましたよ。(笑
マイクロソフトのサイトです。

http://support.microsoft.com/kb/212177/ja

そこには衝撃の処理が・・。


SendKeys "^1", True


・・・・・。(w
わかりますよね。
Ctrl + 1 です。

そう、いわゆる書式設定を表示するためのショートカットです。

え?なにどうゆうこと??????
Ctrl+1 は、選択アイテムを判定しつつダイアログを切り替えるだけじゃなく
非公開ダイアログを表示するための処理が内包されてるのか!よんでるのか?

うーーーーーーーーーーーーーーん。
うーん・・・。

がんばって定数チェックしてみるってのもありだよね。
というか、定数ご存知の方いらっしゃいましたら
教えていただけると幸いです。

VBA全般:「シェイプの書式複写」

シェイプのコピーではなく、書式のみの複写をしたい場合どうするか。
もう・・こんなことすら覚えてない時点で俺の馬鹿馬鹿馬鹿!!


で、自作してしまったわけですが・・。
※ 面倒なのでテストしてませんが、以下の
   Selection.ShapeRange.IncrementLeft sngY
  は、
   Selection.ShapeRange.Left = 配置したい左位置
  でいけると思う。



' 指定した図形を複写して配置します。
Public Function shapeCopy(strShapeName As String, _
sngLeft As Single, sngTop As Single) As String
Dim sngX As Single
Dim sngY As Single

ActiveSheet.Shapes(strShapeName).Select
Selection.ShapeRange.Duplicate.Select
Selection.Name = "Buf" & CStr(ActiveSheet.Shapes.Count)

' 配置位置指定(相対位置しか指定できなかったので相殺して計算)
sngY = sngLeft - Selection.Left
sngX = sngTop - Selection.Top
Selection.ShapeRange.IncrementLeft sngY
Selection.ShapeRange.IncrementTop sngX
shapeCopy = Selection.Name
ActiveSheet.Shapes(strShapeName).Select

End Function


えぇ。
バカです。

以下、複写するだけのものを書きます。


' 指定した図形の書式設定をそのまま別の図形に複写します。
Public Sub shpaeToShapeCopy(strSrcShapeName As String, _
strDstShapeName As String)

ActiveSheet.Shapes.Range(strSrcShapeName).PickUp
ActiveSheet.Shapes.Range(strDstShapeName).Apply
End Sub

以上・・orz
ばか。